diff --git a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc index 3f93393381..8cc3957347 100644 --- a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc +++ b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc @@ -870,9 +870,39 @@ void BaseCapturerPipeWire::OnSessionRequestResponseSignal( return; } + that->session_closed_signal_id_ = g_dbus_connection_signal_subscribe( + that->connection_, kDesktopBusName, kSessionInterfaceName, "Closed", + that->session_handle_, /*arg0=*/nullptr, G_DBUS_SIGNAL_FLAGS_NONE, + OnSessionClosedSignal, that, /*user_data_free_func=*/nullptr); + that->SourcesRequest(); } +// static +void BaseCapturerPipeWire::OnSessionClosedSignal(GDBusConnection* connection, + const gchar* sender_name, + const gchar* object_path, + const gchar* interface_name, + const gchar* signal_name, + GVariant* parameters, + gpointer user_data) { + BaseCapturerPipeWire* that = static_cast(user_data); + RTC_DCHECK(that); + + RTC_LOG(LS_INFO) << "Received closed signal from session."; + + if (that->pw_stream_) { + pw_stream_disconnect(that->pw_stream_); + } + + // Unsubscribe from the signal and free the session handle to avoid calling + // Session::Close from the destructor since it's already closed + g_dbus_connection_signal_unsubscribe(that->connection_, + that->session_closed_signal_id_); + g_free(that->session_handle_); + that->session_handle_ = nullptr; +} + void BaseCapturerPipeWire::SourcesRequest() { GVariantBuilder builder; Scoped variant_string; diff --git a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.h b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.h index 91c863e4b4..65c9fd3e68 100644 --- a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.h +++ b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.h @@ -104,6 +104,7 @@ class BaseCapturerPipeWire : public DesktopCapturer { guint session_request_signal_id_ = 0; guint sources_request_signal_id_ = 0; guint start_request_signal_id_ = 0; + guint session_closed_signal_id_ = 0; int64_t modifier_; DesktopSize video_size_; @@ -166,6 +167,13 @@ class BaseCapturerPipeWire : public DesktopCapturer { const gchar* signal_name, GVariant* parameters, gpointer user_data); + static void OnSessionClosedSignal(GDBusConnection* connection, + const gchar* sender_name, + const gchar* object_path, + const gchar* interface_name, + const gchar* signal_name, + GVariant* parameters, + gpointer user_data); void SourcesRequest(); static void OnSourcesRequested(GDBusProxy* proxy, diff --git a/modules/desktop_capture/linux/wayland/pipewire.sigs b/modules/desktop_capture/linux/wayland/pipewire.sigs index 7a74c7fcd3..06a97b8f29 100644 --- a/modules/desktop_capture/linux/wayland/pipewire.sigs +++ b/modules/desktop_capture/linux/wayland/pipewire.sigs @@ -24,6 +24,7 @@ pw_properties * pw_properties_new_string(const char *args); // stream.h void pw_stream_add_listener(pw_stream *stream, spa_hook *listener, const pw_stream_events *events, void *data); int pw_stream_connect(pw_stream *stream, enum pw_direction direction, uint32_t target_id, enum pw_stream_flags flags, const spa_pod **params, uint32_t n_params); +int pw_stream_disconnect(pw_stream *stream); pw_buffer *pw_stream_dequeue_buffer(pw_stream *stream); void pw_stream_destroy(pw_stream *stream); pw_stream * pw_stream_new(pw_core *core, const char *name, pw_properties *props);