From ced0f853a1670b77fcd4468854ec501c0bd85e89 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 8 Dec 2022 16:14:03 +0100 Subject: [PATCH] impl-node: improve state change when driver changes Imagine this case with pw-loopback: - the output stream is created and connected - the input stream is created and connected - the output stream is linked first and input+output move to the sink as the driver. Start is sent to input+output but delayed for the driver until all is complete. - the input stream is linked to a source. The source becomes the new driver and input+output+sink is moved to the source. - all completes, the source is sent the Start command because it is a driver. The sink also completes but is not sent a Start Command because it is no longer a driver. -> sink is scheduled but not started and gives errors This patch clears the pending state of a driver when it is no longer a driver. This makes the new driver set a new state (and cancel the old state) and all followers will start correctly. --- src/pipewire/impl-node.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c index c820fe177..dd20620a9 100644 --- a/src/pipewire/impl-node.c +++ b/src/pipewire/impl-node.c @@ -838,6 +838,7 @@ int pw_impl_node_set_driver(struct pw_impl_node *node, struct pw_impl_node *driv struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this); struct pw_impl_node *old = node->driver_node; int res; + bool was_driving; if (driver == NULL) driver = node; @@ -860,8 +861,16 @@ int pw_impl_node_set_driver(struct pw_impl_node *node, struct pw_impl_node *driv old->name, old->info.id, driver->name, driver->info.id); } + was_driving = node->driving; node->driving = node->driver && driver == node; + /* When a node was driver (and is waiting for all nodes to complete + * the Start command) cancel the pending state and let the new driver + * calculate a new state so that the Start command is sent to the + * node */ + if (was_driving && !node->driving) + impl->pending_state = node->info.state; + pw_log_debug("%p: driver %p driving:%u", node, driver, node->driving); pw_log_info("(%s-%u) -> change driver (%s-%d -> %s-%d)",