Commit 8fdd99d9 authored by Julian Bouzas's avatar Julian Bouzas
Browse files

global-proxy: delay object creation until bound feature is requested

Allows handling errors if creation fails
parent b8030e13
......@@ -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);
}
......
......@@ -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;
......@@ -130,22 +142,71 @@ wp_global_proxy_activate_get_next_step (WpObject * object,
}
static void
wp_global_proxy_activate_execute_step (WpObject * object,
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);
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_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_INVALID_ARGUMENT,
"No global specified; cannot bind proxy"));
}
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)
{
switch (step) {
case STEP_BIND:
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));
}
......
......@@ -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);
}
/**
......
......@@ -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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment