From 63761c193dfd5a34714db2e85382312c294cb85a Mon Sep 17 00:00:00 2001 Message-Id: <63761c193dfd5a34714db2e85382312c294cb85a.1715196849.git.mdw@distorted.org.uk> From: Mark Wooding Date: Fri, 13 Mar 2009 21:42:33 +0000 Subject: [PATCH] The command backend now sends 0s rather than suspending output when a pause occurs. This saves the receiver from having to infer pauses from flow control. It could usefuly be made into an option. Organization: Straylight/Edgeware From: Richard Kettlewell --- lib/uaudio-alsa.c | 3 ++- lib/uaudio-command.c | 3 ++- lib/uaudio-oss.c | 6 ++++-- lib/uaudio-rtp.c | 3 ++- lib/uaudio-thread.c | 34 +++++++++++++++++++++++----------- lib/uaudio.h | 12 +++++++++++- 6 files changed, 44 insertions(+), 17 deletions(-) diff --git a/lib/uaudio-alsa.c b/lib/uaudio-alsa.c index 48ae1be..721639c 100644 --- a/lib/uaudio-alsa.c +++ b/lib/uaudio-alsa.c @@ -136,7 +136,8 @@ static void alsa_start(uaudio_callback *callback, alsa_open(); uaudio_thread_start(callback, userdata, alsa_play, 32 / uaudio_sample_size, - 4096 / uaudio_sample_size); + 4096 / uaudio_sample_size, + 0); } static void alsa_stop(void) { diff --git a/lib/uaudio-command.c b/lib/uaudio-command.c index 5e4531e..096888d 100644 --- a/lib/uaudio-command.c +++ b/lib/uaudio-command.c @@ -121,7 +121,8 @@ static void command_start(uaudio_callback *callback, userdata, command_play, uaudio_channels, - 4096 / uaudio_sample_size); + 4096 / uaudio_sample_size, + UAUDIO_THREAD_FAKE_PAUSE); } static void command_stop(void) { diff --git a/lib/uaudio-oss.c b/lib/uaudio-oss.c index 35e14c0..6d902cb 100644 --- a/lib/uaudio-oss.c +++ b/lib/uaudio-oss.c @@ -128,13 +128,15 @@ static void oss_start(uaudio_callback *callback, /* Very specific buffer size requirements here apparently */ uaudio_thread_start(callback, userdata, oss_play, 4608 / uaudio_sample_size, - 4608 / uaudio_sample_size); + 4608 / uaudio_sample_size, + 0); #else /* We could SNDCTL_DSP_GETBLKSIZE but only when the device is already open, * which is kind of inconvenient. We go with 1-4Kbyte for now. */ uaudio_thread_start(callback, userdata, oss_play, 32 / uaudio_sample_size, - 4096 / uaudio_sample_size); + 4096 / uaudio_sample_size, + 0); #endif } diff --git a/lib/uaudio-rtp.c b/lib/uaudio-rtp.c index 702747a..31e8f57 100644 --- a/lib/uaudio-rtp.c +++ b/lib/uaudio-rtp.c @@ -281,7 +281,8 @@ static void rtp_start(uaudio_callback *callback, rtp_play, 256 / uaudio_sample_size, (NETWORK_BYTES - sizeof(struct rtp_header)) - / uaudio_sample_size); + / uaudio_sample_size, + 0); } static void rtp_stop(void) { diff --git a/lib/uaudio-thread.c b/lib/uaudio-thread.c index cd0d727..6bed4a8 100644 --- a/lib/uaudio-thread.c +++ b/lib/uaudio-thread.c @@ -68,6 +68,9 @@ static pthread_t uaudio_collect_thread; /** @brief Playing thread ID */ static pthread_t uaudio_play_thread; +/** @brief Flags */ +static unsigned uaudio_thread_flags; + static uaudio_callback *uaudio_thread_collect_callback; static uaudio_playcallback *uaudio_thread_play_callback; static void *uaudio_thread_userdata; @@ -104,7 +107,8 @@ static void *uaudio_collect_thread_fn(void attribute((unused)) *arg) { /* We are definitely active now */ uaudio_thread_collecting = 1; pthread_cond_broadcast(&uaudio_thread_cond); - while(uaudio_thread_activated) { + while(uaudio_thread_activated + || (uaudio_thread_flags & UAUDIO_THREAD_FAKE_PAUSE)) { if(uaudio_buffers_used() < UAUDIO_THREAD_BUFFERS - 1) { /* At least one buffer is available. We release the lock while * collecting data so that other already-filled buffers can be played @@ -115,12 +119,17 @@ static void *uaudio_collect_thread_fn(void attribute((unused)) *arg) { /* Keep on trying until we get the minimum required amount of data */ b->nsamples = 0; - while(b->nsamples < uaudio_thread_min) { - b->nsamples += uaudio_thread_collect_callback - ((char *)b->samples - + b->nsamples * uaudio_sample_size, - uaudio_thread_max - b->nsamples, - uaudio_thread_userdata); + if(uaudio_thread_activated) { + while(b->nsamples < uaudio_thread_min) { + b->nsamples += uaudio_thread_collect_callback + ((char *)b->samples + + b->nsamples * uaudio_sample_size, + uaudio_thread_max - b->nsamples, + uaudio_thread_userdata); + } + } else if(uaudio_thread_flags & UAUDIO_THREAD_FAKE_PAUSE) { + memset(b->samples, 0, uaudio_thread_min * uaudio_sample_size); + b->nsamples += uaudio_thread_min; } pthread_mutex_lock(&uaudio_thread_lock); /* Advance to next buffer */ @@ -199,13 +208,15 @@ void uaudio_thread_start(uaudio_callback *callback, void *userdata, uaudio_playcallback *playcallback, size_t min, - size_t max) { + size_t max, + unsigned flags) { int e; uaudio_thread_collect_callback = callback; uaudio_thread_userdata = userdata; uaudio_thread_play_callback = playcallback; uaudio_thread_min = min; uaudio_thread_max = max; + uaudio_thread_flags = flags; uaudio_thread_started = 1; for(int n = 0; n < UAUDIO_THREAD_BUFFERS; ++n) uaudio_buffers[n].samples = xcalloc_noptr(uaudio_thread_max, @@ -253,9 +264,10 @@ void uaudio_thread_deactivate(void) { pthread_mutex_lock(&uaudio_thread_lock); uaudio_thread_activated = 0; pthread_cond_broadcast(&uaudio_thread_cond); - - while(uaudio_thread_collecting || uaudio_buffers_used()) - pthread_cond_wait(&uaudio_thread_cond, &uaudio_thread_lock); + if(!(uaudio_thread_flags & UAUDIO_THREAD_FAKE_PAUSE)) { + while(uaudio_thread_collecting || uaudio_buffers_used()) + pthread_cond_wait(&uaudio_thread_cond, &uaudio_thread_lock); + } pthread_mutex_unlock(&uaudio_thread_lock); } diff --git a/lib/uaudio.h b/lib/uaudio.h index e796393..d6376c8 100644 --- a/lib/uaudio.h +++ b/lib/uaudio.h @@ -136,7 +136,17 @@ void uaudio_thread_start(uaudio_callback *callback, void *userdata, uaudio_playcallback *playcallback, size_t min, - size_t max); + size_t max, + unsigned flags); + +/** @brief Fake pauses + * + * This flag is used for audio backends that cannot sensibly be paused. + * The thread support code will supply silence while deactivated in this + * case. + */ +#define UAUDIO_THREAD_FAKE_PAUSE 0x00000001 + void uaudio_thread_stop(void); void uaudio_thread_activate(void); void uaudio_thread_deactivate(void); -- [mdw]