From 076dd5d4c17f2484c34b9da11dfb5d1a580d6f99 Mon Sep 17 00:00:00 2001 From: Julian Bouzas Date: Fri, 24 Apr 2026 11:28:39 -0400 Subject: [PATCH] global-proxy: Add _attach_collection() and _get_collection_name() APIs --- lib/wp/global-proxy.c | 116 ++++++++++++++++++++++++++++++++++++++++++ lib/wp/global-proxy.h | 9 ++++ 2 files changed, 125 insertions(+) diff --git a/lib/wp/global-proxy.c b/lib/wp/global-proxy.c index 046795aa..9b7fd8db 100644 --- a/lib/wp/global-proxy.c +++ b/lib/wp/global-proxy.c @@ -7,6 +7,7 @@ */ #include "global-proxy.h" +#include "collection.h" #include "private/registry.h" #include "core.h" #include "error.h" @@ -43,6 +44,8 @@ struct _WpGlobalProxyPrivate WpGlobal *global; gchar factory_name[96]; WpProperties *properties; + GWeakRef collection; + guint32 collected_id; }; enum { @@ -51,6 +54,7 @@ enum { PROP_FACTORY_NAME, PROP_GLOBAL_PROPERTIES, PROP_PERMISSIONS, + PROP_COLLECTION_NAME, }; G_DEFINE_TYPE_WITH_PRIVATE (WpGlobalProxy, wp_global_proxy, WP_TYPE_PROXY) @@ -58,6 +62,11 @@ G_DEFINE_TYPE_WITH_PRIVATE (WpGlobalProxy, wp_global_proxy, WP_TYPE_PROXY) static void wp_global_proxy_init (WpGlobalProxy * self) { + WpGlobalProxyPrivate *priv = + wp_global_proxy_get_instance_private (self); + + g_weak_ref_init (&priv->collection, NULL); + priv->collected_id = SPA_ID_INVALID; } static void @@ -67,6 +76,8 @@ wp_global_proxy_dispose (GObject * object) WpGlobalProxyPrivate *priv = wp_global_proxy_get_instance_private (self); + wp_global_proxy_attach_collection (self, NULL); + if (priv->global) wp_global_rm_flag (priv->global, WP_GLOBAL_FLAG_OWNED_BY_PROXY); @@ -80,6 +91,7 @@ wp_global_proxy_finalize (GObject * object) WpGlobalProxyPrivate *priv = wp_global_proxy_get_instance_private (self); + g_weak_ref_clear (&priv->collection); g_clear_pointer (&priv->properties, wp_properties_unref); g_clear_pointer (&priv->global, wp_global_unref); @@ -125,6 +137,9 @@ wp_global_proxy_get_property (GObject * object, guint property_id, case PROP_GLOBAL_PROPERTIES: g_value_take_boxed (value, wp_global_proxy_get_global_properties (self)); break; + case PROP_COLLECTION_NAME: + g_value_set_string (value, wp_global_proxy_get_collection_name (self)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -250,6 +265,8 @@ wp_global_proxy_destroyed (WpProxy * proxy) WpGlobalProxyPrivate *priv = wp_global_proxy_get_instance_private (self); + wp_global_proxy_attach_collection (self, NULL); + if (priv->global && priv->global->proxy && (priv->global->flags & WP_GLOBAL_FLAG_OWNED_BY_PROXY)) { /* We can end up here as a result of _request_destroy() followed by @@ -308,6 +325,11 @@ wp_global_proxy_class_init (WpGlobalProxyClass * klass) g_param_spec_uint ("permissions", "permissions", "The pipewire global permissions", 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_COLLECTION_NAME, + g_param_spec_string ("collection-name", "collection-name", + "The collection name this global belongs to", NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); } /*! @@ -420,3 +442,97 @@ wp_global_proxy_bind (WpGlobalProxy * self) wp_proxy_set_pw_proxy (WP_PROXY (self), p); return TRUE; } + +static void +on_global_dropped (WpCollection *obj, guint32 global_id, + WpGlobalProxy *self) +{ + WpGlobalProxyPrivate *priv; + + priv = wp_global_proxy_get_instance_private (self); + + /* If this global was dropped from the collection, detach proxy from it */ + if (global_id == priv->collected_id) { + priv->collected_id = SPA_ID_INVALID; + g_weak_ref_set (&priv->collection, NULL); + } +} + +/*! + * \brief Attaches a collection in the global proxy + * + * \ingroup wpglobalproxy + * \param self the pipewire global + * \param collection (transfer none) (nullable): the collection to attach, or + * NULL to detach the current collection. + * \returns TRUE if the collection was attached and the global was collected, + * FALSE otherwise. + */ +gboolean +wp_global_proxy_attach_collection (WpGlobalProxy *self, + WpCollection *collection) +{ + WpGlobalProxyPrivate *priv; + g_autoptr (WpCollection) curr_collection = NULL; + + g_return_val_if_fail (WP_IS_GLOBAL_PROXY (self), FALSE); + + priv = wp_global_proxy_get_instance_private (self); + + /* Dont do anything if this collection is already attached */ + curr_collection = g_weak_ref_get (&priv->collection); + if (curr_collection == collection) + return TRUE; + + /* Make sure the global proxy is bound before attaching a new collection */ + if (collection && + !(wp_object_get_active_features (WP_OBJECT (self)) & + WP_PROXY_FEATURE_BOUND)) { + wp_warning_object (self, + "global proxy %p is not bound, cannot attach collection", self); + return FALSE; + } + + /* Drop this global from the old collection if any */ + if (curr_collection) { + g_signal_handlers_disconnect_by_data (curr_collection, self); + wp_collection_drop_global (curr_collection, priv->collected_id); + priv->collected_id = SPA_ID_INVALID; + g_weak_ref_set (&priv->collection, NULL); + } + + /* Collect this global into the new collection if any */ + if (collection) { + priv->collected_id = wp_proxy_get_bound_id (WP_PROXY (self)); + g_weak_ref_set (&priv->collection, collection); + wp_collection_collect_global (collection, priv->collected_id); + g_signal_connect_object (collection, "global-dropped", + G_CALLBACK (on_global_dropped), self, 0); + } + + return TRUE; +} + +/*! + * \brief Gets the collection naem this global proxy is attached to + * + * \ingroup wpglobalproxy + * \param self the pipewire global + * \returns (nullable): the collection name this global proxy is attached to + */ +const gchar * +wp_global_proxy_get_collection_name (WpGlobalProxy *self) +{ + WpGlobalProxyPrivate *priv; + g_autoptr (WpCollection) c = NULL; + + g_return_val_if_fail (WP_IS_GLOBAL_PROXY (self), NULL); + + priv = wp_global_proxy_get_instance_private (self); + + c = g_weak_ref_get (&priv->collection); + if (!c) + return NULL; + + return wp_collection_get_name (c); +} diff --git a/lib/wp/global-proxy.h b/lib/wp/global-proxy.h index 3bb82084..b96821ec 100644 --- a/lib/wp/global-proxy.h +++ b/lib/wp/global-proxy.h @@ -14,6 +14,8 @@ G_BEGIN_DECLS +typedef struct _WpCollection WpCollection; + /*! * \brief The WpGlobalProxy GType * \ingroup wpglobalproxy @@ -44,6 +46,13 @@ WpProperties * wp_global_proxy_get_global_properties ( WP_API gboolean wp_global_proxy_bind (WpGlobalProxy * self); +WP_API +gboolean wp_global_proxy_attach_collection (WpGlobalProxy *self, + WpCollection *collection); + +WP_API +const gchar * wp_global_proxy_get_collection_name (WpGlobalProxy *self); + G_END_DECLS #endif