impl-node: remove nodes from graph after Pause completes

While we process the Pause, the node might sill emit some events or do
processing, which would give an error because we already removed the
node from the graph.

Instead, remove the node from the graph when the node state is updated
to the new state.
This commit is contained in:
Wim Taymans 2022-10-24 15:24:47 +02:00
parent 8fcfa154eb
commit 1d0adba0f6

View file

@ -158,19 +158,6 @@ static void remove_node(struct pw_impl_node *this)
this->rt.driver_target.node = NULL;
}
static int
do_node_remove(struct spa_loop *loop,
bool async, uint32_t seq, const void *data, size_t size, void *user_data)
{
struct pw_impl_node *this = user_data;
if (this->source.loop != NULL) {
spa_loop_remove_source(loop, &this->source);
remove_node(this);
}
this->added = false;
return 0;
}
static void node_deactivate(struct pw_impl_node *this)
{
struct pw_impl_port *port;
@ -185,7 +172,6 @@ static void node_deactivate(struct pw_impl_node *this)
spa_list_for_each(link, &port->links, output_link)
pw_impl_link_deactivate(link);
}
pw_loop_invoke(this->data_loop, do_node_remove, 1, NULL, 0, true, this);
}
static int idle_node(struct pw_impl_node *this)
@ -354,6 +340,19 @@ do_node_add(struct spa_loop *loop,
return 0;
}
static int
do_node_remove(struct spa_loop *loop,
bool async, uint32_t seq, const void *data, size_t size, void *user_data)
{
struct pw_impl_node *this = user_data;
if (this->source.loop != NULL) {
spa_loop_remove_source(loop, &this->source);
remove_node(this);
}
this->added = false;
return 0;
}
static void node_update_state(struct pw_impl_node *node, enum pw_node_state state, int res, char *error)
{
struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this);
@ -364,20 +363,29 @@ static void node_update_state(struct pw_impl_node *node, enum pw_node_state stat
pw_log_debug("%p: start node driving:%d driver:%d added:%d", node,
node->driving, node->driver, node->added);
if (res >= 0) {
pw_loop_invoke(node->data_loop, do_node_add, 1, NULL, 0, true, node);
}
if (node->driving && node->driver) {
res = spa_node_send_command(node->node,
&SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Start));
if (res < 0) {
state = PW_NODE_STATE_ERROR;
error = spa_aprintf("Start error: %s", spa_strerror(res));
pw_loop_invoke(node->data_loop, do_node_remove, 1, NULL, 0, true, node);
}
}
if (res >= 0) {
pw_loop_invoke(node->data_loop, do_node_add, 1, NULL, 0, true, node);
/* now activate the inputs */
node_activate_inputs(node);
}
break;
case PW_NODE_STATE_IDLE:
case PW_NODE_STATE_SUSPENDED:
case PW_NODE_STATE_ERROR:
if (state != PW_NODE_STATE_IDLE || impl->pause_on_idle)
pw_loop_invoke(node->data_loop, do_node_remove, 1, NULL, 0, true, node);
break;
default:
break;
}