diff --git a/modules/module-config-policy/config-policy.c b/modules/module-config-policy/config-policy.c index 2158dbfa997edf2935702bb5d0a8ef40de6578cc..d6bad7f002bdbecc389c5a2b41bffe99ffa4a953 100644 --- a/modules/module-config-policy/config-policy.c +++ b/modules/module-config-policy/config-policy.c @@ -246,6 +246,34 @@ wp_config_policy_handle_endpoint (WpPolicy *policy, WpEndpoint *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) +{ + 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; + + /* 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; +} + static WpEndpoint * wp_config_policy_find_endpoint (WpPolicy *policy, GVariant *props, guint32 *stream_id) @@ -258,7 +286,7 @@ wp_config_policy_find_endpoint (WpPolicy *policy, GVariant *props, WpEndpoint *target = NULL; g_autoptr (WpProxy) proxy = NULL; g_autoptr (WpProperties) p = NULL; - const char *role = NULL, *target_role = NULL; + const char *role = NULL; /* Get the data from props */ g_variant_lookup (props, "data", "t", &data); @@ -287,11 +315,15 @@ wp_config_policy_find_endpoint (WpPolicy *policy, GVariant *props, /* Set the stream id */ if (stream_id) { - g_variant_lookup (props, "role", "&s", &role); - target_role = role ? role : data->te.stream; - *stream_id = target && target_role ? - wp_endpoint_find_stream (target, target_role) : - WP_CONTROL_ID_NONE; + 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_endpoint_find_stream (target, prioritized) : + WP_STREAM_ID_NONE; + } else { + *stream_id = WP_STREAM_ID_NONE; + } } return g_object_ref (target); diff --git a/modules/module-config-policy/parser-streams.c b/modules/module-config-policy/parser-streams.c index 46e7caf3ebec41f42381a951b1aab91876c5c74e..b1c718aa53484e1c8a66e9301e90b2b4ef20de74 100644 --- a/modules/module-config-policy/parser-streams.c +++ b/modules/module-config-policy/parser-streams.c @@ -31,6 +31,21 @@ wp_parser_streams_find_stream (const struct WpParserStreamsData *data, 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); diff --git a/modules/module-config-policy/parser-streams.h b/modules/module-config-policy/parser-streams.h index 79dba3242d441245df624f420bb5b4a2b7066a90..75c6209bf63844f0ea29ea347fb432e0823fa3ef 100644 --- a/modules/module-config-policy/parser-streams.h +++ b/modules/module-config-policy/parser-streams.h @@ -32,6 +32,8 @@ struct WpParserStreamsData { /* 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, diff --git a/tests/modules/config-policy.c b/tests/modules/config-policy.c index 5d6692c5fa1344d2bf2dc63b2288a81a1613dc38..9a1a9dd80e54311a3b615758066c96efadcdacda 100644 --- a/tests/modules/config-policy.c +++ b/tests/modules/config-policy.c @@ -370,48 +370,69 @@ playback_role (TestConfigPolicyFixture *f, gconstpointer data) g_autoptr (WpEndpointLink) link = NULL; g_autoptr (WpEndpoint) src = NULL; g_autoptr (WpEndpoint) sink = NULL; + g_autoptr (WpEndpoint) dev = NULL; g_autoptr (WpEndpoint) ep1 = NULL; g_autoptr (WpEndpoint) ep2 = NULL; g_autoptr (WpEndpoint) ep3 = NULL; /* Create the device with 2 roles: "0" with id 0, and "1" with id 1 */ - ep1 = wp_config_policy_context_add_endpoint (ctx, "ep1", "Fake/Sink", + dev = wp_config_policy_context_add_endpoint (ctx, "dev", "Fake/Sink", PW_DIRECTION_INPUT, NULL, NULL, 2, &link); - g_assert_nonnull (ep1); + g_assert_nonnull (dev); g_assert_null (link); - g_assert_false (wp_endpoint_is_linked (ep1)); + g_assert_false (wp_endpoint_is_linked (dev)); - /* Create the first client endpoint with role "0" and make sure it has - * priority over the one defined in the configuration file which is "1" */ - ep2 = wp_config_policy_context_add_endpoint (ctx, "ep2", "Stream/Output/Fake", + /* Create the first client endpoint with role "0" and make sure the role + * defined in the configuration file which is "1" is used */ + ep1 = wp_config_policy_context_add_endpoint (ctx, "ep1", "Stream/Output/Fake", PW_DIRECTION_OUTPUT, NULL, "0", 0, &link); + g_assert_nonnull (ep1); + g_assert_nonnull (link); + g_assert_true (wp_endpoint_is_linked (ep1)); + g_assert_true (wp_endpoint_is_linked (dev)); + src = wp_endpoint_link_get_source_endpoint (link); + sink = wp_endpoint_link_get_sink_endpoint (link); + g_assert_true (ep1 == src); + g_assert_true (dev == sink); + g_assert_true ( + WP_STREAM_ID_NONE == wp_endpoint_link_get_source_stream (link)); + g_assert_true (1 == wp_endpoint_link_get_sink_stream (link)); + wp_config_policy_context_remove_endpoint (ctx, ep1); + + /* Create the second client endpoint with role "1" and make sure it uses it + * because there is none defined in the configuration file */ + ep2 = wp_config_policy_context_add_endpoint (ctx, "ep2", "Stream/Output/Fake", + PW_DIRECTION_OUTPUT, NULL, "1", 0, &link); g_assert_nonnull (ep2); g_assert_nonnull (link); g_assert_true (wp_endpoint_is_linked (ep2)); - g_assert_true (wp_endpoint_is_linked (ep1)); + g_assert_true (wp_endpoint_is_linked (dev)); src = wp_endpoint_link_get_source_endpoint (link); sink = wp_endpoint_link_get_sink_endpoint (link); g_assert_true (ep2 == src); - g_assert_true (ep1 == sink); + g_assert_true (dev == sink); g_assert_true ( WP_STREAM_ID_NONE == wp_endpoint_link_get_source_stream (link)); - g_assert_true (0 == wp_endpoint_link_get_sink_stream (link)); + g_assert_true (1 == wp_endpoint_link_get_sink_stream (link)); + wp_config_policy_context_remove_endpoint (ctx, ep2); - /* Create the second client endpoint without role and make sure it uses - * the one defined in the configuration file which is "1" */ + /* Create the third client endpoint without role and make sure it uses the + * lowest priority on from the streams file because the endpoint-link file + * does not have any either */ ep3 = wp_config_policy_context_add_endpoint (ctx, "ep3", "Stream/Output/Fake", PW_DIRECTION_OUTPUT, NULL, NULL, 0, &link); g_assert_nonnull (ep3); g_assert_nonnull (link); g_assert_true (wp_endpoint_is_linked (ep3)); - g_assert_true (wp_endpoint_is_linked (ep1)); + g_assert_true (wp_endpoint_is_linked (dev)); src = wp_endpoint_link_get_source_endpoint (link); sink = wp_endpoint_link_get_sink_endpoint (link); g_assert_true (ep3 == src); - g_assert_true (ep1 == sink); + g_assert_true (dev == sink); g_assert_true ( WP_STREAM_ID_NONE == wp_endpoint_link_get_source_stream (link)); - g_assert_true (1 == wp_endpoint_link_get_sink_stream (link)); + g_assert_true (0 == wp_endpoint_link_get_sink_stream (link)); + wp_config_policy_context_remove_endpoint (ctx, ep3); } int diff --git a/tests/modules/config-policy/config-playback-role/3.streams b/tests/modules/config-policy/config-playback-role/3.streams new file mode 100644 index 0000000000000000000000000000000000000000..ce5d0317a41aa00b3124659a8ed781da540e745f --- /dev/null +++ b/tests/modules/config-policy/config-playback-role/3.streams @@ -0,0 +1,7 @@ +[[streams]] +name = "0" +priority = 0 + +[[streams]] +name = "1" +priority = 1 diff --git a/tests/modules/config-policy/config-playback-role/stream-output-fake.endpoint-link b/tests/modules/config-policy/config-playback-role/stream-output-fake-1.endpoint-link similarity index 92% rename from tests/modules/config-policy/config-playback-role/stream-output-fake.endpoint-link rename to tests/modules/config-policy/config-playback-role/stream-output-fake-1.endpoint-link index 2cf9f57fe83fe2479d334e00f11ad1ffb49e16fc..f323aec63862dc89712722da54d0568ebcbcb8a2 100644 --- a/tests/modules/config-policy/config-playback-role/stream-output-fake.endpoint-link +++ b/tests/modules/config-policy/config-playback-role/stream-output-fake-1.endpoint-link @@ -1,4 +1,5 @@ [match-endpoint] +name = "ep1" direction = "output" media_class = "Stream/Output/Fake" diff --git a/tests/modules/config-policy/config-playback-role/stream-output-fake-2.endpoint-link b/tests/modules/config-policy/config-playback-role/stream-output-fake-2.endpoint-link new file mode 100644 index 0000000000000000000000000000000000000000..2482472b9763980bfa09019259dbb93251a34973 --- /dev/null +++ b/tests/modules/config-policy/config-playback-role/stream-output-fake-2.endpoint-link @@ -0,0 +1,10 @@ +[match-endpoint] +name = "ep2" +direction = "output" +media_class = "Stream/Output/Fake" + +[target-endpoint] +media_class = "Fake/Sink" + +[endpoint-link] +keep = false diff --git a/tests/modules/config-policy/config-playback-role/stream-output-fake-3.endpoint-link b/tests/modules/config-policy/config-playback-role/stream-output-fake-3.endpoint-link new file mode 100644 index 0000000000000000000000000000000000000000..ccdcf8b9c3201a0c7ee64b97dd772bd755353493 --- /dev/null +++ b/tests/modules/config-policy/config-playback-role/stream-output-fake-3.endpoint-link @@ -0,0 +1,11 @@ +[match-endpoint] +name = "ep3" +direction = "output" +media_class = "Stream/Output/Fake" + +[target-endpoint] +media_class = "Fake/Sink" +streams = "3.streams" + +[endpoint-link] +keep = false