graph: add graph datastructure and scheduler

Improve event and command init so that it can be used more easily
as compound literals.
Improve volume
Make it possible to use graph scheduler in test-mixer
This commit is contained in:
Wim Taymans 2017-05-18 17:16:48 +02:00
parent 53dd63eb3a
commit 6691eb7845
18 changed files with 970 additions and 108 deletions

View file

@ -29,6 +29,7 @@
#include <spa/node.h>
#include <spa/log.h>
#include <spa/loop.h>
#include <spa/graph.h>
#include <spa/type-map.h>
#include <spa/audio/format-utils.h>
#include <spa/format-utils.h>
@ -37,6 +38,8 @@
#include <lib/debug.h>
#include <lib/props.h>
#undef USE_GRAPH
typedef struct {
uint32_t node;
uint32_t props;
@ -94,6 +97,17 @@ typedef struct {
SpaSupport support[4];
uint32_t n_support;
SpaGraph graph;
SpaGraphNode source1_node;
SpaGraphPort source1_out;
SpaGraphNode source2_node;
SpaGraphPort source2_out;
SpaGraphPort mix_in[2];
SpaGraphNode mix_node;
SpaGraphPort mix_out;
SpaGraphPort sink_in;
SpaGraphNode sink_node;
SpaNode *sink;
SpaPortIO mix_sink_io[1];
@ -220,6 +234,12 @@ static void
on_sink_need_input (SpaNode *node, void *user_data)
{
AppData *data = user_data;
#ifdef USE_GRAPH
data->sink_node.action = PROCESS_CHECK;
data->sink_node.state = SPA_RESULT_NEED_BUFFER;
spa_graph_node_schedule (&data->graph, &data->sink_node);
#else
SpaResult res;
res = spa_node_process_output (data->mix);
@ -249,6 +269,7 @@ push:
} else {
printf ("got process_output error from mixer %d\n", res);
}
#endif
}
static void
@ -369,6 +390,55 @@ make_nodes (AppData *data, const char *device)
if ((res = spa_node_set_props (data->source2, props)) < 0)
printf ("got set_props error %d\n", res);
data->mix_ports[0] = 0;
if ((res = spa_node_add_port (data->mix, SPA_DIRECTION_INPUT, 0)) < 0)
return res;
data->mix_ports[1] = 1;
if ((res = spa_node_add_port (data->mix, SPA_DIRECTION_INPUT, 1)) < 0)
return res;
spa_node_port_set_io (data->source1, SPA_DIRECTION_OUTPUT, 0, &data->source1_mix_io[0]);
spa_node_port_set_io (data->source2, SPA_DIRECTION_OUTPUT, 0, &data->source2_mix_io[0]);
spa_node_port_set_io (data->mix, SPA_DIRECTION_INPUT, 0, &data->source1_mix_io[0]);
spa_node_port_set_io (data->mix, SPA_DIRECTION_INPUT, 1, &data->source2_mix_io[0]);
spa_node_port_set_io (data->mix, SPA_DIRECTION_OUTPUT, 0, &data->mix_sink_io[0]);
spa_node_port_set_io (data->sink, SPA_DIRECTION_INPUT, 0, &data->mix_sink_io[0]);
#ifdef USE_GRAPH
spa_graph_node_add (&data->graph, &data->source1_node, spa_graph_node_schedule_default, data->source1);
spa_graph_port_add (&data->graph, &data->source1_node,
&data->source1_out, SPA_DIRECTION_OUTPUT, 0,
0, &data->source1_mix_io[0]);
spa_graph_node_add (&data->graph, &data->source2_node, spa_graph_node_schedule_default, data->source2);
spa_graph_port_add (&data->graph, &data->source2_node,
&data->source2_out, SPA_DIRECTION_OUTPUT, 0,
0, &data->source2_mix_io[0]);
spa_graph_node_add (&data->graph, &data->mix_node, spa_graph_node_schedule_default, data->mix);
spa_graph_port_add (&data->graph, &data->mix_node,
&data->mix_in[0], SPA_DIRECTION_INPUT, data->mix_ports[0],
0, &data->source1_mix_io[0]);
spa_graph_port_add (&data->graph, &data->mix_node,
&data->mix_in[1], SPA_DIRECTION_INPUT, data->mix_ports[1],
0, &data->source2_mix_io[0]);
spa_graph_port_link (&data->graph, &data->source1_out, &data->mix_in[0]);
spa_graph_port_link (&data->graph, &data->source2_out, &data->mix_in[1]);
spa_graph_port_add (&data->graph, &data->mix_node,
&data->mix_out, SPA_DIRECTION_OUTPUT, 0,
0, &data->mix_sink_io[0]);
spa_graph_node_add (&data->graph, &data->sink_node, spa_graph_node_schedule_default, data->sink);
spa_graph_port_add (&data->graph, &data->sink_node,
&data->sink_in, SPA_DIRECTION_INPUT, 0,
0, &data->mix_sink_io[0]);
spa_graph_port_link (&data->graph, &data->mix_out, &data->sink_in);
#endif
return res;
}
@ -402,13 +472,9 @@ negotiate_formats (AppData *data)
if ((res = spa_node_port_enum_formats (data->sink, SPA_DIRECTION_INPUT, 0, &format, filter, state)) < 0)
return res;
if ((res = spa_node_port_set_format (data->sink, SPA_DIRECTION_INPUT, 0, 0, format)) < 0)
return res;
spa_node_port_set_io (data->mix, SPA_DIRECTION_OUTPUT, 0, &data->mix_sink_io[0]);
spa_node_port_set_io (data->sink, SPA_DIRECTION_INPUT, 0, &data->mix_sink_io[0]);
if ((res = spa_node_port_set_format (data->mix, SPA_DIRECTION_OUTPUT, 0, 0, format)) < 0)
return res;
@ -418,13 +484,6 @@ negotiate_formats (AppData *data)
if ((res = spa_node_port_use_buffers (data->mix, SPA_DIRECTION_OUTPUT, 0, data->mix_buffers, 1)) < 0)
return res;
data->mix_ports[0] = 0;
if ((res = spa_node_add_port (data->mix, SPA_DIRECTION_INPUT, 0)) < 0)
return res;
spa_node_port_set_io (data->source1, SPA_DIRECTION_OUTPUT, 0, &data->source1_mix_io[0]);
spa_node_port_set_io (data->mix, SPA_DIRECTION_INPUT, 0, &data->source1_mix_io[0]);
if ((res = spa_node_port_set_format (data->mix, SPA_DIRECTION_INPUT, data->mix_ports[0], 0, format)) < 0)
return res;
@ -437,13 +496,6 @@ negotiate_formats (AppData *data)
if ((res = spa_node_port_use_buffers (data->source1, SPA_DIRECTION_OUTPUT, 0, data->source1_buffers, 2)) < 0)
return res;
data->mix_ports[1] = 1;
if ((res = spa_node_add_port (data->mix, SPA_DIRECTION_INPUT, 1)) < 0)
return res;
spa_node_port_set_io (data->source2, SPA_DIRECTION_OUTPUT, 0, &data->source2_mix_io[0]);
spa_node_port_set_io (data->mix, SPA_DIRECTION_INPUT, 1, &data->source2_mix_io[0]);
if ((res = spa_node_port_set_format (data->mix, SPA_DIRECTION_INPUT, data->mix_ports[1], 0, format)) < 0)
return res;
@ -538,8 +590,8 @@ run_async_sink (AppData *data)
data->running = false;
}
printf ("sleeping for 1000 seconds\n");
sleep (1000);
printf ("sleeping for 30 seconds\n");
sleep (30);
if (data->running) {
data->running = false;
@ -574,6 +626,8 @@ main (int argc, char *argv[])
data.data_loop.remove_source = do_remove_source;
data.data_loop.invoke = do_invoke;
spa_graph_init (&data.graph);
if ((str = getenv ("PINOS_DEBUG")))
data.log->level = atoi (str);