]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Version 3.3.8 is 3.3.8rc7.
authorMike Brady <4265913+mikebrady@users.noreply.github.com>
Mon, 26 Apr 2021 10:23:13 +0000 (11:23 +0100)
committerMike Brady <4265913+mikebrady@users.noreply.github.com>
Mon, 26 Apr 2021 10:23:13 +0000 (11:23 +0100)
audio_alsa.c
common.c
configure.ac
dacp.c
rtsp.c
scripts/shairport-sync.conf

index 69722d12f8836f9b031e942784b616967ebcad64..b464279c2e1e6fdfd67909c5288b5031d79213a3 100644 (file)
@@ -1455,19 +1455,31 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
   int ret = snd_pcm_status(alsa_handle, alsa_snd_pcm_status);
   if (ret == 0) {
 
-// must be 1.1 or later to use snd_pcm_status_get_driver_htstamp
-#if SND_LIB_MINOR == 0
     snd_pcm_status_get_htstamp(alsa_snd_pcm_status, &update_timestamp);
-#else
-    snd_pcm_status_get_driver_htstamp(alsa_snd_pcm_status, &update_timestamp);
+
+/*
+// must be 1.1 or later to use snd_pcm_status_get_driver_htstamp
+#if SND_LIB_MINOR != 0
+    snd_htimestamp_t driver_htstamp;
+    snd_pcm_status_get_driver_htstamp(alsa_snd_pcm_status, &driver_htstamp);
+    uint64_t driver_htstamp_ns = driver_htstamp.tv_sec;
+    driver_htstamp_ns = driver_htstamp_ns * 1000000000;
+    driver_htstamp_ns = driver_htstamp_ns + driver_htstamp.tv_nsec;
+    debug(1,"driver_htstamp: %f.", driver_htstamp_ns * 0.000000001);
 #endif
+*/
 
     *state = snd_pcm_status_get_state(alsa_snd_pcm_status);
 
     if ((*state == SND_PCM_STATE_RUNNING) || (*state == SND_PCM_STATE_DRAINING)) {
 
-      uint64_t update_timestamp_ns =
-          update_timestamp.tv_sec * (uint64_t)1000000000 + update_timestamp.tv_nsec;
+ //     uint64_t update_timestamp_ns =
+ //         update_timestamp.tv_sec * (uint64_t)1000000000 + update_timestamp.tv_nsec;
+
+      uint64_t update_timestamp_ns = update_timestamp.tv_sec;
+      update_timestamp_ns = update_timestamp_ns * 1000000000;
+      update_timestamp_ns = update_timestamp_ns + update_timestamp.tv_nsec;
+
 
       // if the update_timestamp is zero, we take this to mean that the device doesn't report
       // interrupt timings. (It could be that it's not a real hardware device.)
@@ -1497,7 +1509,7 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
       if (update_timestamp_ns == 0) {
         ret = snd_pcm_delay(alsa_handle, delay);
       } else {
-        *delay = snd_pcm_status_get_delay(alsa_snd_pcm_status);
+        snd_pcm_sframes_t delay_temp = snd_pcm_status_get_delay(alsa_snd_pcm_status);
 
         /*
         // It seems that the alsa library uses CLOCK_REALTIME before 1.0.28, even though
@@ -1514,11 +1526,15 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
         else
           clock_gettime(CLOCK_REALTIME, &tn);
 
-        uint64_t time_now_ns = tn.tv_sec * (uint64_t)1000000000 + tn.tv_nsec;
+        // uint64_t time_now_ns = tn.tv_sec * (uint64_t)1000000000 + tn.tv_nsec;
+        uint64_t time_now_ns = tn.tv_sec;
+        time_now_ns = time_now_ns * 1000000000;
+        time_now_ns = time_now_ns + tn.tv_nsec;
+
 
         // see if it's stalled
 
-        if ((stall_monitor_start_time != 0) && (stall_monitor_frame_count == *delay)) {
+        if ((stall_monitor_start_time != 0) && (stall_monitor_frame_count == delay_temp)) {
           // hasn't outputted anything since the last call to delay()
 
           if (((update_timestamp_ns - stall_monitor_start_time) > stall_monitor_error_threshold) ||
@@ -1539,19 +1555,27 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
           }
         } else {
           stall_monitor_start_time = update_timestamp_ns;
-          stall_monitor_frame_count = *delay;
+          stall_monitor_frame_count = delay_temp;
         }
 
         if (ret == 0) {
           uint64_t delta = time_now_ns - update_timestamp_ns;
 
-          uint64_t frames_played_since_last_interrupt =
-              ((uint64_t)config.output_rate * delta) / 1000000000;
+//          uint64_t frames_played_since_last_interrupt =
+//              ((uint64_t)config.output_rate * delta) / 1000000000;
+
+            uint64_t frames_played_since_last_interrupt = config.output_rate;
+            frames_played_since_last_interrupt = frames_played_since_last_interrupt * delta;
+            frames_played_since_last_interrupt = frames_played_since_last_interrupt / 1000000000;
+
+
           snd_pcm_sframes_t frames_played_since_last_interrupt_sized =
               frames_played_since_last_interrupt;
-
-          *delay = *delay - frames_played_since_last_interrupt_sized;
+          if ((frames_played_since_last_interrupt_sized < 0) || ((uint64_t)frames_played_since_last_interrupt_sized != frames_played_since_last_interrupt))
+            debug(1,"overflow resizing frames_played_since_last_interrupt % " PRIx64 " to frames_played_since_last_interrupt %lx.", frames_played_since_last_interrupt, frames_played_since_last_interrupt_sized);
+          delay_temp = delay_temp - frames_played_since_last_interrupt_sized;
         }
+        *delay = delay_temp;
       }
     } else { // not running, thus no delay information, thus can't check for
              // stall
@@ -1582,25 +1606,26 @@ int delay(long *the_delay) {
   // sps_extra_code_output_state_cannot_make_ready codes
   int ret = 0;
   *the_delay = 0;
-  if (alsa_handle == NULL)
-    ret = ENODEV;
-  else {
-    int oldState;
 
-    snd_pcm_state_t state;
-    snd_pcm_sframes_t my_delay = 0; // this initialisation is to silence a clang warning
+  int oldState;
 
-    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable
-    pthread_cleanup_debug_mutex_lock(&alsa_mutex, 10000, 0);
+  snd_pcm_state_t state;
+  snd_pcm_sframes_t my_delay = 0; // this initialisation is to silence a clang warning
 
+  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable
+  pthread_cleanup_debug_mutex_lock(&alsa_mutex, 10000, 0);
+
+  if (alsa_handle == NULL)
+    ret = ENODEV;
+  else
     ret = delay_and_status(&state, &my_delay, NULL);
 
-    debug_mutex_unlock(&alsa_mutex, 0);
-    pthread_cleanup_pop(0);
-    pthread_setcancelstate(oldState, NULL);
+  debug_mutex_unlock(&alsa_mutex, 0);
+  pthread_cleanup_pop(0);
+  pthread_setcancelstate(oldState, NULL);
+
+  *the_delay = my_delay; // note: snd_pcm_sframes_t is a long
 
-    *the_delay = my_delay; // note: snd_pcm_sframes_t is a long
-  }
   return ret;
 }
 
index 8520c71475694cd92022c4ab19dbaaabc991968f..6e0f12ab65613d07ccfdf1b2b4d9a7834d47f890 100644 (file)
--- a/common.c
+++ b/common.c
@@ -834,7 +834,7 @@ void command_set_volume(double volume) {
           _exit(EXIT_FAILURE); /* only if execv fails */
         }
       }
-    _exit(EXIT_SUCCESS);
+      _exit(EXIT_SUCCESS);
     } else {
       if (config.cmd_blocking) { /* pid!=0 means parent process and if blocking is true, wait for
                                     process to finish */
index 5898a17218cedffe721f09d5d36cb47be423c4a8..f77087c595d67f5798cd1655d09534afc7ed28e0 100644 (file)
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ([2.50])
-AC_INIT([shairport-sync], [3.3.8rc3], [4265913+mikebrady@users.noreply.github.com])
+AC_INIT([shairport-sync], [3.3.8], [4265913+mikebrady@users.noreply.github.com])
 AM_INIT_AUTOMAKE
 AC_CONFIG_SRCDIR([shairport.c])
 AC_CONFIG_HEADERS([config.h])
@@ -147,17 +147,18 @@ AM_CONDITIONAL([USE_CUSTOMPIDDIR], [ test "x${with_piddir}" != "x" ])
 
 # Look for libdaemon
 AC_ARG_WITH(libdaemon,[AS_HELP_STRING([--with-libdaemon],[include support for daemonising in non-systemd systems])])
-if test "x$with_libdaemon" = "x1"; then
+if test "x$with_libdaemon" = "xyes"; then
        AC_DEFINE([CONFIG_LIBDAEMON], 1, [Include libdaemon for daemonising in non-systemd systems])
        if  test "x${with_pkg_config}" = xyes ; then
                PKG_CHECK_MODULES(
                                [DAEMON], [libdaemon],
-                               [LIBS="${DAEMON_LIBS} ${LIBS}"])
+                               [LIBS="${DAEMON_LIBS} ${LIBS}"],
+                               [AC_MSG_ERROR(the libdaemon library has been selected but is missing -- libdaemon-dev suggested!)])
        else
-               AC_CHECK_LIB([daemon],[daemon_fork], , AC_MSG_ERROR(libdaemon needed))
+               AC_CHECK_LIB([daemon],[daemon_fork], , AC_MSG_ERROR(the libdaemon library has been selected but is missing -- libdaemon-dev suggested!))
        fi
 fi
-AM_CONDITIONAL([USE_LIBDAEMON], [test "x$with_libdaemon" = "x1"])
+AM_CONDITIONAL([USE_LIBDAEMON], [test "x$with_libdaemon" = "xyes"])
 
 # Check --with-ssl=argument
 AC_ARG_WITH(ssl, [AS_HELP_STRING([--with-ssl=<argument>],[choose --with-ssl=openssl, --with-ssl=mbedtls or --with-ssl=polarssl (deprecated) for encryption services  ])])
@@ -241,7 +242,7 @@ if test "x$with_alsa" = "xyes" ; then
   else
     AC_CHECK_LIB([asound], [snd_pcm_open], , AC_MSG_ERROR(ALSA support requires the asound library!))
   fi
-fi  
+fi
 AM_CONDITIONAL([USE_ALSA], [test "x$with_alsa" = "xyes"])
 
 # Look for jack flag
@@ -317,7 +318,7 @@ AM_CONDITIONAL([USE_DNS_SD], [test "x$with_dns_sd" = "xyes"])
 
 # Look for dbus flag
 AC_ARG_WITH(dbus-interface, [AS_HELP_STRING([--with-dbus-interface],[include support for the native Shairport Sync D-Bus interface])])
-if test "x$with_dbus_interface" = "xyes" ; then 
+if test "x$with_dbus_interface" = "xyes" ; then
   AC_DEFINE([CONFIG_DBUS_INTERFACE], 1, [Support the native Shairport Sync D-Bus interface])
   # remember to include glib, below
 fi
diff --git a/dacp.c b/dacp.c
index effbe5ecc18d451ce093332a47199bfb3e412cb2..0230ac1cc0c14d04cbaa8b2cb8bd93c181f832b1 100644 (file)
--- a/dacp.c
+++ b/dacp.c
@@ -446,11 +446,11 @@ void set_dacp_server_information(rtsp_conn_info *conn) {
   if (dacp_server.active_remote_id)
     free(dacp_server.active_remote_id);
   if (conn->dacp_active_remote)
-               dacp_server.active_remote_id =
-                               strdup(conn->dacp_active_remote); // even if the dacp_id remains the same,
-                                                                                                                                                                       // the active remote will change.
+    dacp_server.active_remote_id =
+        strdup(conn->dacp_active_remote); // even if the dacp_id remains the same,
+                                          // the active remote will change.
   else
-       dacp_server.active_remote_id = NULL;
+    dacp_server.active_remote_id = NULL;
 
   debug(3, "set_dacp_server_information set active-remote id to %s.", dacp_server.active_remote_id);
   pthread_cond_signal(&dacp_server_information_cv);
diff --git a/rtsp.c b/rtsp.c
index f3524ae2c93df83990546c9dedc34b4deea07f13..2661ccec6b38d93ac1e2c3f3cc7ada1746de7c21 100644 (file)
--- a/rtsp.c
+++ b/rtsp.c
@@ -1652,40 +1652,41 @@ void *metadata_mqtt_thread_function(__attribute__((unused)) void *ignore) {
 #endif
 
 void metadata_init(void) {
-       int ret;
-       if (config.metadata_enabled) {
-               // create the metadata pipe, if necessary
-               size_t pl = strlen(config.metadata_pipename) + 1;
-               char *path = malloc(pl + 1);
-               snprintf(path, pl + 1, "%s", config.metadata_pipename);
-               mode_t oldumask = umask(000);
-               if (mkfifo(path, 0666) && errno != EEXIST)
-                       die("Could not create metadata pipe \"%s\".", path);
-               umask(oldumask);
-               debug(1, "metadata pipe name is \"%s\".", path);
-
-               // try to open it
-               fd = try_to_open_pipe_for_writing(path);
-               // we check that it's not a "real" error. From the "man 2 open" page:
-               // "ENXIO  O_NONBLOCK | O_WRONLY is set, the named file is a FIFO, and no process has the FIFO
-               // open for reading." Which is okay.
-               if ((fd == -1) && (errno != ENXIO)) {
-                       char errorstring[1024];
-                       strerror_r(errno, (char *)errorstring, sizeof(errorstring));
-                       debug(1, "metadata_hub_thread_function -- error %d (\"%s\") opening pipe: \"%s\".", errno,
-                                               (char *)errorstring, path);
-                       warn("can not open metadata pipe -- error %d (\"%s\") opening pipe: \"%s\".", errno,
-                                        (char *)errorstring, path);
-               }
-               free(path);
-               int ret;
-               ret = pthread_create(&metadata_thread, NULL, metadata_thread_function, NULL);
-               if (ret)
-                       debug(1, "Failed to create metadata thread!");
-
-               ret = pthread_create(&metadata_multicast_thread, NULL, metadata_multicast_thread_function, NULL);
-               if (ret)
-                       debug(1, "Failed to create metadata multicast thread!");
+  int ret;
+  if (config.metadata_enabled) {
+    // create the metadata pipe, if necessary
+    size_t pl = strlen(config.metadata_pipename) + 1;
+    char *path = malloc(pl + 1);
+    snprintf(path, pl + 1, "%s", config.metadata_pipename);
+    mode_t oldumask = umask(000);
+    if (mkfifo(path, 0666) && errno != EEXIST)
+      die("Could not create metadata pipe \"%s\".", path);
+    umask(oldumask);
+    debug(1, "metadata pipe name is \"%s\".", path);
+
+    // try to open it
+    fd = try_to_open_pipe_for_writing(path);
+    // we check that it's not a "real" error. From the "man 2 open" page:
+    // "ENXIO  O_NONBLOCK | O_WRONLY is set, the named file is a FIFO, and no process has the FIFO
+    // open for reading." Which is okay.
+    if ((fd == -1) && (errno != ENXIO)) {
+      char errorstring[1024];
+      strerror_r(errno, (char *)errorstring, sizeof(errorstring));
+      debug(1, "metadata_hub_thread_function -- error %d (\"%s\") opening pipe: \"%s\".", errno,
+            (char *)errorstring, path);
+      warn("can not open metadata pipe -- error %d (\"%s\") opening pipe: \"%s\".", errno,
+           (char *)errorstring, path);
+    }
+    free(path);
+    int ret;
+    ret = pthread_create(&metadata_thread, NULL, metadata_thread_function, NULL);
+    if (ret)
+      debug(1, "Failed to create metadata thread!");
+
+    ret =
+        pthread_create(&metadata_multicast_thread, NULL, metadata_multicast_thread_function, NULL);
+    if (ret)
+      debug(1, "Failed to create metadata multicast thread!");
   }
 #ifdef CONFIG_METADATA_HUB
   ret = pthread_create(&metadata_hub_thread, NULL, metadata_hub_thread_function, NULL);
@@ -1715,19 +1716,19 @@ void metadata_stop(void) {
     pthread_join(metadata_hub_thread, NULL);
     // debug(2, "metadata stop hub done.");
 #endif
-               if (config.metadata_enabled) {
-                       // debug(2, "metadata stop multicast thread.");
-                       if (metadata_multicast_thread) {
-                               pthread_cancel(metadata_multicast_thread);
-                               pthread_join(metadata_multicast_thread, NULL);
-                               // debug(2, "metadata stop multicast done.");
-                       }
-                       if (metadata_thread) {
-                               // debug(2, "metadata stop metadata_thread thread.");
-                               pthread_cancel(metadata_thread);
-                               pthread_join(metadata_thread, NULL);
-                               // debug(2, "metadata_stop finished successfully.");
-                       }
+    if (config.metadata_enabled) {
+      // debug(2, "metadata stop multicast thread.");
+      if (metadata_multicast_thread) {
+        pthread_cancel(metadata_multicast_thread);
+        pthread_join(metadata_multicast_thread, NULL);
+        // debug(2, "metadata stop multicast done.");
+      }
+      if (metadata_thread) {
+        // debug(2, "metadata stop metadata_thread thread.");
+        pthread_cancel(metadata_thread);
+        pthread_join(metadata_thread, NULL);
+        // debug(2, "metadata_stop finished successfully.");
+      }
     }
   }
 }
@@ -1799,8 +1800,9 @@ int send_metadata(uint32_t type, uint32_t code, char *data, uint32_t length, rts
                   int block) {
   int rc;
   if (config.metadata_enabled) {
-       rc = send_metadata_to_queue(&metadata_queue, type, code, data, length, carrier, block);
-       rc = send_metadata_to_queue(&metadata_multicast_queue, type, code, data, length, carrier, block);
+    rc = send_metadata_to_queue(&metadata_queue, type, code, data, length, carrier, block);
+    rc =
+        send_metadata_to_queue(&metadata_multicast_queue, type, code, data, length, carrier, block);
   }
 
 #ifdef CONFIG_METADATA_HUB
index 6444b8a5e736d88fde8d1cb3184afc365245d8c6..e7f9e7480300d2fb05bb8214efee306eda290f94 100644 (file)
@@ -134,6 +134,7 @@ sndio =
 pa =
 {
 //     server = "host"; // Set this to override the default pulseaudio server that should be used.
+//     sink = "Sink Name"; // Set this to override the default pulseaudio sink that should be used. (Untested)
 //     application_name = "Shairport Sync"; //Set this to the name that should appear in the Sounds "Applications" tab when Shairport Sync is active.
 };