]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Split volume function into read-only property and a method for setting it. Making...
authorMike Brady <mikebrady@eircom.net>
Sat, 10 Mar 2018 13:56:44 +0000 (13:56 +0000)
committerMike Brady <mikebrady@eircom.net>
Sat, 10 Mar 2018 13:56:44 +0000 (13:56 +0000)
dacp.c
dacp.h
dbus-service.c
org.gnome.ShairportSync.xml
org.mpris.MediaPlayer2.Player.xml
shairport-sync-dbus-test-client.c

diff --git a/dacp.c b/dacp.c
index ba43689a5ae856b61f3504bd979613c7a44ac60c..4ba7a8289c12efc018ecf08fd28d3a81f30dd378 100644 (file)
--- a/dacp.c
+++ b/dacp.c
@@ -121,6 +121,7 @@ int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
   //  495 Error receiving response
   //  494 This client is already busy
   //  493 Client failed to send a message
+  //  492 Argement out of range
 
   // try to do this transaction on the DACP server, but don't wait for more than 20 ms to be allowed
   // to do it.
@@ -162,7 +163,7 @@ int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
 
     // only do this one at a time -- not sure it is necessary, but better safe than sorry
 
-//    int mutex_reply = pthread_mutex_timedlock(&dacp_conversation_lock, &mutex_wait_time);
+    //    int mutex_reply = pthread_mutex_timedlock(&dacp_conversation_lock, &mutex_wait_time);
     int mutex_reply = pthread_mutex_lock(&dacp_conversation_lock);
     if (mutex_reply == 0) {
 
@@ -662,12 +663,12 @@ int dacp_get_client_volume(int32_t *result) {
 }
 
 int dacp_set_include_speaker_volume(int64_t machine_number, int32_t vo) {
-  debug(1, "dacp_set_include_speaker_volume to %" PRId32 ".", vo);
+  debug(2, "dacp_set_include_speaker_volume to %" PRId32 ".", vo);
   char message[1000];
   memset(message, 0, sizeof(message));
   sprintf(message, "setproperty?include-speaker-id=%" PRId64 "&dmcp.volume=%" PRId32 "",
           machine_number, vo);
-  debug(1, "sending \"%s\"", message);
+  debug(2, "sending \"%s\"", message);
   return send_simple_dacp_command(message);
   // should return 204
 }
@@ -677,7 +678,7 @@ int dacp_set_speaker_volume(int64_t machine_number, int32_t vo) {
   memset(message, 0, sizeof(message));
   sprintf(message, "setproperty?speaker-id=%" PRId64 "&dmcp.volume=%" PRId32 "", machine_number,
           vo);
-  debug(1, "sending \"%s\"", message);
+  debug(2, "sending \"%s\"", message);
   return send_simple_dacp_command(message);
   // should return 204
 }
@@ -852,3 +853,108 @@ int dacp_get_volume(int32_t *the_actual_volume) {
   }
   return http_response;
 }
