diff options
author | Chris Robinson <[email protected]> | 2008-11-19 09:01:03 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2008-11-19 09:01:03 -0800 |
commit | 2d461379efa454e68982dbbcab3add0627d777c8 (patch) | |
tree | 05d3e8ecfa94d2885495bb08583c84ab1b2f0afb /Alc/alsa.c | |
parent | c8123756ffa2ad4b4ae25c9be33e4d9500bc4a00 (diff) |
Handle ALSA capture errors a bit better
Diffstat (limited to 'Alc/alsa.c')
-rw-r--r-- | Alc/alsa.c | 44 |
1 files changed, 35 insertions, 9 deletions
@@ -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); } |