modules: rename config-static-nodes to config-static-objects

This commit is contained in:
Julian Bouzas
2020-06-02 09:54:06 -04:00
parent a3cf986188
commit d3cb1bd84d
11 changed files with 78 additions and 77 deletions

View File

@@ -0,0 +1,187 @@
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#include <wp/wp.h>
#include "parser-node.h"
#include "context.h"
struct _WpConfigStaticObjectsContext
{
GObject parent;
WpObjectManager *devices_om;
GPtrArray *static_objects;
};
enum {
SIGNAL_OBJECT_CREATED,
N_SIGNALS
};
static guint signals[N_SIGNALS];
G_DEFINE_TYPE (WpConfigStaticObjectsContext, wp_config_static_objects_context,
WP_TYPE_PLUGIN)
static void
on_object_created (GObject * proxy, GAsyncResult * res, gpointer user_data)
{
WpConfigStaticObjectsContext *self = user_data;
g_autoptr (GError) error = NULL;
if (!wp_proxy_augment_finish (WP_PROXY (proxy), res, &error)) {
wp_warning_object (self, "failed to export object: %s", error->message);
return;
}
g_ptr_array_add (self->static_objects, g_object_ref (proxy));
/* Emit the node-created signal */
g_signal_emit (self, signals[SIGNAL_OBJECT_CREATED], 0, proxy);
}
static void
wp_config_static_objects_context_create_node (WpConfigStaticObjectsContext *self,
const struct WpParserNodeData *node_data)
{
g_autoptr (WpProxy) node = NULL;
g_autoptr (WpCore) core = wp_plugin_get_core (WP_PLUGIN (self));
g_return_if_fail (core);
/* Create the node */
node = node_data->n.local ?
(WpProxy *) wp_impl_node_new_from_pw_factory (core, node_data->n.factory,
wp_properties_ref (node_data->n.props)) :
(WpProxy *) wp_node_new_from_factory (core, node_data->n.factory,
wp_properties_ref (node_data->n.props));
if (!node) {
wp_warning_object (self, "failed to create node");
return;
}
/* export */
wp_proxy_augment (node, WP_PROXY_FEATURES_STANDARD, NULL, on_object_created,
self);
}
static void
on_device_added (WpObjectManager *om, WpProxy *proxy, gpointer p)
{
WpConfigStaticObjectsContext *self = p;
g_autoptr (WpProperties) dev_props = NULL;
g_autoptr (WpCore) core = wp_plugin_get_core (WP_PLUGIN (self));
g_autoptr (WpConfiguration) config = wp_configuration_get_instance (core);
g_autoptr (WpConfigParser) parser = NULL;
const struct WpParserNodeData *node_data = NULL;
/* Skip devices without info feature */
if ((wp_proxy_get_features(proxy) & WP_PROXY_FEATURE_INFO) == 0)
return;
/* Get the device properties */
dev_props = wp_proxy_get_properties (proxy);
g_return_if_fail (dev_props);
/* Get the parser node data and skip the node if not found */
parser = wp_configuration_get_parser (config, WP_PARSER_NODE_EXTENSION);
node_data = wp_config_parser_get_matched_data (parser, dev_props);
if (!node_data)
return;
/* Create the node */
wp_config_static_objects_context_create_node (self, node_data);
}
static gboolean
parser_node_foreach_func (const struct WpParserNodeData *node_data,
gpointer data)
{
WpConfigStaticObjectsContext *self = data;
/* Only create nodes that don't have match-device info */
if (!node_data->has_md) {
wp_config_static_objects_context_create_node (self, node_data);
return TRUE;
}
return TRUE;
}
static void
wp_config_static_objects_context_activate (WpPlugin * plugin)
{
WpConfigStaticObjectsContext *self = WP_CONFIG_STATIC_OBJECTS_CONTEXT (plugin);
g_autoptr (WpCore) core = wp_plugin_get_core (plugin);
g_autoptr (WpConfiguration) config = wp_configuration_get_instance (core);
g_autoptr (WpConfigParser) parser = NULL;
/* Add the node parser and parse the node files */
wp_configuration_add_extension (config, WP_PARSER_NODE_EXTENSION,
WP_TYPE_PARSER_NODE);
wp_configuration_reload (config, WP_PARSER_NODE_EXTENSION);
/* Install the object manager */
wp_core_install_object_manager (core, self->devices_om);
/* Create static nodes without match-device */
parser = wp_configuration_get_parser (config, WP_PARSER_NODE_EXTENSION);
wp_parser_node_foreach (WP_PARSER_NODE (parser), parser_node_foreach_func,
self);
}
static void
wp_config_static_objects_context_deactivate (WpPlugin *plugin)
{
WpConfigStaticObjectsContext *self = WP_CONFIG_STATIC_OBJECTS_CONTEXT (plugin);
g_clear_object (&self->devices_om);
g_clear_pointer (&self->static_objects, g_ptr_array_unref);
g_autoptr (WpCore) core = wp_plugin_get_core (plugin);
if (core) {
g_autoptr (WpConfiguration) config = wp_configuration_get_instance (core);
wp_configuration_remove_extension (config, WP_PARSER_NODE_EXTENSION);
}
}
static void
wp_config_static_objects_context_init (WpConfigStaticObjectsContext *self)
{
self->static_objects = g_ptr_array_new_with_free_func (g_object_unref);
self->devices_om = wp_object_manager_new ();
/* Only handle devices */
wp_object_manager_add_interest (self->devices_om, WP_TYPE_DEVICE, NULL);
wp_object_manager_request_proxy_features (self->devices_om, WP_TYPE_DEVICE,
WP_PROXY_FEATURE_INFO);
g_signal_connect (self->devices_om, "object-added",
(GCallback) on_device_added, self);
}
static void
wp_config_static_objects_context_class_init (WpConfigStaticObjectsContextClass *klass)
{
WpPluginClass *plugin_class = (WpPluginClass *) klass;
plugin_class->activate = wp_config_static_objects_context_activate;
plugin_class->deactivate = wp_config_static_objects_context_deactivate;
/* Signals */
signals[SIGNAL_OBJECT_CREATED] = g_signal_new ("object-created",
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
G_TYPE_NONE, 1, WP_TYPE_PROXY);
}
WpConfigStaticObjectsContext *
wp_config_static_objects_context_new (WpModule * module)
{
return g_object_new (wp_config_static_objects_context_get_type (),
"module", module,
NULL);
}

