Skip to content
Snippets Groups Projects
Commit cb1b3ebf authored by George Kiagiadakis's avatar George Kiagiadakis
Browse files

proxy: expose pw properties as a spa_dict and store them in a pw_properties

Exposing a spa_dict is necessary to allow using native pipewire API
that deals with these properties.

The internal structure change avoids mem copies when we need to
return a spa_dict.

This commits also removes exposing internal info structures via the
properties mechanism. This needs more thinking...
parent daa49af5
No related branches found
No related tags found
No related merge requests found
...@@ -218,3 +218,21 @@ wp_pipewire_properties_get (WpPipewireProperties * self, const gchar * key) ...@@ -218,3 +218,21 @@ wp_pipewire_properties_get (WpPipewireProperties * self, const gchar * key)
return iface->get (self, key); return iface->get (self, key);
} }
/**
* wp_pipewire_properties_get_as_spa_dict: (virtual get_as_spa_dict)
* @self: the interface
*
* Return: (transfer none): The underlying `struct spa_dict` that holds
* the properties
*/
const struct spa_dict *
wp_pipewire_properties_get_as_spa_dict (WpPipewireProperties * self)
{
WpPipewirePropertiesInterface *iface = WP_PIPEWIRE_PROPERTIES_GET_IFACE (self);
g_return_val_if_fail (WP_IS_PIPEWIRE_PROPERTIES (self), NULL);
g_return_val_if_fail (iface->get_as_spa_dict, NULL);
return iface->get_as_spa_dict (self);
}
...@@ -34,15 +34,20 @@ gboolean wp_object_attach_interface_impl (WpObject * self, gpointer impl, ...@@ -34,15 +34,20 @@ gboolean wp_object_attach_interface_impl (WpObject * self, gpointer impl,
G_DECLARE_INTERFACE (WpPipewireProperties, wp_pipewire_properties, G_DECLARE_INTERFACE (WpPipewireProperties, wp_pipewire_properties,
WP, PIPEWIRE_PROPERTIES, GObject) WP, PIPEWIRE_PROPERTIES, GObject)
struct spa_dict;
struct _WpPipewirePropertiesInterface struct _WpPipewirePropertiesInterface
{ {
GTypeInterface parent; GTypeInterface parent;
const gchar * (*get) (WpPipewireProperties * self, const gchar * key); const gchar * (*get) (WpPipewireProperties * self, const gchar * key);
const struct spa_dict * (*get_as_spa_dict) (WpPipewireProperties * self);
}; };
const gchar * wp_pipewire_properties_get (WpPipewireProperties * self, const gchar * wp_pipewire_properties_get (WpPipewireProperties * self,
const gchar * key); const gchar * key);
const struct spa_dict * wp_pipewire_properties_get_as_spa_dict (
WpPipewireProperties * self);
G_END_DECLS G_END_DECLS
......
...@@ -27,7 +27,7 @@ struct _WpProxy ...@@ -27,7 +27,7 @@ struct _WpProxy
union { union {
const struct spa_dict *initial_properties; const struct spa_dict *initial_properties;
GHashTable *properties; struct pw_properties *properties;
}; };
}; };
...@@ -56,65 +56,15 @@ G_DEFINE_TYPE_WITH_CODE (WpProxy, wp_proxy, WP_TYPE_OBJECT, ...@@ -56,65 +56,15 @@ G_DEFINE_TYPE_WITH_CODE (WpProxy, wp_proxy, WP_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (WP_TYPE_PIPEWIRE_PROPERTIES, wp_proxy_pw_properties_init); G_IMPLEMENT_INTERFACE (WP_TYPE_PIPEWIRE_PROPERTIES, wp_proxy_pw_properties_init);
) )
static void
spa_dict_to_hashtable (const struct spa_dict * dict, GHashTable * htable)
{
const struct spa_dict_item *item;
spa_dict_for_each (item, dict) {
g_hash_table_insert (htable,
GUINT_TO_POINTER (g_quark_from_string (item->key)),
g_strdup (item->value));
}
}
#define UPDATE_PROP(name, lvalue) \
{ \
static GQuark _quark = 0; \
if (!_quark) \
_quark = g_quark_from_static_string (name); \
g_hash_table_insert (self->properties, GUINT_TO_POINTER (_quark), lvalue); \
}
#define STATIC_PROP(name, lvalue) \
{ \
static GQuark _quark = 0; \
if (!_quark) \
_quark = g_quark_from_static_string (name); \
if (!g_hash_table_contains (self->properties, GUINT_TO_POINTER (_quark))) { \
g_hash_table_insert (self->properties, GUINT_TO_POINTER (_quark), lvalue); \
} \
}
static void static void
node_event_info (void *object, const struct pw_node_info *info) node_event_info (void *object, const struct pw_node_info *info)
{ {
WpProxy *self = WP_PROXY (object); WpProxy *self = WP_PROXY (object);
if (info->change_mask & PW_NODE_CHANGE_MASK_NAME) {
UPDATE_PROP ("node-info.name", g_strdup (info->name));
}
if (info->change_mask & PW_NODE_CHANGE_MASK_INPUT_PORTS) {
UPDATE_PROP ("node-info.n-input-ports",
g_strdup_printf ("%u", info->n_input_ports));
UPDATE_PROP ("node-info.max-input-ports",
g_strdup_printf ("%u", info->max_input_ports));
}
if (info->change_mask & PW_NODE_CHANGE_MASK_OUTPUT_PORTS) {
UPDATE_PROP ("node-info.n-output-ports",
g_strdup_printf ("%u", info->n_output_ports));
UPDATE_PROP ("node-info.max-output-ports",
g_strdup_printf ("%u", info->max_output_ports));
}
if (info->change_mask & PW_NODE_CHANGE_MASK_STATE) {
UPDATE_PROP ("node-info.state",
g_strdup (pw_node_state_as_string (info->state)));
UPDATE_PROP ("node-info.error", g_strdup (info->error));
}
if (info->change_mask & PW_NODE_CHANGE_MASK_PROPS) { if (info->change_mask & PW_NODE_CHANGE_MASK_PROPS) {
spa_dict_to_hashtable (info->props, self->properties); g_clear_pointer (&self->properties, pw_properties_free);
self->properties = pw_properties_new_dict (info->props);
} }
// TODO: PW_NODE_CHANGE_MASK_PARAMS
g_signal_emit (self, signals[SIGNAL_CHANGED], 0); g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
} }
...@@ -123,53 +73,14 @@ static const struct pw_node_proxy_events node_events = { ...@@ -123,53 +73,14 @@ static const struct pw_node_proxy_events node_events = {
.info = node_event_info .info = node_event_info
}; };
static void
port_event_info (void *object, const struct pw_port_info *info)
{
WpProxy *self = WP_PROXY (object);
STATIC_PROP ("port-info.direction",
g_strdup (pw_direction_as_string (info->direction)));
if (info->change_mask & PW_PORT_CHANGE_MASK_PROPS) {
spa_dict_to_hashtable (info->props, self->properties);
}
// TODO: PW_PORT_CHANGE_MASK_PARAMS
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
}
static const struct pw_port_proxy_events port_events = {
PW_VERSION_PORT_PROXY_EVENTS,
.info = port_event_info
};
static void static void
link_event_info (void *object, const struct pw_link_info *info) link_event_info (void *object, const struct pw_link_info *info)
{ {
WpProxy *self = WP_PROXY (object); WpProxy *self = WP_PROXY (object);
if (info->change_mask & PW_LINK_CHANGE_MASK_OUTPUT) {
UPDATE_PROP ("link-info.output-node-id",
g_strdup_printf ("%u", info->output_node_id));
UPDATE_PROP ("link-info.output-port-id",
g_strdup_printf ("%u", info->output_port_id));
}
if (info->change_mask & PW_LINK_CHANGE_MASK_INPUT) {
UPDATE_PROP ("link-info.input-node-id",
g_strdup_printf ("%u", info->input_node_id));
UPDATE_PROP ("link-info.input-port-id",
g_strdup_printf ("%u", info->input_port_id));
}
if (info->change_mask & PW_LINK_CHANGE_MASK_STATE) {
UPDATE_PROP ("link-info.state",
g_strdup (pw_link_state_as_string (info->state)));
UPDATE_PROP ("link-info.error", g_strdup (info->error));
}
//TODO: PW_LINK_CHANGE_MASK_FORMAT
if (info->change_mask & PW_LINK_CHANGE_MASK_PROPS) { if (info->change_mask & PW_LINK_CHANGE_MASK_PROPS) {
spa_dict_to_hashtable (info->props, self->properties); g_clear_pointer (&self->properties, pw_properties_free);
self->properties = pw_properties_new_dict (info->props);
} }
g_signal_emit (self, signals[SIGNAL_CHANGED], 0); g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
...@@ -186,7 +97,8 @@ client_event_info (void *object, const struct pw_client_info *info) ...@@ -186,7 +97,8 @@ client_event_info (void *object, const struct pw_client_info *info)
WpProxy *self = WP_PROXY (object); WpProxy *self = WP_PROXY (object);
if (info->change_mask & PW_CLIENT_CHANGE_MASK_PROPS) { if (info->change_mask & PW_CLIENT_CHANGE_MASK_PROPS) {
spa_dict_to_hashtable (info->props, self->properties); g_clear_pointer (&self->properties, pw_properties_free);
self->properties = pw_properties_new_dict (info->props);
} }
g_signal_emit (self, signals[SIGNAL_CHANGED], 0); g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
...@@ -202,12 +114,10 @@ device_event_info (void *object, const struct pw_device_info *info) ...@@ -202,12 +114,10 @@ device_event_info (void *object, const struct pw_device_info *info)
{ {
WpProxy *self = WP_PROXY (object); WpProxy *self = WP_PROXY (object);
STATIC_PROP ("device-info.name", g_strdup (info->name));
if (info->change_mask & PW_DEVICE_CHANGE_MASK_PROPS) { if (info->change_mask & PW_DEVICE_CHANGE_MASK_PROPS) {
spa_dict_to_hashtable (info->props, self->properties); g_clear_pointer (&self->properties, pw_properties_free);
self->properties = pw_properties_new_dict (info->props);
} }
//TODO: PW_DEVICE_CHANGE_MASK_PARAMS
g_signal_emit (self, signals[SIGNAL_CHANGED], 0); g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
} }
...@@ -243,7 +153,6 @@ wp_proxy_constructed (GObject * object) ...@@ -243,7 +153,6 @@ wp_proxy_constructed (GObject * object)
{ {
WpProxy *self = WP_PROXY (object); WpProxy *self = WP_PROXY (object);
g_autoptr (WpProxyRegistry) pr = NULL; g_autoptr (WpProxyRegistry) pr = NULL;
GHashTable *properties;
struct pw_registry_proxy *reg_proxy; struct pw_registry_proxy *reg_proxy;
const void *events = NULL; const void *events = NULL;
uint32_t ver = 0; uint32_t ver = 0;
...@@ -258,10 +167,6 @@ wp_proxy_constructed (GObject * object) ...@@ -258,10 +167,6 @@ wp_proxy_constructed (GObject * object)
events = &node_events; events = &node_events;
ver = PW_VERSION_NODE; ver = PW_VERSION_NODE;
break; break;
case PW_TYPE_INTERFACE_Port:
events = &port_events;
ver = PW_VERSION_PORT;
break;
case PW_TYPE_INTERFACE_Link: case PW_TYPE_INTERFACE_Link:
events = &link_events; events = &link_events;
ver = PW_VERSION_LINK; ver = PW_VERSION_LINK;
...@@ -293,13 +198,12 @@ wp_proxy_constructed (GObject * object) ...@@ -293,13 +198,12 @@ wp_proxy_constructed (GObject * object)
/* /*
* initial_properties is a stack-allocated const spa_dict * * initial_properties is a stack-allocated const spa_dict *
* that is not safe to access beyond the scope of the g_object_new() * that is not safe to access beyond the scope of the g_object_new()
* call, so we replace it with a GHashTable * call, so we replace it with a pw_properties
*/ */
properties = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, g_free);
if (self->initial_properties) if (self->initial_properties)
spa_dict_to_hashtable (self->initial_properties, properties); self->properties = pw_properties_new_dict (self->initial_properties);
self->properties = properties; else
self->properties = pw_properties_new (NULL);
G_OBJECT_CLASS (wp_proxy_parent_class)->constructed (object); G_OBJECT_CLASS (wp_proxy_parent_class)->constructed (object);
} }
...@@ -309,7 +213,7 @@ wp_proxy_finalize (GObject * object) ...@@ -309,7 +213,7 @@ wp_proxy_finalize (GObject * object)
{ {
WpProxy *self = WP_PROXY (object); WpProxy *self = WP_PROXY (object);
g_hash_table_unref (self->properties); g_clear_pointer (&self->properties, pw_properties_free);
g_clear_object (&self->core); g_clear_object (&self->core);
G_OBJECT_CLASS (wp_proxy_parent_class)->finalize (object); G_OBJECT_CLASS (wp_proxy_parent_class)->finalize (object);
...@@ -427,20 +331,25 @@ wp_proxy_class_init (WpProxyClass * klass) ...@@ -427,20 +331,25 @@ wp_proxy_class_init (WpProxyClass * klass)
G_TYPE_NONE, 0); G_TYPE_NONE, 0);
} }
const gchar * static const gchar *
wp_proxy_pw_properties_get (WpPipewireProperties * p, const gchar * property) wp_proxy_pw_properties_get (WpPipewireProperties * p, const gchar * property)
{ {
WpProxy * self = WP_PROXY (p); WpProxy * self = WP_PROXY (p);
GQuark quark = g_quark_try_string (property); return pw_properties_get (self->properties, property);
}
return quark ? static const struct spa_dict *
g_hash_table_lookup (self->properties, GUINT_TO_POINTER (quark)) : NULL; wp_proxy_pw_properties_get_as_spa_dict (WpPipewireProperties * p)
{
WpProxy * self = WP_PROXY (p);
return &self->properties->dict;
} }
static void static void
wp_proxy_pw_properties_init (WpPipewirePropertiesInterface * iface) wp_proxy_pw_properties_init (WpPipewirePropertiesInterface * iface)
{ {
iface->get = wp_proxy_pw_properties_get; iface->get = wp_proxy_pw_properties_get;
iface->get_as_spa_dict = wp_proxy_pw_properties_get_as_spa_dict;
} }
/** /**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment