From b63e44aab0e51b395ed0cff51d0df8d8f2300bcd Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Sun, 9 Dec 2001 12:32:42 +0000 Subject: [PATCH] Synchronized snd_pcm_write_areas and snd_pcm_read_areas with the kernel write/read functions. Changed snd_pcm_xfer_areas_func_t to return snd_pcm_sframes_t (pass errors). --- src/pcm/pcm.c | 35 +++++++++++++++++++++-------------- src/pcm/pcm_local.h | 2 +- src/pcm/pcm_mmap.c | 24 +++++++++++++++++------- src/pcm/pcm_null.c | 2 +- src/pcm/pcm_plugin.c | 22 ++++++++++++++++------ 5 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index b221f925..c5b872a7 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -4945,7 +4945,7 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_ snd_pcm_xfer_areas_func_t func) { snd_pcm_uframes_t xfer = 0; - int err = 0; + snd_pcm_sframes_t err = 0; snd_pcm_state_t state = snd_pcm_state(pcm); if (size == 0) @@ -4976,17 +4976,17 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_ _again: avail = snd_pcm_avail_update(pcm); if (avail < 0) { - err = -EPIPE; + err = avail; goto _end; } - if (state == SND_PCM_STATE_DRAINING) { - if (avail == 0) { + if ((state == SND_PCM_STATE_PAUSED) || + (state == SND_PCM_STATE_DRAINING)) { + if ((snd_pcm_uframes_t)avail < pcm->xfer_align) { err = -EPIPE; goto _end; } - } else if (avail == 0 || - (size >= pcm->xfer_align && - (snd_pcm_uframes_t) avail < pcm->xfer_align)) { + } else if (((snd_pcm_uframes_t)avail < pcm->avail_min && size > (snd_pcm_uframes_t)avail) || + (size >= pcm->xfer_align && (snd_pcm_uframes_t)avail < pcm->xfer_align)) { if (pcm->mode & SND_PCM_NONBLOCK) { err = -EAGAIN; goto _end; @@ -5029,7 +5029,7 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area snd_pcm_xfer_areas_func_t func) { snd_pcm_uframes_t xfer = 0; - int err = 0; + snd_pcm_sframes_t err = 0; snd_pcm_state_t state = snd_pcm_state(pcm); if (size == 0) @@ -5051,19 +5051,26 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area snd_pcm_uframes_t frames; snd_pcm_sframes_t avail; _again: + if (pcm->sleep_min == 0 && state == SND_PCM_STATE_RUNNING) { + snd_pcm_sframes_t delay; + /* update hw_ptr */ + err = snd_pcm_delay(pcm, &delay); + if (err < 0) + goto _end; + } avail = snd_pcm_avail_update(pcm); if (avail < 0) { - err = -EPIPE; + err = avail; goto _end; } - if (state == SND_PCM_STATE_PREPARED) { - if (avail == 0) { + if (state == SND_PCM_STATE_PAUSED || + state == SND_PCM_STATE_PREPARED) { + if ((snd_pcm_uframes_t)avail < pcm->xfer_align) { err = -EPIPE; goto _end; } - } else if (avail == 0 || - (size >= pcm->xfer_align && - (snd_pcm_uframes_t) avail < pcm->xfer_align)) { + } else if (((snd_pcm_uframes_t)avail < pcm->avail_min && size > (snd_pcm_uframes_t)avail) || + (size >= pcm->xfer_align && (snd_pcm_uframes_t)avail < pcm->xfer_align)) { if (pcm->mode & SND_PCM_NONBLOCK) { err = -EAGAIN; goto _end; diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index 6d33f7da..dcea9575 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -232,7 +232,7 @@ snd_pcm_sframes_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_ufram snd_pcm_sframes_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); snd_pcm_sframes_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); -typedef snd_pcm_uframes_t (*snd_pcm_xfer_areas_func_t)(snd_pcm_t *pcm, +typedef snd_pcm_sframes_t (*snd_pcm_xfer_areas_func_t)(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, snd_pcm_uframes_t offset, snd_pcm_uframes_t size); diff --git a/src/pcm/pcm_mmap.c b/src/pcm/pcm_mmap.c index 0dca3106..cf842bc7 100644 --- a/src/pcm/pcm_mmap.c +++ b/src/pcm/pcm_mmap.c @@ -80,12 +80,14 @@ void snd_pcm_mmap_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames) *pcm->hw_ptr = hw_ptr; } -static snd_pcm_uframes_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, snd_pcm_uframes_t offset, snd_pcm_uframes_t size) { - snd_pcm_uframes_t xfer = size; + snd_pcm_uframes_t xfer = 0; + int err; + assert(snd_pcm_mmap_playback_avail(pcm) >= size); while (size > 0) { const snd_pcm_channel_area_t *pcm_areas; @@ -96,31 +98,39 @@ static snd_pcm_uframes_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm, areas, offset, pcm->channels, frames, pcm->format); - snd_pcm_mmap_commit(pcm, pcm_offset, frames); + err = snd_pcm_mmap_commit(pcm, pcm_offset, frames); + if (err < 0) + return xfer > 0 ? xfer : err; offset += frames; + xfer += frames; size -= frames; } return xfer; } -static snd_pcm_uframes_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, snd_pcm_uframes_t offset, snd_pcm_uframes_t size) { - snd_pcm_uframes_t xfer = size; + snd_pcm_uframes_t xfer = 0; + int err; + assert(snd_pcm_mmap_capture_avail(pcm) >= size); while (size > 0) { const snd_pcm_channel_area_t *pcm_areas; snd_pcm_uframes_t pcm_offset; snd_pcm_uframes_t frames = size; snd_pcm_mmap_begin(pcm, &pcm_areas, &pcm_offset, &frames); - snd_pcm_areas_copy(areas, offset, + snd_pcm_areas_copy(areas, offset, pcm_areas, pcm_offset, pcm->channels, frames, pcm->format); - snd_pcm_mmap_commit(pcm, pcm_offset, frames); + err = snd_pcm_mmap_commit(pcm, pcm_offset, frames); + if (err < 0) + return xfer > 0 ? xfer : err; offset += frames; + xfer += frames; size -= frames; } return xfer; diff --git a/src/pcm/pcm_null.c b/src/pcm/pcm_null.c index a5f7b057..79c5abf1 100644 --- a/src/pcm/pcm_null.c +++ b/src/pcm/pcm_null.c @@ -191,7 +191,7 @@ static snd_pcm_sframes_t snd_pcm_null_fwd(snd_pcm_t *pcm, snd_pcm_uframes_t size } } -static snd_pcm_uframes_t snd_pcm_null_xfer_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_null_xfer_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas ATTRIBUTE_UNUSED, snd_pcm_uframes_t offset ATTRIBUTE_UNUSED, snd_pcm_uframes_t size) diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c index 78712e31..c127bc35 100644 --- a/src/pcm/pcm_plugin.c +++ b/src/pcm/pcm_plugin.c @@ -197,14 +197,16 @@ int snd_pcm_plugin_resume(snd_pcm_t *pcm) return snd_pcm_resume(plugin->slave); } -static snd_pcm_uframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, snd_pcm_uframes_t offset, snd_pcm_uframes_t size) { snd_pcm_plugin_t *plugin = pcm->private_data; snd_pcm_t *slave = plugin->slave; - snd_pcm_uframes_t xfer = size; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err; + while (size > 0) { snd_pcm_uframes_t frames = size; const snd_pcm_channel_area_t *slave_areas; @@ -217,22 +219,27 @@ static snd_pcm_uframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm, snd_atomic_write_begin(&plugin->watom); snd_pcm_mmap_appl_forward(pcm, frames); snd_pcm_mmap_hw_forward(pcm, frames); - snd_pcm_mmap_commit(slave, slave_offset, slave_frames); + err = snd_pcm_mmap_commit(slave, slave_offset, slave_frames); snd_atomic_write_end(&plugin->watom); + if (err < 0) + return xfer > 0 ? xfer : err; offset += frames; + xfer += frames; size -= frames; } return xfer; } -static snd_pcm_uframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm, +static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, snd_pcm_uframes_t offset, snd_pcm_uframes_t size) { snd_pcm_plugin_t *plugin = pcm->private_data; snd_pcm_t *slave = plugin->slave; - snd_pcm_uframes_t xfer = size; + snd_pcm_uframes_t xfer = 0; + snd_pcm_sframes_t err; + while (size > 0) { snd_pcm_uframes_t frames = size; const snd_pcm_channel_area_t *slave_areas; @@ -245,9 +252,12 @@ static snd_pcm_uframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm, snd_atomic_write_begin(&plugin->watom); snd_pcm_mmap_appl_forward(pcm, frames); snd_pcm_mmap_hw_forward(pcm, frames); - snd_pcm_mmap_commit(slave, slave_offset, slave_frames); + err = snd_pcm_mmap_commit(slave, slave_offset, slave_frames); snd_atomic_write_end(&plugin->watom); + if (err < 0) + return xfer > 0 ? xfer : err; offset += frames; + xfer += frames; size -= frames; } return xfer; -- 2.47.1