aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/alsa.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2010-06-05 17:41:33 -0700
committerChris Robinson <[email protected]>2010-06-05 17:41:33 -0700
commit0fdec056facefe2dc8a58889651fd5c859d303b7 (patch)
tree2b456c2b27749f2c6a55c913e0db14c6ce4714fd /Alc/alsa.c
parent1915fe831fd8559810bf07f44c54e8deddff1749 (diff)
Improve error recovery when capturing from ALSA
Diffstat (limited to 'Alc/alsa.c')
-rw-r--r--Alc/alsa.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/Alc/alsa.c b/Alc/alsa.c
index 32181370..2ec0e609 100644
--- a/Alc/alsa.c
+++ b/Alc/alsa.c
@@ -39,6 +39,7 @@ typedef struct {
ALvoid *buffer;
ALsizei size;
+ ALboolean doCapture;
RingBuffer *ring;
volatile int killNow;
@@ -929,51 +930,71 @@ static void alsa_start_capture(ALCdevice *Device)
AL_PRINT("start failed: %s\n", psnd_strerror(err));
aluHandleDisconnect(Device);
}
+ else
+ data->doCapture = AL_TRUE;
}
static void alsa_stop_capture(ALCdevice *Device)
{
alsa_data *data = (alsa_data*)Device->ExtraData;
psnd_pcm_drain(data->pcmHandle);
+ data->doCapture = AL_FALSE;
}
static ALCuint alsa_available_samples(ALCdevice *Device)
{
alsa_data *data = (alsa_data*)Device->ExtraData;
snd_pcm_sframes_t avail;
- snd_pcm_sframes_t amt;
avail = (Device->Connected ? psnd_pcm_avail_update(data->pcmHandle) : 0);
if(avail < 0)
{
AL_PRINT("avail update failed: %s\n", psnd_strerror(avail));
- psnd_pcm_recover(data->pcmHandle, avail, 1);
- amt = psnd_pcm_prepare(data->pcmHandle);
- if(amt < 0)
+ if((avail=psnd_pcm_recover(data->pcmHandle, avail, 1)) >= 0 &&
+ (avail=psnd_pcm_prepare(data->pcmHandle)) >= 0)
+ {
+ if(data->doCapture)
+ avail = psnd_pcm_start(data->pcmHandle);
+ if(avail >= 0)
+ avail = psnd_pcm_avail_update(data->pcmHandle);
+ }
+ if(avail < 0)
{
- AL_PRINT("prepare error: %s\n", psnd_strerror(amt));
+ AL_PRINT("restore error: %s\n", psnd_strerror(avail));
aluHandleDisconnect(Device);
}
}
- else while(avail > 0)
+ while(avail > 0)
{
+ snd_pcm_sframes_t amt;
+
amt = psnd_pcm_bytes_to_frames(data->pcmHandle, data->size);
if(avail < amt) amt = avail;
amt = psnd_pcm_readi(data->pcmHandle, data->buffer, amt);
if(amt < 0)
{
+ AL_PRINT("read error: %s\n", psnd_strerror(amt));
+
if(amt == -EAGAIN)
continue;
- psnd_pcm_recover(data->pcmHandle, avail, 1);
- amt = psnd_pcm_prepare(data->pcmHandle);
+ if((amt=psnd_pcm_recover(data->pcmHandle, amt, 1)) >= 0 &&
+ (amt=psnd_pcm_prepare(data->pcmHandle)) >= 0)
+ {
+ if(data->doCapture)
+ amt = psnd_pcm_start(data->pcmHandle);
+ if(amt >= 0)
+ amt = psnd_pcm_avail_update(data->pcmHandle);
+ }
if(amt < 0)
{
- AL_PRINT("prepare error: %s\n", psnd_strerror(amt));
+ AL_PRINT("restore error: %s\n", psnd_strerror(amt));
aluHandleDisconnect(Device);
+ break;
}
- break;
+ avail = amt;
+ continue;
}
WriteRingBuffer(data->ring, data->buffer, amt);