mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-15 06:59:58 -05:00
new configuration subsystem
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@210 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
07d563d6c3
commit
63b35d002a
23 changed files with 626 additions and 231 deletions
281
polyp/conf.c
281
polyp/conf.c
|
|
@ -27,12 +27,34 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <samplerate.h>
|
||||
|
||||
#include "conf.h"
|
||||
#include "util.h"
|
||||
#include "xmalloc.h"
|
||||
#include "strbuf.h"
|
||||
#include "confparser.h"
|
||||
|
||||
#ifndef DEFAULT_SCRIPT_FILE
|
||||
#define DEFAULT_SCRIPT_FILE "/etc/polypaudio/default.pa"
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_SCRIPT_FILE_USER
|
||||
#define DEFAULT_SCRIPT_FILE_USER ".polypaudio/default.pa"
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_CONFIG_FILE
|
||||
#define DEFAULT_CONFIG_FILE "/etc/polypaudio/daemon.conf"
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_CONFIG_FILE_USER
|
||||
#define DEFAULT_CONFIG_FILE_USER ".polypaudio/daemon.conf"
|
||||
#endif
|
||||
|
||||
#define ENV_SCRIPT_FILE "POLYP_SCRIPT"
|
||||
#define ENV_CONFIG_FILE "POLYP_CONFIG"
|
||||
#define ENV_DL_SEARCH_PATH "POLYP_DLPATH"
|
||||
|
||||
static const struct pa_conf default_conf = {
|
||||
.cmd = PA_CMD_DAEMON,
|
||||
|
|
@ -49,28 +71,9 @@ static const struct pa_conf default_conf = {
|
|||
.dl_search_path = NULL,
|
||||
.default_script_file = NULL,
|
||||
.log_target = PA_LOG_SYSLOG,
|
||||
.resample_method = SRC_SINC_FASTEST
|
||||
};
|
||||
|
||||
#define ENV_SCRIPT_FILE "POLYP_SCRIPT"
|
||||
#define ENV_CONFIG_FILE "POLYP_CONFIG"
|
||||
#define ENV_AUTOSPAWNED "POLYP_AUTOSPAWNED"
|
||||
|
||||
#ifndef DEFAULT_SCRIPT_FILE
|
||||
#define DEFAULT_SCRIPT_FILE "/etc/polypaudio/default.pa"
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_CONFIG_FILE
|
||||
#define DEFAULT_CONFIG_FILE "/etc/polypaudio/default.conf"
|
||||
#endif
|
||||
|
||||
#ifndef AUTOSPAWN_CONFIG_FILE
|
||||
#define AUTOSPAWN_CONFIG_FILE "/etc/polypaudio/autospawn.conf"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SCRIPT_FILE_LOCAL ".polypaudio.pa"
|
||||
#define DEFAULT_CONFIG_FILE_LOCAL ".polypaudio.conf"
|
||||
#define AUTOSPAWN_CONFIG_FILE_LOCAL ".polypaudio-autospawn.conf"
|
||||
|
||||
char* default_file(const char *envvar, const char *global, const char *local) {
|
||||
char *p, *h;
|
||||
|
||||
|
|
@ -80,9 +83,8 @@ char* default_file(const char *envvar, const char *global, const char *local) {
|
|||
return pa_xstrdup(p);
|
||||
|
||||
if ((h = getenv("HOME"))) {
|
||||
struct stat st;
|
||||
p = pa_sprintf_malloc("%s/%s", h, local);
|
||||
if (stat(p, &st) >= 0)
|
||||
if (!access(p, F_OK))
|
||||
return p;
|
||||
|
||||
pa_xfree(p);
|
||||
|
|
@ -91,26 +93,12 @@ char* default_file(const char *envvar, const char *global, const char *local) {
|
|||
return pa_xstrdup(global);
|
||||
}
|
||||
|
||||
char *default_config_file(void) {
|
||||
char *b;
|
||||
int autospawned = 0;
|
||||
|
||||
if ((b = getenv(ENV_AUTOSPAWNED)))
|
||||
autospawned = pa_parse_boolean(b) > 0;
|
||||
|
||||
return default_file(ENV_CONFIG_FILE,
|
||||
autospawned ? AUTOSPAWN_CONFIG_FILE : DEFAULT_CONFIG_FILE,
|
||||
autospawned ? AUTOSPAWN_CONFIG_FILE_LOCAL : DEFAULT_CONFIG_FILE_LOCAL);
|
||||
|
||||
}
|
||||
|
||||
char *default_script_file(void) {
|
||||
return default_file(ENV_SCRIPT_FILE, DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_LOCAL);
|
||||
}
|
||||
|
||||
struct pa_conf* pa_conf_new(void) {
|
||||
struct pa_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf));
|
||||
c->default_script_file = default_script_file();
|
||||
c->default_script_file = default_file(ENV_SCRIPT_FILE, DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER);
|
||||
#ifdef DLSEARCHPATH
|
||||
c->dl_search_path = pa_xstrdup(DLSEARCHPATH);
|
||||
#endif
|
||||
return c;
|
||||
}
|
||||
|
||||
|
|
@ -122,166 +110,104 @@ void pa_conf_free(struct pa_conf *c) {
|
|||
pa_xfree(c);
|
||||
}
|
||||
|
||||
#define WHITESPACE " \t\n"
|
||||
#define COMMENTS "#;\n"
|
||||
|
||||
#define PARSE_BOOLEAN(t, v) \
|
||||
do { \
|
||||
if (!strcmp(lvalue, t)) { \
|
||||
int b; \
|
||||
if ((b = pa_parse_boolean(rvalue)) < 0) \
|
||||
goto fail; \
|
||||
c->v = b; \
|
||||
return 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PARSE_STRING(t, v) \
|
||||
do { \
|
||||
if (!strcmp(lvalue, t)) { \
|
||||
pa_xfree(c->v); \
|
||||
c->v = *rvalue ? pa_xstrdup(rvalue) : NULL; \
|
||||
return 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PARSE_INTEGER(t, v) \
|
||||
do { \
|
||||
if (!strcmp(lvalue, t)) { \
|
||||
char *x = NULL; \
|
||||
int i = strtol(rvalue, &x, 0); \
|
||||
if (!x || *x) \
|
||||
goto fail; \
|
||||
c->v = i; \
|
||||
return 0; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static int next_assignment(struct pa_conf *c, char *lvalue, char *rvalue, unsigned n) {
|
||||
PARSE_BOOLEAN("daemonize", daemonize);
|
||||
PARSE_BOOLEAN("fail", fail);
|
||||
PARSE_BOOLEAN("verbose", verbose);
|
||||
PARSE_BOOLEAN("high-priority", high_priority);
|
||||
PARSE_BOOLEAN("disallow-module-loading", disallow_module_loading);
|
||||
|
||||
PARSE_INTEGER("exit-idle-time", exit_idle_time);
|
||||
PARSE_INTEGER("module-idle-time", module_idle_time);
|
||||
PARSE_INTEGER("scache-idle-time", scache_idle_time);
|
||||
int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
struct pa_conf *c = data;
|
||||
assert(filename && lvalue && rvalue && data);
|
||||
|
||||
PARSE_STRING("dl-search-path", dl_search_path);
|
||||
PARSE_STRING("default-script-file", default_script_file);
|
||||
|
||||
if (!strcmp(lvalue, "log-target")) {
|
||||
if (!strcmp(rvalue, "auto"))
|
||||
c->auto_log_target = 1;
|
||||
else if (!strcmp(rvalue, "syslog")) {
|
||||
c->auto_log_target = 0;
|
||||
c->log_target = PA_LOG_SYSLOG;
|
||||
} else if (!strcmp(rvalue, "stderr")) {
|
||||
c->auto_log_target = 0;
|
||||
c->log_target = PA_LOG_STDERR;
|
||||
} else
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
if (!strcmp(rvalue, "auto"))
|
||||
c->auto_log_target = 1;
|
||||
else if (!strcmp(rvalue, "syslog")) {
|
||||
c->auto_log_target = 0;
|
||||
c->log_target = PA_LOG_SYSLOG;
|
||||
} else if (!strcmp(rvalue, "stderr")) {
|
||||
c->auto_log_target = 0;
|
||||
c->log_target = PA_LOG_STDERR;
|
||||
} else {
|
||||
pa_log(__FILE__": [%s:%u] Invalid log target '%s'.\n", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fail:
|
||||
pa_log(__FILE__": line %u: parse error.\n", n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#undef PARSE_STRING
|
||||
#undef PARSE_BOOLEAN
|
||||
|
||||
static int in_string(char c, const char *s) {
|
||||
for (; *s; s++)
|
||||
if (*s == c)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *strip(char *s) {
|
||||
char *b = s+strspn(s, WHITESPACE);
|
||||
char *e, *l = NULL;
|
||||
int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
struct pa_conf *c = data;
|
||||
assert(filename && lvalue && rvalue && data);
|
||||
|
||||
for (e = b; *e; e++)
|
||||
if (!in_string(*e, WHITESPACE))
|
||||
l = e;
|
||||
|
||||
if (l)
|
||||
*(l+1) = 0;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
static int parse_line(struct pa_conf *conf, char *l, unsigned n) {
|
||||
char *e, *c, *b = l+strspn(l, WHITESPACE);
|
||||
|
||||
if ((c = strpbrk(b, COMMENTS)))
|
||||
*c = 0;
|
||||
|
||||
if (!*b)
|
||||
return 0;
|
||||
|
||||
if (!(e = strchr(b, '='))) {
|
||||
pa_log(__FILE__": line %u: missing '='.\n", n);
|
||||
if (!strcmp(rvalue, "sinc-best-quality"))
|
||||
c->resample_method = SRC_SINC_BEST_QUALITY;
|
||||
else if (!strcmp(rvalue, "sinc-medium-quality"))
|
||||
c->resample_method = SRC_SINC_MEDIUM_QUALITY;
|
||||
else if (!strcmp(rvalue, "sinc-fastest"))
|
||||
c->resample_method = SRC_SINC_FASTEST;
|
||||
else if (!strcmp(rvalue, "zero-order-hold"))
|
||||
c->resample_method = SRC_ZERO_ORDER_HOLD;
|
||||
else if (!strcmp(rvalue, "linear"))
|
||||
c->resample_method = SRC_LINEAR;
|
||||
else {
|
||||
pa_log(__FILE__": [%s:%u] Inavalid resample method '%s'.\n", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*e = 0;
|
||||
e++;
|
||||
|
||||
return next_assignment(conf, strip(b), strip(e), n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int pa_conf_load(struct pa_conf *c, const char *filename) {
|
||||
FILE *f;
|
||||
int r = 0;
|
||||
unsigned n = 0;
|
||||
char *def = NULL;
|
||||
assert(c);
|
||||
int r;
|
||||
|
||||
const struct pa_config_item table[] = {
|
||||
{ "verbose", pa_config_parse_bool, &c->verbose },
|
||||
{ "daemonize", pa_config_parse_bool, &c->daemonize },
|
||||
{ "fail", pa_config_parse_bool, &c->fail },
|
||||
{ "high-priority", pa_config_parse_bool, &c->high_priority },
|
||||
{ "disallow-module-loading", pa_config_parse_bool, &c->disallow_module_loading },
|
||||
{ "exit-idle-time", pa_config_parse_int, &c->exit_idle_time },
|
||||
{ "module-idle-time", pa_config_parse_int, &c->module_idle_time },
|
||||
{ "scache-idle-time", pa_config_parse_int, &c->scache_idle_time },
|
||||
{ "dl-search-path", pa_config_parse_string, &c->dl_search_path },
|
||||
{ "default-script-file", pa_config_parse_string, &c->default_script_file },
|
||||
{ "log-target", parse_log_target, c },
|
||||
{ "resample-method", parse_resample_method, c },
|
||||
{ NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
if (!filename)
|
||||
filename = def = default_config_file();
|
||||
|
||||
if (!(f = fopen(filename, "r"))) {
|
||||
if (errno != ENOENT)
|
||||
pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s\n", filename, strerror(errno));
|
||||
|
||||
goto finish;
|
||||
}
|
||||
|
||||
while (!feof(f)) {
|
||||
char l[256];
|
||||
if (!fgets(l, sizeof(l), f)) {
|
||||
if (!feof(f))
|
||||
pa_log(__FILE__": WARNING: failed to read configuration file '%s': %s\n", filename, strerror(errno));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (parse_line(c, l, ++n) < 0)
|
||||
r = -1;
|
||||
}
|
||||
|
||||
finish:
|
||||
|
||||
if (f)
|
||||
fclose(f);
|
||||
filename = def = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER);
|
||||
|
||||
r = pa_config_parse(filename, table, NULL);
|
||||
pa_xfree(def);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int pa_conf_env(struct pa_conf *c) {
|
||||
char *e;
|
||||
|
||||
if ((e = getenv(ENV_DL_SEARCH_PATH))) {
|
||||
pa_xfree(c->dl_search_path);
|
||||
c->dl_search_path = pa_xstrdup(e);
|
||||
}
|
||||
if ((e = getenv(ENV_SCRIPT_FILE))) {
|
||||
pa_xfree(c->default_script_file);
|
||||
c->default_script_file = pa_xstrdup(e);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *pa_conf_dump(struct pa_conf *c) {
|
||||
struct pa_strbuf *s = pa_strbuf_new();
|
||||
char *d;
|
||||
|
||||
d = default_config_file();
|
||||
static const char const* resample_methods[] = {
|
||||
"sinc-best-quality",
|
||||
"sinc-medium-quality",
|
||||
"sinc-fastest",
|
||||
"zero-order-hold",
|
||||
"linear"
|
||||
};
|
||||
|
||||
d = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER);
|
||||
pa_strbuf_printf(s, "### Default configuration file: %s ###\n", d);
|
||||
|
||||
pa_strbuf_printf(s, "verbose = %i\n", !!c->verbose);
|
||||
|
|
@ -295,6 +221,9 @@ char *pa_conf_dump(struct pa_conf *c) {
|
|||
pa_strbuf_printf(s, "dl-search-path = %s\n", c->dl_search_path ? c->dl_search_path : "");
|
||||
pa_strbuf_printf(s, "default-script-file = %s\n", c->default_script_file);
|
||||
pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr"));
|
||||
|
||||
assert(c->resample_method <= 4 && c->resample_method >= 0);
|
||||
pa_strbuf_printf(s, "resample-method = %s\n", resample_methods[c->resample_method]);
|
||||
|
||||
pa_xfree(d);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue