From 03eeb945f396d35c0950fafbead592cfda47277a Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 20 Jun 2019 15:19:28 +0200 Subject: [PATCH] daemon: add support for properties in the config file Make a set-prop command to set a property from the config file into a pw_properties. Pass this to the pw_core_new() and the main-loop to tweak some stuff. Move some warns to errors --- spa/plugins/support/logger.c | 9 +++--- src/daemon/command.c | 60 +++++++++++++++++++++++++++++------- src/daemon/command.h | 19 +++++++++--- src/daemon/daemon-config.c | 33 ++++++++++++-------- src/daemon/daemon-config.h | 3 +- src/daemon/main.c | 19 ++++++++---- src/daemon/pipewire.conf.in | 2 ++ src/pipewire/core.c | 9 ++++-- src/pipewire/data-loop.c | 6 ++-- src/pipewire/pipewire.c | 14 ++++----- src/pipewire/private.h | 13 -------- 11 files changed, 122 insertions(+), 65 deletions(-) diff --git a/spa/plugins/support/logger.c b/spa/plugins/support/logger.c index 9ebbb723f..07151de1d 100644 --- a/spa/plugins/support/logger.c +++ b/spa/plugins/support/logger.c @@ -45,16 +45,15 @@ struct impl { struct spa_handle handle; struct spa_log log; - struct spa_system *system; - - bool colors; FILE *file; + struct spa_system *system; + struct spa_source source; struct spa_ringbuffer trace_rb; uint8_t trace_data[TRACE_BUFFER]; - bool have_source; - struct spa_source source; + unsigned int have_source:1; + unsigned int colors:1; }; static void diff --git a/src/daemon/command.c b/src/daemon/command.c index e9fb7b692..8f27a84e9 100644 --- a/src/daemon/command.c +++ b/src/daemon/command.c @@ -37,16 +37,17 @@ /** \cond */ -static struct pw_command *parse_command_help(const char *line, char **err); -static struct pw_command *parse_command_add_spa_lib(const char *line, char **err); -static struct pw_command *parse_command_module_load(const char *line, char **err); -static struct pw_command *parse_command_exec(const char *line, char **err); +static struct pw_command *parse_command_help(struct pw_properties *properties, const char *line, char **err); +static struct pw_command *parse_command_set_prop(struct pw_properties *properties, const char *line, char **err); +static struct pw_command *parse_command_add_spa_lib(struct pw_properties *properties, const char *line, char **err); +static struct pw_command *parse_command_module_load(struct pw_properties *properties, const char *line, char **err); +static struct pw_command *parse_command_exec(struct pw_properties *properties, const char *line, char **err); struct impl { struct pw_command this; }; -typedef struct pw_command *(*pw_command_parse_func_t) (const char *line, char **err); +typedef struct pw_command *(*pw_command_parse_func_t) (struct pw_properties *properties, const char *line, char **err); struct command_parse { const char *name; @@ -56,6 +57,7 @@ struct command_parse { static const struct command_parse parsers[] = { {"help", "Show this help", parse_command_help}, + {"set-prop", "Set a property", parse_command_set_prop}, {"add-spa-lib", "Add a library that provides a spa factory name regex", parse_command_add_spa_lib}, {"load-module", "Load a module", parse_command_module_load}, {"exec", "Execute a program", parse_command_exec}, @@ -77,7 +79,7 @@ execute_command_help(struct pw_command *command, struct pw_core *core, char **er return 0; } -static struct pw_command *parse_command_help(const char *line, char **err) +static struct pw_command *parse_command_help(struct pw_properties *properties, const char *line, char **err) { struct impl *impl; struct pw_command *this; @@ -97,6 +99,42 @@ no_mem: return NULL; } +static int +execute_command_set_prop(struct pw_command *command, struct pw_core *core, char **err) +{ + return 0; +} + +static struct pw_command *parse_command_set_prop(struct pw_properties *properties, const char *line, char **err) +{ + struct impl *impl; + struct pw_command *this; + + impl = calloc(1, sizeof(struct impl)); + if (impl == NULL) + goto error_alloc; + + this = &impl->this; + this->func = execute_command_set_prop; + this->args = pw_split_strv(line, whitespace, 4, &this->n_args); + + if (this->n_args < 3) + goto error_arguments; + + pw_log_debug("set property: '%s' = '%s'", this->args[1], this->args[2]); + pw_properties_set(properties, this->args[1], this->args[2]); + + return this; + +error_arguments: + asprintf(err, "%s requires ", this->args[0]); + pw_free_strv(this->args); + return NULL; +error_alloc: + asprintf(err, "alloc failed: %m"); + return NULL; +} + static int execute_command_add_spa_lib(struct pw_command *command, struct pw_core *core, char **err) { @@ -110,7 +148,7 @@ execute_command_add_spa_lib(struct pw_command *command, struct pw_core *core, ch return 0; } -static struct pw_command *parse_command_add_spa_lib(const char *line, char **err) +static struct pw_command *parse_command_add_spa_lib(struct pw_properties *properties, const char *line, char **err) { struct impl *impl; struct pw_command *this; @@ -150,7 +188,7 @@ execute_command_module_load(struct pw_command *command, struct pw_core *core, ch return 0; } -static struct pw_command *parse_command_module_load(const char *line, char **err) +static struct pw_command *parse_command_module_load(struct pw_properties *properties, const char *line, char **err) { struct impl *impl; struct pw_command *this; @@ -194,7 +232,7 @@ execute_command_exec(struct pw_command *command, struct pw_core *core, char **er return 0; } -static struct pw_command *parse_command_exec(const char *line, char **err) +static struct pw_command *parse_command_exec(struct pw_properties *properties, const char *line, char **err) { struct impl *impl; struct pw_command *this; @@ -250,7 +288,7 @@ void pw_command_free(struct pw_command *command) * \memberof pw_command */ SPA_EXPORT -struct pw_command *pw_command_parse(const char *line, char **err) +struct pw_command *pw_command_parse(struct pw_properties *properties, const char *line, char **err) { struct pw_command *command = NULL; const struct command_parse *parse; @@ -263,7 +301,7 @@ struct pw_command *pw_command_parse(const char *line, char **err) for (parse = parsers; parse->name != NULL; parse++) { if (strcmp(name, parse->name) == 0) { - command = parse->func(line, err); + command = parse->func(properties, line, err); goto out; } } diff --git a/src/daemon/command.h b/src/daemon/command.h index cda0965e3..79166cd8b 100644 --- a/src/daemon/command.h +++ b/src/daemon/command.h @@ -30,17 +30,26 @@ extern "C" { #endif +#include + +struct pw_command; + +typedef int (*pw_command_func_t) (struct pw_command *command, struct pw_core *core, char **err); + /** \class pw_command * * A configuration command */ -struct pw_command; - -#include - +struct pw_command { + struct spa_list link; /**< link in list of commands */ + pw_command_func_t func; + char **args; + uint32_t id; /**< id of command */ + int n_args; +}; struct pw_command * -pw_command_parse(const char *line, char **err); +pw_command_parse(struct pw_properties *properties, const char *line, char **err); void pw_command_free(struct pw_command *command); diff --git a/src/daemon/daemon-config.c b/src/daemon/daemon-config.c index d6225c018..c70c314bf 100644 --- a/src/daemon/daemon-config.c +++ b/src/daemon/daemon-config.c @@ -32,9 +32,9 @@ #include #include -#include #include +#include "daemon/command.h" #include "daemon/daemon-config.h" #define DEFAULT_CONFIG_FILE PIPEWIRE_CONFIG_DIR "/pipewire.conf" @@ -45,7 +45,6 @@ parse_line(struct pw_daemon_config *config, { struct pw_command *command = NULL; char *p; - int ret = 0; char *local_err = NULL; /* search for comments */ @@ -55,17 +54,20 @@ parse_line(struct pw_daemon_config *config, /* remove whitespaces */ line = pw_strip(line, "\n\r \t"); if (*line == '\0') /* empty line */ - return 0; + goto out; - if ((command = pw_command_parse(line, &local_err)) == NULL) { - asprintf(err, "%s:%u: %s", filename, lineno, local_err); - free(local_err); - ret = -EINVAL; - } else { - spa_list_append(&config->commands, &command->link); - } + if ((command = pw_command_parse(config->properties, line, &local_err)) == NULL) + goto error_parse; - return ret; + spa_list_append(&config->commands, &command->link); + +out: + return 0; + +error_parse: + asprintf(err, "%s:%u: %s", filename, lineno, local_err); + free(local_err); + return -EINVAL; } /** @@ -73,14 +75,21 @@ parse_line(struct pw_daemon_config *config, * * Returns a new empty #struct pw_daemon_config. */ -struct pw_daemon_config *pw_daemon_config_new(void) +struct pw_daemon_config *pw_daemon_config_new(struct pw_properties *properties) { struct pw_daemon_config *config; config = calloc(1, sizeof(struct pw_daemon_config)); + if (config == NULL) + goto error_exit; + + config->properties = properties; spa_list_init(&config->commands); return config; + +error_exit: + return NULL; } /** diff --git a/src/daemon/daemon-config.h b/src/daemon/daemon-config.h index a88b62607..80ce2ee7d 100644 --- a/src/daemon/daemon-config.h +++ b/src/daemon/daemon-config.h @@ -34,9 +34,10 @@ extern "C" { struct pw_daemon_config { struct spa_list commands; + struct pw_properties *properties; }; -struct pw_daemon_config * pw_daemon_config_new(void); +struct pw_daemon_config * pw_daemon_config_new(struct pw_properties *properties); void pw_daemon_config_free(struct pw_daemon_config *config); diff --git a/src/daemon/main.c b/src/daemon/main.c index 90db53232..967321bfb 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -55,6 +55,7 @@ int main(int argc, char *argv[]) struct pw_core *core; struct pw_main_loop *loop; struct pw_daemon_config *config; + struct pw_properties *properties; char *err = NULL; static const struct option long_options[] = { {"help", 0, NULL, 'h'}, @@ -88,8 +89,12 @@ int main(int argc, char *argv[]) } } + properties = pw_properties_new( + PW_KEY_CORE_NAME, daemon_name, + PW_KEY_CORE_DAEMON, "1", NULL); + /* parse configuration */ - config = pw_daemon_config_new(); + config = pw_daemon_config_new(properties); if (pw_daemon_config_load(config, &err) < 0) { pw_log_error("failed to parse config: %s", err); free(err); @@ -97,15 +102,17 @@ int main(int argc, char *argv[]) } - loop = pw_main_loop_new(NULL); + loop = pw_main_loop_new(pw_properties_copy(properties)); + if (loop == NULL) { + pw_log_error("failed to create main-loop: %m"); + return -1; + } + pw_loop_add_signal(pw_main_loop_get_loop(loop), SIGINT, do_quit, loop); pw_loop_add_signal(pw_main_loop_get_loop(loop), SIGTERM, do_quit, loop); core = pw_core_new(pw_main_loop_get_loop(loop), - pw_properties_new( - PW_KEY_CORE_NAME, daemon_name, - PW_KEY_CORE_DAEMON, "1", NULL), - 0); + properties, 0); if (core == NULL) { pw_log_error("failed to create core: %m"); diff --git a/src/daemon/pipewire.conf.in b/src/daemon/pipewire.conf.in index 599073c71..9c4ee75a6 100644 --- a/src/daemon/pipewire.conf.in +++ b/src/daemon/pipewire.conf.in @@ -1,5 +1,7 @@ #daemon config file for PipeWire version @VERSION@ +#set-prop library.name.system support/libspa-support +#set-prop core.data-loop.library.name.system support/libspa-support add-spa-lib api.alsa.* alsa/libspa-alsa add-spa-lib api.v4l2.* v4l2/libspa-v4l2 diff --git a/src/pipewire/core.c b/src/pipewire/core.c index 32c6079a9..ebf29b593 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -463,9 +463,10 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop, { struct impl *impl; struct pw_core *this; - const char *name, *lib; + const char *name, *lib, *str; void *dbus_iface = NULL; uint32_t n_support; + struct pw_properties *pr; int res = 0; impl = calloc(1, sizeof(struct impl) + user_data_size); @@ -490,7 +491,11 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop, this->properties = properties; - this->data_loop_impl = pw_data_loop_new(pw_properties_copy(properties)); + pr = pw_properties_copy(properties); + if ((str = pw_properties_get(pr, "core.data-loop." PW_KEY_LIBRARY_NAME_SYSTEM))) + pw_properties_set(pr, PW_KEY_LIBRARY_NAME_SYSTEM, str); + + this->data_loop_impl = pw_data_loop_new(pr); if (this->data_loop_impl == NULL) { res = -errno; goto error_free; diff --git a/src/pipewire/data-loop.c b/src/pipewire/data-loop.c index c06f8cfa2..eeb731a82 100644 --- a/src/pipewire/data-loop.c +++ b/src/pipewire/data-loop.c @@ -78,14 +78,14 @@ struct pw_data_loop *pw_data_loop_new(struct pw_properties *properties) properties = NULL; if (this->loop == NULL) { res = -errno; - pw_log_debug("data-loop %p: can't create loop: %m", this); + pw_log_error("data-loop %p: can't create loop: %m", this); goto error_free; } this->event = pw_loop_add_event(this->loop, do_stop, this); if (this->event == NULL) { res = -errno; - pw_log_debug("data-loop %p: can't add event: %m", this); + pw_log_error("data-loop %p: can't add event: %m", this); goto error_loop_destroy; } @@ -150,7 +150,7 @@ int pw_data_loop_start(struct pw_data_loop *loop) loop->running = true; if ((err = pthread_create(&loop->thread, NULL, do_loop, loop)) != 0) { - pw_log_warn("data-loop %p: can't create thread: %s", loop, strerror(err)); + pw_log_error("data-loop %p: can't create thread: %s", loop, strerror(err)); loop->running = false; return -err; } diff --git a/src/pipewire/pipewire.c b/src/pipewire/pipewire.c index f3b2a382b..1ff8ecdde 100644 --- a/src/pipewire/pipewire.c +++ b/src/pipewire/pipewire.c @@ -111,12 +111,12 @@ open_plugin(struct registry *registry, if ((hnd = dlopen(filename, RTLD_NOW)) == NULL) { res = -ENOENT; - fprintf(stderr, "can't load %s: %s\n", filename, dlerror()); + pw_log_error("can't load %s: %s", filename, dlerror()); goto error_free_filename; } if ((enum_func = dlsym(hnd, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)) == NULL) { res = -ESRCH; - fprintf(stderr, "can't find enum function\n"); + pw_log_error("can't find enum function"); goto error_dlclose; } @@ -172,7 +172,7 @@ static const struct spa_handle_factory *find_factory(struct plugin *plugin, cons } res = -ENOENT; out: - fprintf(stderr, "can't find factory %s: %s", factory_name, spa_strerror(res)); + pw_log_error("can't find factory %s: %s", factory_name, spa_strerror(res)); errno = -res; return NULL; } @@ -238,14 +238,14 @@ struct spa_handle *pw_load_spa_handle(const char *lib, if ((plugin = open_plugin(sup->registry, sup->plugin_dir, lib)) == NULL) { res = -errno; - pw_log_warn("can't load '%s': %m", lib); + pw_log_error("can't load '%s': %m", lib); goto error_out; } factory = find_factory(plugin, factory_name); if (factory == NULL) { res = -errno; - pw_log_warn("can't find factory '%s': %m %s", factory_name, spa_strerror(res)); + pw_log_error("can't find factory '%s': %m %s", factory_name, spa_strerror(res)); goto error_unref_plugin; } @@ -258,7 +258,7 @@ struct spa_handle *pw_load_spa_handle(const char *lib, if ((res = spa_handle_factory_init(factory, &handle->handle, info, support, n_support)) < 0) { - pw_log_warn("can't make factory instance '%s': %d (%s)", + pw_log_error("can't make factory instance '%s': %d (%s)", factory_name, res, spa_strerror(res)); goto error_free_handle; } @@ -322,7 +322,7 @@ static void *add_interface(struct support *support, if (handle == NULL || (res = spa_handle_get_interface(handle, type, &iface)) < 0) { - fprintf(stderr, "can't get %d interface %d\n", type, res); + pw_log_error("can't get %d interface %d", type, res); } else { support->support[support->n_support++] = SPA_SUPPORT_INIT(type, iface); diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 4ba580683..f25d47607 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -51,19 +51,6 @@ extern "C" { #define MAX_PARAMS 32 -struct pw_command; - -typedef int (*pw_command_func_t) (struct pw_command *command, struct pw_core *core, char **err); - -/** \cond */ -struct pw_command { - struct spa_list link; /**< link in list of commands */ - pw_command_func_t func; - char **args; - uint32_t id; /**< id of command */ - int n_args; -}; - #define pw_protocol_emit_destroy(p) spa_hook_list_call(&p->listener_list, struct pw_protocol_events, destroy, 0) struct pw_protocol {