From: Cody Cutrer Date: Sun, 26 Dec 2021 19:13:42 +0000 (-0700) Subject: extract several pieces of client metadata for AP2 X-Git-Tag: 4.1-rc1~24^2~316^2^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F1389%2Fhead;p=thirdparty%2Fshairport-sync.git extract several pieces of client metadata for AP2 --- diff --git a/MQTT.md b/MQTT.md index ec41a0b1..95779c76 100644 --- 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 912d618c..b898ab9e 100644 --- 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 cd76c537..408d6132 100644 --- 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);