]> code.delx.au - pulseaudio/commitdiff
Properly handle if ALSA sends us an POLLERR event, this should allow us to survive...
authorLennart Poettering <lennart@poettering.net>
Wed, 17 Oct 2007 16:54:46 +0000 (16:54 +0000)
committerLennart Poettering <lennart@poettering.net>
Wed, 17 Oct 2007 16:54:46 +0000 (16:54 +0000)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1941 fefdeb5f-60dc-0310-8127-8f9354f1896f

src/modules/alsa-util.c
src/modules/module-alsa-sink.c
src/modules/module-alsa-source.c

index ee2dfdb83cd919126cf4bc99211479daebee2d16..9ea5ad1293f2eb02e6be55c8fa6dff25da65c00c 100644 (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);
index bb78bca2484481343daa2e39cd3ab581fed5aa9b..a09247fea08bb83ff888b75a18fa3a1ebdeac446 100644 (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;
+                }
             }
         }
     }
index 0f19a4ae5c2c8a3c8027d7e7ea9ac6a740085e1d..d840cac3090a873bb31f1c141183d4910ac25fa7 100644 (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;
+                }
             }
         }
     }