aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/alsa.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2008-11-19 09:01:03 -0800
committerChris Robinson <[email protected]>2008-11-19 09:01:03 -0800
commit2d461379efa454e68982dbbcab3add0627d777c8 (patch)
tree05d3e8ecfa94d2885495bb08583c84ab1b2f0afb /Alc/alsa.c
parentc8123756ffa2ad4b4ae25c9be33e4d9500bc4a00 (diff)
Handle ALSA capture errors a bit better
Diffstat (limited to 'Alc/alsa.c')
-rw-r--r--Alc/alsa.c44
1 files 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);
}