]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Use an explicit 'is_running' flag in the sndio back end. Correct/improve some sndio...
authorMike Brady <4265913+mikebrady@users.noreply.github.com>
Mon, 22 Jul 2024 09:28:30 +0000 (10:28 +0100)
committerMike Brady <4265913+mikebrady@users.noreply.github.com>
Mon, 22 Jul 2024 09:28:30 +0000 (10:28 +0100)
audio_sndio.c
player.c
scripts/shairport-sync.conf

index a369bfb58a801d9cd091cd296b51673604cecbe4..9fa1ea986d6c5842e9823a2bf727c512d2b086d9 100644 (file)
@@ -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,
index 46ef100f6382c31d5a6932be91fcc00c0eb55203..11b0c5385c13b0f9ddde83402a211f0f6c85a624 100644 (file)
--- a/player.c
+++ b/player.c
@@ -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
 
index 78a79c7e1a128ad12cde580df0b84cc12819a3af..517a7560549b6d0fbcefd5a0f5dc86ba3234e5b3 100644 (file)
@@ -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