global-proxy: Add _attach_collection() and _get_collection_name() APIs

This commit is contained in:
Julian Bouzas 2026-04-24 11:28:39 -04:00
parent 35cd7b5c5f
commit 076dd5d4c1
2 changed files with 125 additions and 0 deletions

View file

@ -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);
}

View file

@ -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