+
+int dacp_set_volume(int32_t vo) {
+  int http_response = 492; // argument out of range
+  if ((vo >= 0) && (vo <= 100)) {
+    // get the information we need -- the absolute volume, the speaker list, our ID
+    struct dacp_speaker_stuff speaker_info[50];
+    int32_t overall_volume;
+    http_response = dacp_get_client_volume(&overall_volume);
+    if (http_response == 200) {
+      int speaker_count;
+      http_response = dacp_get_speaker_list((dacp_spkr_stuff *)&speaker_info, 50, &speaker_count);
+      if (http_response == 200) {
+        // get our machine number
+        uint16_t *hn = (uint16_t *)config.hw_addr;
+        uint32_t *ln = (uint32_t *)(config.hw_addr + 2);
+        uint64_t t1 = ntohs(*hn);
+        uint64_t t2 = ntohl(*ln);
+        int64_t machine_number = (t1 << 32) + t2; // this form is useful
+
+        // Let's find our own speaker in the array and pick up its relative volume
+        int i;
+        int32_t active_speakers = 0;
+        for (i = 0; i < speaker_count; i++) {
+          if (speaker_info[i].speaker_number == machine_number) {
+            debug(2, "Our speaker number found: %ld with relative volume.", machine_number,
+                  speaker_info[i].volume);
+          }
+          if (speaker_info[i].active == 1) {
+            active_speakers++;
+          }
+        }
+
+        if (active_speakers == 1) {
+          // must be just this speaker
+          debug(2, "Remote-setting volume to %d on just one speaker.", vo);
+          http_response = dacp_set_include_speaker_volume(machine_number, vo);
+        } else if (active_speakers == 0) {
+          debug(2, "No speakers!");
+        } else {
+          debug(2, "Speakers: %d, active: %d", speaker_count, active_speakers);
+          if (vo >= overall_volume) {
+            debug(2, "Multiple speakers active, but desired new volume is highest");
+            http_response = dacp_set_include_speaker_volume(machine_number, vo);
+          } else {
+            // the desired volume is less than the current overall volume and there is more than
+            // one
+            // speaker
+            // we must find out the highest other speaker volume.
+            // If the desired volume is less than it, we must set the current_overall volume to
+            // that
+            // highest volume
+            // and set our volume relative to it.
+            // If the desired volume is greater than the highest current volume, then we can just
+            // go
+            // ahead
+            // with dacp_set_include_speaker_volume, setting the new current overall volume to the
+            // desired new level
+            // with the speaker at 100%
+
+            int32_t highest_other_volume = 0;
+            for (i = 0; i < speaker_count; i++) {
+              if ((speaker_info[i].speaker_number != machine_number) &&
+                  (speaker_info[i].active == 1) &&
+                  (speaker_info[i].volume > highest_other_volume)) {
+                highest_other_volume = speaker_info[i].volume;
+              }
+            }
+            highest_other_volume = (highest_other_volume * overall_volume + 50) / 100;
+            if (highest_other_volume <= vo) {
+              debug(2,
+                    "Highest other volume %d is less than or equal to the desired new volume %d.",
+                    highest_other_volume, vo);
+              http_response = dacp_set_include_speaker_volume(machine_number, vo);
+            } else {
+              debug(2, "Highest other volume %d is greater than the desired new volume %d.",
+                    highest_other_volume, vo);
+              // if the present overall volume is higher than the highest other volume at present,
+              // then bring it down to it.
+              if (overall_volume > highest_other_volume) {
+                debug(2, "Lower overall volume to new highest volume.");
+                http_response = dacp_set_include_speaker_volume(
+                    machine_number,
+                    highest_other_volume); // set the overall volume to the highest one
+              }
+              int32_t desired_relative_volume =
+                  (vo * 100 + (highest_other_volume / 2)) / highest_other_volume;
+              debug(2, "Set our speaker volume relative to the highest volume.");
+              http_response = dacp_set_speaker_volume(
+                  machine_number,
+                  desired_relative_volume); // set the overall volume to the highest one
+            }
+          }
+        }
+      } else {
+        debug(2, "Can't get speakers list");
+      }
+    } else {
+      debug(2, "Can't get client volume");
+    }
+
+  } else {
+    debug(2, "Invalid volume: %d -- ignored.", vo);
+  }
+  return http_response;
+}
diff --git a/dacp.h b/dacp.h
index bd43300c6669fb7b7f8f65d4f84ca13fd5de498a..1a04e01660c7a92c8d6718b6a73ea9171e3858f6 100644 (file)
--- a/dacp.h
+++ b/dacp.h
@@ -32,3 +32,4 @@ int dacp_set_include_speaker_volume(int64_t machine_number, int32_t vo);
 int dacp_get_client_volume(int32_t *result);
 int dacp_get_volume(
     int32_t *the_actual_volume); // get the speaker volume information from the DACP source
+int dacp_set_volume(int32_t vo); // set the volume of our speaker
index a9b7f67df504031472e9b449cd3c0985061d6569..753d6218012b454a0e59cbbe5710a85193e351c4 100644 (file)
@@ -44,118 +44,12 @@ gboolean notify_loudness_threshold_callback(ShairportSync *skeleton,
   return TRUE;
 }
 
