From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Sun, 7 Aug 2022 09:02:56 +0000 (+0100) Subject: Add a new D-Bus method called "DropSession" to forcibly terminate the current play... X-Git-Tag: 4.1-rc1~24^2~44 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b81fb39a8025f7410a02e7f4e0f4f483bc9346b5;p=thirdparty%2Fshairport-sync.git Add a new D-Bus method called "DropSession" to forcibly terminate the current play session. --- diff --git a/dbus-service.c b/dbus-service.c index e51330bf..c993223a 100644 --- a/dbus-service.c +++ b/dbus-service.c @@ -807,6 +807,16 @@ static gboolean on_handle_remote_command(ShairportSync *skeleton, GDBusMethodInv return TRUE; } +static gboolean on_handle_drop_session(ShairportSync *skeleton, + GDBusMethodInvocation *invocation, + __attribute__((unused)) gpointer user_data) { + if (playing_conn != NULL) + debug(1, ">> stopping current play session"); + get_play_lock(NULL, 1); // stop any current session and don't replace it + shairport_sync_complete_drop_session(skeleton, invocation); + return TRUE; +} + static void on_dbus_name_acquired(GDBusConnection *connection, const gchar *name, __attribute__((unused)) gpointer user_data) { @@ -862,6 +872,9 @@ static void on_dbus_name_acquired(GDBusConnection *connection, const gchar *name g_signal_connect(shairportSyncSkeleton, "handle-remote-command", G_CALLBACK(on_handle_remote_command), NULL); + g_signal_connect(shairportSyncSkeleton, "handle-drop-session", + G_CALLBACK(on_handle_drop_session), NULL); + g_signal_connect(shairportSyncDiagnosticsSkeleton, "notify::verbosity", G_CALLBACK(notify_verbosity_callback), NULL); diff --git a/org.gnome.ShairportSync.xml b/org.gnome.ShairportSync.xml index efa00fd0..1051bab6 100644 --- a/org.gnome.ShairportSync.xml +++ b/org.gnome.ShairportSync.xml @@ -12,6 +12,7 @@ + diff --git a/rtsp.c b/rtsp.c index 2a9d8aae..de095412 100644 --- a/rtsp.c +++ b/rtsp.c @@ -542,19 +542,30 @@ void release_hold_on_play_lock(__attribute__((unused)) rtsp_conn_info *conn) { // make conn no longer the playing_conn void release_play_lock(rtsp_conn_info *conn) { - debug(2, "Connection %d: release play lock.", conn->connection_number); + if (conn != NULL) + debug(2, "Connection %d: release play lock.", conn->connection_number); + else + debug(2, "Release play lock."); lock_player(); if (playing_conn == conn) { // if we have the player + if (conn != NULL) + debug(2, "Connection %d: play lock released.", conn->connection_number); + else + debug(2, "Play lock released."); playing_conn = NULL; // let it go - debug(2, "Connection %d: release play lock.", conn->connection_number); } unlock_player(); } -// make conn the playing_conn, -int get_play_lock(rtsp_conn_info *conn) { - debug(2, "Connection %d: request play lock.", conn->connection_number); +// make conn the playing_conn, and kill the current session if permitted +int get_play_lock(rtsp_conn_info *conn, int allow_session_interruption) { + if (conn != NULL) + debug(2, "Connection %d: request play lock.", conn->connection_number); + else if (playing_conn != NULL) + debug(2, "Connection %d: request release.", playing_conn->connection_number); + else + debug(2, "Request release of non-existent player."); // returns -1 if it failed, 0 if it succeeded and 1 if it succeeded but // interrupted an existing session int response = 0; @@ -572,19 +583,14 @@ int get_play_lock(rtsp_conn_info *conn) { have_the_player = 1; } else if (playing_conn == conn) { have_the_player = 1; - warn("Duplicate attempt to acquire the player by the same connection, by the look of it!"); + if (conn != NULL) + warn("Duplicate attempt to acquire the player by the same connection, by the look of it!"); } else if (playing_conn->stop) { debug(1, "Connection %d: Waiting for Connection %d to stop playing.", conn->connection_number, playing_conn->connection_number); should_wait = 1; -#ifdef CONFIG_AIRPLAY_2 - } else { // ignore the allow_session_interruption in AirPlay 2 -- it is always permissible, it - // seems -#else - } else if (config.allow_session_interruption == 1) { -#endif - debug(2, "Connection %d: Asking Connection %d to stop playing.", conn->connection_number, - playing_conn->connection_number); + } else if (allow_session_interruption != 0) { + debug(2, "Asking Connection %d to stop playing.", playing_conn->connection_number); playing_conn->stop = 1; interrupting_current_session = 1; should_wait = 1; @@ -608,18 +614,23 @@ int get_play_lock(rtsp_conn_info *conn) { time_remaining -= 100000; } } - if ((have_the_player == 1) && (interrupting_current_session == 1)) { - debug(2, "Connection %d: Got player lock", conn->connection_number); + if (conn != NULL) + debug(2, "Connection %d: Got player lock", conn->connection_number); + else + debug(2, "Player released."); response = 1; } else { - debug(1, "Connection %d: failed to get player lock after waiting.", conn->connection_number); + debug(2, "Connection %d: failed to get player lock after waiting.", conn->connection_number); response = -1; } } if ((have_the_player == 1) && (interrupting_current_session == 0)) { - debug(2, "Connection %d: Got player lock.", conn->connection_number); + if (conn != NULL) + debug(2, "Connection %d: Got player lock.", conn->connection_number); + else + debug(2, "Player released."); response = 0; } return response; @@ -2609,7 +2620,7 @@ void handle_teardown_2(rtsp_conn_info *conn, __attribute__((unused)) rtsp_messag } else { teardown_phase_one(conn); // try to do phase one anyway teardown_phase_two(conn); - debug(2, "Connection %d: TEARDOWN phase two complete", conn->connection_number); + debug(1, "Connection %d: TEARDOWN phase two complete", conn->connection_number); } //} else { // warn("Connection %d TEARDOWN received without having the player (no ANNOUNCE?)", @@ -2751,7 +2762,7 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) send_ssnc_metadata('conn', conn->client_ip_string, strlen(conn->client_ip_string), 1); // before disconnecting an existing play #endif - get_play_lock(conn); + get_play_lock(conn, 1); // airplay 2 always allows interruption #ifdef CONFIG_METADATA send_ssnc_metadata('clip', conn->client_ip_string, strlen(conn->client_ip_string), 1); send_ssnc_metadata('svip', conn->self_ip_string, strlen(conn->self_ip_string), 1); @@ -4269,7 +4280,7 @@ static void handle_set_parameter(rtsp_conn_info *conn, rtsp_message *req, rtsp_m static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) { debug(3, "Connection %d: ANNOUNCE", conn->connection_number); - int get_play_status = get_play_lock(conn); + int get_play_status = get_play_lock(conn, config.allow_session_interruption); if (get_play_status != -1) { debug(3, "Connection %d: ANNOUNCE has acquired play lock.", conn->connection_number); diff --git a/rtsp.h b/rtsp.h index b12c07ea..0725f664 100644 --- a/rtsp.h +++ b/rtsp.h @@ -11,6 +11,9 @@ void *rtsp_listen_loop(__attribute((unused)) void *arg); void lock_player(); void unlock_player(); +// this can be used to forcibly stop a play session +int get_play_lock(rtsp_conn_info *conn, int allow_session_interruption); + // initialise and completely delete the metadata stuff void metadata_init(void);