Use an explicit 'is_running' flag in the sndio back end. Correct/improve some sndio documentation.
This commit is contained in:
+60
-34
@@ -4,7 +4,7 @@
|
||||
* Copyright (c) 2017 Tobias Kortkamp <t@tobik.me>
|
||||
*
|
||||
* Modifications for audio synchronisation
|
||||
* and related work, copyright (c) Mike Brady 2014 -- 2022
|
||||
* and related work, copyright (c) Mike Brady 2014 -- 2024
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
static pthread_mutex_t sndio_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct sio_hdl *hdl;
|
||||
static int is_running;
|
||||
static int framesize;
|
||||
static size_t played;
|
||||
static size_t written;
|
||||
@@ -58,7 +59,9 @@ static struct sndio_formats formats[] = {{"S8", SPS_FORMAT_S8, 44100, 8, 1, 1, S
|
||||
{"S24_3BE", SPS_FORMAT_S24_3BE, 44100, 24, 3, 1, 0},
|
||||
{"S32", SPS_FORMAT_S32, 44100, 32, 4, 1, SIO_LE_NATIVE}};
|
||||
|
||||
static void help() { printf(" -d output-device set the output device [default*|...]\n"); }
|
||||
static void help() {
|
||||
printf(" -d output-device set the output device [default|rsnd/0|rsnd/1...]\n");
|
||||
}
|
||||
|
||||
void onmove_cb(__attribute__((unused)) void *arg, int delta) {
|
||||
time_of_last_onmove_cb = get_absolute_time_in_ns();
|
||||
@@ -155,6 +158,7 @@ static int init(int argc, char **argv) {
|
||||
debug(1, "sndio: rate: %u.", par.rate);
|
||||
debug(1, "sndio: bits: %u.", par.bits);
|
||||
|
||||
is_running = 0;
|
||||
hdl = sio_open(devname, SIO_PLAY, 0);
|
||||
if (!hdl)
|
||||
die("sndio: cannot open audio device");
|
||||
@@ -206,26 +210,15 @@ static int init(int argc, char **argv) {
|
||||
}
|
||||
|
||||
static void deinit() {
|
||||
// pthread_mutex_lock(&sndio_mutex);
|
||||
pthread_cleanup_debug_mutex_lock(&sndio_mutex, 1000, 1);
|
||||
sio_close(hdl);
|
||||
// pthread_mutex_unlock(&sndio_mutex);
|
||||
pthread_cleanup_pop(1); // unlock the mutex
|
||||
}
|
||||
|
||||
static void start(__attribute__((unused)) int sample_rate,
|
||||
__attribute__((unused)) int sample_format) {
|
||||
// pthread_mutex_lock(&sndio_mutex);
|
||||
pthread_cleanup_debug_mutex_lock(&sndio_mutex, 1000, 1);
|
||||
at_least_one_onmove_cb_seen = 0;
|
||||
// any previously-reported frame count
|
||||
|
||||
if (!sio_start(hdl))
|
||||
die("sndio: unable to start");
|
||||
written = played = 0;
|
||||
time_of_last_onmove_cb = 0;
|
||||
at_least_one_onmove_cb_seen = 0;
|
||||
// pthread_mutex_unlock(&sndio_mutex);
|
||||
if (hdl != NULL) {
|
||||
if (is_running != 0) {
|
||||
sio_flush(hdl);
|
||||
is_running = 0;
|
||||
}
|
||||
sio_close(hdl);
|
||||
hdl = NULL;
|
||||
}
|
||||
pthread_cleanup_pop(1); // unlock the mutex
|
||||
}
|
||||
|
||||
@@ -233,10 +226,20 @@ static int play(void *buf, int frames, __attribute__((unused)) int sample_type,
|
||||
__attribute__((unused)) uint32_t timestamp,
|
||||
__attribute__((unused)) uint64_t playtime) {
|
||||
if (frames > 0) {
|
||||
// pthread_mutex_lock(&sndio_mutex);
|
||||
pthread_cleanup_debug_mutex_lock(&sndio_mutex, 1000, 1);
|
||||
if (is_running == 0) {
|
||||
if (hdl != NULL) {
|
||||
if (sio_start(hdl) != 1)
|
||||
debug(1, "sndio: unable to start");
|
||||
is_running = 1;
|
||||
written = played = 0;
|
||||
time_of_last_onmove_cb = 0;
|
||||
at_least_one_onmove_cb_seen = 0;
|
||||
} else {
|
||||
debug(1, "sndio: output device is not open for play!");
|
||||
}
|
||||
}
|
||||
written += sio_write(hdl, buf, frames * framesize);
|
||||
// pthread_mutex_unlock(&sndio_mutex);
|
||||
pthread_cleanup_pop(1); // unlock the mutex
|
||||
}
|
||||
return 0;
|
||||
@@ -244,10 +247,17 @@ static int play(void *buf, int frames, __attribute__((unused)) int sample_type,
|
||||
|
||||
static void stop() {
|
||||
pthread_cleanup_debug_mutex_lock(&sndio_mutex, 1000, 1);
|
||||
|
||||
if (!sio_stop(hdl))
|
||||
die("sndio: unable to stop");
|
||||
written = played = 0;
|
||||
if (hdl != NULL) {
|
||||
if (is_running != 0) {
|
||||
if (sio_flush(hdl) != 1)
|
||||
debug(1, "sndio: unable to stop");
|
||||
written = played = is_running = 0;
|
||||
} else {
|
||||
debug(1, "sndio: stop: not running.");
|
||||
}
|
||||
} else {
|
||||
debug(1, "sndio: output device is not open for stop!");
|
||||
}
|
||||
pthread_cleanup_pop(1); // unlock the mutex
|
||||
}
|
||||
|
||||
@@ -276,18 +286,34 @@ int get_delay(long *delay) {
|
||||
static int delay(long *delay) {
|
||||
int result = 0;
|
||||
pthread_cleanup_debug_mutex_lock(&sndio_mutex, 1000, 1);
|
||||
result = get_delay(delay);
|
||||
if (hdl != NULL) {
|
||||
if (is_running != 0) {
|
||||
result = get_delay(delay);
|
||||
} else {
|
||||
debug(1, "sndio: output device is not open for delay!");
|
||||
if (delay != NULL)
|
||||
*delay = 0;
|
||||
}
|
||||
} else {
|
||||
debug(1, "sndio: output device is not open for delay!");
|
||||
}
|
||||
pthread_cleanup_pop(1); // unlock the mutex
|
||||
return result;
|
||||
}
|
||||
|
||||
static void flush() {
|
||||
// pthread_mutex_lock(&sndio_mutex);
|
||||
pthread_cleanup_debug_mutex_lock(&sndio_mutex, 1000, 1);
|
||||
if (!sio_stop(hdl) || !sio_start(hdl))
|
||||
die("sndio: unable to flush");
|
||||
written = played = 0;
|
||||
// pthread_mutex_unlock(&sndio_mutex);
|
||||
if (hdl != NULL) {
|
||||
if (is_running != 0) {
|
||||
if (sio_flush(hdl) != 1)
|
||||
debug(1, "sndio: unable to flush");
|
||||
written = played = is_running = 0;
|
||||
} else {
|
||||
debug(1, "sndio: flush: not running.");
|
||||
}
|
||||
} else {
|
||||
debug(1, "sndio: output device is not open for flush!");
|
||||
}
|
||||
pthread_cleanup_pop(1); // unlock the mutex
|
||||
}
|
||||
|
||||
@@ -296,7 +322,7 @@ audio_output audio_sndio = {.name = "sndio",
|
||||
.init = &init,
|
||||
.deinit = &deinit,
|
||||
.prepare = NULL,
|
||||
.start = &start,
|
||||
.start = NULL,
|
||||
.stop = &stop,
|
||||
.is_running = NULL,
|
||||
.flush = &flush,
|
||||
|
||||
@@ -2141,9 +2141,10 @@ void *player_thread_func(void *arg) {
|
||||
if ((config.output->parameters == NULL) || (conn->input_bit_depth > output_bit_depth) ||
|
||||
(config.playback_mode == ST_mono))
|
||||
conn->enable_dither = 1;
|
||||
|
||||
// remember, the output device may never have been initialised prior to this call
|
||||
config.output->start(config.output_rate, config.output_format); // will need a corresponding stop
|
||||
|
||||
// call the backend's start() function if it exists.
|
||||
if (config.output->start != NULL)
|
||||
config.output->start(config.output_rate, config.output_format);
|
||||
|
||||
// we need an intermediate "transition" buffer
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ pw =
|
||||
// --with-sndio
|
||||
sndio =
|
||||
{
|
||||
// device = "snd/0"; // optional setting to set the name of the output device. Default is the sndio system default.
|
||||
// device = "default"; // optional setting to set the name of the output device, e.g. "rsnd/0", "rsnd/1", etc.
|
||||
// rate = 44100; // optional setting which can be 44100, 88200, 176400 or 352800, but the device must have the capability. Default is 44100.
|
||||
// format = "S16"; // optional setting which can be "U8", "S8", "S16", "S24", "S24_3LE", "S24_3BE" or "S32", but the device must have the capability. Except where stated using (*LE or *BE), endianness matches that of the processor.
|
||||
// round = <number>; // advanced optional setting to set the period size near to this value
|
||||
|
||||
Reference in New Issue
Block a user