]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Continuing to check the high-volume limiter. Add configuration file settings for...
authorMike Brady <4265913+mikebrady@users.noreply.github.com>
Thu, 19 Jan 2023 12:44:26 +0000 (12:44 +0000)
committerMike Brady <4265913+mikebrady@users.noreply.github.com>
Thu, 19 Jan 2023 12:44:26 +0000 (12:44 +0000)
player.c
rtsp.c
scripts/shairport-sync.conf
shairport.c

index db7b8ae00129d4caca0fd8fc7a2cf0cd6b190df5..84f0a9e45168f7761e2e5920645ef2d5fe1b3a70 100644 (file)
--- a/player.c
+++ b/player.c
@@ -1704,33 +1704,31 @@ void statistics_item(const char *heading, const char *format, ...) {
 
 double suggested_volume(rtsp_conn_info *conn) {
   double response = config.airplay_volume;
-  if (conn) {
-    if (conn->own_airplay_volume_set != 0) {
-      response = conn->own_airplay_volume;
-    } else if (config.airplay_volume > config.high_threshold_airplay_volume) {
-      int64_t volume_validity_time = config.limit_to_high_volume_threshold_time_in_minutes;
-      // zero means never check the volume
-      if (volume_validity_time != 0) {
-        // If the volume is higher than the high volume threshold
-        // and enough time has gone past, suggest the default volume.
-        uint64_t time_now = get_absolute_time_in_ns();
-        int64_t time_since_last_access_to_volume_info =
-            time_now - config.last_access_to_volume_info_time;
-
-        volume_validity_time = volume_validity_time * 60;         // to seconds
-        volume_validity_time = volume_validity_time * 1000000000; // to nanoseconds
-
-        if ((config.airplay_volume > config.high_threshold_airplay_volume) &&
-            ((config.last_access_to_volume_info_time == 0) ||
-             (time_since_last_access_to_volume_info > volume_validity_time))) {
-
-          debug(2,
-                "the current volume %.6f is higher than the high volume threshold %.6f, so the "
-                "default volume %.6f is suggested.",
-                config.airplay_volume, config.high_threshold_airplay_volume,
-                config.default_airplay_volume);
-          response = config.default_airplay_volume;
-        }
+  if ((conn != NULL) && (conn->own_airplay_volume_set != 0)) {
+    response = conn->own_airplay_volume;
+  } else if (config.airplay_volume > config.high_threshold_airplay_volume) {
+    int64_t volume_validity_time = config.limit_to_high_volume_threshold_time_in_minutes;
+    // zero means never check the volume
+    if (volume_validity_time != 0) {
+      // If the volume is higher than the high volume threshold
+      // and enough time has gone past, suggest the default volume.
+      uint64_t time_now = get_absolute_time_in_ns();
+      int64_t time_since_last_access_to_volume_info =
+          time_now - config.last_access_to_volume_info_time;
+
+      volume_validity_time = volume_validity_time * 60;         // to seconds
+      volume_validity_time = volume_validity_time * 1000000000; // to nanoseconds
+
+      if ((config.airplay_volume > config.high_threshold_airplay_volume) &&
+          ((config.last_access_to_volume_info_time == 0) ||
+           (time_since_last_access_to_volume_info > volume_validity_time))) {
+
+        debug(2,
+              "the current volume %.6f is higher than the high volume threshold %.6f, so the "
+              "default volume %.6f is suggested.",
+              config.airplay_volume, config.high_threshold_airplay_volume,
+              config.default_airplay_volume);
+        response = config.default_airplay_volume;
       }
     }
   }
diff --git a/rtsp.c b/rtsp.c
index 83374debe4fd5417e99fcd68dfa24841419e52ff..11f09ed07a56bbfa3e2c43a5c4ab59bd43d9511a 100644 (file)
--- a/rtsp.c
+++ b/rtsp.c
@@ -757,19 +757,24 @@ void cleanup_threads(void) {
       free(conns[i]);
       conns[i] = NULL;
     }
-    if (conns[i] != NULL)
+    if (conns[i] != NULL) {
+      debug(1, "Airplay Volume for connection %d is %.6f.", conns[i]->connection_number,
+            suggested_volume(conns[i]));
       connection_count++;
+    }
   }
   debug_mutex_unlock(&conns_lock, 3);
+
   if (old_connection_count != connection_count) {
-    if (connection_count == 0)
+    if (connection_count == 0) {
       debug(2, "No active connections.");
-    else if (connection_count == 1)
+    else if (connection_count == 1)
       debug(2, "One active connection.");
     else
       debug(2, "%d active connections.", connection_count);
     old_connection_count = connection_count;
   }
+  debug(1, "Airplay Volume for new connections is %.6f.", suggested_volume(NULL));
 }
 
 // park a null at the line ending, and return the next line pointer
@@ -5477,6 +5482,7 @@ void *rtsp_listen_loop(__attribute((unused)) void *arg) {
         FD_SET(sockfd[i], &fds);
 
       ret = select(maxfd + 1, &fds, 0, 0, &tv);
+
       if (ret < 0) {
         if (errno == EINTR)
           continue;
index 918ad3774b01c0b0357ada8e4568089155da1d27..5731fe086f56029df0e1629870d99fa1a46c3278 100644 (file)
@@ -43,9 +43,24 @@ general =
 //             "standard" makes the volume change more quickly at lower volumes and slower at higher volumes.
 //             "flat" makes the volume change at the same rate at all volumes.
 //     volume_control_combined_hardware_priority = "no"; // when extending the volume range by combining the built-in software attenuator with the hardware mixer attenuator, set this to "yes" to reduce volume by using the hardware mixer first, then the built-in software attenuator.
+
+//     default_airplay_volume = 24.0; // this is the suggested volume after a reset or after the high_volume_threshold has been exceed and the high_volume_idle_timeout_in_minutes has passed
+
+//     The following settings are for dealing with potentially surprising high ("very loud") volume levels.
+//     When a new play session starts, it usually requests a suggested volume level from Shairport Sync. This is normally the volume level of the last session.
+//     This can cause unpleasant surprises if the last session was (a) very loud and (b) a long time ago.
+//     Thus, the user could be unpleasantly surprised by the volume level of the new session.
+
+//     To deal with this, when the last session volume is "very loud", the following two settings will lower the suggested volume after a period of idleness:
+
+//     high_threshold_airplay_volume = -16.0; // airplay volume greater or equal to this is "very loud"
+//     high_volume_idle_timeout_in_minutes = 0; // if the current volume is "very loud" and the device is not playing for more than this time, suggest the default volume for new connections instead of the current volume.
+//             Note 1: This timeout is set to 0 by default to disable this feature. Set it to some positive number, e.g. 180 to activate the feature.
+//             Note 2: Not all applications use the suggested volume: MacOS Music and Mac OS System Sounds use their own settings.
+
 //     run_this_when_volume_is_set = "/full/path/to/application/and/args"; //  Run the specified application whenever the volume control is set or changed.
 //             The desired AirPlay volume is appended to the end of the command line – leave a space if you want it treated as an extra argument.
-//             AirPlay volume goes from 0 to -30 and -144 means "mute".
+//             AirPlay volume goes from 0.0 to -30.0 and -144.0 means "mute".
 
 //     audio_backend_latency_offset_in_seconds = 0.0; // This is added to the latency requested by the player to delay or advance the output by a fixed amount.
 //             Use it, for example, to compensate for a fixed delay in the audio back end.
index dd2edd4dfdbac06634771755015e647d1ec4260f..17ab9717ed68f29dfb7be12086637e10de1f4700 100644 (file)
@@ -471,8 +471,8 @@ int parse_options(int argc, char **argv) {
       -16.0; // if the volume exceeds this, reset to the default volume if idle for the
              // limit_to_high_volume_threshold_time_in_minutes time
   config.limit_to_high_volume_threshold_time_in_minutes =
-      3 * 60; // after this time in minutes, if the volume is higher, use the default_airplay_volume volume
-         // for new play sessions.
+      0; // after this time in minutes, if the volume is higher, use the default_airplay_volume
+         // volume for new play sessions.
   config.fixedLatencyOffset = 11025; // this sounds like it works properly.
   config.diagnostic_drop_packet_fraction = 0.0;
   config.active_state_timeout = 10.0;
@@ -845,6 +845,37 @@ int parse_options(int argc, char **argv) {
         config.volume_max_db_set = 1;
       }
 
+      /* Get the optional default_volume setting. */
+      if (config_lookup_float(config.cfg, "general.default_airplay_volume", &dvalue)) {
+        // debug(1, "Default airplay volume setting of %f on the -30.0 to 0 scale", dvalue);
+        if ((dvalue >= -30.0) && (dvalue <= 0.0)) {
+          config.default_airplay_volume = dvalue;
+        } else {
+          warn("The default airplay volume setting must be between -30.0 and 0.0.");
+        }
+      }
+
+      /* Get the optional high_volume_threshold setting. */
+      if (config_lookup_float(config.cfg, "general.high_threshold_airplay_volume", &dvalue)) {
+        // debug(1, "High threshold airplay volume setting of %f on the -30.0 to 0 scale", dvalue);
+        if ((dvalue >= -30.0) && (dvalue <= 0.0)) {
+          config.high_threshold_airplay_volume = dvalue;
+        } else {
+          warn("The high threshold airplay volume setting must be between -30.0 and 0.0.");
+        }
+      }
+
+      /* Get the optional high volume idle tiomeout setting. */
+      if (config_lookup_float(config.cfg, "general.high_volume_idle_timeout_in_minutes", &dvalue)) {
+        // debug(1, "High high_volume_idle_timeout_in_minutes setting of %f", dvalue);
+        if (dvalue >= 0.0) {
+          config.limit_to_high_volume_threshold_time_in_minutes = dvalue;
+        } else {
+          warn("The high volume idle timeout in minutes setting must be 0.0 or greater. A setting "
+               "of 0.0 disables the high volume check.");
+        }
+      }
+
       if (config_lookup_string(config.cfg, "general.run_this_when_volume_is_set", &str)) {
         config.cmd_set_volume = (char *)str;
       }
@@ -2392,6 +2423,15 @@ int main(int argc, char **argv) {
   debug(1, "busy timeout time is %d.", config.timeout);
   debug(1, "drift tolerance is %f seconds.", config.tolerance);
   debug(1, "password is \"%s\".", strnull(config.password));
+  debug(1, "default airplay volume is %.6f.", config.default_airplay_volume);
+  debug(1, "high threshold airplay volume is %.6f.", config.high_threshold_airplay_volume);
+  if (config.limit_to_high_volume_threshold_time_in_minutes == 0)
+    debug(1, "check for higher-than-threshold volume for new play session is disabled.");
+  else
+    debug(1,
+          "suggest default airplay volume for new play session instead of higher-than-threshold "
+          "airplay volume after %d minutes.",
+          config.limit_to_high_volume_threshold_time_in_minutes);
   debug(1, "ignore_volume_control is %d.", config.ignore_volume_control);
   if (config.volume_max_db_set)
     debug(1, "volume_max_db is %d.", config.volume_max_db);