diff options
author | Wim Taymans <wtaymans@redhat.com> | 2019-08-21 17:54:17 +0200 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2019-08-22 18:16:08 +0200 |
commit | 0307f7c49f91bb530d2bfdfe4c3d8e605c323447 (patch) | |
tree | f24d093403fad87adbc76a0a1120e34a0f3689d7 | |
parent | ae457625d3aaf517b14e4ce40d53fdb26bc53ed4 (diff) |
core: WIP attempt to rework statesstates
Try to manage the states in a different way. Does not work yet.
-rw-r--r-- | src/pipewire/core.c | 70 | ||||
-rw-r--r-- | src/pipewire/link.c | 53 | ||||
-rw-r--r-- | src/pipewire/node.c | 8 | ||||
-rw-r--r-- | src/pipewire/private.h | 5 |
4 files changed, 97 insertions, 39 deletions
diff --git a/src/pipewire/core.c b/src/pipewire/core.c index cdae50c0..5a3efce4 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -1075,7 +1075,7 @@ static int collect_nodes(struct pw_node *driver) spa_list_for_each(p, &n->input_ports, link) { spa_list_for_each(l, &p->links, input_link) { t = l->output->node; - if (!t->visited && t->active) { + if (l->prepared && !t->visited && t->active) { t->visited = true; spa_list_append(&queue, &t->sort_link); } @@ -1084,7 +1084,7 @@ static int collect_nodes(struct pw_node *driver) spa_list_for_each(p, &n->output_ports, link) { spa_list_for_each(l, &p->links, output_link) { t = l->input->node; - if (!t->visited && t->active) { + if (l->prepared && !t->visited && t->active) { t->visited = true; spa_list_append(&queue, &t->sort_link); } @@ -1101,30 +1101,74 @@ static int collect_nodes(struct pw_node *driver) int pw_core_recalc_graph(struct pw_core *core) { - struct pw_node *n, *s; + struct pw_node *n, *s, *target; + /* start from all drivers and group all nodes that are linked + * to it */ + target = NULL; spa_list_for_each(n, &core->driver_list, driver_link) { - if (!n->visited) + if (n->active && !n->visited) collect_nodes(n); + + n->active_slaves = 0; + + if (!n->master) + continue; + + spa_list_for_each(s, &n->slave_list, slave_link) { + + pw_log_info(NAME" %p: driver %p: slave %p %s: %d", + core, n, s, s->name, s->active); + + if (s != n && s->active) + n->active_slaves++; + } + pw_log_info(NAME" %p: driver %p active slaves %d", + core, n, n->active_slaves); + + if (n->active_slaves > 0) { + if (target == NULL) + target = n; + } } + /* assign each unassigned node to the driver we found above */ spa_list_for_each(n, &core->node_list, link) { - if (!n->visited) { - pw_log_info(NAME" %p: unassigned node %p: '%s' %d", core, - n, n->name, n->active); - pw_node_set_driver(n, NULL); + if (!n->visited && n->active) { + pw_log_info(NAME" %p: unassigned node %p '%s' -> %p", core, + n, n->name, target); + pw_node_set_driver(n, target); + n->active_slaves++; } n->visited = false; } + /* start all drivers with active slaves and pause the other ones */ spa_list_for_each(n, &core->driver_list, driver_link) { + enum pw_node_state state; + if (!n->master) continue; - pw_log_info(NAME" %p: master %p quantum:%d '%s'", core, n, - n->rt.position ? n->rt.position->size : 0, n->name); - spa_list_for_each(s, &n->slave_list, slave_link) - pw_log_info(NAME" %p: slave %p: active:%d '%s'", - core, s, s->active, s->name); + + state = n->info.state; + if (n->active_slaves > 0) + state = PW_NODE_STATE_RUNNING; + else if (state > PW_NODE_STATE_IDLE) + state = PW_NODE_STATE_IDLE; + + pw_log_info(NAME" %p: master %p quantum:%d '%s' state:%d wanted:%d", + core, n, n->rt.position ? n->rt.position->size : 0, + n->name, n->info.state, state); + + spa_list_for_each(s, &n->slave_list, slave_link) { + pw_log_info(NAME" %p: slave %p: active:%d '%s' %d", + core, s, s->active, s->name, s->info.state); + + if (s != n && s->active && s->info.state != state) + pw_node_set_state(s, state); + } + if (state != n->info.state) + pw_node_set_state(n, state); } return 0; } diff --git a/src/pipewire/link.c b/src/pipewire/link.c index 3f6fb825..405fbb3a 100644 --- a/src/pipewire/link.c +++ b/src/pipewire/link.c @@ -55,8 +55,6 @@ struct impl { struct pw_link this; - bool prepare; - bool activated; bool passive; struct pw_work_queue *work; @@ -142,21 +140,32 @@ static void pw_link_update_state(struct pw_link *link, enum pw_link_state state, debug_link(link); if (old != PW_LINK_STATE_PAUSED && state == PW_LINK_STATE_PAUSED) { - if (++out->n_ready_output_links == out->n_used_output_links && + ++out->n_ready_output_links; + ++in->n_ready_input_links; + pw_link_activate(link); + pw_core_recalc_graph(link->core); + +#if 0 + if (out->n_ready_output_links == out->n_used_output_links && out->n_ready_input_links == out->n_used_input_links) pw_node_set_state(out, PW_NODE_STATE_RUNNING); - if (++in->n_ready_input_links == in->n_used_input_links && + if (in->n_ready_input_links == in->n_used_input_links && in->n_ready_output_links == in->n_used_output_links) pw_node_set_state(in, PW_NODE_STATE_RUNNING); - pw_link_activate(link); +#endif } else if (old == PW_LINK_STATE_PAUSED && state < PW_LINK_STATE_PAUSED) { - if (--out->n_ready_output_links == 0 && + --out->n_ready_output_links; + --in->n_ready_input_links; + pw_core_recalc_graph(link->core); +#if 0 + if (out->n_ready_output_links == 0 && out->n_ready_input_links == 0) pw_node_set_state(out, PW_NODE_STATE_IDLE); - if (--in->n_ready_input_links == 0 && + if (in->n_ready_input_links == 0 && in->n_ready_output_links == 0) pw_node_set_state(in, PW_NODE_STATE_IDLE); +#endif } } @@ -750,9 +759,10 @@ int pw_link_activate(struct pw_link *this) struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this); int res; - pw_log_debug(NAME" %p: activate %d %d", this, impl->activated, this->info.state); + pw_log_debug(NAME" %p: activate activated:%d state:%d", + this, this->activated, this->info.state); - if (impl->activated) + if (this->activated) return 0; pw_link_prepare(this); @@ -768,7 +778,7 @@ int pw_link_activate(struct pw_link *this) if (this->info.state == PW_LINK_STATE_PAUSED) { pw_loop_invoke(this->output->node->data_loop, do_activate_link, SPA_ID_INVALID, NULL, 0, false, this); - impl->activated = true; + this->activated = true; } return 0; } @@ -900,12 +910,12 @@ int pw_link_prepare(struct pw_link *this) { struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this); - pw_log_debug(NAME" %p: prepare %d", this, impl->prepare); + pw_log_debug(NAME" %p: prepare %d", this, this->prepared); - if (impl->prepare) + if (this->prepared) return 0; - impl->prepare = true; + this->prepared = true; this->output->node->n_used_output_links++; this->input->node->n_used_input_links++; @@ -953,20 +963,21 @@ int pw_link_deactivate(struct pw_link *this) struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this); struct pw_node *input_node, *output_node; - pw_log_debug(NAME" %p: deactivate %d %d", this, impl->prepare, impl->activated); + pw_log_debug(NAME" %p: deactivate prepared:%d activated:%d", + this, this->prepared, this->activated); - if (!impl->prepare) + if (!this->prepared) return 0; - impl->prepare = false; - if (impl->activated) { + this->prepared = false; + if (this->activated) { pw_loop_invoke(this->output->node->data_loop, do_deactivate_link, SPA_ID_INVALID, NULL, 0, true, this); port_set_io(this, this->output, SPA_IO_Buffers, NULL, 0, &this->rt.out_mix); port_set_io(this, this->input, SPA_IO_Buffers, NULL, 0, &this->rt.in_mix); - impl->activated = false; + this->activated = false; } output_node = this->output->node; @@ -982,6 +993,7 @@ int pw_link_deactivate(struct pw_link *this) debug_link(this); +#if 0 if (input_node->n_used_input_links <= input_node->idle_used_input_links && input_node->n_used_output_links <= input_node->idle_used_output_links && input_node->info.state > PW_NODE_STATE_IDLE) { @@ -997,6 +1009,7 @@ int pw_link_deactivate(struct pw_link *this) pw_log_debug(NAME" %p: output port %p state %d -> %d", this, this->output, this->output->state, PW_PORT_STATE_PAUSED); } +#endif pw_link_update_state(this, PW_LINK_STATE_INIT, NULL); @@ -1357,8 +1370,6 @@ struct pw_link *pw_link_new(struct pw_core *core, pw_node_emit_peer_added(output_node, input_node); - pw_core_recalc_graph(core); - return this; error_same_ports: @@ -1505,8 +1516,6 @@ void pw_link_destroy(struct pw_link *link) pw_properties_free(link->properties); - pw_core_recalc_graph(link->core); - free(link->info.format); free(impl); } diff --git a/src/pipewire/node.c b/src/pipewire/node.c index f21d53e5..01992ca8 100644 --- a/src/pipewire/node.c +++ b/src/pipewire/node.c @@ -198,9 +198,11 @@ static int start_node(struct pw_node *this) this->n_used_output_links, this->n_ready_input_links, this->n_used_input_links); +#if 0 if (this->n_ready_output_links != this->n_used_output_links || this->n_ready_input_links != this->n_used_input_links) return 0; +#endif res = spa_node_send_command(this->node, &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Start)); @@ -1337,8 +1339,6 @@ void pw_node_destroy(struct pw_node *node) pw_global_destroy(node->global); } - pw_core_recalc_graph(node->core); - pw_log_debug(NAME" %p: free", node); pw_node_emit_free(node); @@ -1533,9 +1533,10 @@ static void on_state_complete(void *obj, void *data, int res, uint32_t seq) static void node_activate(struct pw_node *this) { - struct pw_port *port; pw_log_debug(NAME" %p: activate", this); +#if 0 + struct pw_port *port; spa_list_for_each(port, &this->input_ports, link) { struct pw_link *link; spa_list_for_each(link, &port->links, input_link) @@ -1546,6 +1547,7 @@ static void node_activate(struct pw_node *this) spa_list_for_each(link, &port->links, output_link) pw_link_activate(link); } +#endif } /** Set the node state diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 761f8b5f..bbdda60c 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -420,6 +420,7 @@ struct pw_node { struct pw_node *driver_node; struct spa_list slave_list; struct spa_list slave_link; + uint32_t active_slaves; struct spa_list sort_link; /**< link used to sort nodes */ @@ -613,8 +614,10 @@ struct pw_link { void *user_data; - unsigned int registered:1; unsigned int feedback:1; + unsigned int registered:1; + unsigned int prepared:1; + unsigned int activated:1; }; #define pw_resource_emit(o,m,v,...) spa_hook_list_call(&o->listener_list, struct pw_resource_events, m, v, ##__VA_ARGS__) |