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.
This commit is contained in:
Wim Taymans 2022-12-08 16:14:03 +01:00
parent 638de5a3b7
commit ced0f853a1

View file

@ -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)",