View File

@@ -0,0 +1,24 @@
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#ifndef __WIREPLUMBER_CONFIG_STATIC_OBJECTS_CONTEXT_H__
#define __WIREPLUMBER_CONFIG_STATIC_OBJECTS_CONTEXT_H__
#include <wp/wp.h>
G_BEGIN_DECLS
#define WP_TYPE_CONFIG_STATIC_OBJECTS_CONTEXT (wp_config_static_objects_context_get_type ())
G_DECLARE_FINAL_TYPE (WpConfigStaticObjectsContext, wp_config_static_objects_context,
WP, CONFIG_STATIC_OBJECTS_CONTEXT, WpPlugin);
WpConfigStaticObjectsContext * wp_config_static_objects_context_new (WpModule * module);
G_END_DECLS
#endif

View File

@@ -0,0 +1,247 @@
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#include <wptoml/wptoml.h>
#include <pipewire/pipewire.h>
#include "parser-node.h"
struct _WpParserNode
{
GObject parent;
GPtrArray *datas;
};
static void wp_parser_node_config_parser_init (gpointer iface,
gpointer iface_data);
G_DEFINE_TYPE_WITH_CODE (WpParserNode, wp_parser_node,
G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (WP_TYPE_CONFIG_PARSER,
wp_parser_node_config_parser_init))
static void
wp_parser_node_data_destroy (gpointer p)
{
struct WpParserNodeData *data = p;
/* Free the strings */
g_clear_pointer (&data->md.props, wp_properties_unref);
g_clear_pointer (&data->n.factory, g_free);
g_clear_pointer (&data->n.props, wp_properties_unref);
g_slice_free (struct WpParserNodeData, data);
}
static void
parse_properties_for_each (const WpTomlTable *table, gpointer user_data)
{
WpProperties *props = user_data;
g_return_if_fail (props);
/* Skip unparsed tables */
if (!table)
return;
/* Parse the name and value */
g_autofree gchar *name = wp_toml_table_get_string (table, "name");
g_autofree gchar *value = wp_toml_table_get_string (table, "value");
/* Set the property */
if (name && value)
wp_properties_set (props, name, value);
}
static WpProperties *
parse_properties (WpTomlTable *table, const char *name)
{
WpProperties *props = wp_properties_new_empty ();
g_autoptr (WpTomlTableArray) properties = NULL;
properties = wp_toml_table_get_array_table (table, name);
if (properties)
wp_toml_table_array_for_each (properties, parse_properties_for_each, props);
return props;
}
static struct WpParserNodeData *
wp_parser_node_data_new (const gchar *location)
{
g_autoptr (WpTomlFile) file = NULL;
g_autoptr (WpTomlTable) table = NULL, md = NULL, n = NULL;
struct WpParserNodeData *res = NULL;
/* File format:
* ------------
* [match-device]
* priority (uint32)
* properties (WpProperties)
*
* [node]
* factory (string)
* local (boolean)
* properties (WpProperties)
*/
/* Get the TOML file */
file = wp_toml_file_new (location);
if (!file)
return NULL;
/* Get the file table */
table = wp_toml_file_get_table (file);
if (!table)
return NULL;
/* Create the node data */
res = g_slice_new0(struct WpParserNodeData);
/* Get the match-device table */
res->has_md = FALSE;
md = wp_toml_table_get_table (table, "match-device");
if (md) {
res->has_md = TRUE;
/* Get the priority from the match-device table */
res->md.priority = 0;
wp_toml_table_get_uint32 (md, "priority", &res->md.priority);
/* Get the match device properties */
res->md.props = parse_properties (md, "properties");
}
/* Get the node table */
n = wp_toml_table_get_table (table, "node");
if (!n)
goto error;
/* Get factory from the node table */
res->n.factory = wp_toml_table_get_string (n, "factory");
/* Get local from the node table */
res->n.local = FALSE;
wp_toml_table_get_boolean (n, "local", &res->n.local);
/* Get the node properties */
res->n.props = parse_properties (n, "properties");
return res;
error:
g_clear_pointer (&res, wp_parser_node_data_destroy);
return NULL;
}
static gint
compare_datas_func (gconstpointer a, gconstpointer b)
{
struct WpParserNodeData *da = *(struct WpParserNodeData *const *)a;
struct WpParserNodeData *db = *(struct WpParserNodeData *const *)b;
return db->md.priority - da->md.priority;
}
static gboolean
wp_parser_node_add_file (WpConfigParser *parser,
const gchar *name)
{
WpParserNode *self = WP_PARSER_NODE (parser);
struct WpParserNodeData *data;
/* Parse the file */
data = wp_parser_node_data_new (name);
if (!data) {
g_warning ("Failed to parse configuration file '%s'", name);
return FALSE;
}
/* Add the data to the array */
g_ptr_array_add(self->datas, data);
/* Sort the array by priority */
g_ptr_array_sort(self->datas, compare_datas_func);
return TRUE;
}
static gconstpointer
wp_parser_node_get_matched_data (WpConfigParser *parser, gpointer data)
{
WpParserNode *self = WP_PARSER_NODE (parser);
WpProperties *props = data;
const struct WpParserNodeData *d = NULL;
g_return_val_if_fail (props, NULL);
/* Find the first data that matches device properties */
for (guint i = 0; i < self->datas->len; i++) {
d = g_ptr_array_index(self->datas, i);
if (d->has_md && wp_properties_matches (props, d->md.props))
return d;
}
return NULL;
}
static void
wp_parser_node_reset (WpConfigParser *parser)
{
WpParserNode *self = WP_PARSER_NODE (parser);
g_ptr_array_set_size (self->datas, 0);
}
static void
wp_parser_node_config_parser_init (gpointer iface, gpointer iface_data)
{
WpConfigParserInterface *cp_iface = iface;
cp_iface->add_file = wp_parser_node_add_file;
cp_iface->get_matched_data = wp_parser_node_get_matched_data;
cp_iface->reset = wp_parser_node_reset;
}
static void
wp_parser_node_finalize (GObject * object)
{
WpParserNode *self = WP_PARSER_NODE (object);
g_clear_pointer (&self->datas, g_ptr_array_unref);
G_OBJECT_CLASS (wp_parser_node_parent_class)->finalize (object);
}
static void
wp_parser_node_init (WpParserNode * self)
{
self->datas = g_ptr_array_new_with_free_func (wp_parser_node_data_destroy);
}
static void
wp_parser_node_class_init (WpParserNodeClass * klass)
{
GObjectClass *object_class = (GObjectClass *) klass;
object_class->finalize = wp_parser_node_finalize;
}
void
wp_parser_node_foreach (WpParserNode *self, WpParserNodeForeachFunction f,
gpointer data)
{
const struct WpParserNodeData *d;
for (guint i = 0; i < self->datas->len; i++) {
d = g_ptr_array_index(self->datas, i);
if (!f (d, data))
break;
}
}

View File

@@ -0,0 +1,41 @@
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#ifndef __WIREPLUMBER_PARSER_NODE_H__
#define __WIREPLUMBER_PARSER_NODE_H__
#include <wp/wp.h>
G_BEGIN_DECLS
#define WP_PARSER_NODE_EXTENSION "node"
struct WpParserNodeData {
struct MatchDevice {
guint priority;
WpProperties *props;
} md;
gboolean has_md;
struct Node {
char *factory;
gboolean local;
WpProperties *props;
} n;
};
#define WP_TYPE_PARSER_NODE (wp_parser_node_get_type ())
G_DECLARE_FINAL_TYPE (WpParserNode, wp_parser_node, WP, PARSER_NODE, GObject)
typedef gboolean (*WpParserNodeForeachFunction) (
const struct WpParserNodeData *parser_data, gpointer data);
void wp_parser_node_foreach (WpParserNode *self, WpParserNodeForeachFunction f,
gpointer data);
G_END_DECLS
#endif