From fa1895aa2b4f3f154e537bee92860fe793045643 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Sun, 3 Jan 2021 16:34:04 +0100 Subject: [PATCH 24/33] pcm: plugin - tidy snd_pcm_plugin_avail_update() No functional changes - move the code to snd_pcm_plugin_sync_hw_ptr() and put the mmap capture updates to separate function for readability. Signed-off-by: Jaroslav Kysela --- src/pcm/pcm_plugin.c | 142 +++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 66 deletions(-) diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c index ea60eb98986e..83793397a7f0 100644 --- a/src/pcm/pcm_plugin.c +++ b/src/pcm/pcm_plugin.c @@ -460,82 +460,92 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm, return xfer > 0 ? xfer : err; } -static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) +static snd_pcm_sframes_t +snd_pcm_plugin_sync_hw_ptr_capture(snd_pcm_t *pcm, + snd_pcm_sframes_t slave_size) { snd_pcm_plugin_t *plugin = pcm->private_data; snd_pcm_t *slave = plugin->gen.slave; - snd_pcm_sframes_t slave_size; + const snd_pcm_channel_area_t *areas; + snd_pcm_uframes_t xfer, hw_offset, size; int err; - slave_size = snd_pcm_avail_update(slave); + xfer = snd_pcm_mmap_capture_avail(pcm); + size = pcm->buffer_size - xfer; + areas = snd_pcm_mmap_areas(pcm); + hw_offset = snd_pcm_mmap_hw_offset(pcm); + while (size > 0 && slave_size > 0) { + snd_pcm_uframes_t frames = size; + snd_pcm_uframes_t cont = pcm->buffer_size - hw_offset; + const snd_pcm_channel_area_t *slave_areas; + snd_pcm_uframes_t slave_offset; + snd_pcm_uframes_t slave_frames = ULONG_MAX; + snd_pcm_sframes_t result; + /* As mentioned in the ALSA API (see pcm/pcm.c:942): + * The function #snd_pcm_avail_update() + * have to be called before any mmap begin+commit operation. + * Otherwise the snd_pcm_areas_copy will not called a second time. + * But this is needed, if the ring buffer wrap is reached and + * there is more data available. + */ + slave_size = snd_pcm_avail_update(slave); + result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames); + if (result < 0) { + err = result; + goto error; + } + if (frames > cont) + frames = cont; + frames = (plugin->read)(pcm, areas, hw_offset, frames, + slave_areas, slave_offset, &slave_frames); + result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames); + if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) { + snd_pcm_sframes_t res; + res = plugin->undo_read(slave, areas, hw_offset, frames, slave_frames - result); + if (res < 0) { + err = res; + goto error; + } + frames -= res; + } + if (result <= 0) { + err = result; + goto error; + } + snd_pcm_mmap_hw_forward(pcm, frames); + if (frames == cont) + hw_offset = 0; + else + hw_offset += frames; + size -= frames; + slave_size -= slave_frames; + xfer += frames; + } + return (snd_pcm_sframes_t)xfer; +error: + return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; +} + +static snd_pcm_sframes_t snd_pcm_plugin_sync_hw_ptr(snd_pcm_t *pcm, + snd_pcm_uframes_t slave_hw_ptr, + snd_pcm_sframes_t slave_size) +{ if (pcm->stream == SND_PCM_STREAM_CAPTURE && pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED && pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) - goto _capture; - *pcm->hw.ptr = *slave->hw.ptr; + return snd_pcm_plugin_sync_hw_ptr_capture(pcm, slave_size); + *pcm->hw.ptr = slave_hw_ptr; return slave_size; - _capture: - { - const snd_pcm_channel_area_t *areas; - snd_pcm_uframes_t xfer, hw_offset, size; - - xfer = snd_pcm_mmap_capture_avail(pcm); - size = pcm->buffer_size - xfer; - areas = snd_pcm_mmap_areas(pcm); - hw_offset = snd_pcm_mmap_hw_offset(pcm); - while (size > 0 && slave_size > 0) { - snd_pcm_uframes_t frames = size; - snd_pcm_uframes_t cont = pcm->buffer_size - hw_offset; - const snd_pcm_channel_area_t *slave_areas; - snd_pcm_uframes_t slave_offset; - snd_pcm_uframes_t slave_frames = ULONG_MAX; - snd_pcm_sframes_t result; - /* As mentioned in the ALSA API (see pcm/pcm.c:942): - * The function #snd_pcm_avail_update() - * have to be called before any mmap begin+commit operation. - * Otherwise the snd_pcm_areas_copy will not called a second time. - * But this is needed, if the ring buffer wrap is reached and - * there is more data available. - */ - slave_size = snd_pcm_avail_update(slave); - result = snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames); - if (result < 0) { - err = result; - goto error; - } - if (frames > cont) - frames = cont; - frames = (plugin->read)(pcm, areas, hw_offset, frames, - slave_areas, slave_offset, &slave_frames); - result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames); - if (result > 0 && (snd_pcm_uframes_t)result != slave_frames) { - snd_pcm_sframes_t res; - - res = plugin->undo_read(slave, areas, hw_offset, frames, slave_frames - result); - if (res < 0) { - err = res; - goto error; - } - frames -= res; - } - if (result <= 0) { - err = result; - goto error; - } - snd_pcm_mmap_hw_forward(pcm, frames); - if (frames == cont) - hw_offset = 0; - else - hw_offset += frames; - size -= frames; - slave_size -= slave_frames; - xfer += frames; - } - return (snd_pcm_sframes_t)xfer; +} - error: - return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; - } +static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm) +{ + snd_pcm_plugin_t *plugin = pcm->private_data; + snd_pcm_t *slave = plugin->gen.slave; + snd_pcm_sframes_t slave_size; + + slave_size = snd_pcm_avail_update(slave); + return snd_pcm_plugin_sync_hw_ptr(pcm, *slave->hw.ptr, slave_size); } static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status) -- 2.26.2