Properly handle if ALSA sends us an POLLERR event, this should allow us to survive a system suspend cycle better

git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1941 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
Lennart Poettering 2007-10-17 16:54:46 +00:00
parent 2385efef61
commit 190081782c
3 changed files with 66 additions and 10 deletions

View file

@ -56,7 +56,7 @@ struct pa_alsa_fdlist {
};
static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void *userdata) {
struct pa_alsa_fdlist *fdl = userdata;
int err, i;
unsigned short revents;
@ -139,7 +139,7 @@ static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *u
if (fdl->ios) {
for (i = 0; i < fdl->num_fds; i++)
a->io_free(fdl->ios[i]);
if (num_fds != fdl->num_fds) {
pa_xfree(fdl->ios);
fdl->ios = NULL;
@ -290,7 +290,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
pa_assert(period_size);
snd_pcm_hw_params_alloca(&hwparams);
buffer_size = *periods * *period_size;
if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 ||
@ -302,11 +302,11 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
goto finish;
} else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
} else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
goto finish;
else if (*use_mmap)
*use_mmap = 0;
if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
goto finish;
@ -363,7 +363,7 @@ finish:
int pa_alsa_set_sw_params(snd_pcm_t *pcm) {
snd_pcm_sw_params_t *swparams;
int err;
pa_assert(pcm);
snd_pcm_sw_params_alloca(&swparams);
@ -382,7 +382,7 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm) {
pa_log_warn("Unable to set start threshold: %s\n", snd_strerror(err));
return err;
}
if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
pa_log_warn("Unable to set sw params: %s\n", snd_strerror(err));
return err;
@ -418,7 +418,7 @@ int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) {
snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback) {
snd_mixer_elem_t *elem;
snd_mixer_selem_id_t *sid = NULL;
snd_mixer_selem_id_alloca(&sid);
pa_assert(mixer);

View file

@ -654,6 +654,7 @@ static void thread_func(void *userdata) {
}
if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
if (revents & POLLERR)
pa_log_warn("Got POLLERR from ALSA");
if (revents & POLLNVAL)
@ -661,7 +662,34 @@ static void thread_func(void *userdata) {
if (revents & POLLHUP)
pa_log_warn("Got POLLHUP from ALSA");
goto fail;
/* Try to recover from this error */
switch (snd_pcm_state(u->pcm_handle)) {
case SND_PCM_STATE_XRUN:
if ((err = snd_pcm_recover(u->pcm_handle, -EPIPE, 1)) != 0) {
pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", snd_strerror(err));
goto fail;
}
break;
case SND_PCM_STATE_SUSPENDED:
if ((err = snd_pcm_recover(u->pcm_handle, -ESTRPIPE, 1)) != 0) {
pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", snd_strerror(err));
goto fail;
}
break;
default:
snd_pcm_drop(u->pcm_handle);
if ((err = snd_pcm_prepare(u->pcm_handle)) < 0) {
pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", snd_strerror(err));
goto fail;
}
break;
}
}
}
}

View file

@ -636,6 +636,7 @@ static void thread_func(void *userdata) {
}
if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
if (revents & POLLERR)
pa_log_warn("Got POLLERR from ALSA");
if (revents & POLLNVAL)
@ -643,7 +644,34 @@ static void thread_func(void *userdata) {
if (revents & POLLHUP)
pa_log_warn("Got POLLHUP from ALSA");
goto fail;
/* Try to recover from this error */
switch (snd_pcm_state(u->pcm_handle)) {
case SND_PCM_STATE_XRUN:
if ((err = snd_pcm_recover(u->pcm_handle, -EPIPE, 1)) != 0) {
pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", snd_strerror(err));
goto fail;
}
break;
case SND_PCM_STATE_SUSPENDED:
if ((err = snd_pcm_recover(u->pcm_handle, -ESTRPIPE, 1)) != 0) {
pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", snd_strerror(err));
goto fail;
}
break;
default:
snd_pcm_drop(u->pcm_handle);
if ((err = snd_pcm_prepare(u->pcm_handle)) < 0) {
pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", snd_strerror(err));
goto fail;
}
break;
}
}
}
}