-gboolean notify_volume_callback(ShairportSync *skeleton,
-                                __attribute__((unused)) gpointer user_data) {
-  metadata_hub_read_prolog();
-  int md_speaker_volume = metadata_store.speaker_volume;
-  metadata_hub_read_epilog();
-  gint gvo = shairport_sync_get_volume(skeleton);
-  int32_t vo = gvo;
-  if ((vo >= 0) && (vo <= 100)) {
-    if (vo !=
-        md_speaker_volume) { // this is to stop an infinite loop of setting->checking->setting...
-      // get the information we need -- the absolute volume, the speaker list, our ID
-      struct dacp_speaker_stuff speaker_info[50];
-      int32_t overall_volume;
-      int http_response = dacp_get_client_volume(&overall_volume);
-      if (http_response == 200) {
-        int speaker_count;
-        http_response = dacp_get_speaker_list((dacp_spkr_stuff *)&speaker_info, 50, &speaker_count);
-        if (http_response == 200) {
-          // get our machine number
-          uint16_t *hn = (uint16_t *)config.hw_addr;
-          uint32_t *ln = (uint32_t *)(config.hw_addr + 2);
-          uint64_t t1 = ntohs(*hn);
-          uint64_t t2 = ntohl(*ln);
-          int64_t machine_number = (t1 << 32) + t2; // this form is useful
-
-          // Let's find our own speaker in the array and pick up its relative volume
-          int i;
-          int32_t active_speakers = 0;
-          for (i = 0; i < speaker_count; i++) {
-            if (speaker_info[i].speaker_number == machine_number) {
-              debug(2, "Our speaker number found: %ld with relative volume.", machine_number,
-                    speaker_info[i].volume);
-            }
-            if (speaker_info[i].active == 1) {
-              active_speakers++;
-            }
-          }
-
-          if (active_speakers == 1) {
-            // must be just this speaker
-            debug(2, "Remote-setting volume to %d on just one speaker.", vo);
-            dacp_set_include_speaker_volume(machine_number, vo);
-          } else if (active_speakers == 0) {
-            debug(2, "No speakers!");
-          } else {
-            debug(2, "Speakers: %d, active: %d", speaker_count, active_speakers);
-            if (vo >= overall_volume) {
-              debug(2, "Multiple speakers active, but desired new volume is highest");
-              dacp_set_include_speaker_volume(machine_number, vo);
-            } else {
-              // the desired volume is less than the current overall volume and there is more than
-              // one
-              // speaker
-              // we must find out the highest other speaker volume.
-              // If the desired volume is less than it, we must set the current_overall volume to
-              // that
-              // highest volume
-              // and set our volume relative to it.
-              // If the desired volume is greater than the highest current volume, then we can just
-              // go
-              // ahead
-              // with dacp_set_include_speaker_volume, setting the new current overall volume to the
-              // desired new level
-              // with the speaker at 100%
-
-              int32_t highest_other_volume = 0;
-              for (i = 0; i < speaker_count; i++) {
-                if ((speaker_info[i].speaker_number != machine_number) &&
-                    (speaker_info[i].active == 1) &&
-                    (speaker_info[i].volume > highest_other_volume)) {
-                  highest_other_volume = speaker_info[i].volume;
-                }
-              }
-              highest_other_volume = (highest_other_volume * overall_volume + 50) / 100;
-              if (highest_other_volume <= vo) {
-                debug(2,
-                      "Highest other volume %d is less than or equal to the desired new volume %d.",
-                      highest_other_volume, vo);
-                dacp_set_include_speaker_volume(machine_number, vo);
-              } else {
-                debug(2, "Highest other volume %d is greater than the desired new volume %d.",
-                      highest_other_volume, vo);
-                // if the present overall volume is higher than the highest other volume at present,
-                // then bring it down to it.
-                if (overall_volume > highest_other_volume) {
-                  debug(2, "Lower overall volume to new highest volume.");
-                  dacp_set_include_speaker_volume(
-                      machine_number,
-                      highest_other_volume); // set the overall volume to the highest one
-                }
-                int32_t desired_relative_volume =
-                    (vo * 100 + (highest_other_volume / 2)) / highest_other_volume;
-                debug(2, "Set our speaker volume relative to the highest volume.");
-                dacp_set_speaker_volume(
-                    machine_number,
-                    desired_relative_volume); // set the overall volume to the highest one
-              }
-            }
-          }
-        } else {
-          debug(2, "Can't get speakers list");
-        }
-      } else {
-        debug(2, "Can't get client volume");
-      }
-    } // else {
-      // debug(1, "No need to remote-set volume to %d, as it is already set to this value.", vo);
-    // }
-
-  } else {
-    debug(2, "Invalid volume: %d -- ignored.", vo);
-  }
+static gboolean on_handle_set_volume(ShairportSync *skeleton, GDBusMethodInvocation *invocation,
+                                     const gint volume,
+                                     __attribute__((unused)) gpointer user_data) {
+  // debug(1, "1 Set volume to d.", volume);
+  dacp_set_volume(volume);
+  shairport_sync_complete_set_volume(skeleton, invocation);
   return TRUE;
 }
 
@@ -194,10 +88,10 @@ static void on_dbus_name_acquired(GDBusConnection *connection, const gchar *name
                    G_CALLBACK(notify_loudness_filter_active_callback), NULL);
   g_signal_connect(shairportSyncSkeleton, "notify::loudness-threshold",
                    G_CALLBACK(notify_loudness_threshold_callback), NULL);
-  g_signal_connect(shairportSyncSkeleton, "notify::volume", G_CALLBACK(notify_volume_callback),
-                   &metadata_store);
   g_signal_connect(shairportSyncSkeleton, "handle-remote-command",
                    G_CALLBACK(on_handle_remote_command), NULL);
+  g_signal_connect(shairportSyncSkeleton, "handle-set-volume", G_CALLBACK(on_handle_set_volume),
+                   NULL);
 
   add_metadata_watcher(dbus_metadata_watcher, NULL);
 
index 8bba3609da5473108f5b5bbecd9db0913063fb29..5d5da742bf6211f8401ca3e6d47c210358fc5b4c 100644 (file)
@@ -3,9 +3,12 @@
   <interface name="org.gnome.ShairportSync">
     <property name="LoudnessFilterActive" type="b" access="readwrite" />
     <property name="LoudnessThreshold" type="d" access="readwrite" />
-    <property name="Volume" type="d" access="readwrite" />
+    <property name="Volume" type="i" access="read" />
     <method name="RemoteCommand">
       <arg name="command" type="s" direction="in" />
     </method>
+    <method name="SetVolume">
+      <arg name="volume" type="i" direction="in" />
+    </method>
   </interface>
 </node>
index 8ef73584adac0697bfa1c8fdb8a419496c7c5547..72362379b7a8959b505a196130b7418e6fe4e653 100755 (executable)
@@ -29,7 +29,7 @@
                <property name='Metadata' type='a{sv}' access='read'>
                        <annotation name="org.qtproject.QtDBus.QtTypeName" value="QVariantMap"/>
                </property>
-               <property name='Volume' type='d' access='readwrite'/>
+               <property name='Volume' type='d' access='read'/>
                <property name='Position' type='x' access='read'/>
                <property name='MinimumRate' type='d' access='read'/>
                <property name='MaximumRate' type='d' access='read'/>
index 05ec5f7bb2922f6a12fe405d187295496ff49ec9..eb464b02c651606d2baf454af353f86471d94179 100644 (file)
@@ -132,13 +132,13 @@ int main(int argc, char *argv[]) {
 
   g_print("Starting test...\n");
 
-  shairport_sync_set_volume(SHAIRPORT_SYNC(proxy), 20);
+  shairport_sync_call_set_volume(SHAIRPORT_SYNC(proxy), 20, NULL, NULL, 0);
   sleep(5);
-  shairport_sync_set_volume(SHAIRPORT_SYNC(proxy), 100);
+  shairport_sync_call_set_volume(SHAIRPORT_SYNC(proxy), 100, NULL, NULL, 0);
   sleep(5);
-  shairport_sync_set_volume(SHAIRPORT_SYNC(proxy), 40);
+  shairport_sync_call_set_volume(SHAIRPORT_SYNC(proxy), 40, NULL, NULL, 0);
   sleep(5);
-  shairport_sync_set_volume(SHAIRPORT_SYNC(proxy), 60);
+  shairport_sync_call_set_volume(SHAIRPORT_SYNC(proxy), 60, NULL, NULL, 0);
   // sleep(1);
   /*
     shairport_sync_set_volume(SHAIRPORT_SYNC(proxy), 10);