diff --git a/.gitignore b/.gitignore index 5187a2b8..b78d32b7 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,7 @@ shairport-sync.core # macOS stuff .DS_Store shairport-sync.xcodeproj + +# version string generation +gitversion.h + diff --git a/Makefile.am b/Makefile.am index b20ffbc3..d0a025e1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,6 +32,18 @@ else endif endif +# include information generated by 'git describe --dirty' if requested +if USE_GIT_VERSION +common.c: gitversion.h +gitversion.h: .git/index + echo "// Do not edit!" > gitversion.h + echo "// This file is automatically generated by 'git describe --dirty', if available." >> gitversion.h + echo -n " char git_version_string[] = \"" >> gitversion.h + git describe --dirty | tr -d '[[:space:]]' >> gitversion.h + echo "\";" >> gitversion.h +CLEANFILES += gitversion.h +endif + if USE_APPLE_ALAC shairport_sync_SOURCES += apple_alac.cpp endif @@ -214,13 +226,13 @@ if INSTALL_SYSTEMV getent group shairport-sync &>/dev/null || groupadd -r shairport-sync >/dev/null getent passwd shairport-sync &> /dev/null || useradd -r -M -g shairport-sync -s /usr/bin/nologin -G audio shairport-sync >/dev/null [ -e $(DESTDIR)$(sysconfdir)/init.d ] || mkdir -p $(DESTDIR)$(sysconfdir)/init.d - [ -f $(DESTDIR)$(sysconfdir)/init.d/shairport-sync ] || cp scripts/shairport-sync $(DESTDIR)$(sysconfdir)/init.d/ + cp scripts/shairport-sync $(DESTDIR)$(sysconfdir)/init.d/ endif if INSTALL_SYSTEMD getent group shairport-sync &>/dev/null || groupadd -r shairport-sync >/dev/null getent passwd shairport-sync &> /dev/null || useradd -r -M -g shairport-sync -s /usr/bin/nologin -G audio shairport-sync >/dev/null [ -e $(DESTDIR)$(systemdsystemunitdir) ] || mkdir -p $(DESTDIR)$(systemdsystemunitdir) - [ -f $(DESTDIR)$(systemdsystemunitdir)/shairport-sync.service ] || cp scripts/shairport-sync.service $(DESTDIR)$(systemdsystemunitdir) + cp scripts/shairport-sync.service $(DESTDIR)$(systemdsystemunitdir) endif if INSTALL_FREEBSD_SERVICE # Choose a uid and gid of 801 completely arbitrarity, except that it should be below 1000. FreeBSD doesn't seem to allow you to say "an ID in the range of..." @@ -228,7 +240,7 @@ if INSTALL_FREEBSD_SERVICE pw showuser shairport-sync > /dev/null 2>&1 || pw adduser -c "shairport-sync unprivileged user" -n shairport-sync -u 801 -s /usr/sbin/nologin -d /nonexistent > /dev/null 2>&1 [ -e /var/run/shairport-sync ] || mkdir -p /var/run/shairport-sync chown shairport-sync:shairport-sync /var/run/shairport-sync - [ -f /usr/local/etc/rc.d/shairport_sync ] || cp scripts/shairport-sync.freebsd /usr/local/etc/rc.d/shairport_sync + cp scripts/shairport-sync.freebsd /usr/local/etc/rc.d/shairport_sync chmod 555 /usr/local/etc/rc.d/shairport_sync endif if INSTALL_CYGWIN_SERVICE diff --git a/common.c b/common.c index 69270cb9..ce43d004 100644 --- a/common.c +++ b/common.c @@ -2,7 +2,7 @@ * Utility routines. This file is part of Shairport. * Copyright (c) James Laird 2013 * The volume to attenuation function vol2attn copyright (c) Mike Brady 2014 - * Further changes and additions (c) Mike Brady 2014 -- 2019 + * Further changes and additions (c) Mike Brady 2014 -- 2021 * All rights reserved. * * Permission is hereby granted, free of charge, to any person @@ -27,6 +27,11 @@ */ #include "common.h" + +#ifdef CONFIG_USE_GIT_VERSION_STRING +#include "gitversion.h" +#endif + #include #include #include @@ -88,6 +93,8 @@ #include #endif + + #ifdef CONFIG_ALSA void set_alsa_out_dev(char *); #endif @@ -1602,9 +1609,16 @@ void pthread_cleanup_debug_mutex_unlock(void *arg) { pthread_mutex_unlock((pthre char *get_version_string() { char *version_string = malloc(1024); - if (version_string) { + if (version_string) { +#ifdef CONFIG_USE_GIT_VERSION_STRING + if (git_version_string[0] != '\0') + strcpy(version_string, git_version_string); + else +#endif strcpy(version_string, PACKAGE_VERSION); - +#ifdef CONFIG_AIRPLAY_2 + strcat(version_string, "-AirPlay2"); +#endif #ifdef CONFIG_APPLE_ALAC strcat(version_string, "-alac"); #endif diff --git a/configure.ac b/configure.ac index ca4cc228..6b7c6d07 100644 --- a/configure.ac +++ b/configure.ac @@ -2,12 +2,19 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.50]) -AC_INIT([shairport-sync], [4.0d4], [4265913+mikebrady@users.noreply.github.com]) +AC_INIT([shairport-sync], [4.0-dev], [4265913+mikebrady@users.noreply.github.com]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([shairport.c]) AC_CONFIG_HEADERS([config.h]) AC_PROG_RANLIB +AC_CHECK_PROGS([GIT], [git]) +if test -n "$GIT"; then + AC_DEFINE([CONFIG_USE_GIT_VERSION_STRING], 1, [Use the version string produced by running 'git describe --dirty'.]) +fi +AM_CONDITIONAL([USE_GIT_VERSION], [test -n "$GIT"]) + + # Derived from the Avahi configure.ac file # Specifying the OS type, defaulting to linux. # diff --git a/player.c b/player.c index 7c308b9a..efa40c63 100644 --- a/player.c +++ b/player.c @@ -1974,10 +1974,13 @@ void *player_thread_func(void *arg) { #endif pthread_setcancelstate(oldState, NULL); - + + double initial_volume = config.airplay_volume; // default + if (conn->initial_airplay_volume_set) // if we have been given an initial volume + initial_volume = conn->initial_airplay_volume; // set the default volume to whatever it was before, as stored in the config airplay_volume - debug(2, "Set initial volume to %f.", config.airplay_volume); - player_volume(config.airplay_volume, conn); // will contain a cancellation point if asked to wait + debug(2, "Set initial volume to %f.", initial_volume); + player_volume(initial_volume, conn); // will contain a cancellation point if asked to wait debug(2, "Play begin"); while (1) { diff --git a/player.h b/player.h index eb210ae5..cc4dda2c 100644 --- a/player.h +++ b/player.h @@ -205,7 +205,11 @@ typedef struct { // mutexes and condition variables pthread_cond_t flowcontrol; pthread_mutex_t ab_mutex, flush_mutex, volume_control_mutex; + int fix_volume; + double initial_airplay_volume; + int initial_airplay_volume_set; + uint32_t timestamp_epoch, last_timestamp, maximum_timestamp_interval; // timestamp_epoch of zero means not initialised, could start at 2 // or 1. diff --git a/rtp.c b/rtp.c index a78a1156..90362752 100644 --- a/rtp.c +++ b/rtp.c @@ -2128,7 +2128,7 @@ void *rtp_buffered_audio_processor(void *arg) { madly late int rtp_diff = pcm_buffer_read_point_rtptime - at_rtp; */ - if (play_enabled) { + if ((play_enabled) && (have_ptp_timing_information(conn) != 0)) { uint64_t buffer_should_be_time; if (frame_to_local_time(pcm_buffer_read_point_rtptime, &buffer_should_be_time, conn) == 0) { @@ -2137,7 +2137,7 @@ void *rtp_buffered_audio_processor(void *arg) { if ((lead_time >= (int64_t)(reqested_lead_time * 1000000000)) || (streaming_has_started == 1)) { if (streaming_has_started == 0) - debug(2, "Connection %d: buffered audio lead time is %f seconds.", + debug(2, "Connection %d: buffered audio lead time is %f seconds.", conn->connection_number, 0.000000001 * lead_time); streaming_has_started = 1; player_put_packet(0, 0, pcm_buffer_read_point_rtptime, diff --git a/rtsp.c b/rtsp.c index c670455b..da94052e 100644 --- a/rtsp.c +++ b/rtsp.c @@ -3,7 +3,7 @@ * Copyright (c) James Laird 2013 * Modifications associated with audio synchronization, mutithreading and - * metadata handling copyright (c) Mike Brady 2014-2020 + * metadata handling copyright (c) Mike Brady 2014-2021 * All rights reserved. * * Permission is hereby granted, free of charge, to any person @@ -1411,7 +1411,7 @@ void handle_setrateanchori(rtsp_conn_info *conn, rtsp_message *req, rtsp_message } } else { player_full_flush(conn); - ptp_send_control_message_string("T"); // ensure an obsolete clock isn't picked up later. + // ptp_send_control_message_string("T"); // ensure an obsolete clock isn't picked up later. } } pthread_cleanup_pop(1); // plist_free the messagePlist; @@ -2281,8 +2281,16 @@ void handle_set_parameter_parameter(rtsp_conn_info *conn, rtsp_message *req, if (!strncmp(cp, "volume: ", strlen("volume: "))) { float volume = atof(cp + strlen("volume: ")); - // debug(2, "AirPlay request to set volume to: %f.", volume); - player_volume(volume, conn); + debug(1, "Connection %d: request to set AirPlay Volume to: %f.", conn->connection_number, volume); + // if we are playing, go ahead and change the volume + if (try_to_hold_play_lock(conn) == 0) { + player_volume(volume, conn); + release_hold_on_play_lock(conn); + } else { + // otherwise use the volume as the initial setting for when/if the player starts + conn->initial_airplay_volume = volume; + conn->initial_airplay_volume_set = 1; + } } else #ifdef CONFIG_METADATA if (!strncmp(cp, "progress: ", strlen("progress: "))) { @@ -2294,7 +2302,7 @@ void handle_set_parameter_parameter(rtsp_conn_info *conn, rtsp_message *req, } else #endif { - debug(1, "unrecognised parameter: \"%s\" (%d)\n", cp, strlen(cp)); + debug(1, "Connection %d, unrecognised parameter: \"%s\" (%d)\n", conn->connection_number, cp, strlen(cp)); } cp = next; } @@ -3015,7 +3023,7 @@ static void handle_get_parameter(__attribute__((unused)) rtsp_conn_info *conn, r if ((req->content) && (req->contentlength == strlen("volume\r\n")) && strstr(req->content, "volume") == req->content) { - // debug(1,"Current volume sought"); + debug(2,"Connection %d: Current volume (%.6f) requested", conn->connection_number, config.airplay_volume); char *p = malloc(128); // will be automatically deallocated with the response is deleted if (p) { resp->content = p; @@ -3110,10 +3118,11 @@ static void handle_set_parameter(rtsp_conn_info *conn, rtsp_message *req, rtsp_m // debug(2, "received parameters in SET_PARAMETER request."); handle_set_parameter_parameter(conn, req, resp); // this could be volume or progress } else { - debug(1, "received unknown Content-Type \"%s\" in SET_PARAMETER request.", ct); + debug(1, "Connection %d: received unknown Content-Type \"%s\" in SET_PARAMETER request.", conn->connection_number, ct); + debug_print_msg_headers(1,req); } } else { - debug(1, "missing Content-Type header in SET_PARAMETER request."); + debug(1, "Connection %d: missing Content-Type header in SET_PARAMETER request.", conn->connection_number); } resp->respcode = 200; }