diff --git a/lib/wp/core.c b/lib/wp/core.c index 85d45b6871f596dcd80d8193e2fd0704bb573be6..5a86415cf9ae4ca498c1baaa18b3f8a2ab58dffb 100644 --- a/lib/wp/core.c +++ b/lib/wp/core.c @@ -552,7 +552,7 @@ wp_core_create_local_object (WpCore * self, const gchar *factory_name, { struct pw_proxy *pw_proxy = NULL; struct pw_factory *factory = NULL; - gpointer iface = NULL; + gpointer local_object = NULL; g_return_val_if_fail (WP_IS_CORE (self), NULL); g_return_val_if_fail (self->pw_core, NULL); @@ -562,24 +562,27 @@ wp_core_create_local_object (WpCore * self, const gchar *factory_name, if (!factory) return NULL; - iface = pw_factory_create_object (factory, + local_object = pw_factory_create_object (factory, NULL, interface_type, interface_version, properties ? wp_properties_to_pw_properties (properties) : NULL, 0); - if (!iface) + if (!local_object) return NULL; pw_proxy = pw_remote_export (self->pw_remote, interface_type, properties ? wp_properties_to_pw_properties (properties) : NULL, - iface, + local_object, 0); - if (!pw_proxy) + if (!pw_proxy) { + wp_proxy_local_object_destroy_for_type (interface_type, local_object); return NULL; + } - return wp_proxy_new_wrap (self, pw_proxy, interface_type, interface_version); + return wp_proxy_new_wrap (self, pw_proxy, interface_type, interface_version, + local_object); } WpProxy * @@ -595,8 +598,8 @@ wp_core_create_remote_object (WpCore *self, pw_proxy = pw_core_proxy_create_object (self->core_proxy, factory_name, interface_type, interface_version, properties ? wp_properties_peek_dict (properties) : NULL, 0); - return wp_proxy_new_wrap (self, pw_proxy, interface_type, - interface_version); + return wp_proxy_new_wrap (self, pw_proxy, interface_type, interface_version, + NULL); } struct pw_core_proxy * diff --git a/lib/wp/monitor.c b/lib/wp/monitor.c index 7be2aae6f9858959f949298a91d35e36cee7a1b8..d32bb8cee6a245b90bca33497dd6436c06893102 100644 --- a/lib/wp/monitor.c +++ b/lib/wp/monitor.c @@ -301,7 +301,7 @@ node_new (struct object *dev, uint32_t id, node->type = SPA_TYPE_INTERFACE_Node; node->node = pw_node; node->proxy = wp_proxy_new_wrap (core, pw_proxy, PW_TYPE_INTERFACE_Node, - PW_VERSION_NODE_PROXY); + PW_VERSION_NODE_PROXY, NULL); return node; } @@ -368,7 +368,7 @@ device_new (WpMonitor *self, uint32_t id, const gchar *factory_name, dev->spa_dev = g_steal_pointer (&spa_dev); dev->properties = g_steal_pointer (&props); dev->proxy = wp_proxy_new_wrap (core, proxy, PW_TYPE_INTERFACE_Device, - PW_VERSION_DEVICE_PROXY); + PW_VERSION_DEVICE_PROXY, NULL); /* Add device listener for events */ if ((ret = spa_device_add_listener ((struct spa_device *) dev->spa_dev->interface, diff --git a/lib/wp/private.h b/lib/wp/private.h index 2dbda9193aed5bc15629f5f25029a73b2837b915..682c06dd41bb3d50a8f47b1ffe6cfa99bcced12d 100644 --- a/lib/wp/private.h +++ b/lib/wp/private.h @@ -85,6 +85,9 @@ void wp_object_manager_rm_object (WpObjectManager * self, GObject * object); /* proxy */ +void wp_proxy_local_object_destroy_for_type (guint32 type, + gpointer local_object); + WpProxy * wp_proxy_new_global (WpCore * core, WpGlobal * global); void wp_proxy_set_feature_ready (WpProxy * self, WpProxyFeatures feature); diff --git a/lib/wp/proxy.c b/lib/wp/proxy.c index 99a4e3a02a9be29b9ae6d795ecbf626706817d81..e5b2c62613e8993aa0f71a83acd9f1c9d17ee1e5 100644 --- a/lib/wp/proxy.c +++ b/lib/wp/proxy.c @@ -34,6 +34,7 @@ struct _WpProxyPrivate guint32 iface_type; guint32 iface_version; + gpointer local_object; struct pw_proxy *pw_proxy; @@ -58,6 +59,7 @@ enum { PROP_INTERFACE_NAME, PROP_INTERFACE_QUARK, PROP_INTERFACE_VERSION, + PROP_LOCAL_OBJECT, PROP_PW_PROXY, PROP_FEATURES, }; @@ -101,24 +103,26 @@ static struct { GType (*get_type) (void); /* a function returning a quark that identifies the interface */ GQuark (*get_quark) (void); + /* the destroy function of the local object, if any */ + void (*local_object_destroy) (gpointer); } types_assoc[] = { - { PW_TYPE_INTERFACE_Core, 0, wp_proxy_get_type, wp_proxy_core_quark }, - { PW_TYPE_INTERFACE_Registry, 0, wp_proxy_get_type, wp_proxy_registry_quark }, - { PW_TYPE_INTERFACE_Node, 0, wp_proxy_node_get_type, wp_proxy_node_quark }, - { PW_TYPE_INTERFACE_Port, 0, wp_proxy_port_get_type, wp_proxy_port_quark }, - { PW_TYPE_INTERFACE_Factory, 0, wp_proxy_get_type, wp_proxy_factory_quark }, - { PW_TYPE_INTERFACE_Link, 0, wp_proxy_link_get_type, wp_proxy_link_quark }, - { PW_TYPE_INTERFACE_Client, 0, wp_proxy_client_get_type, wp_proxy_client_quark }, - { PW_TYPE_INTERFACE_Module, 0, wp_proxy_get_type, wp_proxy_module_quark }, - { PW_TYPE_INTERFACE_Device, 0, wp_proxy_device_get_type, wp_proxy_device_quark }, - { PW_TYPE_INTERFACE_Metadata, 0, wp_proxy_get_type, wp_proxy_metadata_quark }, - { PW_TYPE_INTERFACE_Session, 0, wp_proxy_session_get_type, wp_proxy_session_quark }, - { PW_TYPE_INTERFACE_Endpoint, 0, wp_proxy_endpoint_get_type, wp_proxy_endpoint_quark }, - { PW_TYPE_INTERFACE_EndpointStream, 0, wp_proxy_get_type, wp_proxy_endpoint_stream_quark }, - { PW_TYPE_INTERFACE_EndpointLink, 0, wp_proxy_get_type, wp_proxy_endpoint_link_quark }, - { PW_TYPE_INTERFACE_ClientNode, 0, wp_proxy_get_type, wp_proxy_client_node_quark }, - { PW_TYPE_INTERFACE_ClientSession, 0, wp_proxy_get_type, wp_proxy_client_session_quark }, - { PW_TYPE_INTERFACE_ClientEndpoint, 0, wp_proxy_get_type, wp_proxy_client_endpoint_quark }, + { PW_TYPE_INTERFACE_Core, 0, wp_proxy_get_type, wp_proxy_core_quark, NULL }, + { PW_TYPE_INTERFACE_Registry, 0, wp_proxy_get_type, wp_proxy_registry_quark, NULL }, + { PW_TYPE_INTERFACE_Node, 0, wp_proxy_node_get_type, wp_proxy_node_quark, (GDestroyNotify)pw_node_destroy }, + { PW_TYPE_INTERFACE_Port, 0, wp_proxy_port_get_type, wp_proxy_port_quark, NULL, }, + { PW_TYPE_INTERFACE_Factory, 0, wp_proxy_get_type, wp_proxy_factory_quark, (GDestroyNotify)pw_factory_destroy }, + { PW_TYPE_INTERFACE_Link, 0, wp_proxy_link_get_type, wp_proxy_link_quark, (GDestroyNotify)pw_link_destroy }, + { PW_TYPE_INTERFACE_Client, 0, wp_proxy_client_get_type, wp_proxy_client_quark, (GDestroyNotify)pw_client_destroy }, + { PW_TYPE_INTERFACE_Module, 0, wp_proxy_get_type, wp_proxy_module_quark, (GDestroyNotify)pw_module_destroy }, + { PW_TYPE_INTERFACE_Device, 0, wp_proxy_device_get_type, wp_proxy_device_quark, (GDestroyNotify)pw_device_destroy }, + { PW_TYPE_INTERFACE_Metadata, 0, wp_proxy_get_type, wp_proxy_metadata_quark, NULL }, + { PW_TYPE_INTERFACE_Session, 0, wp_proxy_session_get_type, wp_proxy_session_quark, NULL }, + { PW_TYPE_INTERFACE_Endpoint, 0, wp_proxy_endpoint_get_type, wp_proxy_endpoint_quark, NULL }, + { PW_TYPE_INTERFACE_EndpointStream, 0, wp_proxy_get_type, wp_proxy_endpoint_stream_quark, NULL, }, + { PW_TYPE_INTERFACE_EndpointLink, 0, wp_proxy_get_type, wp_proxy_endpoint_link_quark, NULL, }, + { PW_TYPE_INTERFACE_ClientNode, 0, wp_proxy_get_type, wp_proxy_client_node_quark, NULL }, + { PW_TYPE_INTERFACE_ClientSession, 0, wp_proxy_get_type, wp_proxy_client_session_quark, NULL }, + { PW_TYPE_INTERFACE_ClientEndpoint, 0, wp_proxy_get_type, wp_proxy_client_endpoint_quark, NULL }, }; static inline GType @@ -144,6 +148,20 @@ wp_proxy_find_quark_for_type (guint32 type) return 0; } +void +wp_proxy_local_object_destroy_for_type (guint32 type, gpointer local_object) +{ + g_return_if_fail (local_object); + + for (gint i = 0; i < SPA_N_ELEMENTS (types_assoc); i++) { + if (types_assoc[i].pw_type == type) { + if (types_assoc[i].local_object_destroy) + types_assoc[i].local_object_destroy (local_object); + return; + } + } +} + static void proxy_event_destroy (void *data) { @@ -255,7 +273,15 @@ wp_proxy_dispose (GObject * object) static void wp_proxy_finalize (GObject * object) { - WpProxyPrivate *priv = wp_proxy_get_instance_private (WP_PROXY(object)); + WpProxy *self = WP_PROXY (object); + WpProxyPrivate *priv = wp_proxy_get_instance_private (self); + + /* Clear the local object */ + if (priv->local_object) { + wp_proxy_local_object_destroy_for_type (priv->iface_type, + priv->local_object); + priv->local_object = NULL; + } g_clear_pointer (&priv->augment_tasks, g_ptr_array_unref); g_clear_pointer (&priv->global, wp_global_unref); @@ -284,6 +310,9 @@ wp_proxy_set_property (GObject * object, guint property_id, case PROP_INTERFACE_VERSION: priv->iface_version = g_value_get_uint (value); break; + case PROP_LOCAL_OBJECT: + priv->local_object = g_value_get_pointer (value); + break; case PROP_PW_PROXY: priv->pw_proxy = g_value_get_pointer (value); break; @@ -325,6 +354,9 @@ wp_proxy_get_property (GObject * object, guint property_id, GValue * value, case PROP_INTERFACE_VERSION: g_value_set_uint (value, priv->iface_version); break; + case PROP_LOCAL_OBJECT: + g_value_set_pointer (value, priv->local_object); + break; case PROP_PW_PROXY: g_value_set_pointer (value, priv->pw_proxy); break; @@ -429,6 +461,11 @@ wp_proxy_class_init (WpProxyClass * klass) "The pipewire interface version", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_LOCAL_OBJECT, + g_param_spec_pointer ("local-object", "local-object", + "The local object this proxy refers to, if any", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_PW_PROXY, g_param_spec_pointer ("pw-proxy", "pw-proxy", "The struct pw_proxy *", G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); @@ -463,8 +500,8 @@ wp_proxy_new_global (WpCore * core, WpGlobal * global) } WpProxy * -wp_proxy_new_wrap (WpCore * core, - struct pw_proxy * proxy, guint32 type, guint32 version) +wp_proxy_new_wrap (WpCore * core, struct pw_proxy * proxy, guint32 type, + guint32 version, gpointer local_object) { GType gtype = wp_proxy_find_instance_type (type, version); return g_object_new (gtype, @@ -472,6 +509,7 @@ wp_proxy_new_wrap (WpCore * core, "pw-proxy", proxy, "interface-type", type, "interface-version", version, + "local-object", local_object, NULL); } diff --git a/lib/wp/proxy.h b/lib/wp/proxy.h index 75eda4d58f4424748619a9f798655c2b8986e289..5408ab86affffcbdc3084f11b90c10214049f8a2 100644 --- a/lib/wp/proxy.h +++ b/lib/wp/proxy.h @@ -40,8 +40,8 @@ struct _WpProxyClass void (*pw_proxy_destroyed) (WpProxy * self); }; -WpProxy * wp_proxy_new_wrap (WpCore * core, - struct pw_proxy * proxy, guint32 type, guint32 version); +WpProxy * wp_proxy_new_wrap (WpCore * core, struct pw_proxy * proxy, + guint32 type, guint32 version, gpointer local_object); void wp_proxy_augment (WpProxy *self, WpProxyFeatures wanted_features, GCancellable * cancellable,