diff --git a/src/pipewire/client.c b/src/pipewire/client.c index 29d908462..711f1d86f 100644 --- a/src/pipewire/client.c +++ b/src/pipewire/client.c @@ -301,9 +301,8 @@ void pw_client_destroy(struct pw_client *client) spa_hook_remove(&impl->core_listener); - if (client->registered) { + if (client->registered) spa_list_remove(&client->link); - } if (client->global) { spa_hook_remove(&client->global_listener); diff --git a/src/pipewire/link.c b/src/pipewire/link.c index 4ad9333ed..b94e45982 100644 --- a/src/pipewire/link.c +++ b/src/pipewire/link.c @@ -1253,17 +1253,8 @@ void pw_link_destroy(struct pw_link *link) pw_link_deactivate(link); - if (link->registered) { + if (link->registered) spa_list_remove(&link->link); - } - - if (link->global) { - spa_hook_remove(&link->global_listener); - pw_global_destroy(link->global); - } - - spa_list_for_each_safe(resource, tmp, &link->resource_list, link) - pw_resource_destroy(resource); input_remove(link, link->input); spa_list_remove(&link->input_link); @@ -1275,6 +1266,14 @@ void pw_link_destroy(struct pw_link *link) spa_hook_list_call(&link->output->listener_list, struct pw_port_events, link_removed, link); link->output = NULL; + if (link->global) { + spa_hook_remove(&link->global_listener); + pw_global_destroy(link->global); + } + + spa_list_for_each_safe(resource, tmp, &link->resource_list, link) + pw_resource_destroy(resource); + pw_log_debug("link %p: free", impl); spa_hook_list_call(&link->listener_list, struct pw_link_events, free); diff --git a/src/pipewire/module.c b/src/pipewire/module.c index 580bb529e..36d8ce89a 100644 --- a/src/pipewire/module.c +++ b/src/pipewire/module.c @@ -300,6 +300,12 @@ void pw_module_destroy(struct pw_module *module) pw_log_debug("module %p: destroy", module); spa_hook_list_call(&module->listener_list, struct pw_module_events, destroy); + spa_list_remove(&module->link); + + if (module->global) { + spa_hook_remove(&module->global_listener); + pw_global_destroy(module->global); + } spa_list_for_each_safe(resource, tmp, &module->resource_list, link) pw_resource_destroy(resource); @@ -310,12 +316,6 @@ void pw_module_destroy(struct pw_module *module) if (module->info.args) free((char *) module->info.args); - spa_list_remove(&module->link); - - if (module->global) { - spa_hook_remove(&module->global_listener); - pw_global_destroy(module->global); - } dlclose(impl->hnd); free(impl); } diff --git a/src/pipewire/node.c b/src/pipewire/node.c index 03d9de9df..2438921ed 100644 --- a/src/pipewire/node.c +++ b/src/pipewire/node.c @@ -621,25 +621,29 @@ void pw_node_destroy(struct pw_node *node) spa_list_remove(&node->link); } - if (node->global) { - spa_hook_remove(&node->global_listener); - pw_global_destroy(node->global); - } - - spa_list_for_each_safe(resource, tmp, &node->resource_list, link) - pw_resource_destroy(resource); + pw_log_debug("node %p: unlink ports", node); + spa_list_for_each(port, &node->input_ports, link) + pw_port_unlink(port); + spa_list_for_each(port, &node->output_ports, link) + pw_port_unlink(port); pw_log_debug("node %p: destroy ports", node); spa_list_for_each_safe(port, tmpp, &node->input_ports, link) { spa_hook_list_call(&node->listener_list, struct pw_node_events, port_removed, port); pw_port_destroy(port); } - spa_list_for_each_safe(port, tmpp, &node->output_ports, link) { spa_hook_list_call(&node->listener_list, struct pw_node_events, port_removed, port); pw_port_destroy(port); } + if (node->global) { + spa_hook_remove(&node->global_listener); + pw_global_destroy(node->global); + } + spa_list_for_each_safe(resource, tmp, &node->resource_list, link) + pw_resource_destroy(resource); + pw_log_debug("node %p: free", node); spa_hook_list_call(&node->listener_list, struct pw_node_events, free); diff --git a/src/pipewire/port.c b/src/pipewire/port.c index a4d342710..813358b35 100644 --- a/src/pipewire/port.c +++ b/src/pipewire/port.c @@ -391,6 +391,20 @@ int pw_port_add(struct pw_port *port, struct pw_node *node) return 0; } +void pw_port_unlink(struct pw_port *port) +{ + struct pw_link *l, *t; + + if (port->direction == PW_DIRECTION_OUTPUT) { + spa_list_for_each_safe(l, t, &port->links, output_link) + pw_link_destroy(l); + } + else { + spa_list_for_each_safe(l, t, &port->links, input_link) + pw_link_destroy(l); + } +} + static int do_remove_port(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data) { @@ -409,6 +423,28 @@ static int do_remove_port(struct spa_loop *loop, return 0; } +static void pw_port_remove(struct pw_port *port) +{ + struct pw_node *node = port->node; + + pw_log_debug("port %p: remove", port); + + if (port->rt.graph) + pw_loop_invoke(port->node->data_loop, do_remove_port, + SPA_ID_INVALID, NULL, 0, true, port); + + if (port->direction == PW_DIRECTION_INPUT) { + pw_map_remove(&node->input_port_map, port->port_id); + node->info.n_input_ports--; + } + else { + pw_map_remove(&node->output_port_map, port->port_id); + node->info.n_output_ports--; + } + spa_list_remove(&port->link); + spa_hook_list_call(&node->listener_list, struct pw_node_events, port_removed, port); +} + void pw_port_destroy(struct pw_port *port) { struct pw_node *node = port->node; @@ -418,33 +454,19 @@ void pw_port_destroy(struct pw_port *port) spa_hook_list_call(&port->listener_list, struct pw_port_events, destroy); - if (port->global) { - spa_hook_remove(&port->global_listener); - pw_global_destroy(port->global); - } - - if (node) { - if (port->rt.graph) - pw_loop_invoke(port->node->data_loop, do_remove_port, - SPA_ID_INVALID, NULL, 0, true, port); - - if (port->direction == PW_DIRECTION_INPUT) { - pw_map_remove(&node->input_port_map, port->port_id); - node->info.n_input_ports--; - } - else { - pw_map_remove(&node->output_port_map, port->port_id); - node->info.n_output_ports--; - } - spa_list_remove(&port->link); - spa_hook_list_call(&node->listener_list, struct pw_node_events, port_removed, port); - } + if (node) + pw_port_remove(port); spa_list_for_each_safe(control, ctemp, &port->control_list[0], port_link) pw_control_destroy(control); spa_list_for_each_safe(control, ctemp, &port->control_list[1], port_link) pw_control_destroy(control); + if (port->global) { + spa_hook_remove(&port->global_listener); + pw_global_destroy(port->global); + } + pw_log_debug("port %p: free", port); spa_hook_list_call(&port->listener_list, struct pw_port_events, free); diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 038a77dc7..39680ed10 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -487,6 +487,9 @@ void * pw_port_get_user_data(struct pw_port *port); /** Add a port to a node \memberof pw_port */ int pw_port_add(struct pw_port *port, struct pw_node *node); +/** Unlink a port \memberof pw_port */ +void pw_port_unlink(struct pw_port *port); + /** Destroy a port \memberof pw_port */ void pw_port_destroy(struct pw_port *port);