diff --git a/lib/wp/device.c b/lib/wp/device.c index 02caa6e6..6271980c 100644 --- a/lib/wp/device.c +++ b/lib/wp/device.c @@ -182,20 +182,11 @@ wp_device_new_from_factory (WpCore * core, const gchar * factory_name, WpProperties * properties) { g_autoptr (WpProperties) props = properties; - WpDevice *self = NULL; - struct pw_core *pw_core = wp_core_get_pw_core (core); - - if (G_UNLIKELY (!pw_core)) { - g_critical ("The WirePlumber core is not connected; " - "device cannot be created"); - return NULL; - } - - self = g_object_new (WP_TYPE_DEVICE, "core", core, NULL); - wp_proxy_set_pw_proxy (WP_PROXY (self), pw_core_create_object (pw_core, - factory_name, PW_TYPE_INTERFACE_Device, PW_VERSION_DEVICE, - props ? wp_properties_peek_dict (props) : NULL, 0)); - return self; + return g_object_new (WP_TYPE_DEVICE, + "core", core, + "factory-name", factory_name, + "global-properties", props, + NULL); } diff --git a/lib/wp/global-proxy.c b/lib/wp/global-proxy.c index 3eefc73c..bc64b58b 100644 --- a/lib/wp/global-proxy.c +++ b/lib/wp/global-proxy.c @@ -22,13 +22,16 @@ typedef struct _WpGlobalProxyPrivate WpGlobalProxyPrivate; struct _WpGlobalProxyPrivate { WpGlobal *global; + gchar factory_name[96]; + WpProperties *properties; }; enum { PROP_0, PROP_GLOBAL, - PROP_PERMISSIONS, + PROP_FACTORY_NAME, PROP_GLOBAL_PROPERTIES, + PROP_PERMISSIONS, }; /** @@ -64,6 +67,7 @@ wp_global_proxy_finalize (GObject * object) WpGlobalProxyPrivate *priv = wp_global_proxy_get_instance_private (self); + g_clear_pointer (&priv->properties, wp_properties_unref); g_clear_pointer (&priv->global, wp_global_unref); G_OBJECT_CLASS (wp_global_proxy_parent_class)->finalize (object); @@ -81,6 +85,14 @@ wp_global_proxy_set_property (GObject * object, guint property_id, case PROP_GLOBAL: priv->global = g_value_dup_boxed (value); break; + case PROP_FACTORY_NAME: + priv->factory_name[0] = '\0'; + strncpy (priv->factory_name, g_value_get_string (value), + sizeof (priv->factory_name) - 1); + break; + case PROP_GLOBAL_PROPERTIES: + priv->properties = g_value_dup_boxed (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -129,23 +141,72 @@ wp_global_proxy_activate_get_next_step (WpObject * object, return STEP_BIND; } +static void +wp_global_proxy_step_bind (WpObject * object, + WpFeatureActivationTransition * transition, guint step, + WpObjectFeatures missing) +{ + WpProxyClass *proxy_klass = WP_PROXY_GET_CLASS (WP_PROXY (object)); + WpGlobalProxy *self = WP_GLOBAL_PROXY (object); + WpGlobalProxyPrivate *priv = wp_global_proxy_get_instance_private (self); + + wp_proxy_watch_bind_error (WP_PROXY (self), WP_TRANSITION (transition)); + + /* Create the pipewire object if global is NULL */ + if (priv->global == NULL && priv->factory_name[0] != '\0') { + g_autoptr (WpCore) core = NULL; + struct pw_core *pw_core = NULL; + struct pw_proxy * p = NULL; + + core = wp_object_get_core (WP_OBJECT (self)); + if (G_UNLIKELY (!core)) { + wp_transition_return_error (WP_TRANSITION (transition), g_error_new ( + WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED, + "The WirePlumber core is not valid; object cannot be created")); + return; + } + + pw_core = wp_core_get_pw_core (core); + if (G_UNLIKELY (!pw_core)) { + wp_transition_return_error (WP_TRANSITION (transition), g_error_new ( + WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED, + "The WirePlumber core is not connected; object cannot be created")); + return; + } + + p = pw_core_create_object (pw_core, priv->factory_name, + proxy_klass->pw_iface_type, proxy_klass->pw_iface_version, + priv->properties ? + wp_properties_peek_dict (priv->properties) : NULL, 0); + if (G_UNLIKELY (!p)) { + wp_transition_return_error (WP_TRANSITION (transition), g_error_new ( + WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED, + "Failed to create object with given factory name and properties")); + return; + } + + wp_proxy_set_pw_proxy (WP_PROXY (self), p); + } + + /* Bind */ + if (wp_proxy_get_pw_proxy (WP_PROXY (self)) == NULL) { + if (!wp_global_proxy_bind (self)) { + wp_transition_return_error (WP_TRANSITION (transition), g_error_new ( + WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT, + "No global specified; cannot bind proxy")); + } + } +} + + static void wp_global_proxy_activate_execute_step (WpObject * object, WpFeatureActivationTransition * transition, guint step, WpObjectFeatures missing) { - WpGlobalProxy *self = WP_GLOBAL_PROXY (object); - switch (step) { case STEP_BIND: - wp_proxy_watch_bind_error (WP_PROXY (self), WP_TRANSITION (transition)); - if (wp_proxy_get_pw_proxy (WP_PROXY (self)) == NULL) { - if (!wp_global_proxy_bind (self)) { - wp_transition_return_error (WP_TRANSITION (transition), g_error_new ( - WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT, - "No global specified; cannot bind proxy")); - } - } + wp_global_proxy_step_bind (object, transition, step, missing); break; case WP_TRANSITION_STEP_ERROR: break; @@ -165,7 +226,9 @@ wp_global_proxy_bound (WpProxy * proxy, guint32 global_id) if (!priv->global) { wp_registry_prepare_new_global (wp_core_get_registry (core), global_id, PW_PERM_ALL, WP_GLOBAL_FLAG_OWNED_BY_PROXY, - G_TYPE_FROM_INSTANCE (self), self, NULL, &priv->global); + G_TYPE_FROM_INSTANCE (self), self, + priv->properties ? wp_properties_peek_dict (priv->properties) : NULL, + &priv->global); } } @@ -206,14 +269,19 @@ wp_global_proxy_class_init (WpGlobalProxyClass * klass) wp_global_get_type (), G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (object_class, PROP_PERMISSIONS, - 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_FACTORY_NAME, + g_param_spec_string ("factory-name", "factory-name", + "The factory name", "", + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_GLOBAL_PROPERTIES, g_param_spec_boxed ("global-properties", "global-properties", "The pipewire global properties", WP_TYPE_PROPERTIES, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_PERMISSIONS, + g_param_spec_uint ("permissions", "permissions", + "The pipewire global permissions", 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); } diff --git a/lib/wp/link.c b/lib/wp/link.c index 070f2bec..a5223d62 100644 --- a/lib/wp/link.c +++ b/lib/wp/link.c @@ -141,19 +141,11 @@ wp_link_new_from_factory (WpCore * core, const gchar * factory_name, WpProperties * properties) { g_autoptr (WpProperties) props = properties; - WpLink *self = NULL; - struct pw_core *pw_core = wp_core_get_pw_core (core); - - if (G_UNLIKELY (!pw_core)) { - g_critical ("The WirePlumber core is not connected; link cannot be created"); - return NULL; - } - - self = g_object_new (WP_TYPE_LINK, "core", core, NULL); - wp_proxy_set_pw_proxy (WP_PROXY (self), pw_core_create_object (pw_core, - factory_name, PW_TYPE_INTERFACE_Link, PW_VERSION_LINK, - props ? wp_properties_peek_dict (props) : NULL, 0)); - return self; + return g_object_new (WP_TYPE_LINK, + "core", core, + "factory-name", factory_name, + "global-properties", props, + NULL); } /** diff --git a/lib/wp/node.c b/lib/wp/node.c index cfec16d0..07faa911 100644 --- a/lib/wp/node.c +++ b/lib/wp/node.c @@ -289,19 +289,11 @@ wp_node_new_from_factory (WpCore * core, const gchar * factory_name, WpProperties * properties) { g_autoptr (WpProperties) props = properties; - WpNode *self = NULL; - struct pw_core *pw_core = wp_core_get_pw_core (core); - - if (G_UNLIKELY (!pw_core)) { - g_critical ("The WirePlumber core is not connected; node cannot be created"); - return NULL; - } - - self = g_object_new (WP_TYPE_NODE, "core", core, NULL); - wp_proxy_set_pw_proxy (WP_PROXY (self), pw_core_create_object (pw_core, - factory_name, PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, - props ? wp_properties_peek_dict (props) : NULL, 0)); - return self; + return g_object_new (WP_TYPE_NODE, + "core", core, + "factory-name", factory_name, + "global-properties", props, + NULL); } WpNodeState