From b69bdc1eff2c40fc438dfbe937ea0eea376697fc Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 27 Apr 2020 11:12:10 +0200 Subject: [PATCH] context: improve graph states Keep the first active node as the fallback node. We use this node as the target when no oher active nodes exist. Only assign the target node to active nodes. When we assign an unassigned node, simply update the active followers of the target, the state of the nodes and target itself will then be taken care of later. When registering nodes, only active nodes can influence the state of the graph. Update some comments --- src/pipewire/context.c | 21 ++++++++++++++------- src/pipewire/impl-node.c | 4 ++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/pipewire/context.c b/src/pipewire/context.c index e30bfb7de..c487f85f5 100644 --- a/src/pipewire/context.c +++ b/src/pipewire/context.c @@ -803,7 +803,7 @@ static int collect_nodes(struct pw_impl_node *driver) int pw_context_recalc_graph(struct pw_context *context, const char *reason) { struct impl *impl = SPA_CONTAINER_OF(context, struct impl, this); - struct pw_impl_node *n, *s, *target; + struct pw_impl_node *n, *s, *target, *fallback; pw_log_info(NAME" %p: busy:%d reason:%s", context, impl->recalc, reason); @@ -817,7 +817,7 @@ int pw_context_recalc_graph(struct pw_context *context, const char *reason) * will end up 'unassigned' to a master. Other nodes are master * and if they have active followers, we can use them to schedule * the unassigned nodes. */ - target = NULL; + target = fallback = NULL; spa_list_for_each(n, &context->driver_list, driver_link) { n->active_followers = 0; @@ -842,6 +842,9 @@ int pw_context_recalc_graph(struct pw_context *context, const char *reason) pw_log_debug(NAME" %p: driver %p active followers %d", context, n, n->active_followers); + /* first active master node is fallback */ + if (fallback == NULL) + fallback = n; /* if the master has active followers, it is a target for our * unassigned nodes */ if (n->active_followers > 0) { @@ -849,10 +852,13 @@ int pw_context_recalc_graph(struct pw_context *context, const char *reason) target = n; } } + /* no active node, use fallback master */ + if (target == NULL) + target = fallback; /* now go through all available nodes. The ones we didn't visit * in collect_nodes() are not linked to any master. We assign them - * to an active master */ + * to either an active master of the first master */ spa_list_for_each(n, &context->node_list, link) { if (n->exported) continue; @@ -863,21 +869,22 @@ int pw_context_recalc_graph(struct pw_context *context, const char *reason) pw_log_debug(NAME" %p: unassigned node %p: '%s' %d %d", context, n, n->name, n->active, n->want_driver); - t = n->want_driver ? target : NULL; + t = n->active && n->want_driver ? target : NULL; if (t != NULL) { if (n->quantum_size > 0 && n->quantum_size < t->quantum_current) t->quantum_current = SPA_MAX(context->defaults.clock_min_quantum, n->quantum_size); + t->active_followers++; } pw_impl_node_set_driver(n, t); - pw_impl_node_set_state(n, t && n->active ? - PW_NODE_STATE_RUNNING : PW_NODE_STATE_IDLE); + if (t == NULL) + pw_impl_node_set_state(n, PW_NODE_STATE_IDLE); } n->visited = false; } - /* assign final quantum and debug masters and followers */ + /* assign final quantum and set state followers and master */ spa_list_for_each(n, &context->driver_list, driver_link) { enum pw_node_state state; diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c index 47806df71..38e0d54ef 100644 --- a/src/pipewire/impl-node.c +++ b/src/pipewire/impl-node.c @@ -611,8 +611,8 @@ int pw_impl_node_register(struct pw_impl_node *this, spa_list_for_each(port, &this->output_ports, link) pw_impl_port_register(port, NULL); - if (this->active || this->want_driver) - pw_context_recalc_graph(context, "active node register"); + if (this->active) + pw_context_recalc_graph(context, "register active node"); return 0;