summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2019-08-21 17:54:17 +0200
committerWim Taymans <wtaymans@redhat.com>2019-08-22 18:16:08 +0200
commit0307f7c49f91bb530d2bfdfe4c3d8e605c323447 (patch)
treef24d093403fad87adbc76a0a1120e34a0f3689d7
parentae457625d3aaf517b14e4ce40d53fdb26bc53ed4 (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.c70
-rw-r--r--src/pipewire/link.c53
-rw-r--r--src/pipewire/node.c8
-rw-r--r--src/pipewire/private.h5
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__)