From 7c201b510a33e48bdce97fb74b8bc3988aa18e10 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 17 Mar 2004 11:48:14 +0000 Subject: [PATCH] - added poll_ask callback to mangle avail_min (rate_plugin as example) - added mangling of avail_min to rate_plugin - added poll_fd_count variable - FIXME: move poll_revents callback to fast_ops --- src/pcm/pcm.c | 23 ++++++++++++++++- src/pcm/pcm_dmix.c | 1 + src/pcm/pcm_dshare.c | 1 + src/pcm/pcm_dsnoop.c | 1 + src/pcm/pcm_file.c | 9 +++++++ src/pcm/pcm_hooks.c | 9 +++++++ src/pcm/pcm_hw.c | 1 + src/pcm/pcm_local.h | 2 ++ src/pcm/pcm_meter.c | 9 +++++++ src/pcm/pcm_multi.c | 18 ++++++++++++++ src/pcm/pcm_null.c | 1 + src/pcm/pcm_plugin.c | 9 +++++++ src/pcm/pcm_rate.c | 59 +++++++++++++++++++++++++++++++++++--------- src/pcm/pcm_share.c | 1 + src/pcm/pcm_shm.c | 1 + 15 files changed, 132 insertions(+), 13 deletions(-) diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 2c37c344..971dba08 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -1230,7 +1230,15 @@ int snd_pcm_poll_descriptors_count(snd_pcm_t *pcm) */ int snd_pcm_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space) { + int err; + assert(pcm && pfds); + if (pcm->fast_ops->poll_ask) { + err = pcm->fast_ops->poll_ask(pcm->fast_op_arg); + if (err < 0) + return err; + } + assert(pcm->poll_fd >= 0); if (space >= 1 && pfds) { pfds->fd = pcm->poll_fd; pfds->events = pcm->poll_events | POLLERR | POLLNVAL; @@ -1255,7 +1263,7 @@ int snd_pcm_poll_descriptors_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsign { assert(pcm && pfds && revents); if (pcm->ops->poll_revents) - return pcm->ops->poll_revents(pcm, pfds, nfds, revents); + return pcm->ops->poll_revents(pcm->op_arg, pfds, nfds, revents); if (nfds == 1) { *revents = pfds->revents; return 0; @@ -2008,6 +2016,8 @@ int snd_pcm_new(snd_pcm_t **pcmp, snd_pcm_type_t type, const char *name, pcm->name = strdup(name); pcm->stream = stream; pcm->mode = mode; + pcm->poll_fd_count = 1; + pcm->poll_fd = -1; pcm->op_arg = pcm; pcm->fast_op_arg = pcm; INIT_LIST_HEAD(&pcm->async_handlers); @@ -2061,6 +2071,17 @@ int snd_pcm_wait(snd_pcm_t *pcm, int timeout) err_poll = poll(&pfd, 1, timeout); if (err_poll < 0) return -errno; +#if 0 /* very useful code to test poll related problems */ + { + snd_pcm_sframes_t delay, avail_update; + snd_pcm_hwsync(pcm); + avail_update = snd_pcm_avail_update(pcm); + if (avail_update < pcm->avail_min) { + printf("*** snd_pcm_wait() FATAL ERROR!!!\n"); + printf("avail_min = %li, avail_update = %li\n", pcm->avail_min, avail_update); + } + } +#endif err = snd_pcm_poll_descriptors_revents(pcm, &pfd, 1, &revents); if (err < 0) return err; diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c index 04f4ebc0..309514e9 100644 --- a/src/pcm/pcm_dmix.c +++ b/src/pcm/pcm_dmix.c @@ -766,6 +766,7 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = { .rewind = snd_pcm_dmix_rewind, .forward = snd_pcm_dmix_forward, .resume = snd_pcm_dmix_resume, + .poll_ask = NULL, .writei = snd_pcm_mmap_writei, .writen = snd_pcm_mmap_writen, .readi = snd_pcm_dmix_readi, diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c index 92ca3663..fe729cec 100644 --- a/src/pcm/pcm_dshare.c +++ b/src/pcm/pcm_dshare.c @@ -495,6 +495,7 @@ static snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = { .rewind = snd_pcm_dshare_rewind, .forward = snd_pcm_dshare_forward, .resume = snd_pcm_dshare_resume, + .poll_ask = NULL, .writei = snd_pcm_mmap_writei, .writen = snd_pcm_mmap_writen, .readi = snd_pcm_dshare_readi, diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c index 2ac62dc8..6e219558 100644 --- a/src/pcm/pcm_dsnoop.c +++ b/src/pcm/pcm_dsnoop.c @@ -463,6 +463,7 @@ static snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = { .rewind = snd_pcm_dsnoop_rewind, .forward = snd_pcm_dsnoop_forward, .resume = snd_pcm_dsnoop_resume, + .poll_ask = NULL, .writei = snd_pcm_dsnoop_writei, .writen = snd_pcm_dsnoop_writen, .readi = snd_pcm_mmap_readi, diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c index db1e33cb..6559545b 100644 --- a/src/pcm/pcm_file.c +++ b/src/pcm/pcm_file.c @@ -273,6 +273,14 @@ static int snd_pcm_file_resume(snd_pcm_t *pcm) return snd_pcm_resume(file->slave); } +static int snd_pcm_file_poll_ask(snd_pcm_t *pcm) +{ + snd_pcm_file_t *file = pcm->private_data; + if (file->slave->fast_ops->poll_ask) + return file->slave->fast_ops->poll_ask(file->slave->fast_op_arg); + return 0; +} + static snd_pcm_sframes_t snd_pcm_file_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) { snd_pcm_file_t *file = pcm->private_data; @@ -467,6 +475,7 @@ static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = { .rewind = snd_pcm_file_rewind, .forward = snd_pcm_file_forward, .resume = snd_pcm_file_resume, + .poll_ask = snd_pcm_file_poll_ask, .writei = snd_pcm_file_writei, .writen = snd_pcm_file_writen, .readi = snd_pcm_file_readi, diff --git a/src/pcm/pcm_hooks.c b/src/pcm/pcm_hooks.c index ea3e117c..0cf6d563 100644 --- a/src/pcm/pcm_hooks.c +++ b/src/pcm/pcm_hooks.c @@ -182,6 +182,14 @@ static int snd_pcm_hooks_resume(snd_pcm_t *pcm) return snd_pcm_resume(h->slave); } +static int snd_pcm_hooks_poll_ask(snd_pcm_t *pcm) +{ + snd_pcm_hooks_t *h = pcm->private_data; + if (h->slave->fast_ops->poll_ask) + return h->slave->fast_ops->poll_ask(h->slave->fast_op_arg); + return 0; +} + static snd_pcm_sframes_t snd_pcm_hooks_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) { snd_pcm_hooks_t *h = pcm->private_data; @@ -315,6 +323,7 @@ static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = { .rewind = snd_pcm_hooks_rewind, .forward = snd_pcm_hooks_forward, .resume = snd_pcm_hooks_resume, + .poll_ask = snd_pcm_hooks_poll_ask, .writei = snd_pcm_hooks_writei, .writen = snd_pcm_hooks_writen, .readi = snd_pcm_hooks_readi, diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index 1f5eadff..de269290 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -872,6 +872,7 @@ static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = { .rewind = snd_pcm_hw_rewind, .forward = snd_pcm_hw_forward, .resume = snd_pcm_hw_resume, + .poll_ask = NULL, .writei = snd_pcm_hw_writei, .writen = snd_pcm_hw_writen, .readi = snd_pcm_hw_readi, diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index f01f7a00..20c1784e 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -149,6 +149,7 @@ typedef struct { int (*hwsync)(snd_pcm_t *pcm); int (*delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp); int (*resume)(snd_pcm_t *pcm); + int (*poll_ask)(snd_pcm_t *pcm); snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames); snd_pcm_sframes_t (*forward)(snd_pcm_t *pcm, snd_pcm_uframes_t frames); snd_pcm_sframes_t (*writei)(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size); @@ -165,6 +166,7 @@ struct _snd_pcm { snd_pcm_type_t type; snd_pcm_stream_t stream; int mode; + int poll_fd_count; int poll_fd; unsigned short poll_events; int setup; diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c index 18f86deb..2f7fd6f0 100644 --- a/src/pcm/pcm_meter.c +++ b/src/pcm/pcm_meter.c @@ -411,6 +411,14 @@ static int snd_pcm_meter_resume(snd_pcm_t *pcm) return snd_pcm_resume(meter->slave); } +static int snd_pcm_meter_poll_ask(snd_pcm_t *pcm) +{ + snd_pcm_meter_t *meter = pcm->private_data; + if (meter->slave->fast_ops->poll_ask) + return meter->slave->fast_ops->poll_ask(meter->slave->fast_op_arg); + return 0; +} + static snd_pcm_sframes_t snd_pcm_meter_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t size) @@ -619,6 +627,7 @@ static snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = { .rewind = snd_pcm_meter_rewind, .forward = snd_pcm_meter_forward, .resume = snd_pcm_meter_resume, + .poll_ask = snd_pcm_meter_poll_ask, .writei = snd_pcm_mmap_writei, .writen = snd_pcm_mmap_writen, .readi = snd_pcm_mmap_readi, diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c index 0f047ecf..ea5b0633 100644 --- a/src/pcm/pcm_multi.c +++ b/src/pcm/pcm_multi.c @@ -560,6 +560,23 @@ static int snd_pcm_multi_resume(snd_pcm_t *pcm) return err; } +static int snd_pcm_multi_poll_ask(snd_pcm_t *pcm) +{ + snd_pcm_multi_t *multi = pcm->private_data; + snd_pcm_t *slave; + int err = 0; + unsigned int i; + for (i = 0; i < multi->slaves_count; ++i) { + slave = multi->slaves[i].pcm; + if (slave->fast_ops->poll_ask == NULL) + continue; + err = slave->fast_ops->poll_ask(slave->fast_op_arg); + if (err < 0) + return err; + } + return err; +} + static snd_pcm_sframes_t snd_pcm_multi_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t size) @@ -646,6 +663,7 @@ static snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = { .rewind = snd_pcm_multi_rewind, .forward = snd_pcm_multi_forward, .resume = snd_pcm_multi_resume, + .poll_ask = snd_pcm_multi_poll_ask, .avail_update = snd_pcm_multi_avail_update, .mmap_commit = snd_pcm_multi_mmap_commit, }; diff --git a/src/pcm/pcm_null.c b/src/pcm/pcm_null.c index c19826cc..c98943be 100644 --- a/src/pcm/pcm_null.c +++ b/src/pcm/pcm_null.c @@ -342,6 +342,7 @@ static snd_pcm_fast_ops_t snd_pcm_null_fast_ops = { .rewind = snd_pcm_null_rewind, .forward = snd_pcm_null_forward, .resume = snd_pcm_null_resume, + .poll_ask = NULL, .writei = snd_pcm_null_writei, .writen = snd_pcm_null_writen, .readi = snd_pcm_null_readi, diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c index 5ffb50c9..f5972911 100644 --- a/src/pcm/pcm_plugin.c +++ b/src/pcm/pcm_plugin.c @@ -343,6 +343,14 @@ int snd_pcm_plugin_resume(snd_pcm_t *pcm) return snd_pcm_resume(plugin->slave); } +int snd_pcm_plugin_poll_ask(snd_pcm_t *pcm) +{ + snd_pcm_plugin_t *plugin = pcm->private_data; + if (plugin->slave->fast_ops->poll_ask) + return plugin->slave->fast_ops->poll_ask(plugin->slave->fast_op_arg); + return 0; +} + 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, @@ -662,6 +670,7 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = { .rewind = snd_pcm_plugin_rewind, .forward = snd_pcm_plugin_forward, .resume = snd_pcm_plugin_resume, + .poll_ask = snd_pcm_plugin_poll_ask, .writei = snd_pcm_plugin_writei, .writen = snd_pcm_plugin_writen, .readi = snd_pcm_plugin_readi, diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index 51f2c1c6..897eafa6 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -79,6 +79,8 @@ typedef struct { int close_slave; snd_atomic_write_t watom; snd_pcm_uframes_t appl_ptr, hw_ptr; + snd_pcm_uframes_t orig_avail_min; + snd_pcm_sw_params_t sw_params; enum rate_type type; unsigned int get_idx; unsigned int put_idx; @@ -556,10 +558,11 @@ static int snd_pcm_rate_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) { snd_pcm_rate_t *rate = pcm->private_data; snd_pcm_t *slave = rate->slave; - snd_pcm_sw_params_t sparams; + snd_pcm_sw_params_t *sparams; snd_pcm_uframes_t boundary1, boundary2; - sparams = *params; + rate->sw_params = *params; + sparams = &rate->sw_params; if ((rate->pitch >= LINEAR_DIV ? 1 : 0) ^ (pcm->stream == SND_PCM_STREAM_CAPTURE ? 1 : 0)) { boundary1 = pcm->buffer_size; boundary2 = slave->buffer_size; @@ -576,7 +579,7 @@ static int snd_pcm_rate_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) } } params->boundary = boundary1; - sparams.boundary = boundary2; + sparams->boundary = boundary2; if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { rate->pitch = (((u_int64_t)slave->period_size * LINEAR_DIV) + pcm->period_size - 1) / pcm->period_size; do { @@ -624,17 +627,18 @@ static int snd_pcm_rate_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) } while (1); assert((snd_pcm_uframes_t)snd_pcm_rate_slave_frames(pcm, pcm->period_size - 1) == slave->period_size - 1); } - recalc(pcm, &sparams.avail_min); - recalc(pcm, &sparams.xfer_align); - recalc(pcm, &sparams.start_threshold); - if (sparams.stop_threshold >= sparams.boundary) { - sparams.stop_threshold = sparams.boundary; + recalc(pcm, &sparams->avail_min); + rate->orig_avail_min = sparams->avail_min; + recalc(pcm, &sparams->xfer_align); + recalc(pcm, &sparams->start_threshold); + if (sparams->stop_threshold >= sparams->boundary) { + sparams->stop_threshold = sparams->boundary; } else { - recalc(pcm, &sparams.stop_threshold); + recalc(pcm, &sparams->stop_threshold); } - recalc(pcm, &sparams.silence_threshold); - recalc(pcm, &sparams.silence_size); - return snd_pcm_sw_params(slave, &sparams); + recalc(pcm, &sparams->silence_threshold); + recalc(pcm, &sparams->silence_size); + return snd_pcm_sw_params(slave, sparams); } static int snd_pcm_rate_init(snd_pcm_t *pcm) @@ -913,6 +917,36 @@ static int snd_pcm_rate_resume(snd_pcm_t *pcm) return snd_pcm_resume(rate->slave); } +static int snd_pcm_rate_poll_ask(snd_pcm_t *pcm) +{ + snd_pcm_rate_t *rate = pcm->private_data; + snd_pcm_uframes_t avail_min; + int err; + + if (rate->slave->fast_ops->poll_ask) { + err = rate->slave->fast_ops->poll_ask(rate->slave->fast_op_arg); + if (err < 0) + return err; + } + avail_min = rate->appl_ptr % pcm->period_size; + if (avail_min > 0) { + recalc(pcm, &avail_min); + if (avail_min < rate->slave->buffer_size && + avail_min != rate->slave->period_size) + avail_min++; /* 1st small little rounding correction */ + if (avail_min < rate->slave->buffer_size && + avail_min != rate->slave->period_size) + avail_min++; /* 2nd small little rounding correction */ + avail_min += rate->orig_avail_min; + } else { + avail_min = rate->orig_avail_min; + } + if (rate->sw_params.avail_min == avail_min) + return 0; + rate->sw_params.avail_min = avail_min; + return snd_pcm_sw_params(rate->slave, &rate->sw_params); +} + static int snd_pcm_rate_commit_next_period(snd_pcm_t *pcm, snd_pcm_uframes_t appl_offset) { snd_pcm_rate_t *rate = pcm->private_data; @@ -1291,6 +1325,7 @@ static snd_pcm_fast_ops_t snd_pcm_rate_fast_ops = { .rewind = snd_pcm_rate_rewind, .forward = snd_pcm_rate_forward, .resume = snd_pcm_rate_resume, + .poll_ask = snd_pcm_rate_poll_ask, .writei = snd_pcm_mmap_writei, .writen = snd_pcm_mmap_writen, .readi = snd_pcm_mmap_readi, diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c index 89220135..6e1001e8 100644 --- a/src/pcm/pcm_share.c +++ b/src/pcm/pcm_share.c @@ -1296,6 +1296,7 @@ static snd_pcm_fast_ops_t snd_pcm_share_fast_ops = { .rewind = snd_pcm_share_rewind, .forward = snd_pcm_share_forward, .resume = snd_pcm_share_resume, + .poll_ask = NULL, /* FIXME */ .avail_update = snd_pcm_share_avail_update, .mmap_commit = snd_pcm_share_mmap_commit, }; diff --git a/src/pcm/pcm_shm.c b/src/pcm/pcm_shm.c index 1c963aff..1d46cd14 100644 --- a/src/pcm/pcm_shm.c +++ b/src/pcm/pcm_shm.c @@ -602,6 +602,7 @@ static snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = { .rewind = snd_pcm_shm_rewind, .forward = snd_pcm_shm_forward, .resume = snd_pcm_shm_resume, + .poll_ask = NULL, .writei = snd_pcm_mmap_writei, .writen = snd_pcm_mmap_writen, .readi = snd_pcm_mmap_readi, -- 2.47.1