alsa: handle correctly if alsa returns us 0 or EAGAIN on snd_pcm_mmap_begin if we...
authorLennart Poettering <lennart@poettering.net>
Fri, 24 Jul 2009 11:45:59 +0000 (13:45 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 24 Jul 2009 11:45:59 +0000 (13:45 +0200)
src/modules/alsa/alsa-sink.c
src/modules/alsa/alsa-source.c

index e792590..46562cb 100644 (file)
@@ -401,6 +401,7 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle
         snd_pcm_sframes_t n;
         size_t n_bytes;
         int r;
+        pa_bool_t after_avail = TRUE;
 
         /* First we determine how many samples are missing to fill the
          * buffer up to 100% */
@@ -484,6 +485,9 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle
 
             if (PA_UNLIKELY((err = pa_alsa_safe_mmap_begin(u->pcm_handle, &areas, &offset, &frames, u->hwbuf_size, &u->sink->sample_spec)) < 0)) {
 
+                if (!after_avail && err == -EAGAIN)
+                    break;
+
                 if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0)
                     continue;
 
@@ -494,9 +498,12 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle
             if (frames > pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size)
                 frames = pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size;
 
-            if (frames == 0)
+            if (!after_avail && frames == 0)
                 break;
 
+            pa_assert(frames > 0);
+            after_avail = FALSE;
+
             /* Check these are multiples of 8 bit */
             pa_assert((areas[0].first & 7) == 0);
             pa_assert((areas[0].step & 7)== 0);
@@ -617,6 +624,7 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle
         for (;;) {
             snd_pcm_sframes_t frames;
             void *p;
+            pa_bool_t after_avail = TRUE;
 
 /*         pa_log_debug("%lu frames to write", (unsigned long) frames); */
 
@@ -634,17 +642,23 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle
             frames = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, (snd_pcm_uframes_t) frames);
             pa_memblock_release(u->memchunk.memblock);
 
-            if (frames == 0)
-                break;
-
             if (PA_UNLIKELY(frames < 0)) {
 
+                if (!after_avail && (int) frames == -EAGAIN)
+                    break;
+
                 if ((r = try_recover(u, "snd_pcm_writei", (int) frames)) == 0)
                     continue;
 
                 return r;
             }
 
+            if (!after_avail && frames == 0)
+                break;
+
+            pa_assert(frames > 0);
+            after_avail = FALSE;
+
             u->memchunk.index += (size_t) frames * u->frame_size;
             u->memchunk.length -= (size_t) frames * u->frame_size;
 
index 41bb768..8a1fbe5 100644 (file)
@@ -391,6 +391,7 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled
         snd_pcm_sframes_t n;
         size_t n_bytes;
         int r;
+        pa_bool_t after_avail = TRUE;
 
         if (PA_UNLIKELY((n = pa_alsa_safe_avail(u->pcm_handle, u->hwbuf_size, &u->source->sample_spec)) < 0)) {
 
@@ -463,6 +464,9 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled
 
             if (PA_UNLIKELY((err = pa_alsa_safe_mmap_begin(u->pcm_handle, &areas, &offset, &frames, u->hwbuf_size, &u->source->sample_spec)) < 0)) {
 
+                if (!after_avail && err == -EAGAIN)
+                    break;
+
                 if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0)
                     continue;
 
@@ -473,9 +477,12 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled
             if (frames > pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size)
                 frames = pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size;
 
-            if (frames == 0)
+            if (!after_avail && frames == 0)
                 break;
 
+            pa_assert(frames > 0);
+            after_avail = FALSE;
+
             /* Check these are multiples of 8 bit */
             pa_assert((areas[0].first & 7) == 0);
             pa_assert((areas[0].step & 7)== 0);
@@ -542,6 +549,7 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled
         snd_pcm_sframes_t n;
         size_t n_bytes;
         int r;
+        pa_bool_t after_avail = TRUE;
 
         if (PA_UNLIKELY((n = pa_alsa_safe_avail(u->pcm_handle, u->hwbuf_size, &u->source->sample_spec)) < 0)) {
 
@@ -602,20 +610,26 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled
             frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, (snd_pcm_uframes_t) frames);
             pa_memblock_release(chunk.memblock);
 
-            if (frames == 0) {
-                pa_memblock_unref(chunk.memblock);
-                break;
-            }
-
             if (PA_UNLIKELY(frames < 0)) {
                 pa_memblock_unref(chunk.memblock);
 
-                if ((r = try_recover(u, "snd_pcm_readi", (int) (frames))) == 0)
+                if (!after_avail && (int) frames == -EAGAIN)
+                    break;
+
+                if ((r = try_recover(u, "snd_pcm_readi", (int) frames)) == 0)
                     continue;
 
                 return r;
             }
 
+            if (!after_avail && frames == 0) {
+                pa_memblock_unref(chunk.memblock);
+                break;
+            }
+
+            pa_assert(frames > 0);
+            after_avail = FALSE;
+
             chunk.index = 0;
             chunk.length = (size_t) frames * u->frame_size;