aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2008-09-07 17:45:05 -0700
committerEric Wong <normalperson@yhbt.net>2008-09-07 17:54:42 -0700
commit30a3603f35a3d2a752d601c60b61bddfd4c21ef1 (patch)
tree6dd06a1bc15a7c973ce1cd99e3efe8a74b69d449
parentbc44454d2b249d80275107dcfca41a20afb48ba9 (diff)
downloadmpd-30a3603f35a3d2a752d601c60b61bddfd4c21ef1.tar.gz
mpd-30a3603f35a3d2a752d601c60b61bddfd4c21ef1.tar.xz
mpd-30a3603f35a3d2a752d601c60b61bddfd4c21ef1.zip
alsa: optimistically try resuming from suspend
Apparently snd_pcm_hw_params_can_resume() can return false even though my hardware does in fact support resuming. So stop carrying that value in the canResume flag and just try to resume when we're in the suspended state; falling back to snd_pcm_prepare only if resuming fails. libao does something similar on resume, too. While we're at it, use the E() macro which will enable us to have better error reporting.
-rw-r--r--src/audioOutputs/audioOutput_alsa.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/src/audioOutputs/audioOutput_alsa.c b/src/audioOutputs/audioOutput_alsa.c
index 890049779..932f2dbc0 100644
--- a/src/audioOutputs/audioOutput_alsa.c
+++ b/src/audioOutputs/audioOutput_alsa.c
@@ -61,7 +61,6 @@ typedef struct _AlsaData {
int sampleSize;
int useMmap;
int canPause;
- int canResume;
} AlsaData;
static AlsaData *newAlsaData(void)
@@ -260,7 +259,6 @@ configure_hw:
goto error;
ad->canPause = snd_pcm_hw_params_can_pause(hwparams);
- ad->canResume = snd_pcm_hw_params_can_resume(hwparams);
/* configure SW params */
snd_pcm_sw_params_alloca(&swparams);
@@ -307,7 +305,8 @@ fail:
static int alsa_errorRecovery(AlsaData * ad, int err)
{
- snd_pcm_state_t state;
+ snd_pcm_state_t state = snd_pcm_state(ad->pcmHandle);
+ const char *err_cmd = NULL;
if (err == -EPIPE) {
DEBUG("Underrun on alsa device \"%s\"\n", ad->device);
@@ -315,18 +314,17 @@ static int alsa_errorRecovery(AlsaData * ad, int err)
DEBUG("alsa device \"%s\" was suspended\n", ad->device);
}
- switch (state = snd_pcm_state(ad->pcmHandle)) {
+ switch (state) {
case SND_PCM_STATE_PAUSED:
- err = snd_pcm_pause(ad->pcmHandle, /* disable */ 0);
+ err = E(snd_pcm_pause, ad->pcmHandle, /* disable */ 0);
break;
case SND_PCM_STATE_SUSPENDED:
- err = ad->canResume ?
- snd_pcm_resume(ad->pcmHandle) :
- snd_pcm_prepare(ad->pcmHandle);
- break;
+ if ((err = E(snd_pcm_resume, ad->pcmHandle)) == -EAGAIN)
+ return 0;
+ /* fall-through to snd_pcm_prepare: */
case SND_PCM_STATE_SETUP:
case SND_PCM_STATE_XRUN:
- err = snd_pcm_prepare(ad->pcmHandle);
+ err = E(snd_pcm_prepare, ad->pcmHandle);
break;
case SND_PCM_STATE_DISCONNECTED:
/* so alsa_closeDevice won't try to drain: */
@@ -345,7 +343,10 @@ static int alsa_errorRecovery(AlsaData * ad, int err)
DEBUG("ALSA in unknown state: %s\n", snd_pcm_state_name(state));
break;
}
-
+error:
+ if (err && err_cmd)
+ ERROR("ALSA error on device \"%s\" (%s): %s\n",
+ ad->device, err_cmd, snd_strerror(-err));
return err;
}