conf: more work on config changes

Add -c option to pipewire to select config file. Use this to select
the uninstalled conf file.
Rename conf properties, prefix with context.
Simplify the main daemon now that everything can go in config.
Simplify pipewire-pulse now that we can put everything in config, it's
now virtually the same as pipewire but with a differenct config file.
Parse server addresses as array of strings.
This commit is contained in:
Wim Taymans 2021-02-11 21:01:58 +01:00
parent fc90a4e48a
commit 80825aeaea
16 changed files with 104 additions and 156 deletions

View file

@ -17,7 +17,7 @@ run: all
PIPEWIRE_CONFIG_DIR=@BUILD_ROOT@/src/daemon/ \
ACP_PATHS_DIR=@SOURCE_ROOT@/spa/plugins/alsa/mixer/paths \
ACP_PROFILES_DIR=@SOURCE_ROOT@/spa/plugins/alsa/mixer/profile-sets \
$(DBG) @BUILD_ROOT@/src/daemon/pipewire
$(DBG) @BUILD_ROOT@/src/daemon/pipewire -c pipewire-uninstalled.conf
gdb:
$(MAKE) run DBG=gdb

View file

@ -2424,6 +2424,9 @@ jack_client_t * jack_client_open (const char *client_name,
client->context.l,
pw_properties_copy(client->props),
0);
if (client->context.context == NULL)
goto no_props;
client->allow_mlock = client->context.context->defaults.mem_allow_mlock;
client->warn_mlock = client->context.context->defaults.mem_warn_mlock;

View file

