Recover stream when it's suspended upon rewind
authorLubomir Rintel <lkundrak@v3.sk>
Sun, 2 Aug 2009 15:52:05 +0000 (17:52 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 3 Aug 2009 20:47:15 +0000 (22:47 +0200)
Error from snd_pcm_rewind() might mean we just woke up from suspend and
didn't have a chance to try to recover the stream since we didn't write
to it in between. Call try_recover() in such cases.

Note that for this to work kernel must return ESTRPIPE instead of EBADF
for rewind/forward attempts on suspended streams, so that
snd_pcm_recover() can recognize it should snd_pcm_resume() the stream.
This is not the case yet (2.6.31-rc5), patch is available.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
src/modules/alsa/alsa-sink.c

index 7fc602b..2a734e3 100644 (file)
@@ -340,6 +340,9 @@ static int try_recover(struct userdata *u, const char *call, int err) {
     if (err == -EPIPE)
         pa_log_debug("%s: Buffer underrun!", call);
 
+    if (err == -EBADFD)
+        pa_log_debug("%s: Stream suspended!", call);
+
     if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) < 0) {
         pa_log("%s: %s", call, pa_alsa_strerror(err));
         return -1;
@@ -1199,8 +1202,11 @@ static int process_rewind(struct userdata *u) {
         pa_log_debug("before: %lu", (unsigned long) in_frames);
         if ((out_frames = snd_pcm_rewind(u->pcm_handle, (snd_pcm_uframes_t) in_frames)) < 0) {
             pa_log("snd_pcm_rewind() failed: %s", pa_alsa_strerror((int) out_frames));
-            return -1;
+            if (try_recover(u, "process_rewind", out_frames) < 0)
+                return -1;
+            out_frames = 0;
         }
+
         pa_log_debug("after: %lu", (unsigned long) out_frames);
 
         rewind_nbytes = (size_t) out_frames * u->frame_size;