From e6c0014f94e995e49b72bea7ae56b960416e6b29 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 1 Jul 2024 14:50:34 +0200 Subject: [PATCH 3/5] context: Fix node collect with groups and sync enabled Keep track of the sync nodes we added to a driver and bring in the other nodes from the same sync group, group or link groups. This makes it possible to have disjoint sync groups each with their own driver. Fixes export in ardour8 Fixes #4083 --- src/pipewire/context.c | 49 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/pipewire/context.c b/src/pipewire/context.c index 686dd5eee..f3e1b4d76 100644 --- a/src/pipewire/context.c +++ b/src/pipewire/context.c @@ -1163,13 +1163,14 @@ static inline int run_nodes(struct pw_context *context, struct pw_impl_node *nod * This ensures that we only activate the paths from the runnable nodes to the * driver nodes and leave the other nodes idle. */ -static int collect_nodes(struct pw_context *context, struct pw_impl_node *node, struct spa_list *collect, - char **sync) +static int collect_nodes(struct pw_context *context, struct pw_impl_node *node, struct spa_list *collect) { struct spa_list queue; struct pw_impl_node *n, *t; struct pw_impl_port *p; struct pw_impl_link *l; + uint32_t n_sync; + char *sync[MAX_SYNC+1]; pw_log_debug("node %p: '%s'", node, node->name); @@ -1178,20 +1179,30 @@ static int collect_nodes(struct pw_context *context, struct pw_impl_node *node, spa_list_append(&queue, &node->sort_link); node->visited = true; + n_sync = 0; + sync[0] = NULL; + /* now follow all the links from the nodes in the queue * and add the peers to the queue. */ spa_list_consume(n, &queue, sort_link) { spa_list_remove(&n->sort_link); spa_list_append(collect, &n->sort_link); - pw_log_debug(" next node %p: '%s' runnable:%u", n, n->name, n->runnable); + pw_log_debug(" next node %p: '%s' runnable:%u active:%d", + n, n->name, n->runnable, n->active); if (!n->active) continue; - if (sync[0] != NULL) { - if (pw_strv_find_common(n->sync_groups, sync) < 0) - continue; + if (n->sync) { + for (uint32_t i = 0; n->sync_groups[i]; i++) { + if (n_sync >= MAX_SYNC) + break; + if (pw_strv_find(sync, n->sync_groups[i]) >= 0) + continue; + sync[n_sync++] = n->sync_groups[i]; + sync[n_sync] = NULL; + } } spa_list_for_each(p, &n->input_ports, link) { @@ -1242,6 +1253,8 @@ static int collect_nodes(struct pw_context *context, struct pw_impl_node *node, spa_list_for_each(t, &context->node_list, link) { if (t->exported || !t->active || t->visited) continue; + /* the other node will be scheduled with this one if it's in + * the same group or link group */ if (pw_strv_find_common(t->groups, n->groups) < 0 && pw_strv_find_common(t->link_groups, n->link_groups) < 0 && pw_strv_find_common(t->sync_groups, sync) < 0) @@ -1253,7 +1266,8 @@ static int collect_nodes(struct pw_context *context, struct pw_impl_node *node, spa_list_append(&queue, &t->sort_link); } } - pw_log_debug(" next node %p: '%s' runnable:%u", n, n->name, n->runnable); + pw_log_debug(" next node %p: '%s' runnable:%u %p %p %p", n, n->name, n->runnable, + n->groups, n->link_groups, sync); } spa_list_for_each(n, collect, sort_link) if (!n->driving && n->runnable) { @@ -1497,10 +1511,9 @@ int pw_context_recalc_graph(struct pw_context *context, const char *reason) struct pw_impl_node *n, *s, *target, *fallback; const uint32_t *rates; uint32_t max_quantum, min_quantum, def_quantum, rate_quantum, floor_quantum, ceil_quantum; - uint32_t n_rates, def_rate, n_sync; + uint32_t n_rates, def_rate; bool freewheel, global_force_rate, global_force_quantum, transport_start; struct spa_list collect; - char *sync[MAX_SYNC+1]; pw_log_info("%p: busy:%d reason:%s", context, impl->recalc, reason); @@ -1514,23 +1527,11 @@ again: freewheel = false; transport_start = false; - /* clean up the flags first and collect sync */ - n_sync = 0; - sync[0] = NULL; + /* clean up the flags first */ spa_list_for_each(n, &context->node_list, link) { n->visited = false; n->checked = 0; n->runnable = n->always_process && n->active; - if (n->sync) { - for (uint32_t i = 0; n->sync_groups[i]; i++) { - if (n_sync >= MAX_SYNC) - break; - if (pw_strv_find(sync, n->sync_groups[i]) >= 0) - continue; - sync[n_sync++] = n->sync_groups[i]; - sync[n_sync] = NULL; - } - } } get_quantums(context, &def_quantum, &min_quantum, &max_quantum, &rate_quantum, @@ -1551,7 +1552,7 @@ again: if (!n->visited) { spa_list_init(&collect); - collect_nodes(context, n, &collect, sync); + collect_nodes(context, n, &collect); move_to_driver(context, &collect, n); } /* from now on we are only interested in active driving nodes @@ -1605,7 +1606,7 @@ again: /* collect all nodes in this group */ spa_list_init(&collect); - collect_nodes(context, n, &collect, sync); + collect_nodes(context, n, &collect); driver = NULL; spa_list_for_each(t, &collect, sort_link) { -- 2.45.2