From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Mon, 26 Apr 2021 10:23:13 +0000 (+0100) Subject: Version 3.3.8 is 3.3.8rc7. X-Git-Tag: 3.3.8~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b9854d3fdcfc66a0b593b39cbfd15480abf319cb;p=thirdparty%2Fshairport-sync.git Version 3.3.8 is 3.3.8rc7. --- diff --git a/audio_alsa.c b/audio_alsa.c index 69722d12..b464279c 100644 --- a/audio_alsa.c +++ b/audio_alsa.c @@ -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; } diff --git a/common.c b/common.c index 8520c714..6e0f12ab 100644 --- 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 */ diff --git a/configure.ac b/configure.ac index 5898a172..f77087c5 100644 --- a/configure.ac +++ b/configure.ac @@ -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=],[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 effbe5ec..0230ac1c 100644 --- 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 f3524ae2..2661ccec 100644 --- 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 diff --git a/scripts/shairport-sync.conf b/scripts/shairport-sync.conf index 6444b8a5..e7f9e748 100644 --- a/scripts/shairport-sync.conf +++ b/scripts/shairport-sync.conf @@ -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. };