diff options
author | Chris Robinson <[email protected]> | 2010-06-05 17:41:33 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2010-06-05 17:41:33 -0700 |
commit | 0fdec056facefe2dc8a58889651fd5c859d303b7 (patch) | |
tree | 2b456c2b27749f2c6a55c913e0db14c6ce4714fd /Alc/alsa.c | |
parent | 1915fe831fd8559810bf07f44c54e8deddff1749 (diff) |
Improve error recovery when capturing from ALSA
Diffstat (limited to 'Alc/alsa.c')
-rw-r--r-- | Alc/alsa.c | 41 |
1 files changed, 31 insertions, 10 deletions
@@ -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); |