]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Make player.c send information to the metadata store rather than initiating d-bus...
authorMike Brady <mikebrady@eircom.net>
Wed, 10 Jan 2018 21:30:30 +0000 (21:30 +0000)
committerMike Brady <mikebrady@eircom.net>
Wed, 10 Jan 2018 21:30:30 +0000 (21:30 +0000)
dacp.c
dacp.h
metadata_hub.h
player.c
player.h

diff --git a/dacp.c b/dacp.c
index bd170b4dd1ba889bc72f9a1004d5578490c5946d..b51e4afa5108526bebb79da5779c435ea5c2f77c 100644 (file)
--- a/dacp.c
+++ b/dacp.c
@@ -104,7 +104,7 @@ static pthread_mutex_t dacp_conversation_lock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t dacp_server_information_lock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t dacp_server_information_cv = PTHREAD_COND_INITIALIZER;
 
-int dacp_send_command(const char *command, char **body, size_t *bodysize) {
+int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
 
   // will malloc space for the body or set it to NULL -- the caller should free it.
 
@@ -604,16 +604,35 @@ uint32_t dacp_tlv_crawl(char **p, int32_t *length) {
   return type;
 }
 
-int32_t dacp_get_client_volume(rtsp_conn_info *conn) {
+int32_t dacp_get_client_volume(void) {
   char *server_reply = NULL;
   int32_t overall_volume = -1;
   ssize_t reply_size;
   int response =
       dacp_send_command("getproperty?properties=dmcp.volume", &server_reply, &reply_size);
   if (response == 200) { // if we get an okay
-    uint32_t *np = (uint32_t *)server_reply;
-    overall_volume = ntohl(*np);
-    // debug(1,"Overall Volume is %d.",overall_volume);
+    char *sp = server_reply;
+    int32_t item_size;
+    if (reply_size >= 8) {
+      if (dacp_tlv_crawl(&sp, &item_size) == 'cmgt') {
+        debug(1,"Volume:",item_size);
+        sp -= item_size; // drop down into the array -- don't skip over it
+        reply_size -= 8;
+        while (reply_size >= 8) {
+          uint32_t type = dacp_tlv_crawl(&sp, &item_size);
+          reply_size -= item_size + 8;
+          if (type == 'cmvo') { // drop down into the dictionary -- don't skip over it
+            char *t = sp - item_size;
+            overall_volume = ntohl(*(int32_t *)(t));
+          }
+        }
+      } else {
+        debug(1,"Unexpected payload response from getproperty?properties=dmcp.volume");
+      }
+    } else {
+      debug(1,"Too short a response from getproperty?properties=dmcp.volume");  
+    }
+    debug(1,"Overall Volume is %d.",overall_volume);
     free(server_reply);
   } else {
     debug(1, "Unexpected response %d to dacp volume control request", response);
@@ -621,7 +640,7 @@ int32_t dacp_get_client_volume(rtsp_conn_info *conn) {
   return overall_volume;
 }
 
-int dacp_set_include_speaker_volume(rtsp_conn_info *conn, int64_t machine_number, int32_t vo) {
+int dacp_set_include_speaker_volume(int64_t machine_number, int32_t vo) {
   char message[1000];
   memset(message, 0, sizeof(message));
   sprintf(message, "setproperty?include-speaker-id=%ld&dmcp.volume=%d", machine_number, vo);
@@ -630,7 +649,7 @@ int dacp_set_include_speaker_volume(rtsp_conn_info *conn, int64_t machine_number
   // should return 204
 }
 
-int dacp_set_speaker_volume(rtsp_conn_info *conn, int64_t machine_number, int32_t vo) {
+int dacp_set_speaker_volume(int64_t machine_number, int32_t vo) {
   char message[1000];
   memset(message, 0, sizeof(message));
   sprintf(message, "setproperty?speaker-id=%ld&dmcp.volume=%d", machine_number, vo);
@@ -639,7 +658,7 @@ int dacp_set_speaker_volume(rtsp_conn_info *conn, int64_t machine_number, int32_
   // should return 204
 }
 
-int dacp_get_speaker_list(rtsp_conn_info *conn, dacp_spkr_stuff *speaker_info,
+int dacp_get_speaker_list(dacp_spkr_stuff *speaker_info,
                           int max_size_of_array) {
   char *server_reply = NULL;
   int speaker_index = -1; // will be incremented before use
@@ -746,3 +765,43 @@ int dacp_get_speaker_list(rtsp_conn_info *conn, dacp_spkr_stuff *speaker_info,
   }
   return reply;
 }
+
+void dacp_get_volume(void) {
+  // get the speaker volume information from the DACP source and store it in the metadata_hub
+  // A volume command has been sent from the client
+  // let's get the master volume from the DACP remote control
+  struct dacp_speaker_stuff speaker_info[50];
+  // we need the overall volume and the speakers information to get this device's relative volume to
+  // calculate the real volume
+
+  int32_t overall_volume = dacp_get_client_volume();
+  debug(1,"DACP Volume: %d.",overall_volume);
+  int speaker_count = dacp_get_speaker_list((dacp_spkr_stuff *)&speaker_info, 50);
+  // debug(1,"DACP Speaker Count: %d.",speaker_count);
+
+  // 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 relative_volume = 0;
+  for (i = 0; i < speaker_count; i++) {
+    if (speaker_info[i].speaker_number == machine_number) {
+      // debug(1,"Our speaker number found: %ld.",machine_number);
+      relative_volume = speaker_info[i].volume;
+    }
+  }
+  int32_t actual_volume = (overall_volume * relative_volume + 50) / 100;
+  // debug(1,"Overall volume: %d, relative volume: %d%, actual volume:
+  // %d.",overall_volume,relative_volume,actual_volume);
+  // debug(1,"Our actual speaker volume is %d.",actual_volume);
+  if (metadata_store.speaker_volume != actual_volume) {
+    metadata_store.speaker_volume = actual_volume;
+    run_metadata_watchers();
+  }
+}
+
diff --git a/dacp.h b/dacp.h
index c3d36b7d42f318fe4d35feff34997681236e1a31..728512c0eeb340852be3175f151bc0d626fd688e 100644 (file)
--- a/dacp.h
+++ b/dacp.h
@@ -22,12 +22,13 @@ uint32_t dacp_tlv_crawl(
     char **p,
     int32_t *length); // return the code of the next TLV entity and advance the pointer beyond it.
 
-int32_t dacp_get_client_volume(rtsp_conn_info *conn); // return the overall volume from the client
-int dacp_set_include_speaker_volume(rtsp_conn_info *conn, int64_t machine_number, int32_t vo);
-int dacp_set_speaker_volume(rtsp_conn_info *conn, int64_t machine_number, int32_t vo);
-int dacp_get_speaker_list(rtsp_conn_info *conn, dacp_spkr_stuff *speaker_array,
+int dacp_set_speaker_volume(int64_t machine_number, int32_t vo);
+
+int dacp_get_speaker_list(dacp_spkr_stuff *speaker_array,
                           int max_size_of_array);
 void set_dacp_server_information(rtsp_conn_info *conn); // tell the DACP conversation thread that
                                                         // the dacp server information has been set
                                                         // or changed
 int send_simple_dacp_command(const char *command);
+
+void dacp_get_volume(void); // get the speaker volume information from the DACP source and store it in the metadata_hub
index 7ce9ed483f6dc53de48c82e08dea12b530f5309c..d8a238dfa940babc94eb4e4f8d86b0ee9e223249 100644 (file)
@@ -63,6 +63,8 @@ typedef struct metadata_bundle {
   
   enum play_status_type player_state; // this is the state of the actual player itself, which can be a bit noisy.
   
+  int speaker_volume; // this is the actual speaker volume, allowing for the main volume and the speaker volume control
+  int previous_speaker_volume; // this is needed to prevent a loop
   
   metadata_watcher watchers[number_of_watchers]; // functions to call if the metadata is changed.
   void *watchers_data[number_of_watchers];       // their individual data
index 27520753524dae600f4716f30a1dfcb9c933319d..b18d939451a2f7e1f65c83a44c6528bae0ba4a9d 100644 (file)
--- a/player.c
+++ b/player.c
@@ -4,7 +4,7 @@
  * All rights reserved.
  *
  * Modifications for audio synchronisation
- * and related work, copyright (c) Mike Brady 2014
+ * and related work, copyright (c) Mike Brady 2014 -- 2018
  * All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person
 #include "dbus-service.h"
 #endif
 
-#ifdef HAVE_MPRIS
-#include "mpris-interface.h"
-#include "mpris-player-interface.h"
-#include "mpris-service.h"
-#endif
-
 #include "common.h"
 #include "player.h"
 #include "rtp.h"
@@ -822,12 +816,10 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
 
 // say we have started playing here
 #ifdef HAVE_METADATA_HUB
-            if ((conn->play_state != SST_stopped) && (conn->play_state != SST_playing)) {
-              conn->play_state = SST_playing;
-              debug(1, "Player State: Playing");
-              metadata_store.player_state = PS_PLAYING;
-//              media_player2_player_set_playback_status(mprisPlayerPlayerSkeleton, "Playing");
-            }
+  if (metadata_store.player_state != PS_PLAYING) {
+    metadata_store.player_state = PS_PLAYING;
+    run_metadata_watchers();
+  }  
 #endif
             if (reference_timestamp) { // if we have a reference time
               // debug(1,"First frame seen with timestamp...");
@@ -2484,43 +2476,10 @@ void player_volume_without_notification(double airplay_volume, rtsp_conn_info *c
 
 void player_volume(double airplay_volume, rtsp_conn_info *conn) {
   command_set_volume(airplay_volume);
-
-#ifdef HAVE_DBUS
-  // A volume command has been sent from the client
-  // let's get the master volume from the DACP remote control
-
-  struct dacp_speaker_stuff speaker_info[50];
-  // we need the overall volume and the speakers information to get this device's relative volume to
-  // calculate the real volume
-
-  int32_t overall_volume = dacp_get_client_volume(conn);
-  // debug(1,"DACP Volume: %d.",overall_volume);
-  int speaker_count = dacp_get_speaker_list(conn, (dacp_spkr_stuff *)&speaker_info, 50);
-  // debug(1,"DACP Speaker Count: %d.",speaker_count);
-
-  // 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 relative_volume = 0;
-  for (i = 0; i < speaker_count; i++) {
-    if (speaker_info[i].speaker_number == machine_number) {
-      // debug(1,"Our speaker number found: %ld.",machine_number);
-      relative_volume = speaker_info[i].volume;
-    }
-  }
-  int32_t actual_volume = (overall_volume * relative_volume + 50) / 100;
-  // debug(1,"Overall volume: %d, relative volume: %d%, actual volume:
-  // %d.",overall_volume,relative_volume,actual_volume);
-  // debug(1,"Our actual speaker volume is %d.",actual_volume);
-  conn->dacp_volume = actual_volume; // this is needed to prevent a loop
-  shairport_sync_set_volume(SHAIRPORT_SYNC(shairportSyncSkeleton), actual_volume);
+#ifdef HAVE_DACP_CLIENT
+  dacp_get_volume();
 #endif
+
   player_volume_without_notification(airplay_volume, conn);
 }
 
@@ -2536,12 +2495,14 @@ void player_flush(int64_t timestamp, rtsp_conn_info *conn) {
 #ifdef CONFIG_METADATA
   send_ssnc_metadata('pfls', NULL, 0, 1);
 #endif
-#if defined(HAVE_MPRIS)
-  if ((conn->play_state != SST_stopped) && (conn->play_state != SST_paused))
-    conn->play_state = SST_paused;
-  debug(1, "MPRIS Paused");
-  media_player2_player_set_playback_status(mprisPlayerPlayerSkeleton, "Paused");
+
+#ifdef HAVE_METADATA_HUB
+  if (metadata_store.player_state != PS_PAUSED) {
+    metadata_store.player_state = PS_PAUSED;
+    run_metadata_watchers();
+  }  
 #endif
+
 }
 
 int player_play(rtsp_conn_info *conn) {
@@ -2567,11 +2528,11 @@ int player_play(rtsp_conn_info *conn) {
     debug(1, "Error setting stack size for player_thread: %s", strerror(errno));
   pthread_create(pt, &tattr, player_thread_func, (void *)conn);
   pthread_attr_destroy(&tattr);
-#if defined(HAVE_MPRIS)
-  if (conn->play_state != SST_playing)
-    conn->play_state = SST_playing;
-  debug(1, "MPRIS Playing (play)");
-  media_player2_player_set_playback_status(mprisPlayerPlayerSkeleton, "Playing");
+#ifdef HAVE_METADATA_HUB
+  if (metadata_store.player_state != PS_PLAYING) {
+    metadata_store.player_state = PS_PLAYING;
+    run_metadata_watchers();
+  }  
 #endif
   return 0;
 }
@@ -2588,13 +2549,12 @@ void player_stop(rtsp_conn_info *conn) {
     command_stop();
     free(conn->player_thread);
     conn->player_thread = NULL;
-#if defined(HAVE_MPRIS)
-    if (conn->play_state != SST_stopped)
-      conn->play_state = SST_stopped;
-    debug(1, "MPRIS Stopped");
-    media_player2_player_set_playback_status(mprisPlayerPlayerSkeleton, "Stopped");
+#ifdef HAVE_METADATA_HUB
+  if (metadata_store.player_state != PS_STOPPED) {
+    metadata_store.player_state = PS_STOPPED;
+    run_metadata_watchers();
+  }  
 #endif
-
   } else {
     debug(3, "player thread of RTSP conversation %d is already deleted.", conn->connection_number);
   }
index 6310dec79c46a9fb7ddd4c46cacfcf57ad8b9c1a..0632e0fb3efe242a4d8a0dd9428e58799dfdf67e 100644 (file)
--- a/player.h
+++ b/player.h
 
 #define time_ping_history 8
 
-#if defined(HAVE_DBUS) || defined(HAVE_MPRIS)
-enum session_status_type {
-  SST_stopped = 0, // not playing anything
-  SST_paused,      // paused
-  SST_playing,
-} sst_type;
-#endif
-
 typedef struct time_ping_record {
   uint64_t local_to_remote_difference;
   uint64_t dispersion;
@@ -67,9 +59,6 @@ typedef struct {
   int64_t minimum_latency; // set if an a=min-latency: line appears in the ANNOUNCE message; zero otherwise
   int64_t maximum_latency; // set if an a=max-latency: line appears in the ANNOUNCE message; zero otherwise
   
-#if defined(HAVE_DBUS) || defined(HAVE_MPRIS)
-  enum session_status_type play_state;
-#endif
   int fd;
   int authorized; // set if a password is required and has been supplied
   stream_cfg stream;