impl-node: implement WpPipewireObject
This fixes adjusting volume for bluetooth nodes. Previously, the spa device would request a software volume change that we did not handle because WpImplNode was not a WpPipewireObject and there was no way to set the Props param on it.
This commit is contained in:
106
lib/wp/node.c
106
lib/wp/node.c
@@ -519,8 +519,7 @@ void wp_node_send_command (WpNode * self, const gchar * command)
|
|||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_PW_IMPL_NODE = WP_PW_OBJECT_MIXIN_PROP_CUSTOM_START,
|
||||||
PROP_PW_IMPL_NODE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _WpImplNode
|
struct _WpImplNode
|
||||||
@@ -528,9 +527,11 @@ struct _WpImplNode
|
|||||||
WpProxy parent;
|
WpProxy parent;
|
||||||
GWeakRef core;
|
GWeakRef core;
|
||||||
struct pw_impl_node *pw_impl_node;
|
struct pw_impl_node *pw_impl_node;
|
||||||
struct pw_proxy *proxy;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void wp_impl_node_pw_object_mixin_priv_interface_init (
|
||||||
|
WpPwObjectMixinPrivInterface * iface);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WpImplNode:
|
* WpImplNode:
|
||||||
*
|
*
|
||||||
@@ -539,13 +540,50 @@ struct _WpImplNode
|
|||||||
* constructed `pw_impl_node`. This object can then be exported to PipeWire
|
* constructed `pw_impl_node`. This object can then be exported to PipeWire
|
||||||
* by requesting %WP_PROXY_FEATURE_BOUND.
|
* by requesting %WP_PROXY_FEATURE_BOUND.
|
||||||
*/
|
*/
|
||||||
G_DEFINE_TYPE (WpImplNode, wp_impl_node, WP_TYPE_PROXY)
|
G_DEFINE_TYPE_WITH_CODE (WpImplNode, wp_impl_node, WP_TYPE_PROXY,
|
||||||
|
G_IMPLEMENT_INTERFACE (WP_TYPE_PIPEWIRE_OBJECT,
|
||||||
|
wp_pw_object_mixin_object_interface_init)
|
||||||
|
G_IMPLEMENT_INTERFACE (WP_TYPE_PW_OBJECT_MIXIN_PRIV,
|
||||||
|
wp_impl_node_pw_object_mixin_priv_interface_init))
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wp_impl_node_init (WpImplNode * self)
|
wp_impl_node_init (WpImplNode * self)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wp_impl_node_constructed (GObject * object)
|
||||||
|
{
|
||||||
|
WpImplNode * self = WP_IMPL_NODE (object);
|
||||||
|
WpPwObjectMixinData * data = wp_pw_object_mixin_get_data (self);
|
||||||
|
|
||||||
|
data->info = (gpointer) pw_impl_node_get_info (self->pw_impl_node);
|
||||||
|
data->iface = pw_impl_node_get_implementation (self->pw_impl_node);
|
||||||
|
|
||||||
|
/* TODO handle the actual node properties */
|
||||||
|
data->properties = wp_properties_new_empty();
|
||||||
|
|
||||||
|
WpObjectFeatures ft =
|
||||||
|
wp_pw_object_mixin_get_supported_features (WP_OBJECT (self))
|
||||||
|
& ~WP_PROXY_FEATURE_BOUND;
|
||||||
|
wp_object_update_features (WP_OBJECT (self), ft, 0);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (wp_impl_node_parent_class)->constructed (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wp_impl_node_dispose (GObject * object)
|
||||||
|
{
|
||||||
|
WpImplNode *self = WP_IMPL_NODE (object);
|
||||||
|
|
||||||
|
WpObjectFeatures ft =
|
||||||
|
wp_pw_object_mixin_get_supported_features (WP_OBJECT (self))
|
||||||
|
& ~WP_PROXY_FEATURE_BOUND;
|
||||||
|
wp_object_update_features (WP_OBJECT (self), 0, ft);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (wp_impl_node_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wp_impl_node_finalize (GObject * object)
|
wp_impl_node_finalize (GObject * object)
|
||||||
{
|
{
|
||||||
@@ -583,17 +621,11 @@ wp_impl_node_get_property (GObject * object, guint property_id, GValue * value,
|
|||||||
g_value_set_pointer (value, self->pw_impl_node);
|
g_value_set_pointer (value, self->pw_impl_node);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
wp_pw_object_mixin_get_property (object, property_id, value, pspec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static WpObjectFeatures
|
|
||||||
wp_impl_node_get_supported_features (WpObject * object)
|
|
||||||
{
|
|
||||||
return WP_PROXY_FEATURE_BOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
STEP_EXPORT = WP_TRANSITION_STEP_CUSTOM_START,
|
STEP_EXPORT = WP_TRANSITION_STEP_CUSTOM_START,
|
||||||
};
|
};
|
||||||
@@ -603,8 +635,7 @@ wp_impl_node_activate_get_next_step (WpObject * object,
|
|||||||
WpFeatureActivationTransition * transition, guint step,
|
WpFeatureActivationTransition * transition, guint step,
|
||||||
WpObjectFeatures missing)
|
WpObjectFeatures missing)
|
||||||
{
|
{
|
||||||
/* we only support BOUND, so this is the only
|
/* BOUND is the only feature that can be in @missing */
|
||||||
feature that can be in @missing */
|
|
||||||
g_return_val_if_fail (missing == WP_PROXY_FEATURE_BOUND,
|
g_return_val_if_fail (missing == WP_PROXY_FEATURE_BOUND,
|
||||||
WP_TRANSITION_STEP_ERROR);
|
WP_TRANSITION_STEP_ERROR);
|
||||||
|
|
||||||
@@ -640,20 +671,67 @@ wp_impl_node_class_init (WpImplNodeClass * klass)
|
|||||||
GObjectClass *object_class = (GObjectClass *) klass;
|
GObjectClass *object_class = (GObjectClass *) klass;
|
||||||
WpObjectClass *wpobject_class = (WpObjectClass *) klass;
|
WpObjectClass *wpobject_class = (WpObjectClass *) klass;
|
||||||
|
|
||||||
|
object_class->constructed = wp_impl_node_constructed;
|
||||||
|
object_class->dispose = wp_impl_node_dispose;
|
||||||
object_class->finalize = wp_impl_node_finalize;
|
object_class->finalize = wp_impl_node_finalize;
|
||||||
object_class->set_property = wp_impl_node_set_property;
|
object_class->set_property = wp_impl_node_set_property;
|
||||||
object_class->get_property = wp_impl_node_get_property;
|
object_class->get_property = wp_impl_node_get_property;
|
||||||
|
|
||||||
wpobject_class->get_supported_features = wp_impl_node_get_supported_features;
|
wpobject_class->get_supported_features =
|
||||||
|
wp_pw_object_mixin_get_supported_features;
|
||||||
wpobject_class->activate_get_next_step = wp_impl_node_activate_get_next_step;
|
wpobject_class->activate_get_next_step = wp_impl_node_activate_get_next_step;
|
||||||
wpobject_class->activate_execute_step = wp_impl_node_activate_execute_step;
|
wpobject_class->activate_execute_step = wp_impl_node_activate_execute_step;
|
||||||
|
|
||||||
|
wp_pw_object_mixin_class_override_properties (object_class);
|
||||||
|
|
||||||
g_object_class_install_property (object_class, PROP_PW_IMPL_NODE,
|
g_object_class_install_property (object_class, PROP_PW_IMPL_NODE,
|
||||||
g_param_spec_pointer ("pw-impl-node", "pw-impl-node",
|
g_param_spec_pointer ("pw-impl-node", "pw-impl-node",
|
||||||
"The actual node implementation, struct pw_impl_node *",
|
"The actual node implementation, struct pw_impl_node *",
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
impl_node_collect_params (void *data, int seq,
|
||||||
|
uint32_t id, uint32_t index, uint32_t next, struct spa_pod *param)
|
||||||
|
{
|
||||||
|
GPtrArray *result = data;
|
||||||
|
g_ptr_array_add (result, wp_spa_pod_new_wrap_const (param));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GPtrArray *
|
||||||
|
wp_impl_node_enum_params_sync (gpointer instance, guint32 id,
|
||||||
|
guint32 start, guint32 num, WpSpaPod *filter)
|
||||||
|
{
|
||||||
|
WpImplNode *self = WP_IMPL_NODE (instance);
|
||||||
|
GPtrArray *result =
|
||||||
|
g_ptr_array_new_with_free_func ((GDestroyNotify) wp_spa_pod_unref);
|
||||||
|
|
||||||
|
pw_impl_node_for_each_param (self->pw_impl_node, 1, id, start, num,
|
||||||
|
filter ? wp_spa_pod_get_spa_pod (filter) : NULL,
|
||||||
|
impl_node_collect_params, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
wp_impl_node_set_param (gpointer instance, guint32 id, guint32 flags,
|
||||||
|
WpSpaPod * param)
|
||||||
|
{
|
||||||
|
WpPwObjectMixinData *d = wp_pw_object_mixin_get_data (instance);
|
||||||
|
return spa_node_set_param (d->iface, id, flags,
|
||||||
|
wp_spa_pod_get_spa_pod (param));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wp_impl_node_pw_object_mixin_priv_interface_init (
|
||||||
|
WpPwObjectMixinPrivInterface * iface)
|
||||||
|
{
|
||||||
|
wp_pw_object_mixin_priv_interface_info_init (iface, node, NODE);
|
||||||
|
iface->flags = WP_PW_OBJECT_MIXIN_PRIV_NO_PARAM_CACHE;
|
||||||
|
iface->enum_params_sync = wp_impl_node_enum_params_sync;
|
||||||
|
iface->set_param = wp_impl_node_set_param;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wp_impl_node_new_wrap:
|
* wp_impl_node_new_wrap:
|
||||||
* @core: the wireplumber core
|
* @core: the wireplumber core
|
||||||
|
Reference in New Issue
Block a user