Commit 3fe1e96e authored by Julian Bouzas's avatar Julian Bouzas
Browse files

config-policy: remove parsing of streams file

This is now done by the config endpoint module
parent acda80d7
......@@ -60,7 +60,6 @@ shared_library(
'wireplumber-module-config-policy',
[
'module-config-policy/parser-endpoint-link.c',
'module-config-policy/parser-streams.c',
'module-config-policy/config-policy.c',
'module-config-policy.c',
],
......
......@@ -14,7 +14,6 @@
#include "config-policy.h"
#include "parser-endpoint-link.h"
#include "parser-streams.h"
struct _WpConfigPolicy
{
......@@ -85,11 +84,6 @@ wp_config_policy_can_link_stream (WpConfigPolicy *self, WpBaseEndpoint *target,
const struct WpParserEndpointLinkData *data, guint32 stream_id)
{
g_autoptr (WpConfigParser) parser = NULL;
const struct WpParserStreamsData *streams_data = NULL;
/* If no streams data is specified, we can link */
if (!data->te.streams)
return TRUE;
/* If the endpoint is not linked, we can link */
if (!wp_base_endpoint_is_linked (target))
......@@ -123,34 +117,18 @@ wp_config_policy_can_link_stream (WpConfigPolicy *self, WpBaseEndpoint *target,
if (!g_variant_lookup (ts, "name", "&s", &target_stream_name))
return TRUE;
/* Get the linked and ep streams data */
parser = wp_configuration_get_parser (self->config,
WP_PARSER_STREAMS_EXTENSION);
streams_data = wp_config_parser_get_matched_data (parser, data->te.streams);
if (!streams_data)
return TRUE;
const struct WpParserStreamsStreamData *linked_stream_data =
wp_parser_streams_find_stream (streams_data, linked_stream_name);
const struct WpParserStreamsStreamData *ep_stream_data =
wp_parser_streams_find_stream (streams_data, target_stream_name);
/* Get the linked and ep streams priority */
guint linked_stream_priority = 0;
guint target_stream_priority = 0;
g_variant_lookup (s, "priority", "u", &linked_stream_priority);
g_variant_lookup (ts, "priority", "u", &target_stream_priority);
g_debug ("Trying to link to '%s' (%d); target is linked on '%s' (%d)",
target_stream_name, ep_stream_data ? ep_stream_data->priority : -1,
linked_stream_name, linked_stream_data ? linked_stream_data->priority : -1);
target_stream_name, target_stream_priority, linked_stream_name,
linked_stream_priority);
/* Return false if linked stream has higher priority than ep stream */
if (linked_stream_data && ep_stream_data) {
if (linked_stream_data->priority > ep_stream_data->priority)
return FALSE;
else
return TRUE;
}
if (linked_stream_data && !ep_stream_data)
return FALSE;
if (!linked_stream_data && ep_stream_data)
return TRUE;
return TRUE;
/* Return true if linked stream has lower priority than target stream */
return linked_stream_priority < target_stream_priority;
}
static gboolean
......@@ -267,32 +245,34 @@ wp_config_policy_handle_endpoint (WpPolicy *policy, WpBaseEndpoint *ep)
WP_STREAM_ID_NONE, target, stream_id, data);
}
static const char *
wp_config_policy_get_prioritized_stream (WpPolicy *policy,
const char *ep_stream, const char *te_stream, const char *te_streams)
static guint
wp_config_policy_get_endpoint_lowest_priority_stream_id (WpBaseEndpoint *ep)
{
WpConfigPolicy *self = WP_CONFIG_POLICY (policy);
/* The target stream has higher priority than the endpoint stream */
const char *res = te_stream ? te_stream : ep_stream;
if (res)
return res;
/* If both streams are null, and no streams file is defined, return NULL */
if (!te_streams)
return NULL;
g_autoptr (GVariant) streams = NULL;
g_autoptr (GVariant) child = NULL;
GVariantIter *iter;
guint lowest_priority = G_MAXUINT;
guint res = WP_STREAM_ID_NONE;
guint priority;
guint id;
g_return_val_if_fail (ep, WP_STREAM_ID_NONE);
streams = wp_base_endpoint_list_streams (ep);
g_return_val_if_fail (streams, WP_STREAM_ID_NONE);
g_variant_get (streams, "aa{sv}", &iter);
while ((child = g_variant_iter_next_value (iter))) {
g_variant_lookup (child, "id", "u", &id);
g_variant_lookup (child, "priority", "u", &priority);
if (priority <= lowest_priority) {
lowest_priority = priority;
res = id;
}
}
g_variant_iter_free (iter);
/* Otherwise get the lowest stream from streams */
g_autoptr (WpConfigParser) parser = NULL;
const struct WpParserStreamsData *streams = NULL;
const struct WpParserStreamsStreamData *lowest = NULL;
parser = wp_configuration_get_parser (self->config,
WP_PARSER_STREAMS_EXTENSION);
streams = wp_config_parser_get_matched_data (parser, (gpointer)te_streams);
if (!streams)
return NULL;
lowest = wp_parser_streams_get_lowest_stream (streams);
return lowest ? lowest->name : NULL;
return res;
}
static WpBaseEndpoint *
......@@ -338,10 +318,11 @@ wp_config_policy_find_endpoint (WpPolicy *policy, GVariant *props,
if (stream_id) {
if (target) {
g_variant_lookup (props, "role", "&s", &role);
const char *prioritized = wp_config_policy_get_prioritized_stream (policy,
role, data->te.stream, data->te.streams);
*stream_id = prioritized ? wp_base_endpoint_find_stream (target, prioritized) :
WP_STREAM_ID_NONE;
/* The target stream has higher priority than the endpoint stream */
const char *prioritized = data->te.stream ? data->te.stream : role;
*stream_id = prioritized ?
wp_base_endpoint_find_stream (target, prioritized) :
wp_config_policy_get_endpoint_lowest_priority_stream_id (target);
} else {
*stream_id = WP_STREAM_ID_NONE;
}
......@@ -469,12 +450,9 @@ wp_config_policy_constructed (GObject * object)
/* Add the parsers */
wp_configuration_add_extension (self->config,
WP_PARSER_ENDPOINT_LINK_EXTENSION, WP_TYPE_PARSER_ENDPOINT_LINK);
wp_configuration_add_extension (self->config,
WP_PARSER_STREAMS_EXTENSION, WP_TYPE_PARSER_STREAMS);
/* Parse the file */
wp_configuration_reload (self->config, WP_PARSER_ENDPOINT_LINK_EXTENSION);
wp_configuration_reload (self->config, WP_PARSER_STREAMS_EXTENSION);
G_OBJECT_CLASS (wp_config_policy_parent_class)->constructed (object);
}
......@@ -487,8 +465,6 @@ wp_config_policy_finalize (GObject *object)
/* Remove the extensions from the configuration */
wp_configuration_remove_extension (self->config,
WP_PARSER_ENDPOINT_LINK_EXTENSION);
wp_configuration_remove_extension (self->config,
WP_PARSER_STREAMS_EXTENSION);
/* Clear the configuration */
g_clear_object (&self->config);
......
......@@ -85,7 +85,6 @@ wp_parser_endpoint_link_data_destroy (gpointer p)
g_clear_pointer (&data->te.endpoint_data.name, g_free);
g_clear_pointer (&data->te.endpoint_data.media_class, g_free);
g_clear_pointer (&data->te.endpoint_data.props, wp_properties_unref);
g_clear_pointer (&data->te.streams, g_free);
g_clear_pointer (&data->te.stream, g_free);
g_clear_pointer (&data->el.state, g_free);
......@@ -221,9 +220,6 @@ wp_parser_endpoint_link_data_new (const gchar *location)
/* Get the target endpoint properties (Optional) */
res->te.endpoint_data.props = parse_properties (te, "properties");
/* Get the target endpoint streams */
res->te.streams = wp_toml_table_get_string (te, "streams");
/* Get the target endpoint stream */
res->te.stream = wp_toml_table_get_string (te, "stream");
......
......@@ -29,7 +29,6 @@ struct WpParserEndpointLinkData {
} me;
struct TargetEndpoint {
struct WpParserEndpointLinkEndpointData endpoint_data;
char *streams;
char *stream;
} te;
struct EndpointLink {
......
/* 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;
}
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#ifndef __WIREPLUMBER_PARSER_STREAMS_H__
#define __WIREPLUMBER_PARSER_STREAMS_H__
#include <wp/wp.h>
G_BEGIN_DECLS
#define WP_PARSER_STREAMS_EXTENSION "streams"
/* For simplicity, we limit the number of streams */
#define MAX_STREAMS 32
struct WpParserStreamsStreamData {
char *name;
guint priority;
};
struct WpParserStreamsData {
char *location;
struct WpParserStreamsStreamData streams[MAX_STREAMS];
guint n_streams;
};
/* Helpers */
const struct WpParserStreamsStreamData *wp_parser_streams_find_stream (
const struct WpParserStreamsData *data, const char *name);
const struct WpParserStreamsStreamData *wp_parser_streams_get_lowest_stream (
const struct WpParserStreamsData *data);
#define WP_TYPE_PARSER_STREAMS (wp_parser_streams_get_type ())
G_DECLARE_FINAL_TYPE (WpParserStreams, wp_parser_streams,
WP, PARSER_STREAMS, GObject);
G_END_DECLS
#endif
......@@ -6,7 +6,6 @@ media_class = "Stream/Input/Audio"
[target-endpoint]
media_class = "Audio/Source"
streams = "default.streams"
stream = "Multimedia"
properties = [
{ name = "api.alsa.path", value = "hw:0,0" },
......
......@@ -6,7 +6,6 @@ media_class = "Stream/Output/Audio"
[target-endpoint]
media_class = "Audio/Sink"
streams = "default.streams"
stream = "Multimedia"
properties = [
{ name = "api.alsa.path", value = "hw:0,0" },
......
......@@ -5,7 +5,6 @@ media_class = "Stream/Input/Audio"
[target-endpoint]
media_class = "Audio/Source"
streams = "default.streams"
properties = [
{ name = "api.alsa.path", value = "hw:0,0" },
]
......
......@@ -5,7 +5,6 @@ media_class = "Stream/Output/Audio"
[target-endpoint]
media_class = "Audio/Sink"
streams = "default.streams"
properties = [
{ name = "api.alsa.path", value = "hw:0,0" },
]
......
......@@ -273,7 +273,7 @@ playback_priority (TestConfigPolicyFixture *f, gconstpointer data)
g_assert_null (link);
g_assert_false (wp_base_endpoint_is_linked (dev));
/* Create the client endpoint for steam 2 (priority 50) and make sure it
/* Create the client endpoint for steam 2 (priority 2) and make sure it
* is linked */
ep2 = wp_config_policy_context_add_endpoint (ctx, "ep_for_stream_2",
"Stream/Output/Fake", PW_DIRECTION_OUTPUT, NULL, NULL, 0, &link);
......@@ -286,7 +286,7 @@ playback_priority (TestConfigPolicyFixture *f, gconstpointer data)
g_assert_true (ep2 == src);
g_assert_true (dev == sink);
/* Create the client endpoint for steam 1 (priority 25) and make sure it
/* Create the client endpoint for steam 1 (priority 1) and make sure it
* is not linked */
ep1 = wp_config_policy_context_add_endpoint (ctx, "ep_for_stream_1",
"Stream/Output/Fake", PW_DIRECTION_OUTPUT, NULL, NULL, 0, &link);
......@@ -296,7 +296,7 @@ playback_priority (TestConfigPolicyFixture *f, gconstpointer data)
g_assert_true (wp_base_endpoint_is_linked (ep2));
g_assert_true (wp_base_endpoint_is_linked (dev));
/* Create the client endpoint for steam 3 (priority 75) and make sure it
/* Create the client endpoint for steam 3 (priority 3) and make sure it
* is linked */
ep3 = wp_config_policy_context_add_endpoint (ctx, "ep_for_stream_3",
"Stream/Output/Fake", PW_DIRECTION_OUTPUT, NULL, NULL, 0, &link);
......@@ -315,7 +315,7 @@ playback_priority (TestConfigPolicyFixture *f, gconstpointer data)
wp_config_policy_context_remove_endpoint (ctx, ep2);
wp_config_policy_context_remove_endpoint (ctx, ep1);
/* Create the client endpoint with role "1" (priority 25) and make sure it
/* Create the client endpoint with role "1" (priority 1) and make sure it
* is not linked */
ep4 = wp_config_policy_context_add_endpoint (ctx, "ep_with_role",
"Stream/Output/Fake", PW_DIRECTION_OUTPUT, NULL, "1", 0, &link);
......@@ -323,7 +323,7 @@ playback_priority (TestConfigPolicyFixture *f, gconstpointer data)
g_assert_null (link);
g_assert_false (wp_base_endpoint_is_linked (ep4));
/* Create the client endpoint with role "3" (priority 75) and make sure it
/* Create the client endpoint with role "3" (priority 3) and make sure it
* is linked (last one wins) */
ep5 = wp_config_policy_context_add_endpoint (ctx, "ep_with_role",
"Stream/Output/Fake", PW_DIRECTION_OUTPUT, NULL, "3", 0, &link);
......
[[streams]]
name = "0"
priority = 0
[[streams]]
name = "1"
priority = 25
[[streams]]
name = "2"
priority = 50
[[streams]]
name = "3"
priority = 75
......@@ -5,7 +5,6 @@ media_class = "Stream/Output/Fake"
[target-endpoint]
media_class = "Fake/Sink"
streams = "default.streams"
stream = "1"
[endpoint-link]
......
......@@ -5,7 +5,6 @@ media_class = "Stream/Output/Fake"
[target-endpoint]
media_class = "Fake/Sink"
streams = "default.streams"
stream = "2"
[endpoint-link]
......
......@@ -5,7 +5,6 @@ media_class = "Stream/Output/Fake"
[target-endpoint]
media_class = "Fake/Sink"
streams = "default.streams"
stream = "3"
[endpoint-link]
......
[[streams]]
name = "0"
priority = 0
[[streams]]
name = "1"
priority = 1
......@@ -5,7 +5,6 @@ media_class = "Stream/Output/Fake"
[target-endpoint]
media_class = "Fake/Sink"
streams = "3.streams"
[endpoint-link]
keep = false
......@@ -76,6 +76,7 @@ wp_fake_endpoint_constructed (GObject * object)