mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-05 13:30:02 -05:00
media-session: don't try to link to the same link-group
Avoid linking streams to a node of the same link-group because that would be a circular link. Fixes #1360
This commit is contained in:
parent
c4971d17c4
commit
d1c6114423
1 changed files with 52 additions and 1 deletions
|
|
@ -439,6 +439,49 @@ static struct node *find_node_by_id_name(struct impl *impl, uint32_t id, const c
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool can_link_check(struct impl *impl, const char *link_group, struct node *target, int hops)
|
||||||
|
{
|
||||||
|
const char *g, *ng;
|
||||||
|
struct node *n;
|
||||||
|
|
||||||
|
if (hops == 8)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pw_log_debug("link group %s", link_group);
|
||||||
|
|
||||||
|
if (target->obj->info == NULL || target->obj->info->props == NULL)
|
||||||
|
return true;
|
||||||
|
g = spa_dict_lookup(target->obj->info->props, PW_KEY_NODE_LINK_GROUP);
|
||||||
|
if (g == NULL)
|
||||||
|
return true;
|
||||||
|
if (spa_streq(g, link_group))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
spa_list_for_each(n, &impl->node_list, link) {
|
||||||
|
if (n == target || n->direction != target->direction)
|
||||||
|
continue;
|
||||||
|
if (n->obj->info == NULL || n->obj->info->props == NULL)
|
||||||
|
return true;
|
||||||
|
ng = spa_dict_lookup(n->obj->info->props, PW_KEY_NODE_LINK_GROUP);
|
||||||
|
if (ng == NULL || !spa_streq(ng, g))
|
||||||
|
continue;
|
||||||
|
if (n->peer != NULL && !can_link_check(impl, link_group, n->peer, hops + 1))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool can_link(struct impl *impl, struct node *node, struct node *target)
|
||||||
|
{
|
||||||
|
const char *link_group;
|
||||||
|
|
||||||
|
link_group = spa_dict_lookup(node->obj->info->props, PW_KEY_NODE_LINK_GROUP);
|
||||||
|
if (link_group == NULL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return can_link_check(impl, link_group, target, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static const char *get_device_name(struct node *node)
|
static const char *get_device_name(struct node *node)
|
||||||
{
|
{
|
||||||
if (node->type != NODE_TYPE_DEVICE ||
|
if (node->type != NODE_TYPE_DEVICE ||
|
||||||
|
|
@ -508,6 +551,7 @@ struct find_data {
|
||||||
struct node *node;
|
struct node *node;
|
||||||
|
|
||||||
const char *media;
|
const char *media;
|
||||||
|
const char *link_group;
|
||||||
bool capture_sink;
|
bool capture_sink;
|
||||||
enum pw_direction direction;
|
enum pw_direction direction;
|
||||||
|
|
||||||
|
|
@ -545,6 +589,11 @@ static int find_node(void *data, struct node *node)
|
||||||
pw_log_debug(".. incompatible media %s <-> %s", node->media, find->media);
|
pw_log_debug(".. incompatible media %s <-> %s", node->media, find->media);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (find->link_group && !can_link_check(impl, find->link_group, node, 0)) {
|
||||||
|
pw_log_info(".. connecting link-group %s", find->link_group);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
plugged = node->plugged;
|
plugged = node->plugged;
|
||||||
priority = node->priority;
|
priority = node->priority;
|
||||||
|
|
||||||
|
|
@ -794,6 +843,7 @@ static int rescan_node(struct impl *impl, struct node *n)
|
||||||
find.capture_sink = n->capture_sink;
|
find.capture_sink = n->capture_sink;
|
||||||
find.direction = n->direction;
|
find.direction = n->direction;
|
||||||
find.exclusive = exclusive;
|
find.exclusive = exclusive;
|
||||||
|
find.link_group = n->peer == NULL ? spa_dict_lookup(props, PW_KEY_NODE_LINK_GROUP) : NULL;
|
||||||
|
|
||||||
/* we always honour the target node asked for by the client */
|
/* we always honour the target node asked for by the client */
|
||||||
path_id = SPA_ID_INVALID;
|
path_id = SPA_ID_INVALID;
|
||||||
|
|
@ -809,7 +859,8 @@ static int rescan_node(struct impl *impl, struct node *n)
|
||||||
spa_list_for_each(peer, &impl->node_list, link)
|
spa_list_for_each(peer, &impl->node_list, link)
|
||||||
find_node(&find, peer);
|
find_node(&find, peer);
|
||||||
|
|
||||||
if (follows_default && find.node != NULL && find.node != n->peer) {
|
if (follows_default && find.node != NULL &&
|
||||||
|
find.node != n->peer && can_link(impl, n, find.node)) {
|
||||||
pw_log_debug(NAME " %p: node %d follows default, changed (%d -> %d)", impl, n->id,
|
pw_log_debug(NAME " %p: node %d follows default, changed (%d -> %d)", impl, n->id,
|
||||||
n->peer->id, find.node->id);
|
n->peer->id, find.node->id);
|
||||||
unlink_nodes(n, n->peer);
|
unlink_nodes(n, n->peer);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue