mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2025-12-27 19:20:06 +01:00
The purpose of this change is to have a generic API that allows modules to read configuration data from files under a specific directory. Since we can have many types of configuration files, this new class maps file extensions with generic parsers defined in the modules, giving modules full freedom to parse any kind of data.
225 lines
5.7 KiB
C
225 lines
5.7 KiB
C
/* WirePlumber
|
|
*
|
|
* Copyright © 2019 Collabora Ltd.
|
|
* @author Julian Bouzas <julian.bouzas@collabora.com>
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "configuration.h"
|
|
#include "private.h"
|
|
|
|
struct _WpConfiguration
|
|
{
|
|
GObject parent;
|
|
|
|
GPtrArray *paths;
|
|
GHashTable *parsers;
|
|
};
|
|
|
|
G_DEFINE_INTERFACE (WpConfigParser, wp_config_parser, G_TYPE_OBJECT)
|
|
|
|
static void
|
|
wp_config_parser_default_init (WpConfigParserInterface *klass)
|
|
{
|
|
}
|
|
|
|
gboolean
|
|
wp_config_parser_add_file (WpConfigParser *self, const char *location)
|
|
{
|
|
g_return_val_if_fail (WP_IS_CONFIG_PARSER (self), FALSE);
|
|
g_return_val_if_fail (WP_CONFIG_PARSER_GET_IFACE (self)->add_file, FALSE);
|
|
|
|
return WP_CONFIG_PARSER_GET_IFACE (self)->add_file (self, location);
|
|
}
|
|
|
|
gconstpointer
|
|
wp_config_parser_get_matched_data (WpConfigParser *self, gpointer data)
|
|
{
|
|
g_return_val_if_fail (WP_IS_CONFIG_PARSER (self), NULL);
|
|
g_return_val_if_fail (WP_CONFIG_PARSER_GET_IFACE (self)->get_matched_data, NULL);
|
|
|
|
return WP_CONFIG_PARSER_GET_IFACE (self)->get_matched_data (self, data);
|
|
}
|
|
|
|
void
|
|
wp_config_parser_reset (WpConfigParser *self)
|
|
{
|
|
g_return_if_fail (WP_IS_CONFIG_PARSER (self));
|
|
g_return_if_fail (WP_CONFIG_PARSER_GET_IFACE (self)->reset);
|
|
|
|
WP_CONFIG_PARSER_GET_IFACE (self)->reset (self);
|
|
}
|
|
|
|
G_DEFINE_TYPE (WpConfiguration, wp_configuration, G_TYPE_OBJECT)
|
|
|
|
static void
|
|
wp_configuration_finalize (GObject * obj)
|
|
{
|
|
WpConfiguration * self = WP_CONFIGURATION (obj);
|
|
|
|
g_clear_pointer (&self->paths, g_ptr_array_unref);
|
|
g_clear_pointer (&self->parsers, g_hash_table_unref);
|
|
|
|
G_OBJECT_CLASS (wp_configuration_parent_class)->finalize (obj);
|
|
}
|
|
|
|
static void
|
|
wp_configuration_init (WpConfiguration * self)
|
|
{
|
|
self->paths = g_ptr_array_new_with_free_func (g_free);
|
|
self->parsers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
|
|
g_object_unref);
|
|
}
|
|
|
|
static void
|
|
wp_configuration_class_init (WpConfigurationClass * klass)
|
|
{
|
|
GObjectClass *object_class = (GObjectClass *) klass;
|
|
|
|
object_class->finalize = wp_configuration_finalize;
|
|
}
|
|
|
|
WpConfiguration *
|
|
wp_configuration_get_instance (WpCore *core)
|
|
{
|
|
WpConfiguration *self;
|
|
|
|
g_return_val_if_fail (WP_IS_CORE (core), NULL);
|
|
|
|
self = wp_core_find_object (core, (GEqualFunc) WP_IS_CONFIGURATION, NULL);
|
|
if (!self) {
|
|
self = g_object_new (WP_TYPE_CONFIGURATION, NULL);
|
|
wp_core_register_object (core, g_object_ref (self));
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
void
|
|
wp_configuration_add_path (WpConfiguration *self, const char *path)
|
|
{
|
|
guint i;
|
|
|
|
g_return_if_fail (self);
|
|
g_return_if_fail (WP_IS_CONFIGURATION (self));
|
|
|
|
/* Make sure the path is not already added */
|
|
for (i = 0; i < self->paths->len; i++) {
|
|
const char *p = g_ptr_array_index(self->paths, i);
|
|
if (g_strcmp0(p, path) == 0)
|
|
return;
|
|
}
|
|
|
|
g_ptr_array_add (self->paths, g_strdup (path));
|
|
}
|
|
|
|
void
|
|
wp_configuration_remove_path (WpConfiguration *self, const char *path)
|
|
{
|
|
guint i;
|
|
|
|
g_return_if_fail (self);
|
|
g_return_if_fail (WP_IS_CONFIGURATION (self));
|
|
|
|
/* Find the path index */
|
|
for (i = 0; i < self->paths->len; i++) {
|
|
const char *p = g_ptr_array_index(self->paths, i);
|
|
if (g_strcmp0(p, path) == 0)
|
|
break;
|
|
}
|
|
|
|
/* Only remove the path if the index is valid */
|
|
if (i < self->paths->len)
|
|
g_ptr_array_remove_index (self->paths, i);
|
|
}
|
|
|
|
gboolean
|
|
wp_configuration_add_extension (WpConfiguration *self, const gchar * extension,
|
|
GType parser_type)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (WP_IS_CONFIGURATION (self), FALSE);
|
|
|
|
/* create the parser */
|
|
g_autoptr (WpConfigParser) parser = g_object_new (parser_type, FALSE);
|
|
g_return_val_if_fail (WP_IS_CONFIG_PARSER (parser), FALSE);
|
|
|
|
return g_hash_table_insert (self->parsers, g_strdup (extension),
|
|
g_steal_pointer (&parser));
|
|
|
|
}
|
|
|
|
gboolean
|
|
wp_configuration_remove_extension (WpConfiguration *self,
|
|
const gchar * extension)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (WP_IS_CONFIGURATION (self), FALSE);
|
|
|
|
return g_hash_table_remove (self->parsers, extension);
|
|
}
|
|
|
|
WpConfigParser *
|
|
wp_configuration_get_parser (WpConfiguration *self, const char *extension)
|
|
{
|
|
WpConfigParser *parser = NULL;
|
|
|
|
g_return_val_if_fail (self, NULL);
|
|
g_return_val_if_fail (WP_IS_CONFIGURATION (self), NULL);
|
|
|
|
parser = g_hash_table_lookup (self->parsers, extension);
|
|
return parser ? g_object_ref (parser) : NULL;
|
|
}
|
|
|
|
void
|
|
wp_configuration_reload (WpConfiguration *self, const char *extension)
|
|
{
|
|
guint i;
|
|
const char *path = NULL;
|
|
GDir* conf_dir = NULL;
|
|
GError* error = NULL;
|
|
const gchar *file_name = NULL;
|
|
g_autofree gchar *ext = NULL;
|
|
g_autofree gchar *location = NULL;
|
|
|
|
g_return_if_fail (self);
|
|
g_return_if_fail (WP_IS_CONFIGURATION (self));
|
|
|
|
/* Get the parser for the extension */
|
|
WpConfigParser *parser = g_hash_table_lookup (self->parsers, extension);
|
|
if (!parser) {
|
|
g_warning ("Could not find parser for extension '%s'", extension);
|
|
return;
|
|
}
|
|
|
|
/* Reset the parser */
|
|
wp_config_parser_reset (parser);
|
|
|
|
/* Load extension files in all paths */
|
|
for (i = 0; i < self->paths->len; i++) {
|
|
/* Get the path */
|
|
path = g_ptr_array_index(self->paths, i);
|
|
|
|
/* Open the directory */
|
|
conf_dir = g_dir_open (path, 0, &error);
|
|
if (!conf_dir) {
|
|
g_warning ("Could not open configuration path '%s'", path);
|
|
continue;
|
|
}
|
|
|
|
/* Parse each configuration file matching the extension */
|
|
ext = g_strdup_printf (".%s", extension);
|
|
while ((file_name = g_dir_read_name (conf_dir))) {
|
|
/* Only parse files that have the proper extension */
|
|
if (g_str_has_suffix (file_name, ext)) {
|
|
location = g_build_filename (path, file_name, NULL);
|
|
if (!wp_config_parser_add_file (parser, location))
|
|
g_warning ("Failed to parse file '%s'", location);
|
|
}
|
|
}
|
|
|
|
/* Close the directory */
|
|
g_dir_close (conf_dir);
|
|
}
|
|
}
|