@ -1,6 +1,6 @@
# Daemon config file for PipeWire RT clients version @VERSION@ #
# Real-time Client config file for PipeWire version @VERSION@ #
properties = {
context.properties = {
## Configure properties in the system.
#mem.warn-mlock = false
#mem.allow-mlock = true
@ -8,7 +8,7 @@ properties = {
#log.level = 2
}
spa-libs = {
context.spa-libs = {
## <factory-name regex> = <library-name>
#
# Used to find spa factory names. It maps an spa factory name
@ -19,7 +19,7 @@ spa-libs = {
support.* = support/libspa-support
}
modules = {
context.modules = {
## <module-name> = { [args = { <key>=<value> ... }]
# [flags = [ [ifexists] [nofail] ]}
#

View file

@ -1,6 +1,5 @@
# Daemon config file for PipeWire clients version @VERSION@ #
properties = {
# Client config file for PipeWire version @VERSION@ #
context.properties = {
## Configure properties in the system.
#mem.warn-mlock = false
#mem.allow-mlock = true
@ -8,7 +7,7 @@ properties = {
#log.level = 2
}
spa-libs = {
context.spa-libs = {
## <factory-name regex> = <library-name>
#
# Used to find spa factory names. It maps an spa factory name
@ -19,7 +18,7 @@ spa-libs = {
support.* = support/libspa-support
}
modules = {
context.modules = {
## <module-name> = { [args = { <key>=<value> ... }]
# [flags = [ [ifexists] [nofail] ]}
#

View file

@ -1,6 +1,6 @@
# Daemon config file for PipeWire JACK clients version @VERSION@ #
# JACK client config file for PipeWire version @VERSION@ #
properties = {
context.properties = {
## Configure properties in the system.
#mem.warn-mlock = false
#mem.allow-mlock = true
@ -8,7 +8,7 @@ properties = {
#log.level = 2
}
spa-libs = {
context.spa-libs = {
## <factory-name regex> = <library-name>
#
# Used to find spa factory names. It maps an spa factory name
@ -18,7 +18,7 @@ spa-libs = {
support.* = support/libspa-support
}
modules = {
context.modules = {
## <module-name> = { [args = { <key>=<value> ... }]
# [flags = [ [ifexists] [nofail] ]}
#

View file

@ -24,56 +24,39 @@
#include <signal.h>
#include <getopt.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <spa/utils/result.h>
#include <spa/utils/json.h>
#include <pipewire/impl.h>
#include <pipewire/pipewire.h>
#include "config.h"
#define NAME "daemon"
#define DEFAULT_CONFIG_FILE "pipewire.conf"
struct data {
struct pw_context *context;
struct pw_main_loop *loop;
const char *daemon_name;
};
static const char *config_name = "pipewire.conf";
static void do_quit(void *data, int signal_number)
{
struct data *d = data;
pw_main_loop_quit(d->loop);
struct pw_main_loop *loop = data;
pw_main_loop_quit(loop);
}
static void show_help(struct data *d, const char *name)
static void show_help(const char *name)
{
fprintf(stdout, "%s [options]\n"
" -h, --help Show this help\n"
" --version Show version\n"
" -n, --name Daemon name (Default %s)\n",
" -c, --config Load config (Default %s)\n",
name,
d->daemon_name);
config_name);
}
int main(int argc, char *argv[])
{
struct data d;
struct pw_context *context;
struct pw_main_loop *loop;
struct pw_properties *properties;
static const struct option long_options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ "name", required_argument, NULL, 'n' },
{ "config", required_argument, NULL, 'c' },
{ NULL, 0, NULL, 0}
};
@ -82,19 +65,14 @@ int main(int argc, char *argv[])
if (setenv("PIPEWIRE_INTERNAL", "1", 1) < 0)
fprintf(stderr, "can't set PIPEWIRE_INTERNAL env: %m");
spa_zero(d);
pw_init(&argc, &argv);
d.daemon_name = getenv("PIPEWIRE_CORE");
if (d.daemon_name == NULL)
d.daemon_name = PW_DEFAULT_REMOTE;
while ((c = getopt_long(argc, argv, "hVn:", long_options, NULL)) != -1) {
while ((c = getopt_long(argc, argv, "hVc:", long_options, NULL)) != -1) {
switch (c) {
case 'h' :
show_help(&d, argv[0]);
case 'h':
show_help(argv[0]);
return 0;
case 'V' :
case 'V':
fprintf(stdout, "%s\n"
"Compiled with libpipewire %s\n"
"Linked with libpipewire %s\n",
@ -102,9 +80,8 @@ int main(int argc, char *argv[])
pw_get_headers_version(),
pw_get_library_version());
return 0;
case 'n' :
d.daemon_name = optarg;
fprintf(stdout, "set name %s\n", d.daemon_name);
case 'c':
config_name = optarg;
break;
default:
return -1;
@ -112,31 +89,30 @@ int main(int argc, char *argv[])
}
properties = pw_properties_new(
PW_KEY_CORE_NAME, d.daemon_name,
PW_KEY_CONFIG_NAME, "pipewire-uninstalled.conf",
PW_KEY_CORE_DAEMON, "true", NULL);
PW_KEY_CONFIG_NAME, config_name,
NULL);
d.loop = pw_main_loop_new(&properties->dict);
if (d.loop == NULL) {
loop = pw_main_loop_new(&properties->dict);
if (loop == NULL) {
pw_log_error("failed to create main-loop: %m");
return -1;
}
pw_loop_add_signal(pw_main_loop_get_loop(d.loop), SIGINT, do_quit, &d);
pw_loop_add_signal(pw_main_loop_get_loop(d.loop), SIGTERM, do_quit, &d);
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);
d.context = pw_context_new(pw_main_loop_get_loop(d.loop), properties, 0);
if (d.context == NULL) {
context = pw_context_new(pw_main_loop_get_loop(loop), properties, 0);
if (context == NULL) {
pw_log_error("failed to create context: %m");
return -1;
}
pw_log_info("start main loop");
pw_main_loop_run(d.loop);
pw_main_loop_run(loop);
pw_log_info("leave main loop");
pw_context_destroy(d.context);
pw_main_loop_destroy(d.loop);
pw_context_destroy(context);
pw_main_loop_destroy(loop);
pw_deinit();
return 0;

View file

@ -1,6 +1,5 @@
# Media session config file #
properties = {
context.properties = {
# Properties to configure the session and some
# modules.
#mem.mlock-all = false
@ -8,7 +7,7 @@ properties = {
#dbus = true
}
spa-libs = {
context.spa-libs = {
# Mapping from factory name to library.
api.bluez5.* = bluez5/libspa-bluez5
api.alsa.* = alsa/libspa-alsa
@ -16,7 +15,7 @@ spa-libs = {
api.libcamera.* = libcamera/libspa-libcamera
}
modules = {
context.modules = {
## <module-name> = { [args = { <key>=<value> ... }]
# [flags = [ [ifexists] [nofail] ]}
#

View file

@ -11,12 +11,15 @@ pipewire_c_args = [
conf_config = configuration_data()
conf_config.set('VERSION', '"@0@"'.format(pipewire_version))
conf_config.set('media_session_path', join_paths(pipewire_bindir, 'pipewire-media-session'))
conf_config.set('pipewire_path', join_paths(pipewire_bindir, 'pipewire'))
conf_config.set('pipewire_pulse_path', join_paths(pipewire_bindir, 'pipewire-pulse'))
conf_install_dir = join_paths(get_option('sysconfdir'), 'pipewire')
conf_config_uninstalled = conf_config
conf_config_uninstalled.set('media_session_path',
join_paths(meson.build_root(), 'src', 'examples', 'pipewire-media-session'))
conf_config_uninstalled.set('pipewire_path',
join_paths(meson.build_root(), 'src', 'daemon', 'pipewire'))
conf_config_uninstalled.set('pipewire_pulse_path',
join_paths(meson.build_root(), 'src', 'daemon', 'pipewire-pulse'))

View file

@ -27,11 +27,11 @@
#include <spa/utils/result.h>
#include <pipewire/impl.h>
#include <pipewire/pipewire.h>
#include "config.h"
static const char *address;
static const char *config_name = "pipewire-pulse.conf";
static void do_quit(void *data, int signal_number)
{
@ -45,11 +45,9 @@ static void show_help(const char *name)
"Start a pulseaudio compatible daemon.\n\n"
" -h, --help Show this help\n"
" --version Show version\n"
" -a --address comma separated list of addresses (Default %s)\n"
" unix:<socket-name>\n"
" tcp:[<ip>][:<port>]\n",
" -c, --config Load config (Default %s)\n",
name,
address);
config_name);
}
int main(int argc, char *argv[])
@ -57,20 +55,17 @@ int main(int argc, char *argv[])
struct pw_context *context;
struct pw_main_loop *loop;
struct pw_properties *properties;
char *args;
static const struct option long_options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ "address", required_argument, NULL, 'a' },
{ "config", required_argument, NULL, 'c' },
{ NULL, 0, NULL, 0}
};
int c;
pw_init(&argc, &argv);
address = "unix:native";
while ((c = getopt_long(argc, argv, "hVa:", long_options, NULL)) != -1) {
while ((c = getopt_long(argc, argv, "hVc:", long_options, NULL)) != -1) {
switch (c) {
case 'h':
show_help(argv[0]);
@ -83,9 +78,8 @@ int main(int argc, char *argv[])
pw_get_headers_version(),
pw_get_library_version());
return 0;
case 'a':
address = optarg;
fprintf(stdout, "set address %s\n", address);
case 'c':
config_name = optarg;
break;
default:
return -1;
@ -93,7 +87,7 @@ int main(int argc, char *argv[])
}
properties = pw_properties_new(
PW_KEY_CONFIG_NAME, "pipewire-pulse.conf",
PW_KEY_CONFIG_NAME, config_name,
NULL);
loop = pw_main_loop_new(&properties->dict);
@ -111,19 +105,10 @@ int main(int argc, char *argv[])
return -1;
}
args = spa_aprintf("server.address=\"%s\"", address);
if (pw_context_load_module(context,
"libpipewire-module-protocol-pulse",
args, NULL) == NULL) {
pw_log_error("failed to create pulse module: %m");
return -1;
}
pw_log_info("start main loop");
pw_main_loop_run(loop);
pw_log_info("leave main loop");
free(args);
pw_context_destroy(context);
pw_main_loop_destroy(loop);
pw_deinit();

View file

@ -1,6 +1,5 @@
# Daemon config file for PipeWire pulse version @VERSION@ #
properties = {
# PulseAudio config file for PipeWire version @VERSION@ #
context.properties = {
## Configure properties in the system.
#mem.warn-mlock = false
#mem.allow-mlock = true
@ -8,49 +7,30 @@ properties = {
#log.level = 2
}
spa-libs = {
## <factory-name regex> = <library-name>
#
# Used to find spa factory names. It maps an spa factory name
# regular expression to a library name that should contain
# that factory.
#
context.spa-libs = {
audio.convert* = audioconvert/libspa-audioconvert
support.* = support/libspa-support
}
modules = {
## <module-name> = { [args = { <key>=<value> ... }]
# [flags = [ [ifexists] [nofail] ]}
#
# Loads a module with the given parameters.
# If ifexists is given, the module is ignored when it is not found.
# If nofail is given, module initialization failures are ignored.
#
# Uses RTKit to boost the data thread priority.
context.modules = {
libpipewire-module-rtkit = {
args = {
nice.level = -14
#nice.level = -11
#rt.prio = 20
#rt.time.soft = 200000
#rt.time.hard = 200000
}
flags = [ ifexists nofail ]
}
# The native communication protocol.
libpipewire-module-protocol-native = null
# Allows creating nodes that run in the context of the
# client. Is used by all clients that want to provide
# data to PipeWire.
libpipewire-module-client-node = null
# Makes a factory for wrapping nodes in an adapter with a
# converter and resampler.
libpipewire-module-adapter = null
# Allows applications to create metadata objects. It creates
# a factory for Metadata objects.
libpipewire-module-metadata = null
libpipewire-module-protocol-pulse = {
args = {
server.address = [
"unix:native"
# "tcp:4713"
}
}
}

View file

@ -1,6 +1,5 @@
# Daemon config file for PipeWire version @VERSION@ #
properties = {
context.properties = {
## Configure properties in the system.
#library.name.system = support/libspa-support
#context.data-loop.library.name.system = support/libspa-support
@ -11,6 +10,9 @@ properties = {
#mem.mlock-all = false
#log.level = 2
core.daemon = true # listening for socket connections
core.name = pipewire-0 # core name and socket name
## Properties for the DSP configuration.
#default.clock.rate = 48000
#default.clock.quantum = 1024
@ -22,7 +24,7 @@ properties = {
#default.video.rate.denom = 1
}
spa-libs = {
context.spa-libs = {
#<factory-name regex> = <library-name>
#
# Used to find spa factory names. It maps an spa factory name
@ -41,7 +43,7 @@ spa-libs = {
#audiotestsrc = audiotestsrc/libspa-audiotestsrc
}
modules = {
context.modules = {
#<module-name> = {
# [ args = { <key> = <value> ... } ]
# [ flags = [ [ ifexists ] [ nofail ] ]
@ -130,7 +132,7 @@ modules = {
libpipewire-module-session-manager = null
}
objects = {
context.objects = {
#<factory-name> = {
# [ args = { <key> = <value> ... } ]
# [ flags = [ [ nofail ] ]
@ -168,7 +170,7 @@ objects = {
#}
}
exec = {
context.exec = {
#<program-name> = { [ args = "<arguments>" ] }
#
# Execute the given program with arguments.
@ -183,5 +185,5 @@ exec = {
# It can be interesting to start another daemon here that listens
# on another address with the -a option (eg. -a tcp:4713).
#
#"@pipewire_pulse_path@" = { "#args" = "-a tcp:4713" }
#"@pipewire_path@" = { args = "-c pipewire-pulse.conf" }
}

View file

@ -5736,8 +5736,9 @@ struct pw_protocol_pulse *pw_protocol_pulse_new(struct pw_context *context,
{
struct impl *impl;
const char *str;
int i, n_addr;
char **addr, *free_str = NULL;
char *free_str = NULL;
struct spa_json it[2];
char value[512];
impl = calloc(1, sizeof(struct impl) + user_data_size);
if (impl == NULL)
@ -5747,7 +5748,7 @@ struct pw_protocol_pulse *pw_protocol_pulse_new(struct pw_context *context,
if (props != NULL)
str = pw_properties_get(props, "server.address");
if (str == NULL) {
str = free_str = spa_aprintf("%s-%s",
str = free_str = spa_aprintf("[ \"%s-%s\" ]",
PW_PROTOCOL_PULSE_DEFAULT_SERVER,
get_server_name(context));
}
@ -5775,16 +5776,15 @@ struct pw_protocol_pulse *pw_protocol_pulse_new(struct pw_context *context,
pw_context_add_listener(context, &impl->context_listener,
&context_events, impl);
addr = pw_split_strv(str, ",", INT_MAX, &n_addr);
for (i = 0; i < n_addr; i++) {
if (addr[i] == NULL)
continue;
if (create_server(impl, addr[i]) == NULL) {
pw_log_warn(NAME" %p: can't create server for %s: %m",
impl, addr[i]);
spa_json_init(&it[0], str, strlen(str));
if (spa_json_enter_array(&it[0], &it[1]) > 0) {
while (spa_json_get_string(&it[1], value, sizeof(value)-1) > 0) {
if (create_server(impl, value) == NULL) {
pw_log_warn(NAME" %p: can't create server for %s: %m",
impl, value);
}
}
}
pw_free_strv(addr);
free(free_str);
dbus_request_name(context, "org.pulseaudio.Server");

View file

@ -535,13 +535,13 @@ int pw_context_parse_conf_section(struct pw_context *context,
if ((str = pw_properties_get(conf, section)) == NULL)
return -ENOENT;
if (strcmp(section, "spa-libs") == 0)
if (strcmp(section, "context.spa-libs") == 0)
res = parse_spa_libs(context, str);
else if (strcmp(section, "modules") == 0)
else if (strcmp(section, "context.modules") == 0)
res = parse_modules(context, str);
else if (strcmp(section, "objects") == 0)
else if (strcmp(section, "context.objects") == 0)
res = parse_objects(context, str);
else if (strcmp(section, "exec") == 0)
else if (strcmp(section, "context.exec") == 0)
res = parse_exec(context, str);
else
res = -EINVAL;

View file

@ -219,8 +219,11 @@ struct pw_context *pw_context_new(struct pw_loop *main_loop,
this, conf_name, spa_strerror(res));
goto error_free;
} else {
pw_log_warn(NAME" %p: can't load config %s: %s. Using client.conf fallback",
this, conf_name, spa_strerror(res));
pw_log_warn(NAME" %p: can't load config %s%s%s: %s. Using client.conf fallback",
this,
conf_prefix ? conf_prefix : "",
conf_prefix ? "/" : "",
conf_name, spa_strerror(res));
}
conf_prefix = NULL;
if ((res = pw_conf_load_conf(NULL, "client.conf", conf)) < 0) {
@ -231,7 +234,7 @@ struct pw_context *pw_context_new(struct pw_loop *main_loop,
}
this->conf = conf;
if ((str = pw_properties_get(conf, "properties")) != NULL)
if ((str = pw_properties_get(conf, "context.properties")) != NULL)
pw_properties_update_string(properties, str, strlen(str));
if ((str = pw_properties_get(properties, "mem.mlock-all")) != NULL &&
@ -329,10 +332,10 @@ struct pw_context *pw_context_new(struct pw_loop *main_loop,
this->sc_pagesize = sysconf(_SC_PAGESIZE);
pw_context_parse_conf_section(this, conf, "spa-libs");
pw_context_parse_conf_section(this, conf, "modules");
pw_context_parse_conf_section(this, conf, "objects");
pw_context_parse_conf_section(this, conf, "exec");
pw_context_parse_conf_section(this, conf, "context.spa-libs");
pw_context_parse_conf_section(this, conf, "context.modules");
pw_context_parse_conf_section(this, conf, "context.objects");
pw_context_parse_conf_section(this, conf, "context.exec");
pw_log_debug(NAME" %p: created", this);

View file

@ -65,7 +65,6 @@ extern "C" {
/* context */
#define PW_KEY_CONTEXT_PROFILE_MODULES "context.profile.modules" /**< a context profile for modules, deprecated */
#define PW_KEY_CONTEXT_MODULES_ARGS "context.modules.args" /**< arguments for context modules */
#define PW_KEY_USER_NAME "context.user-name" /**< The user name that runs pipewire */
#define PW_KEY_HOST_NAME "context.host-name" /**< The host name of the machine */

View file

@ -530,7 +530,6 @@ static void core_dump(struct object *o)
put_value(d, "host-name", i->host_name);
put_value(d, "version", i->version);
put_value(d, "name", i->name);
put_value(d, "name", i->name);
put_flags(d, "change-mask", i->change_mask, fl);
put_dict(d, "props", i->props);
put_end(d, "}", 0);