From 2d461379efa454e68982dbbcab3add0627d777c8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 19 Nov 2008 09:01:03 -0800 Subject: Handle ALSA capture errors a bit better --- Alc/alsa.c | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/Alc/alsa.c b/Alc/alsa.c index 14450a95..27e43e53 100644 --- a/Alc/alsa.c +++ b/Alc/alsa.c @@ -724,9 +724,8 @@ static void alsa_close_capture(ALCdevice *pDevice) static void alsa_start_capture(ALCdevice *pDevice) { alsa_data *data = (alsa_data*)pDevice->ExtraData; - if(data->thread) - data->doCapture = 1; - else + data->doCapture = 1; + if(!data->thread) { psnd_pcm_prepare(data->pcmHandle); psnd_pcm_start(data->pcmHandle); @@ -736,9 +735,8 @@ static void alsa_start_capture(ALCdevice *pDevice) static void alsa_stop_capture(ALCdevice *pDevice) { alsa_data *data = (alsa_data*)pDevice->ExtraData; - if(data->thread) - data->doCapture = 0; - else + data->doCapture = 0; + if(!data->thread) psnd_pcm_drain(data->pcmHandle); } @@ -748,6 +746,7 @@ static void alsa_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint l const snd_pcm_channel_area_t *areas = NULL; snd_pcm_sframes_t frames, commitres; snd_pcm_uframes_t size, offset; + snd_pcm_state_t state; int err; if(data->thread) @@ -759,6 +758,17 @@ static void alsa_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint l return; } + state = psnd_pcm_state(data->pcmHandle); + if(state == SND_PCM_STATE_XRUN) + { + err = xrun_recovery(data->pcmHandle, -EPIPE); + if(err < 0) + { + AL_PRINT("XRUN recovery failed: %s\n", psnd_strerror(err)); + return; + } + } + frames = psnd_pcm_avail_update(data->pcmHandle); if(frames < 0) { @@ -815,20 +825,36 @@ static ALCuint alsa_available_samples(ALCdevice *pDevice) { alsa_data *data = (alsa_data*)pDevice->ExtraData; snd_pcm_sframes_t frames; + snd_pcm_state_t state; + int err; if(data->thread) return RingBufferSize(data->ring); + state = psnd_pcm_state(data->pcmHandle); + if(state == SND_PCM_STATE_XRUN) + { + err = xrun_recovery(data->pcmHandle, -EPIPE); + if(err >= 0) + { + if(data->doCapture) + err = psnd_pcm_start(data->pcmHandle); + } + if (err < 0) + { + AL_PRINT("XRUN recovery failed: %s\n", psnd_strerror(err)); + return 0; + } + } + frames = psnd_pcm_avail_update(data->pcmHandle); if(frames < 0) { - int err = xrun_recovery(data->pcmHandle, frames); + err = xrun_recovery(data->pcmHandle, frames); if (err < 0) AL_PRINT("available update failed: %s\n", psnd_strerror(err)); else frames = psnd_pcm_avail_update(data->pcmHandle); - if(frames < 0) /* ew.. */ - SetALCError(ALC_INVALID_DEVICE); } return max(frames, 0); } -- cgit v1.2.3