diff --git a/lib/wp/endpoint-stream.c b/lib/wp/endpoint-stream.c index 995b707d6dfacc6d6102c8e1f9a9afdc00537959..8a4ee979db62f15dcfe46a235968f8ad4bb0a7d5 100644 --- a/lib/wp/endpoint-stream.c +++ b/lib/wp/endpoint-stream.c @@ -708,6 +708,7 @@ wp_impl_endpoint_stream_augment (WpProxy * proxy, WpProxyFeatures features) if (features & WP_PROXY_FEATURE_INFO) { const gchar *key, *value; + g_autoptr (WpProxy) endpoint = NULL; /* initialize info struct */ priv->info = &self->info; @@ -718,6 +719,11 @@ wp_impl_endpoint_stream_augment (WpProxy * proxy, WpProxyFeatures features) &self->info.name, &immutable_props); + endpoint = wp_session_item_get_associated_proxy ( + WP_SESSION_ITEM (self->item), WP_TYPE_ENDPOINT); + self->info.endpoint_id = + endpoint ? wp_proxy_get_bound_id (endpoint) : SPA_ID_INVALID; + populate_endpoint_stream_info (self, PW_ENDPOINT_STREAM_CHANGE_MASK_ALL); /* subscribe to changes */ @@ -729,6 +735,10 @@ wp_impl_endpoint_stream_augment (WpProxy * proxy, WpProxyFeatures features) props = wp_properties_new ( PW_KEY_ENDPOINT_STREAM_NAME, self->info.name, NULL); + if (self->info.endpoint_id != SPA_ID_INVALID) { + wp_properties_setf (props, PW_KEY_ENDPOINT_ID, "%u", + self->info.endpoint_id); + } while (g_variant_iter_next (immutable_props, "{&s&s}", &key, &value)) { wp_properties_set (props, key, value); } diff --git a/lib/wp/endpoint.c b/lib/wp/endpoint.c index 7722cc4f838528d3968528b7fcf4a00358ed33c7..d1e807f9e107d7b7bbe65dc2f788cd2b8a85b356 100644 --- a/lib/wp/endpoint.c +++ b/lib/wp/endpoint.c @@ -647,10 +647,10 @@ populate_endpoint_info (WpImplEndpoint * self, guint32 change_mask) } if (change_mask & PW_ENDPOINT_CHANGE_MASK_SESSION) { - g_autoptr (WpSession) session = - wp_session_item_get_session (WP_SESSION_ITEM (self->item)); + g_autoptr (WpProxy) session = wp_session_item_get_associated_proxy ( + WP_SESSION_ITEM (self->item), WP_TYPE_SESSION); self->info.session_id = - session ? wp_proxy_get_bound_id (WP_PROXY (session)) : SPA_ID_INVALID; + session ? wp_proxy_get_bound_id (session) : SPA_ID_INVALID; } if (change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) { diff --git a/lib/wp/session-item.c b/lib/wp/session-item.c index 402873d8ca0508a92eb6e112e7e877e541367400..10aef8a9d7cfab78407f9daa8f79140c59a825bb 100644 --- a/lib/wp/session-item.c +++ b/lib/wp/session-item.c @@ -117,6 +117,34 @@ wp_session_item_finalize (GObject * object) G_OBJECT_CLASS (wp_session_item_parent_class)->finalize (object); } +static gpointer +wp_session_item_default_get_associated_proxy (WpSessionItem * self, + GType proxy_type) +{ + WpSessionItemPrivate *priv; + + if (WP_IS_SI_STREAM (self)) { + WpSiEndpoint *ep = wp_si_stream_get_parent_endpoint (WP_SI_STREAM (self)); + priv = wp_session_item_get_instance_private (WP_SESSION_ITEM (ep)); + } else { + priv = wp_session_item_get_instance_private (self); + } + + if (proxy_type == WP_TYPE_SESSION) { + return g_weak_ref_get (&priv->session); + } + else if (proxy_type == WP_TYPE_ENDPOINT) { + return priv->impl_endpoint ? g_object_ref (priv->impl_endpoint) : NULL; + } + else if (proxy_type == WP_TYPE_ENDPOINT_STREAM) { + gpointer impl_stream = priv->impl_streams ? + g_hash_table_lookup (priv->impl_streams, self) : NULL; + return impl_stream ? g_object_ref (impl_stream) : NULL; + } + + return NULL; +} + static guint wp_session_item_default_get_next_step (WpSessionItem * self, WpTransition * transition, guint step) @@ -352,6 +380,7 @@ wp_session_item_class_init (WpSessionItemClass * klass) object_class->dispose = wp_session_item_dispose; object_class->finalize = wp_session_item_finalize; + klass->get_associated_proxy = wp_session_item_default_get_associated_proxy; klass->get_next_step = wp_session_item_default_get_next_step; klass->execute_step = wp_session_item_default_execute_step; klass->reset = wp_session_item_default_reset; @@ -370,23 +399,6 @@ wp_session_item_class_init (WpSessionItemClass * klass) G_TYPE_NONE, 1, WP_TYPE_SI_FLAGS); } -/** - * wp_session_item_get_session: - * @self: the session item - * - * Returns: (nullable) (transfer full): the session that owns this item, or - * %NULL if this item is not part of a session - */ -WpSession * -wp_session_item_get_session (WpSessionItem * self) -{ - g_return_val_if_fail (WP_IS_SESSION_ITEM (self), NULL); - - WpSessionItemPrivate *priv = - wp_session_item_get_instance_private (self); - return g_weak_ref_get (&priv->session); -} - /** * wp_session_item_get_flags: * @self: the session item @@ -455,6 +467,37 @@ wp_session_item_clear_flag (WpSessionItem * self, WpSiFlags flag) } } +/** + * wp_session_item_get_associated_proxy: (virtual get_associated_proxy) + * @self: the session item + * @proxy_type: a #WpProxy subclass #GType + * + * An associated proxy is a #WpProxy subclass instance that is somehow related + * to this item. For example: + * - An exported #WpSiEndpoint should have at least: + * - an associated #WpEndpoint + * - an associated #WpSession + * - An exported #WpSiStream should have at least: + * - an associated #WpEndpointStream + * - an associated #WpEndpoint + * - In cases where the item wraps a single PipeWire node, it should also + * have an associated #WpNode + * + * Returns: (nullable) (transfer full) (type WpProxy): the associated proxy + * of the specified @proxy_type, or %NULL if there is no association to + * such a proxy + */ +gpointer +wp_session_item_get_associated_proxy (WpSessionItem * self, GType proxy_type) +{ + g_return_val_if_fail (WP_IS_SESSION_ITEM (self), NULL); + g_return_val_if_fail (WP_SESSION_ITEM_GET_CLASS (self)->get_associated_proxy, + NULL); + g_return_val_if_fail (g_type_is_a (proxy_type, WP_TYPE_PROXY), NULL); + + return WP_SESSION_ITEM_GET_CLASS (self)->get_associated_proxy (self, proxy_type); +} + /** * wp_session_item_configure: (virtual configure) * @self: the session item diff --git a/lib/wp/session-item.h b/lib/wp/session-item.h index 07407dc838a0cb1e62fa874f3fa4ede20f9af287..96cf638c568a689515726ddae3676d190c99a0b7 100644 --- a/lib/wp/session-item.h +++ b/lib/wp/session-item.h @@ -64,6 +64,7 @@ typedef enum { /** * WpSessionItemClass: + * @get_associated_proxy: See wp_session_item_get_associated_proxy() * @configure: See wp_session_item_configure() * @get_configuration: See wp_session_item_get_configuration() * @get_next_step: Implements #WpTransitionClass.get_next_step() for the @@ -79,6 +80,8 @@ struct _WpSessionItemClass { GObjectClass parent_class; + gpointer (*get_associated_proxy) (WpSessionItem * self, GType proxy_type); + gboolean (*configure) (WpSessionItem * self, GVariant * args); GVariant * (*get_configuration) (WpSessionItem * self); @@ -97,10 +100,7 @@ struct _WpSessionItemClass void (*unexport) (WpSessionItem * self); }; -/* properties */ - -WP_API -WpSession * wp_session_item_get_session (WpSessionItem * self); +/* flags */ WP_API WpSiFlags wp_session_item_get_flags (WpSessionItem * self); @@ -111,6 +111,12 @@ void wp_session_item_set_flag (WpSessionItem * self, WpSiFlags flag); WP_API void wp_session_item_clear_flag (WpSessionItem * self, WpSiFlags flag); +/* associated proxies */ + +WP_API +gpointer wp_session_item_get_associated_proxy (WpSessionItem * self, + GType proxy_type); + /* configuration */ WP_API diff --git a/modules/module-si-adapter.c b/modules/module-si-adapter.c index dc3698d1ac3c46aed548b2d4e58ff297e4d435e3..e715f1724f5520d674bae92ebd2766cacab415b9 100644 --- a/modules/module-si-adapter.c +++ b/modules/module-si-adapter.c @@ -79,6 +79,18 @@ si_adapter_reset (WpSessionItem * item) WP_SESSION_ITEM_CLASS (si_adapter_parent_class)->reset (item); } +static gpointer +si_adapter_get_associated_proxy (WpSessionItem * item, GType proxy_type) +{ + WpSiAdapter *self = WP_SI_ADAPTER (item); + + if (proxy_type == WP_TYPE_NODE) + return self->node ? g_object_ref (self->node) : NULL; + + return WP_SESSION_ITEM_CLASS (si_adapter_parent_class)->get_associated_proxy ( + item, proxy_type); +} + static GVariant * si_adapter_get_configuration (WpSessionItem * item) { @@ -355,6 +367,7 @@ si_adapter_class_init (WpSiAdapterClass * klass) object_class->finalize = si_adapter_finalize; + si_class->get_associated_proxy = si_adapter_get_associated_proxy; si_class->configure = si_adapter_configure; si_class->get_configuration = si_adapter_get_configuration; si_class->get_next_step = si_adapter_get_next_step;