pause occurs. This saves the receiver from having to infer pauses
from flow control. It could usefuly be made into an option.
alsa_open();
uaudio_thread_start(callback, userdata, alsa_play,
32 / uaudio_sample_size,
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) {
}
static void alsa_stop(void) {
userdata,
command_play,
uaudio_channels,
userdata,
command_play,
uaudio_channels,
- 4096 / uaudio_sample_size);
+ 4096 / uaudio_sample_size,
+ UAUDIO_THREAD_FAKE_PAUSE);
}
static void command_stop(void) {
}
static void command_stop(void) {
/* Very specific buffer size requirements here apparently */
uaudio_thread_start(callback, userdata, oss_play,
4608 / uaudio_sample_size,
/* 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,
#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);
rtp_play,
256 / uaudio_sample_size,
(NETWORK_BYTES - sizeof(struct rtp_header))
rtp_play,
256 / uaudio_sample_size,
(NETWORK_BYTES - sizeof(struct rtp_header))
+ / uaudio_sample_size,
+ 0);
}
static void rtp_stop(void) {
}
static void rtp_stop(void) {
/** @brief Playing thread ID */
static pthread_t uaudio_play_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;
static uaudio_callback *uaudio_thread_collect_callback;
static uaudio_playcallback *uaudio_thread_play_callback;
static void *uaudio_thread_userdata;
/* We are definitely active now */
uaudio_thread_collecting = 1;
pthread_cond_broadcast(&uaudio_thread_cond);
/* 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
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
/* Keep on trying until we get the minimum required amount of data */
b->nsamples = 0;
/* 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 */
}
pthread_mutex_lock(&uaudio_thread_lock);
/* Advance to next buffer */
void *userdata,
uaudio_playcallback *playcallback,
size_t min,
void *userdata,
uaudio_playcallback *playcallback,
size_t min,
+ 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;
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,
uaudio_thread_started = 1;
for(int n = 0; n < UAUDIO_THREAD_BUFFERS; ++n)
uaudio_buffers[n].samples = xcalloc_noptr(uaudio_thread_max,
pthread_mutex_lock(&uaudio_thread_lock);
uaudio_thread_activated = 0;
pthread_cond_broadcast(&uaudio_thread_cond);
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);
}
pthread_mutex_unlock(&uaudio_thread_lock);
}
void *userdata,
uaudio_playcallback *playcallback,
size_t min,
void *userdata,
uaudio_playcallback *playcallback,
size_t min,
+ 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);
void uaudio_thread_stop(void);
void uaudio_thread_activate(void);
void uaudio_thread_deactivate(void);