diff options
author | Julian Bouzas <julian.bouzas@collabora.com> | 2020-01-20 11:12:10 -0500 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2020-02-04 11:55:28 +0100 |
commit | 1eba8d7f74c292d2375f2971e3427cc4106e4820 (patch) | |
tree | 38b11e4f2ad768da82f45483436053d30810b9bb | |
parent | 1cce9a69c8178df896e36fb533592009a11b8e42 (diff) |
spa: add support system so that example-control can play audio
The example-control executable does not play audio. This is because
alsa-pcm-sink needs a data system to run. This patch fixes the example by
loading a data system from libspa-support before creating the nodes.
-rw-r--r-- | spa/examples/example-control.c | 237 |
1 files changed, 122 insertions, 115 deletions
diff --git a/spa/examples/example-control.c b/spa/examples/example-control.c index ec7dd4bd..b749f8f4 100644 --- a/spa/examples/example-control.c +++ b/spa/examples/example-control.c @@ -64,9 +64,10 @@ struct buffer { struct data { struct spa_log *log; - struct spa_loop data_loop; - - struct spa_support support[4]; + struct spa_system *system; + struct spa_loop *loop; + struct spa_loop_control *control; + struct spa_support support[5]; uint32_t n_support; struct spa_graph graph; @@ -91,18 +92,11 @@ struct data { bool running; pthread_t thread; - - struct spa_source sources[16]; - unsigned int n_sources; - - bool rebuild_fds; - struct pollfd fds[16]; - unsigned int n_fds; }; #define MIN_LATENCY 1024 -#define BUFFER_SIZE MIN_LATENCY +#define BUFFER_SIZE 4096 static void init_buffer(struct data *data, struct spa_buffer **bufs, struct buffer *ba, int n_buffers, @@ -251,30 +245,6 @@ static const struct spa_node_callbacks sink_callbacks = { .reuse_buffer = on_sink_reuse_buffer }; -static int do_add_source(void *object, struct spa_source *source) -{ - struct data *data = object; - - data->sources[data->n_sources] = *source; - data->n_sources++; - data->rebuild_fds = true; - - return 0; -} - -static int -do_invoke(void *object, - spa_invoke_func_t func, uint32_t seq, const void *data, size_t size, bool block, void *user_data) -{ - return func(object, false, seq, data, size, user_data); -} - -static const struct spa_loop_methods impl_loop = { - SPA_VERSION_LOOP_METHODS, - .add_source = do_add_source, - .invoke = do_invoke, -}; - static int make_nodes(struct data *data, const char *device) { int res; @@ -358,31 +328,17 @@ static int make_nodes(struct data *data, const char *device) static int negotiate_formats(struct data *data) { int res; - struct spa_pod *format, *filter; - uint32_t state = 0; + struct spa_pod *format; struct spa_pod_builder b = { 0 }; uint8_t buffer[4096]; spa_pod_builder_init(&b, buffer, sizeof(buffer)); - filter = spa_format_audio_raw_build(&b, 0, + format = spa_format_audio_raw_build(&b, 0, &SPA_AUDIO_INFO_RAW_INIT( .format = SPA_AUDIO_FORMAT_S16, - .rate = 44100, + .rate = 48000, .channels = 2 )); - spa_debug_pod(0, NULL, filter); - - spa_log_debug(&default_log.log, "enum_params"); - if ((res = spa_node_port_enum_params_sync(data->sink, - SPA_DIRECTION_INPUT, 0, - SPA_PARAM_EnumFormat, &state, - filter, &format, &b)) != 1) - return -EBADF; - - spa_log_debug(&default_log.log, "sink set_param"); - spa_debug_pod(0, NULL, format); - spa_pod_fixate(format); - if ((res = spa_node_port_set_param(data->sink, SPA_DIRECTION_INPUT, 0, SPA_PARAM_Format, 0, format)) < 0) @@ -412,61 +368,29 @@ static void *loop(void *user_data) { struct data *data = user_data; - printf("enter thread %d\n", data->n_sources); - while (data->running) { - int r; - unsigned int i; - - /* rebuild */ - if (data->rebuild_fds) { - for (i = 0; i < data->n_sources; i++) { - struct spa_source *p = &data->sources[i]; - data->fds[i].fd = p->fd; - data->fds[i].events = p->mask; - } - data->n_fds = data->n_sources; - data->rebuild_fds = false; - } - - r = poll(data->fds, data->n_fds, -1); - if (r < 0) { - if (errno == EINTR) - continue; - break; - } - if (r == 0) { - fprintf(stderr, "select timeout"); - break; - } + printf("enter thread\n"); + spa_loop_control_enter(data->control); - /* after */ - for (i = 0; i < data->n_sources; i++) { - struct spa_source *p = &data->sources[i]; - p->rmask = data->fds[i].revents; - } - for (i = 0; i < data->n_sources; i++) { - struct spa_source *p = &data->sources[i]; - if (p->rmask) - p->func(p); - } + while (data->running) { + spa_loop_control_iterate(data->control, -1); } + printf("leave thread\n"); + spa_loop_control_leave(data->control); return NULL; } static void run_async_sink(struct data *data) { - int res; - int err; - - { - struct spa_command cmd = SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Start); - if ((res = spa_node_send_command(data->source, &cmd)) < 0) - printf("got source error %d\n", res); - if ((res = spa_node_send_command(data->sink, &cmd)) < 0) - printf("got sink error %d\n", res); - } + int res, err; + struct spa_command cmd; + + cmd = SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Start); + if ((res = spa_node_send_command(data->sink, &cmd)) < 0) + printf("got error %d\n", res); + + spa_loop_control_leave(data->control); data->running = true; if ((err = pthread_create(&data->thread, NULL, loop, data)) != 0) { @@ -482,34 +406,113 @@ static void run_async_sink(struct data *data) pthread_join(data->thread, NULL); } - { - struct spa_command cmd = SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Pause); - if ((res = spa_node_send_command(data->sink, &cmd)) < 0) - printf("got error %d\n", res); - if ((res = spa_node_send_command(data->source, &cmd)) < 0) - printf("got source error %d\n", res); + spa_loop_control_enter(data->control); + + cmd = SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Pause); + if ((res = spa_node_send_command(data->sink, &cmd)) < 0) + printf("got error %d\n", res); +} + +static int load_handle(struct data *data, struct spa_handle **handle, const char *lib, const char *name) +{ + int res; + void *hnd; + spa_handle_factory_enum_func_t enum_func; + uint32_t i; + + if ((hnd = dlopen(lib, RTLD_NOW)) == NULL) { + printf("can't load %s: %s\n", lib, dlerror()); + return -errno; } + if ((enum_func = dlsym(hnd, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)) == NULL) { + printf("can't find enum function\n"); + return -errno; + } + + for (i = 0;;) { + const struct spa_handle_factory *factory; + + if ((res = enum_func(&factory, &i)) <= 0) { + if (res != 0) + printf("can't enumerate factories: %s\n", spa_strerror(res)); + break; + } + if (strcmp(factory->name, name)) + continue; + + *handle = calloc(1, spa_handle_factory_get_size(factory, NULL)); + if ((res = spa_handle_factory_init(factory, *handle, + NULL, data->support, + data->n_support)) < 0) { + printf("can't make factory instance: %d\n", res); + return res; + } + return 0; + } + return -EBADF; } -int main(int argc, char *argv[]) +int init_data(struct data *data) { - struct data data = { NULL }; int res; const char *str; + struct spa_handle *handle = NULL; + void *iface; - spa_graph_init(&data.graph, &data.graph_state); + /* init the graph */ + spa_graph_init(&data->graph, &data->graph_state); - data.log = &default_log.log; - data.data_loop.iface = SPA_INTERFACE_INIT( - SPA_TYPE_INTERFACE_Loop, SPA_VERSION_LOOP, &impl_loop, &data); + /* set the default log */ + data->log = &default_log.log; + data->support[data->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_Log, data->log); + + /* load and set support system */ + if ((res = load_handle(data, &handle, + "build/spa/plugins/support/libspa-support.so", + SPA_NAME_SUPPORT_SYSTEM)) < 0) + return res; + if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_System, &iface)) < 0) { + printf("can't get System interface %d\n", res); + return res; + } + data->system = iface; + data->support[data->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_System, data->system); + data->support[data->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_DataSystem, data->system); + + /* load and set support loop and loop control */ + if ((res = load_handle(data, &handle, + "build/spa/plugins/support/libspa-support.so", + SPA_NAME_SUPPORT_LOOP)) < 0) + return res; + + if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Loop, &iface)) < 0) { + printf("can't get interface %d\n", res); + return res; + } + data->loop = iface; + data->support[data->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_Loop, data->loop); + data->support[data->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_DataLoop, data->loop); + if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_LoopControl, &iface)) < 0) { + printf("can't get interface %d\n", res); + return res; + } + data->control = iface; if ((str = getenv("SPA_DEBUG"))) - data.log->level = atoi(str); + data->log->level = atoi(str); + + return 0; +} - data.support[0] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_Log, data.log); - data.support[1] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_Loop, &data.data_loop); - data.support[2] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_DataLoop, &data.data_loop); - data.n_support = 3; +int main(int argc, char *argv[]) +{ + struct data data = { NULL }; + int res; + + if ((res = init_data(&data)) < 0) { + printf("can't init data: %d (%s)\n", res, spa_strerror(res)); + return -1; + } if ((res = make_nodes(&data, argc > 1 ? argv[1] : NULL)) < 0) { printf("can't make nodes: %d (%s)\n", res, spa_strerror(res)); @@ -520,5 +523,9 @@ int main(int argc, char *argv[]) return -1; } + spa_loop_control_enter(data.control); run_async_sink(&data); + spa_loop_control_leave(data.control); + + return 0; } |