diff options
| author | Lennart Poettering <lennart@poettering.net> | 2009-07-24 13:45:59 +0200 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2009-07-24 13:45:59 +0200 | 
| commit | 18433c19b690432179e9a0ed83eff611f5cecc67 (patch) | |
| tree | 8aa3cc0b9cdbec422fbeabb21eb3d7ae1042bb63 | |
| parent | a81244a726b28fb7e3ccf5fd1d1d823023602c30 (diff) | |
alsa: handle correctly if alsa returns us 0 or EAGAIN on snd_pcm_mmap_begin if we didn't call snd_pcm_avail immediately before
| -rw-r--r-- | src/modules/alsa/alsa-sink.c | 22 | ||||
| -rw-r--r-- | src/modules/alsa/alsa-source.c | 28 | 
2 files changed, 39 insertions, 11 deletions
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index e7925902..46562cbd 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -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; diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index 41bb768b..8a1fbe5f 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -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;  | 
