From: Mike Brady Date: Wed, 10 Jan 2018 21:30:30 +0000 (+0000) Subject: Make player.c send information to the metadata store rather than initiating d-bus... X-Git-Tag: 3.2d29~126 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3e2c3e837a70362602f72d2c96b65a1ed6bb07ca;p=thirdparty%2Fshairport-sync.git Make player.c send information to the metadata store rather than initiating d-bus messages --- diff --git a/dacp.c b/dacp.c index bd170b4d..b51e4afa 100644 --- 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 c3d36b7d..728512c0 100644 --- 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 diff --git a/metadata_hub.h b/metadata_hub.h index 7ce9ed48..d8a238df 100644 --- a/metadata_hub.h +++ b/metadata_hub.h @@ -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 diff --git a/player.c b/player.c index 27520753..b18d9394 100644 --- 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 @@ -82,12 +82,6 @@ #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); } diff --git a/player.h b/player.h index 6310dec7..0632e0fb 100644 --- a/player.h +++ b/player.h @@ -26,14 +26,6 @@ #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;