policy: add a hack that allows some clients to be linked always

This allows the bluealsa gstreamer helper to link to the speakers
constantly, with both A2DP and HFP streams. If this is not enabled,
only one of those will manage to connect, randomly.

This is definitely something to be superseeded by proper policy
management implemented with configuration files
This commit is contained in:
George Kiagiadakis 2019-10-04 22:04:22 +03:00
parent 22957e6e6d
commit 50db6a5930
2 changed files with 50 additions and 10 deletions

View file

@ -260,6 +260,7 @@ on_proxy_node_created(GObject *initable, GAsyncResult *res, gpointer data)
uint32_t ids[1] = { SPA_PARAM_Props };
uint32_t n_ids = 1;
struct pw_node_proxy *node_proxy = NULL;
const struct spa_dict *props;
/* Get the proxy node */
self->proxy_node = WP_PROXY_NODE (object_safe_new_finish (self, initable,
@ -267,11 +268,18 @@ on_proxy_node_created(GObject *initable, GAsyncResult *res, gpointer data)
if (!self->proxy_node)
return;
props = wp_proxy_node_get_info (self->proxy_node)->props;
/* Set the role and target name */
self->role = g_strdup (spa_dict_lookup (
wp_proxy_node_get_info (self->proxy_node)->props, "media.role"));
self->target = g_strdup (spa_dict_lookup (
wp_proxy_node_get_info (self->proxy_node)->props, "target.name"));
self->role = g_strdup (spa_dict_lookup (props, "media.role"));
self->target = g_strdup (spa_dict_lookup (props, "target.name"));
/* HACK to tell the policy module that this endpoint needs to be linked always */
if (spa_dict_lookup (props, "wireplumber.keep-linked")) {
g_autofree gchar *c = g_strdup_printf ("Persistent/%s",
spa_dict_lookup(props, "media.class"));
g_object_set (self, "media-class", c, NULL);
}
/* Emit the ports */
emit_endpoint_ports(self);

View file

@ -273,10 +273,12 @@ handle_client (WpPolicy *policy, WpEndpoint *ep)
g_autoptr (WpEndpoint) target = NULL;
guint32 stream_id;
gboolean is_capture = FALSE;
gboolean is_persistent = FALSE;
g_autofree gchar *role, *target_name = NULL;
/* Detect if the client is doing capture or playback */
is_capture = g_str_has_prefix (media_class, "Stream/Input");
is_persistent = g_str_has_prefix (media_class, "Persistent/");
/* Locate the target endpoint */
g_variant_dict_init (&d, NULL);
@ -334,11 +336,20 @@ handle_client (WpPolicy *policy, WpEndpoint *ep)
* this function is being called after sorting all the client endpoints
* and therefore we can safely unlink the previous client
*/
if (wp_endpoint_is_linked (target) && !is_capture) {
if (!is_capture && wp_endpoint_is_linked (target)) {
if (is_persistent) {
/* HACK: link persistent endpoints to the already linked stream,
as linking to another stream does not work properly
(floatmix on the master dsp port does not accept the link) */
GPtrArray *links = wp_endpoint_get_links (target);
WpEndpointLink *l = g_ptr_array_index (links, 0);
stream_id = wp_endpoint_link_get_sink_stream (l);
} else {
g_debug ("Unlink target '%s' from other clients",
wp_endpoint_get_name (target));
wp_endpoint_unlink (target);
}
}
/* Link the client with the target */
if (is_capture) {
@ -411,6 +422,17 @@ simple_policy_rescan_in_idle (WpSimplePolicy *self)
handle_client (WP_POLICY (self), ep);
}
}
g_clear_pointer (&endpoints, g_ptr_array_unref);
endpoints = wp_endpoint_find (core, "Persistent/Stream/Input/Audio");
if (endpoints) {
/* link all persistent capture clients */
for (i = 0; i < endpoints->len; i++) {
ep = g_ptr_array_index (endpoints, i);
handle_client (WP_POLICY (self), ep);
}
}
g_clear_pointer (&endpoints, g_ptr_array_unref);
endpoints = wp_endpoint_find (core, "Stream/Output/Audio");
if (endpoints && endpoints->len > 0) {
@ -422,6 +444,17 @@ simple_policy_rescan_in_idle (WpSimplePolicy *self)
ep = g_ptr_array_index (endpoints, 0);
handle_client (WP_POLICY (self), ep);
}
g_clear_pointer (&endpoints, g_ptr_array_unref);
endpoints = wp_endpoint_find (core, "Persistent/Stream/Output/Audio");
if (endpoints) {
/* link all persistent output clients */
for (i = 0; i < endpoints->len; i++) {
ep = g_ptr_array_index (endpoints, i);
handle_client (WP_POLICY (self), ep);
}
}
g_clear_pointer (&endpoints, g_ptr_array_unref);
self->pending_rescan = 0;
return G_SOURCE_REMOVE;
@ -443,8 +476,7 @@ simple_policy_handle_endpoint (WpPolicy *policy, WpEndpoint *ep)
/* TODO: For now we only accept audio stream clients */
media_class = wp_endpoint_get_media_class(ep);
if (!g_str_has_prefix (media_class, "Stream") ||
!g_str_has_suffix (media_class, "Audio")) {
if (!g_str_has_suffix (media_class, "Audio")) {
return FALSE;
}