]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
extract several pieces of client metadata for AP2 1388/head 1389/head
authorCody Cutrer <cody@cutrer.us>
Sun, 26 Dec 2021 19:13:42 +0000 (12:13 -0700)
committerCody Cutrer <cody@cutrer.us>
Sun, 26 Dec 2021 19:13:42 +0000 (12:13 -0700)
MQTT.md
mqtt.c
rtsp.c

diff --git a/MQTT.md b/MQTT.md
index ec41a0b1daa600694f2f3ee81b732dde221ebcef..95779c760acdc3bbfe97ece3cc8d90c6fb2e5150 100644 (file)
--- a/MQTT.md
+++ b/MQTT.md
@@ -107,7 +107,10 @@ Here are some of the `core` codes commonly passed from the source:
 Here are the 'ssnc' codes defined so far:
  * `PICT` -- the payload is a picture, either a JPEG or a PNG. Check the first few bytes to see which.
  * `acre` -- Active Remote
+ * `cdid` -- Client advertised Device ID
  * `clip` -- the payload is the IP address of the client, i.e. the sender of audio. Can be an IPv4 or an IPv6 address.
+ * `cmac` -- Client advertised MAC address
+ * `cmod` -- Client advertised model ("iPhone14,2")
  * `daid` -- DACP ID
  * `dapo` -- DACP Port
  * `mden` -- a sequence of metadata has ended. The RTP timestamp associated with the metadata sequence is included as data, if available.
@@ -120,7 +123,7 @@ Here are the 'ssnc' codes defined so far:
  * `prsm` -- play stream resume. No arguments
  * `prgr` -- progress -- this is metadata from AirPlay consisting of RTP timestamps for the start of the current play sequence, the current play point and the end of the play sequence.
  * `pvol` -- play volume. The volume is sent as a string -- "airplay_volume,volume,lowest_volume,highest_volume", where "volume", "lowest_volume" and "highest_volume" are given in dB. The "airplay_volume" is what's sent by the source (e.g. iTunes) to the player, and is from 0.00 down to -30.00, with -144.00 meaning "mute". This is linear on the volume control slider of iTunes or iOS AirPlay. If the volume setting is being ignored by Shairport Sync itself, the volume, lowest_volume and highest_volume values are zero.
- * `snam` -- a device e.g. "Joe's iPhone" has started a play session. Specifically, it's the "X-Apple-Client-Name" string.
+ * `snam` -- a device e.g. "Joe's iPhone" has started a play session. Specifically, it's the "X-Apple-Client-Name" string for AP1, or direct from the configuration Plist for AP2.
  * `snua` -- a "user agent" e.g. "iTunes/12..." has started a play session. Specifically, it's the "User-Agent" string.
  * `stal` -- this is an error message meaning that reception of a large piece of metadata, usually a large picture, has stalled; bad things may happen.
  * `svip` -- the payload is the IP address of the server, i.e. shairport-sync. Can be an IPv4 or an IPv6 address.
@@ -135,6 +138,10 @@ The MQTT service can parse the above raw messages into a subset of human-readabl
 * `artist` -- text of artist name 
 * `album` -- text of album name
 * `client_ip` -- IP address of the connected client
+* `client_device_id` -- Client advertised Device ID
+* `client_mac_address` -- Client advertised MAC address
+* `client_model` -- Client advertised model ("iPhone14,2")
+* `client_name` -- Client advertised name ("Joe's iPhone")
 * `dacp_id` -- DACP ID
 * `format` -- ??
 * `genre` -- text of genre
diff --git a/mqtt.c b/mqtt.c
index 912d618c67311697b6398be8a23ba13bcfec072e..b898ab9e1d3ecc853b1e2992f88cfd8fcd7f8c23 100644 (file)
--- a/mqtt.c
+++ b/mqtt.c
@@ -173,6 +173,15 @@ void mqtt_process_metadata(uint32_t type, uint32_t code, char *data, uint32_t le
       case 'clip':
         mqtt_publish("client_ip", data, length);
         break;
+      case 'cdid':
+        mqtt_publish("client_device_id", data, length);
+        break;
+      case 'cmac':
+        mqtt_publish("client_mac_address", data, length);
+        break;
+      case 'cmod':
+        mqtt_publish("client_model", data, length);
+        break;
       case 'daid':
         mqtt_publish("dacp_id", data, length);
         break;
@@ -196,6 +205,9 @@ void mqtt_process_metadata(uint32_t type, uint32_t code, char *data, uint32_t le
       case 'pvol':
         mqtt_publish("volume", data, length);
         break;
+      case 'snam':
+        mqtt_publish("client_name", data, length);
+        break;
       case 'svip':
         mqtt_publish("server_ip", data, length);
         break;
diff --git a/rtsp.c b/rtsp.c
index cd76c537f457f3ebb137968f2664e92a8c9dd4f4..408d6132f69a44db657447553fd1a346d41e97d7 100644 (file)
--- a/rtsp.c
+++ b/rtsp.c
@@ -2613,6 +2613,19 @@ void handle_flush(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) {
 }
 
 #ifdef CONFIG_AIRPLAY_2
+
+static void check_and_send_plist_metadata(plist_t messagePlist, const char *plist_key, uint32_t metadata_code)
+{
+  plist_t item = plist_dict_get_item(messagePlist, plist_key);
+  if (item) {
+    char *value;
+    plist_get_string_val(item, &value);
+    if (value != NULL) {
+      send_metadata('ssnc', metadata_code, value, strlen(value), NULL, 0);
+    }
+  }
+}
+
 void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) {
   int err;
   debug(2, "Connection %d: SETUP (AirPlay 2)", conn->connection_number);
@@ -2845,6 +2858,13 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
             debug(1, "SETUP on Connection %d: PTP setup -- no timingPeerInfo plist.",
                   conn->connection_number);
           }
+
+#ifdef CONFIG_METADATA
+          check_and_send_plist_metadata(messagePlist, "name", 'snam');
+          check_and_send_plist_metadata(messagePlist, "deviceID", 'cdid');
+          check_and_send_plist_metadata(messagePlist, "model", 'cmod');
+          check_and_send_plist_metadata(messagePlist, "macAddress", 'cmac');
+#endif
         } else if (conn->airplay_stream_category == ntp_stream) {
           debug(1, "SETUP on Connection %d: ntp stream handling is not implemented!",
                 conn->connection_number, req);