224 lines
5.2 KiB
C
224 lines
5.2 KiB
C
/* 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-streams.h"
|
|
|
|
struct _WpParserStreams
|
|
{
|
|
GObject parent;
|
|
|
|
GPtrArray *datas;
|
|
};
|
|
|
|
const struct WpParserStreamsStreamData *
|
|
wp_parser_streams_find_stream (const struct WpParserStreamsData *data,
|
|
const char *name)
|
|
{
|
|
for (guint i = 0; i < data->n_streams; i++) {
|
|
const struct WpParserStreamsStreamData *s = data->streams + i;
|
|
if (g_strcmp0 (s->name, name) == 0)
|
|
return s;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
const struct WpParserStreamsStreamData *
|
|
wp_parser_streams_get_lowest_stream (const struct WpParserStreamsData *data)
|
|
{
|
|
const struct WpParserStreamsStreamData *res = NULL;
|
|
guint lowest = G_MAXUINT;
|
|
for (guint i = 0; i < data->n_streams; i++) {
|
|
const struct WpParserStreamsStreamData *s = data->streams + i;
|
|
if (s->priority < lowest) {
|
|
lowest = s->priority;
|
|
res = s;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
static void wp_parser_streams_config_parser_init (gpointer iface,
|
|
gpointer iface_data);
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (WpParserStreams, wp_parser_streams,
|
|
G_TYPE_OBJECT,
|
|
G_IMPLEMENT_INTERFACE (WP_TYPE_CONFIG_PARSER,
|
|
wp_parser_streams_config_parser_init))
|
|
|
|
static void
|
|
wp_parser_streams_data_destroy (gpointer p)
|
|
{
|
|
struct WpParserStreamsData *data = p;
|
|
|
|
/* Clear the location */
|
|
g_clear_pointer (&data->location, g_free);
|
|
|
|
/* Clear the streams */
|
|
for (guint i = 0; i < data->n_streams; i++) {
|
|
struct WpParserStreamsStreamData *s = data->streams + i;
|
|
g_clear_pointer (&s->name, g_free);
|
|
}
|
|
data->n_streams = 0;
|
|
|
|
g_slice_free (struct WpParserStreamsData, data);
|
|
}
|
|
|
|
static void
|
|
streams_for_each (const WpTomlTable *table, gpointer user_data)
|
|
{
|
|
struct WpParserStreamsData *data = user_data;
|
|
struct WpParserStreamsStreamData *stream = NULL;
|
|
g_return_if_fail (data);
|
|
|
|
/* Make sure we don't parse more MAX_STREAMS streams */
|
|
if (data->n_streams >= MAX_STREAMS)
|
|
return;
|
|
|
|
/* Skip unparsed tables */
|
|
if (!table)
|
|
return;
|
|
|
|
/* Parse the mandatory name */
|
|
stream = data->streams + data->n_streams;
|
|
stream->name = wp_toml_table_get_string (table, "name");
|
|
if (!stream->name)
|
|
return;
|
|
|
|
/* Parse the optional priority */
|
|
stream->priority = 0;
|
|
wp_toml_table_get_uint32 (table, "priority", &stream->priority);
|
|
|
|
/* Increment the number of streams */
|
|
data->n_streams++;
|
|
}
|
|
|
|
|
|
static struct WpParserStreamsData *
|
|
wp_parser_streams_data_new (const gchar *location)
|
|
{
|
|
g_autoptr (WpTomlFile) file = NULL;
|
|
g_autoptr (WpTomlTable) table = NULL;
|
|
g_autoptr (WpTomlTableArray) streams = NULL;
|
|
struct WpParserStreamsData *res = NULL;
|
|
|
|
/* File format:
|
|
* ------------
|
|
* [[streams]]
|
|
* name (string)
|
|
* priority (uint32)
|
|
*/
|
|
|
|
/* 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 streams data */
|
|
res = g_slice_new0 (struct WpParserStreamsData);
|
|
|
|
/* Set the location */
|
|
res->location = g_strdup (location);
|
|
|
|
/* Parse the streams */
|
|
res->n_streams = 0;
|
|
streams = wp_toml_table_get_array_table (table, "streams");
|
|
if (streams)
|
|
wp_toml_table_array_for_each (streams, streams_for_each, res);
|
|
|
|
return res;
|
|
}
|
|
|
|
static gboolean
|
|
wp_parser_streams_add_file (WpConfigParser *parser,
|
|
const gchar *name)
|
|
{
|
|
WpParserStreams *self = WP_PARSER_STREAMS (parser);
|
|
struct WpParserStreamsData *data;
|
|
|
|
/* Parse the file */
|
|
data = wp_parser_streams_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);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gconstpointer
|
|
wp_parser_streams_get_matched_data (WpConfigParser *parser, gpointer data)
|
|
{
|
|
WpParserStreams *self = WP_PARSER_STREAMS (parser);
|
|
const char *location = data;
|
|
const struct WpParserStreamsData *d = NULL;
|
|
|
|
/* Find the first data that matches location */
|
|
for (guint i = 0; i < self->datas->len; i++) {
|
|
d = g_ptr_array_index(self->datas, i);
|
|
if (g_strrstr (d->location, location))
|
|
return d;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
wp_parser_streams_reset (WpConfigParser *parser)
|
|
{
|
|
WpParserStreams *self = WP_PARSER_STREAMS (parser);
|
|
|
|
g_ptr_array_set_size (self->datas, 0);
|
|
}
|
|
|
|
static void
|
|
wp_parser_streams_config_parser_init (gpointer iface,
|
|
gpointer iface_data)
|
|
{
|
|
WpConfigParserInterface *cp_iface = iface;
|
|
|
|
cp_iface->add_file = wp_parser_streams_add_file;
|
|
cp_iface->get_matched_data = wp_parser_streams_get_matched_data;
|
|
cp_iface->reset = wp_parser_streams_reset;
|
|
}
|
|
|
|
static void
|
|
wp_parser_streams_finalize (GObject * object)
|
|
{
|
|
WpParserStreams *self = WP_PARSER_STREAMS (object);
|
|
|
|
g_clear_pointer (&self->datas, g_ptr_array_unref);
|
|
|
|
G_OBJECT_CLASS (wp_parser_streams_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
wp_parser_streams_init (WpParserStreams * self)
|
|
{
|
|
self->datas = g_ptr_array_new_with_free_func (wp_parser_streams_data_destroy);
|
|
}
|
|
|
|
static void
|
|
wp_parser_streams_class_init (WpParserStreamsClass * klass)
|
|
{
|
|
GObjectClass *object_class = (GObjectClass *) klass;
|
|
|
|
object_class->finalize = wp_parser_streams_finalize;
|
|
}
|