diff --git a/src/pipewire/context.c b/src/pipewire/context.c index 31383e2e8..e30bfb7de 100644 --- a/src/pipewire/context.c +++ b/src/pipewire/context.c @@ -61,6 +61,7 @@ struct impl { struct pw_context this; struct spa_handle *dbus_handle; + unsigned int recalc; }; @@ -799,10 +800,18 @@ static int collect_nodes(struct pw_impl_node *driver) return 0; } -int pw_context_recalc_graph(struct pw_context *context) +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; + pw_log_info(NAME" %p: busy:%d reason:%s", context, impl->recalc, reason); + + if (impl->recalc) + return -EBUSY; + + impl->recalc = true; + /* start from all drivers and group all nodes that are linked * to it. Some nodes are not (yet) linked to anything and they * will end up 'unassigned' to a master. Other nodes are master @@ -882,9 +891,11 @@ int pw_context_recalc_graph(struct pw_context *context) state = PW_NODE_STATE_IDLE; if (n->rt.position && n->quantum_current != n->rt.position->clock.duration) { + pw_log_info("(%s-%u) new quantum:%"PRIu64"->%u", + n->name, n->info.id, + n->rt.position->clock.duration, + n->quantum_current); n->rt.position->clock.duration = n->quantum_current; - pw_log_info("(%s-%u) new quantum:%u", - n->name, n->info.id, n->quantum_current); } pw_log_debug(NAME" %p: master %p quantum:%u '%s'", context, n, @@ -897,6 +908,7 @@ int pw_context_recalc_graph(struct pw_context *context) } pw_impl_node_set_state(n, state); } + impl->recalc = false; return 0; } diff --git a/src/pipewire/impl-link.c b/src/pipewire/impl-link.c index 908cf081f..2334d577c 100644 --- a/src/pipewire/impl-link.c +++ b/src/pipewire/impl-link.c @@ -117,10 +117,10 @@ static void pw_impl_link_update_state(struct pw_impl_link *link, enum pw_link_st if (old != PW_LINK_STATE_PAUSED && state == PW_LINK_STATE_PAUSED) { link->prepared = true; - pw_context_recalc_graph(link->context); + pw_context_recalc_graph(link->context, "link prepared"); } else if (old == PW_LINK_STATE_PAUSED && state < PW_LINK_STATE_PAUSED) { link->prepared = false; - pw_context_recalc_graph(link->context); + pw_context_recalc_graph(link->context, "link unprepared"); } } @@ -1080,8 +1080,6 @@ struct pw_impl_link *pw_context_create_link(struct pw_context *context, pw_impl_node_emit_peer_added(output_node, input_node); - pw_context_recalc_graph(context); - return this; error_same_ports: @@ -1229,8 +1227,6 @@ void pw_impl_link_destroy(struct pw_impl_link *link) pw_properties_free(link->properties); - pw_context_recalc_graph(link->context); - free(link->name); free(link->info.format); free(impl); diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c index 1719a476a..223cf0960 100644 --- a/src/pipewire/impl-node.c +++ b/src/pipewire/impl-node.c @@ -161,7 +161,7 @@ static int pause_node(struct pw_impl_node *this) pw_log_debug(NAME" %p: pause node state:%s pause-on-idle:%d", this, pw_node_state_as_string(this->info.state), impl->pause_on_idle); - if (this->info.state <= PW_NODE_STATE_IDLE && impl->pause_on_idle) + if (this->info.state <= PW_NODE_STATE_IDLE) return 0; node_deactivate(this); @@ -611,7 +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); - pw_context_recalc_graph(context); + if (this->active || this->want_driver) + pw_context_recalc_graph(context, "active node register"); return 0; @@ -774,7 +775,7 @@ static void check_properties(struct pw_impl_node *node) pw_log_debug(NAME" %p: driver:%d recalc:%d", node, node->driver, do_recalc); if (do_recalc) - pw_context_recalc_graph(context); + pw_context_recalc_graph(context, "quantum change"); } static const char *str_status(uint32_t status) @@ -1521,7 +1522,9 @@ void pw_impl_node_destroy(struct pw_impl_node *node) struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this); struct pw_impl_port *port; struct pw_impl_node *follower; + bool active; + active = node->active; node->active = false; pw_log_debug(NAME" %p: destroy", impl); @@ -1569,7 +1572,8 @@ void pw_impl_node_destroy(struct pw_impl_node *node) pw_global_destroy(node->global); } - pw_context_recalc_graph(node->context); + if (active) + pw_context_recalc_graph(node->context, "active node destroy"); pw_log_debug(NAME" %p: free", node); pw_impl_node_emit_free(node); @@ -1861,7 +1865,8 @@ int pw_impl_node_set_active(struct pw_impl_node *node, bool active) pw_impl_node_emit_active_changed(node, active); if (node->registered) - pw_context_recalc_graph(node->context); + pw_context_recalc_graph(node->context, + active ? "node activate" : "node deactivate"); } return 0; } diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 3464ebbdc..dc5f9b96e 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -964,7 +964,7 @@ int pw_proxy_init(struct pw_proxy *proxy, const char *type, uint32_t version); void pw_proxy_remove(struct pw_proxy *proxy); -int pw_context_recalc_graph(struct pw_context *context); +int pw_context_recalc_graph(struct pw_context *context, const char *reason); void pw_impl_port_update_info(struct pw_impl_port *port, const struct spa_port_info *info);