diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 359d2955..f8b68ed9 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -2357,7 +2357,7 @@ int snd_pcm_open_named_slave(snd_pcm_t **pcmp, const char *name, */ int snd_pcm_wait(snd_pcm_t *pcm, int timeout) { - if (snd_pcm_mmap_avail(pcm) >= pcm->avail_min) { + if (!snd_pcm_may_wait_for_avail_min(pcm, snd_pcm_mmap_avail(pcm))) { /* check more precisely */ switch (snd_pcm_state(pcm)) { case SND_PCM_STATE_XRUN: @@ -6776,14 +6776,14 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area goto _end; } if ((state == SND_PCM_STATE_RUNNING && - (snd_pcm_uframes_t)avail < pcm->avail_min && - size > (snd_pcm_uframes_t)avail)) { + size > (snd_pcm_uframes_t)avail && + snd_pcm_may_wait_for_avail_min(pcm, avail))) { if (pcm->mode & SND_PCM_NONBLOCK) { err = -EAGAIN; goto _end; } - err = snd_pcm_wait(pcm, -1); + err = snd_pcm_wait_nocheck(pcm, -1); if (err < 0) break; goto _again; diff --git a/src/pcm/pcm_generic.c b/src/pcm/pcm_generic.c index d56e5d3f..5fc48885 100644 --- a/src/pcm/pcm_generic.c +++ b/src/pcm/pcm_generic.c @@ -341,4 +341,10 @@ int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map) return snd_pcm_set_chmap(generic->slave, map); } +int snd_pcm_generic_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail ATTRIBUTE_UNUSED) +{ + snd_pcm_generic_t *generic = pcm->private_data; + return snd_pcm_may_wait_for_avail_min(generic->slave, snd_pcm_mmap_avail(generic->slave)); +} + #endif /* DOC_HIDDEN */ diff --git a/src/pcm/pcm_generic.h b/src/pcm/pcm_generic.h index 916c6eca..d1890774 100644 --- a/src/pcm/pcm_generic.h +++ b/src/pcm/pcm_generic.h @@ -109,6 +109,8 @@ typedef struct { snd1_pcm_generic_get_chmap #define snd_pcm_generic_set_chmap \ snd1_pcm_generic_set_chmap +#define snd_pcm_generic_may_wait_for_avail_min \ + snd1_pcm_generic_may_wait_for_avail_min int snd_pcm_generic_close(snd_pcm_t *pcm); int snd_pcm_generic_nonblock(snd_pcm_t *pcm, int nonblock); @@ -158,5 +160,5 @@ int snd_pcm_generic_munmap(snd_pcm_t *pcm); snd_pcm_chmap_query_t **snd_pcm_generic_query_chmaps(snd_pcm_t *pcm); snd_pcm_chmap_t *snd_pcm_generic_get_chmap(snd_pcm_t *pcm); int snd_pcm_generic_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map); - +int snd_pcm_generic_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail); diff --git a/src/pcm/pcm_hooks.c b/src/pcm/pcm_hooks.c index 0feb4a3a..f8372824 100644 --- a/src/pcm/pcm_hooks.c +++ b/src/pcm/pcm_hooks.c @@ -199,6 +199,7 @@ static const snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = { .poll_descriptors_count = snd_pcm_generic_poll_descriptors_count, .poll_descriptors = snd_pcm_generic_poll_descriptors, .poll_revents = snd_pcm_generic_poll_revents, + .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min, }; /** diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index e7798fd0..8cf7c3d7 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -177,6 +177,7 @@ typedef struct { int (*poll_descriptors_count)(snd_pcm_t *pcm); int (*poll_descriptors)(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space); int (*poll_revents)(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); + int (*may_wait_for_avail_min)(snd_pcm_t *pcm, snd_pcm_uframes_t avail); } snd_pcm_fast_ops_t; struct _snd_pcm { @@ -984,3 +985,13 @@ _snd_pcm_parse_config_chmaps(snd_config_t *conf); snd_pcm_chmap_t * _snd_pcm_choose_fixed_chmap(snd_pcm_t *pcm, snd_pcm_chmap_query_t * const *maps); +/* return true if the PCM stream may wait to get avail_min space */ +static inline int snd_pcm_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail) +{ + if (avail >= pcm->avail_min) + return 0; + if (pcm->fast_ops->may_wait_for_avail_min) + return pcm->fast_ops->may_wait_for_avail_min(pcm, avail); + return 1; +} + diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c index 42a125e5..e60b92d9 100644 --- a/src/pcm/pcm_meter.c +++ b/src/pcm/pcm_meter.c @@ -545,6 +545,7 @@ static const snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = { .poll_descriptors_count = snd_pcm_generic_poll_descriptors_count, .poll_descriptors = snd_pcm_generic_poll_descriptors, .poll_revents = snd_pcm_generic_poll_revents, + .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min, }; /** diff --git a/src/pcm/pcm_mmap_emul.c b/src/pcm/pcm_mmap_emul.c index 811cb1cb..67d2e050 100644 --- a/src/pcm/pcm_mmap_emul.c +++ b/src/pcm/pcm_mmap_emul.c @@ -400,6 +400,7 @@ static const snd_pcm_fast_ops_t snd_pcm_mmap_emul_fast_ops = { .poll_descriptors = snd_pcm_generic_poll_descriptors, .poll_descriptors_count = snd_pcm_generic_poll_descriptors_count, .poll_revents = snd_pcm_generic_poll_revents, + .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min, }; #ifndef DOC_HIDDEN diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c index ffb1b532..2db82c0c 100644 --- a/src/pcm/pcm_multi.c +++ b/src/pcm/pcm_multi.c @@ -739,6 +739,13 @@ static int snd_pcm_multi_mmap(snd_pcm_t *pcm) return 0; } +static int snd_pcm_multi_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail) +{ + snd_pcm_multi_t *multi = pcm->private_data; + snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm; + return snd_pcm_may_wait_for_avail_min(slave, snd_pcm_mmap_avail(slave)); +} + static snd_pcm_chmap_query_t **snd_pcm_multi_query_chmaps(snd_pcm_t *pcm) { snd_pcm_multi_t *multi = pcm->private_data; @@ -937,6 +944,7 @@ static const snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = { .poll_descriptors_count = snd_pcm_multi_poll_descriptors_count, .poll_descriptors = snd_pcm_multi_poll_descriptors, .poll_revents = snd_pcm_multi_poll_revents, + .may_wait_for_avail_min = snd_pcm_multi_may_wait_for_avail_min, }; /** diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c index d88e1178..96218a8d 100644 --- a/src/pcm/pcm_plugin.c +++ b/src/pcm/pcm_plugin.c @@ -570,6 +570,7 @@ const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = { .poll_descriptors_count = snd_pcm_generic_poll_descriptors_count, .poll_descriptors = snd_pcm_generic_poll_descriptors, .poll_revents = snd_pcm_generic_poll_revents, + .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min, }; #endif diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index 4ba8521e..54a3e670 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -1234,6 +1234,7 @@ static const snd_pcm_fast_ops_t snd_pcm_rate_fast_ops = { .poll_descriptors_count = snd_pcm_generic_poll_descriptors_count, .poll_descriptors = snd_pcm_generic_poll_descriptors, .poll_revents = snd_pcm_rate_poll_revents, + .may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min, }; static const snd_pcm_ops_t snd_pcm_rate_ops = {