mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-31 22:25:33 -04: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
1
doc/todo
1
doc/todo
|
|
@ -5,6 +5,7 @@
|
||||||
- fix tcp/native in regard to latencies
|
- fix tcp/native in regard to latencies
|
||||||
- add client config file
|
- add client config file
|
||||||
- remove autospawn stuff in conf.c
|
- remove autospawn stuff in conf.c
|
||||||
|
- make resampler configurable
|
||||||
|
|
||||||
*** 0.6 ****
|
*** 0.6 ****
|
||||||
- per-channel volume
|
- per-channel volume
|
||||||
|
|
|
||||||
|
|
@ -25,14 +25,14 @@ modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@
|
||||||
AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS)
|
AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS)
|
||||||
AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\"
|
AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\"
|
||||||
AM_CFLAGS+=-DDEFAULT_SCRIPT_FILE=\"$(polypconfdir)/default.pa\"
|
AM_CFLAGS+=-DDEFAULT_SCRIPT_FILE=\"$(polypconfdir)/default.pa\"
|
||||||
AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/default.conf\"
|
AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/daemon.conf\"
|
||||||
AM_CFLAGS+=-DAUTOSPAWN_CONFIG_FILE=\"$(polypconfdir)/autospawn.conf\"
|
AM_CFLAGS+=-DDEFAULT_CLIENT_CONFIG_FILE=\"$(polypconfdir)/client.conf\"
|
||||||
AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\"
|
AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\"
|
||||||
|
|
||||||
AM_LDADD=$(PTHREAD_LIBS) -lm
|
AM_LDADD=$(PTHREAD_LIBS) -lm
|
||||||
AM_LIBADD=$(PTHREAD_LIBS) -lm
|
AM_LIBADD=$(PTHREAD_LIBS) -lm
|
||||||
|
|
||||||
EXTRA_DIST = default.pa config depmod.py esdcompat.sh.in
|
EXTRA_DIST = default.pa daemon.conf client.conf config depmod.py esdcompat.sh.in
|
||||||
bin_PROGRAMS = polypaudio pacat pactl
|
bin_PROGRAMS = polypaudio pacat pactl
|
||||||
bin_SCRIPTS = esdcompat.sh
|
bin_SCRIPTS = esdcompat.sh
|
||||||
noinst_PROGRAMS = \
|
noinst_PROGRAMS = \
|
||||||
|
|
@ -42,7 +42,7 @@ noinst_PROGRAMS = \
|
||||||
cpulimit-test \
|
cpulimit-test \
|
||||||
cpulimit-test2
|
cpulimit-test2
|
||||||
|
|
||||||
polypconf_DATA=default.pa config
|
polypconf_DATA=default.pa daemon.conf client.conf
|
||||||
|
|
||||||
BUILT_SOURCES=polyplib-version.h
|
BUILT_SOURCES=polyplib-version.h
|
||||||
|
|
||||||
|
|
@ -158,7 +158,8 @@ polypaudio_SOURCES = idxset.c idxset.h \
|
||||||
gcc-printf.h \
|
gcc-printf.h \
|
||||||
modinfo.c modinfo.h \
|
modinfo.c modinfo.h \
|
||||||
conf.c conf.h \
|
conf.c conf.h \
|
||||||
dumpmodules.c dumpmodules.h
|
dumpmodules.c dumpmodules.h \
|
||||||
|
conparser.h confparser.c
|
||||||
|
|
||||||
polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
|
polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
|
||||||
polypaudio_INCLUDES = $(INCLTDL)
|
polypaudio_INCLUDES = $(INCLTDL)
|
||||||
|
|
@ -332,7 +333,9 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \
|
||||||
cdecl.h \
|
cdecl.h \
|
||||||
llist.h \
|
llist.h \
|
||||||
log.c log.h \
|
log.c log.h \
|
||||||
gcc-printf.h
|
gcc-printf.h \
|
||||||
|
config-client.c config-client.h \
|
||||||
|
confparser.c confparser.h
|
||||||
|
|
||||||
libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS)
|
libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS)
|
||||||
libpolyp_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
|
libpolyp_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
|
||||||
|
|
|
||||||
39
polyp/client.conf
Normal file
39
polyp/client.conf
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
# $Id$
|
||||||
|
#
|
||||||
|
# This file is part of polypaudio.
|
||||||
|
#
|
||||||
|
# polypaudio is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# polypaudio is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with polypaudio; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
# USA.
|
||||||
|
|
||||||
|
## Configuration file for polypaudio clients. Default values are
|
||||||
|
## commented out. Use either ; or # for commenting
|
||||||
|
|
||||||
|
## Path to the polypaudio daemon to run when autospawning.
|
||||||
|
; daemon_binary = @POLYPAUDIO_BINARY
|
||||||
|
|
||||||
|
## Extra arguments to pass to the polypaudio daemon
|
||||||
|
; extra_arguments = --daemonize=yes --log-target=syslog
|
||||||
|
|
||||||
|
## The default sink to connect to
|
||||||
|
; default_sink =
|
||||||
|
|
||||||
|
## The default source to connect to
|
||||||
|
; default_source =
|
||||||
|
|
||||||
|
## The default sever to connect to
|
||||||
|
; default_server =
|
||||||
|
|
||||||
|
## Autospawn daemons?
|
||||||
|
; autospawn = 0
|
||||||
281
polyp/conf.c
281
polyp/conf.c
|
|
@ -27,12 +27,34 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/stat.h>
|
#include <unistd.h>
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "strbuf.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 = {
|
static const struct pa_conf default_conf = {
|
||||||
.cmd = PA_CMD_DAEMON,
|
.cmd = PA_CMD_DAEMON,
|
||||||
|
|
@ -49,28 +71,9 @@ static const struct pa_conf default_conf = {
|
||||||
.dl_search_path = NULL,
|
.dl_search_path = NULL,
|
||||||
.default_script_file = NULL,
|
.default_script_file = NULL,
|
||||||
.log_target = PA_LOG_SYSLOG,
|
.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* default_file(const char *envvar, const char *global, const char *local) {
|
||||||
char *p, *h;
|
char *p, *h;
|
||||||
|
|
||||||
|
|
@ -80,9 +83,8 @@ char* default_file(const char *envvar, const char *global, const char *local) {
|
||||||
return pa_xstrdup(p);
|
return pa_xstrdup(p);
|
||||||
|
|
||||||
if ((h = getenv("HOME"))) {
|
if ((h = getenv("HOME"))) {
|
||||||
struct stat st;
|
|
||||||
p = pa_sprintf_malloc("%s/%s", h, local);
|
p = pa_sprintf_malloc("%s/%s", h, local);
|
||||||
if (stat(p, &st) >= 0)
|
if (!access(p, F_OK))
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
pa_xfree(p);
|
pa_xfree(p);
|
||||||
|
|
@ -91,26 +93,12 @@ char* default_file(const char *envvar, const char *global, const char *local) {
|
||||||
return pa_xstrdup(global);
|
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* pa_conf_new(void) {
|
||||||
struct pa_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf));
|
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;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,166 +110,104 @@ void pa_conf_free(struct pa_conf *c) {
|
||||||
pa_xfree(c);
|
pa_xfree(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WHITESPACE " \t\n"
|
int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||||
#define COMMENTS "#;\n"
|
struct pa_conf *c = data;
|
||||||
|
assert(filename && lvalue && rvalue && data);
|
||||||
|
|
||||||
#define PARSE_BOOLEAN(t, v) \
|
if (!strcmp(rvalue, "auto"))
|
||||||
do { \
|
c->auto_log_target = 1;
|
||||||
if (!strcmp(lvalue, t)) { \
|
else if (!strcmp(rvalue, "syslog")) {
|
||||||
int b; \
|
c->auto_log_target = 0;
|
||||||
if ((b = pa_parse_boolean(rvalue)) < 0) \
|
c->log_target = PA_LOG_SYSLOG;
|
||||||
goto fail; \
|
} else if (!strcmp(rvalue, "stderr")) {
|
||||||
c->v = b; \
|
c->auto_log_target = 0;
|
||||||
return 0; \
|
c->log_target = PA_LOG_STDERR;
|
||||||
} \
|
} else {
|
||||||
} while (0)
|
pa_log(__FILE__": [%s:%u] Invalid log target '%s'.\n", filename, line, rvalue);
|
||||||
|
return -1;
|
||||||
#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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *strip(char *s) {
|
int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||||
char *b = s+strspn(s, WHITESPACE);
|
struct pa_conf *c = data;
|
||||||
char *e, *l = NULL;
|
assert(filename && lvalue && rvalue && data);
|
||||||
|
|
||||||
for (e = b; *e; e++)
|
if (!strcmp(rvalue, "sinc-best-quality"))
|
||||||
if (!in_string(*e, WHITESPACE))
|
c->resample_method = SRC_SINC_BEST_QUALITY;
|
||||||
l = e;
|
else if (!strcmp(rvalue, "sinc-medium-quality"))
|
||||||
|
c->resample_method = SRC_SINC_MEDIUM_QUALITY;
|
||||||
if (l)
|
else if (!strcmp(rvalue, "sinc-fastest"))
|
||||||
*(l+1) = 0;
|
c->resample_method = SRC_SINC_FASTEST;
|
||||||
|
else if (!strcmp(rvalue, "zero-order-hold"))
|
||||||
return b;
|
c->resample_method = SRC_ZERO_ORDER_HOLD;
|
||||||
}
|
else if (!strcmp(rvalue, "linear"))
|
||||||
|
c->resample_method = SRC_LINEAR;
|
||||||
static int parse_line(struct pa_conf *conf, char *l, unsigned n) {
|
else {
|
||||||
char *e, *c, *b = l+strspn(l, WHITESPACE);
|
pa_log(__FILE__": [%s:%u] Inavalid resample method '%s'.\n", filename, line, rvalue);
|
||||||
|
|
||||||
if ((c = strpbrk(b, COMMENTS)))
|
|
||||||
*c = 0;
|
|
||||||
|
|
||||||
if (!*b)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!(e = strchr(b, '='))) {
|
|
||||||
pa_log(__FILE__": line %u: missing '='.\n", n);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*e = 0;
|
return 0;
|
||||||
e++;
|
|
||||||
|
|
||||||
return next_assignment(conf, strip(b), strip(e), n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int pa_conf_load(struct pa_conf *c, const char *filename) {
|
int pa_conf_load(struct pa_conf *c, const char *filename) {
|
||||||
FILE *f;
|
|
||||||
int r = 0;
|
|
||||||
unsigned n = 0;
|
|
||||||
char *def = NULL;
|
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)
|
if (!filename)
|
||||||
filename = def = default_config_file();
|
filename = def = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
r = pa_config_parse(filename, table, NULL);
|
||||||
pa_xfree(def);
|
pa_xfree(def);
|
||||||
|
|
||||||
return r;
|
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) {
|
char *pa_conf_dump(struct pa_conf *c) {
|
||||||
struct pa_strbuf *s = pa_strbuf_new();
|
struct pa_strbuf *s = pa_strbuf_new();
|
||||||
char *d;
|
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, "### Default configuration file: %s ###\n", d);
|
||||||
|
|
||||||
pa_strbuf_printf(s, "verbose = %i\n", !!c->verbose);
|
pa_strbuf_printf(s, "verbose = %i\n", !!c->verbose);
|
||||||
|
|
@ -296,6 +222,9 @@ char *pa_conf_dump(struct pa_conf *c) {
|
||||||
pa_strbuf_printf(s, "default-script-file = %s\n", c->default_script_file);
|
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"));
|
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);
|
pa_xfree(d);
|
||||||
|
|
||||||
return pa_strbuf_tostring_free(s);
|
return pa_strbuf_tostring_free(s);
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ struct pa_conf {
|
||||||
auto_log_target;
|
auto_log_target;
|
||||||
char *script_commands, *dl_search_path, *default_script_file;
|
char *script_commands, *dl_search_path, *default_script_file;
|
||||||
enum pa_log_target log_target;
|
enum pa_log_target log_target;
|
||||||
|
int resample_method;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pa_conf* pa_conf_new(void);
|
struct pa_conf* pa_conf_new(void);
|
||||||
|
|
|
||||||
138
polyp/config-client.c
Normal file
138
polyp/config-client.c
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/***
|
||||||
|
This file is part of polypaudio.
|
||||||
|
|
||||||
|
polypaudio is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published
|
||||||
|
by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
polypaudio is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with polypaudio; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
USA.
|
||||||
|
***/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "config-client.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "confparser.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#ifndef DEFAULT_CLIENT_CONFIG_FILE
|
||||||
|
#define DEFAULT_CLIENT_CONFIG_FILE "/etc/polypaudio/client.conf"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DEFAULT_CLIENT_CONFIG_FILE_USER
|
||||||
|
#define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio/client.conf"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ENV_CLIENT_CONFIG_FILE "POLYP_CLIENTCONFIG"
|
||||||
|
#define ENV_DEFAULT_SINK "POLYP_SINK"
|
||||||
|
#define ENV_DEFAULT_SOURCE "POLYP_SOURCE"
|
||||||
|
#define ENV_DEFAULT_SERVER "POLYP_SERVER"
|
||||||
|
#define ENV_DAEMON_BINARY "POLYP_BINARY"
|
||||||
|
|
||||||
|
|
||||||
|
static const struct pa_client_conf default_conf = {
|
||||||
|
.daemon_binary = NULL,
|
||||||
|
.extra_arguments = NULL,
|
||||||
|
.default_sink = NULL,
|
||||||
|
.default_source = NULL,
|
||||||
|
.default_server = NULL,
|
||||||
|
.autospawn = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pa_client_conf *pa_client_conf_new(void) {
|
||||||
|
struct pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf));
|
||||||
|
|
||||||
|
c->daemon_binary = pa_xstrdup(POLYPAUDIO_BINARY);
|
||||||
|
c->extra_arguments = pa_xstrdup("--daemonize=yes --log-target=syslog");
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pa_client_conf_free(struct pa_client_conf *c) {
|
||||||
|
assert(c);
|
||||||
|
pa_xfree(c->daemon_binary);
|
||||||
|
pa_xfree(c->extra_arguments);
|
||||||
|
pa_xfree(c->default_sink);
|
||||||
|
pa_xfree(c->default_source);
|
||||||
|
pa_xfree(c->default_server);
|
||||||
|
pa_xfree(c);
|
||||||
|
}
|
||||||
|
int pa_client_conf_load(struct pa_client_conf *c, const char *filename) {
|
||||||
|
char *def = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
const struct pa_config_item table[] = {
|
||||||
|
{ "daemon-binary", pa_config_parse_string, &c->daemon_binary },
|
||||||
|
{ "extra-arguments", pa_config_parse_string, &c->extra_arguments },
|
||||||
|
{ "default-sink", pa_config_parse_string, &c->default_sink },
|
||||||
|
{ "default-source", pa_config_parse_string, &c->default_source },
|
||||||
|
{ "default-server", pa_config_parse_string, &c->default_server },
|
||||||
|
{ "autospawn", pa_config_parse_bool, &c->autospawn },
|
||||||
|
{ NULL, NULL, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!filename)
|
||||||
|
filename = getenv(ENV_CLIENT_CONFIG_FILE);
|
||||||
|
|
||||||
|
if (!filename) {
|
||||||
|
char *h;
|
||||||
|
|
||||||
|
if ((h = getenv("HOME"))) {
|
||||||
|
def = pa_sprintf_malloc("%s/%s", h, DEFAULT_CLIENT_CONFIG_FILE_USER);
|
||||||
|
|
||||||
|
if (!access(def, F_OK))
|
||||||
|
filename = def;
|
||||||
|
else {
|
||||||
|
pa_xfree(def);
|
||||||
|
def = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filename)
|
||||||
|
filename = DEFAULT_CLIENT_CONFIG_FILE;
|
||||||
|
|
||||||
|
r = pa_config_parse(filename, table, NULL);
|
||||||
|
pa_xfree(def);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pa_client_conf_env(struct pa_client_conf *c) {
|
||||||
|
char *e;
|
||||||
|
|
||||||
|
if ((e = getenv(ENV_DEFAULT_SINK))) {
|
||||||
|
pa_xfree(c->default_sink);
|
||||||
|
c->default_sink = pa_xstrdup(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((e = getenv(ENV_DEFAULT_SOURCE))) {
|
||||||
|
pa_xfree(c->default_source);
|
||||||
|
c->default_source = pa_xstrdup(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((e = getenv(ENV_DEFAULT_SERVER))) {
|
||||||
|
pa_xfree(c->default_server);
|
||||||
|
c->default_server = pa_xstrdup(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((e = getenv(ENV_DAEMON_BINARY))) {
|
||||||
|
pa_xfree(c->daemon_binary);
|
||||||
|
c->daemon_binary = pa_xstrdup(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
36
polyp/config-client.h
Normal file
36
polyp/config-client.h
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef fooconfigclienthfoo
|
||||||
|
#define fooconfigclienthfoo
|
||||||
|
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/***
|
||||||
|
This file is part of polypaudio.
|
||||||
|
|
||||||
|
polypaudio is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published
|
||||||
|
by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
polypaudio is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with polypaudio; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
USA.
|
||||||
|
***/
|
||||||
|
|
||||||
|
struct pa_client_conf {
|
||||||
|
char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server;
|
||||||
|
int autospawn;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pa_client_conf *pa_client_conf_new(void);
|
||||||
|
void pa_client_conf_free(struct pa_client_conf *c);
|
||||||
|
|
||||||
|
int pa_client_conf_load(struct pa_client_conf *c, const char *filename);
|
||||||
|
int pa_client_conf_env(struct pa_client_conf *c);
|
||||||
|
|
||||||
|
#endif
|
||||||
168
polyp/confparser.c
Normal file
168
polyp/confparser.c
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/***
|
||||||
|
This file is part of polypaudio.
|
||||||
|
|
||||||
|
polypaudio is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published
|
||||||
|
by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
polypaudio is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with polypaudio; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
USA.
|
||||||
|
***/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "confparser.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
#define WHITESPACE " \t\n"
|
||||||
|
#define COMMENTS "#;\n"
|
||||||
|
|
||||||
|
static int next_assignment(const char *filename, unsigned line, const struct pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) {
|
||||||
|
assert(filename && t && lvalue && rvalue);
|
||||||
|
|
||||||
|
for (; t->parse; t++)
|
||||||
|
if (!strcmp(lvalue, t->lvalue))
|
||||||
|
return t->parse(filename, line, lvalue, rvalue, t->data, userdata);
|
||||||
|
|
||||||
|
pa_log(__FILE__": [%s:%u] Unknown lvalue '%s'.\n", filename, line, lvalue);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int in_string(char c, const char *s) {
|
||||||
|
assert(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;
|
||||||
|
|
||||||
|
for (e = b; *e; e++)
|
||||||
|
if (!in_string(*e, WHITESPACE))
|
||||||
|
l = e;
|
||||||
|
|
||||||
|
if (l)
|
||||||
|
*(l+1) = 0;
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_line(const char *filename, unsigned line, const struct pa_config_item *t, char *l, void *userdata) {
|
||||||
|
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__": [%s:%u] Missing '='.\n", filename, line);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*e = 0;
|
||||||
|
e++;
|
||||||
|
|
||||||
|
return next_assignment(filename, line, t, strip(b), strip(e), userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int pa_config_parse(const char *filename, const struct pa_config_item *t, void *userdata) {
|
||||||
|
FILE *f;
|
||||||
|
int r = -1;
|
||||||
|
unsigned line = 0;
|
||||||
|
assert(filename && t);
|
||||||
|
|
||||||
|
if (!(f = fopen(filename, "r"))) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
r = 0;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
break;
|
||||||
|
|
||||||
|
pa_log(__FILE__": WARNING: failed to read configuration file '%s': %s\n", filename, strerror(errno));
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parse_line(filename, ++line, t, l, userdata) < 0)
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = 0;
|
||||||
|
|
||||||
|
finish:
|
||||||
|
|
||||||
|
if (f)
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||||
|
int *i = data, k;
|
||||||
|
char *x = NULL;
|
||||||
|
assert(filename && lvalue && rvalue && data);
|
||||||
|
|
||||||
|
k = strtol(rvalue, &x, 0);
|
||||||
|
if (!*rvalue || !x || *x) {
|
||||||
|
pa_log(__FILE__": [%s:%u] Failed to parse numeric value: %s\n", filename, line, rvalue);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*i = k;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||||
|
int *b = data, k;
|
||||||
|
assert(filename && lvalue && rvalue && data);
|
||||||
|
|
||||||
|
if ((k = pa_parse_boolean(rvalue)) < 0) {
|
||||||
|
pa_log(__FILE__": [%s:%u] Failed to parse boolean value: %s\n", filename, line, rvalue);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*b = k;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||||
|
char **s = data;
|
||||||
|
assert(filename && lvalue && rvalue && data);
|
||||||
|
|
||||||
|
pa_xfree(*s);
|
||||||
|
*s = *rvalue ? pa_xstrdup(rvalue) : NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
37
polyp/confparser.h
Normal file
37
polyp/confparser.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef fooconfparserhfoo
|
||||||
|
#define fooconfparserhfoo
|
||||||
|
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/***
|
||||||
|
This file is part of polypaudio.
|
||||||
|
|
||||||
|
polypaudio is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published
|
||||||
|
by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
polypaudio is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with polypaudio; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
USA.
|
||||||
|
***/
|
||||||
|
|
||||||
|
struct pa_config_item {
|
||||||
|
const char *lvalue;
|
||||||
|
int (*parse)(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
int pa_config_parse(const char *filename, const struct pa_config_item *t, void *userdata);
|
||||||
|
|
||||||
|
int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
|
||||||
|
int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
|
||||||
|
int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <samplerate.h>
|
||||||
|
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
|
@ -80,6 +81,8 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
|
||||||
c->module_idle_time = 20;
|
c->module_idle_time = 20;
|
||||||
c->scache_idle_time = 20;
|
c->scache_idle_time = 20;
|
||||||
|
|
||||||
|
c->resample_method = SRC_SINC_FASTEST;
|
||||||
|
|
||||||
pa_check_signal_is_blocked(SIGPIPE);
|
pa_check_signal_is_blocked(SIGPIPE);
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ struct pa_core {
|
||||||
struct pa_time_event *quit_event;
|
struct pa_time_event *quit_event;
|
||||||
|
|
||||||
struct pa_time_event *scache_auto_unload_event;
|
struct pa_time_event *scache_auto_unload_event;
|
||||||
|
|
||||||
|
int resample_method;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pa_core* pa_core_new(struct pa_mainloop_api *m);
|
struct pa_core* pa_core_new(struct pa_mainloop_api *m);
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
# USA.
|
# USA.
|
||||||
|
|
||||||
## Configuration file for polypaudio. Default values are commented out.
|
## Configuration file for the polypaudio daemon. Default values are
|
||||||
## Use either ; or # for commenting
|
## commented out. Use either ; or # for commenting
|
||||||
|
|
||||||
# Extra verbositiy
|
# Extra verbositiy
|
||||||
; verbose = 0
|
; verbose = 0
|
||||||
|
|
@ -46,16 +46,22 @@ high-priority = 0
|
||||||
## Unload autoloaded modules after being idle for this time
|
## Unload autoloaded modules after being idle for this time
|
||||||
module-idle-time = 20
|
module-idle-time = 20
|
||||||
|
|
||||||
## The path were to look for dynamic shared objects (DSOs aka plugins).
|
## The path were to look for dynamic shared objects (DSOs aka
|
||||||
## Specify an empty string for the default search path. You may specify
|
## plugins). You may specify more than one path seperated by
|
||||||
## more than one path seperated by colons.
|
## colons.
|
||||||
; dl-search-path =
|
; dl-search-path = @DLSEARCHPATH@
|
||||||
|
|
||||||
## The default script file to load. Specify an empty string for not
|
## The default script file to load. Specify an empty string for not
|
||||||
## loading a default script file
|
## loading a default script file. The
|
||||||
; default-script-file = /etc/polyp/default.pa
|
; default-script-file = @DEFAULT_CONFIG_FILE@
|
||||||
|
|
||||||
## The default log target. Use either "stderr", "syslog" or
|
## The default log target. Use either "stderr", "syslog" or
|
||||||
## "auto". The latter is equivalent to "sylog" in case daemonize is
|
## "auto". The latter is equivalent to "sylog" in case daemonize is
|
||||||
## true, otherwise to "stderr".
|
## true, otherwise to "stderr".
|
||||||
; log-target = auto
|
; log-target = auto
|
||||||
|
|
||||||
|
## The resampling algorithm to use. Use one of sinc-best-quality,
|
||||||
|
## sinc-medium-quality, sinc-fastest, zero-order-hold, linear. See
|
||||||
|
## the documentation of libsamplerate for an explanation fot the
|
||||||
|
## different methods.
|
||||||
|
; resample-method = sinc-fastest
|
||||||
|
|
@ -119,10 +119,6 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
if (conf->dl_search_path)
|
if (conf->dl_search_path)
|
||||||
lt_dlsetsearchpath(conf->dl_search_path);
|
lt_dlsetsearchpath(conf->dl_search_path);
|
||||||
#ifdef DLSEARCHPATH
|
|
||||||
else
|
|
||||||
lt_dlsetsearchpath(DLSEARCHPATH);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (conf->cmd) {
|
switch (conf->cmd) {
|
||||||
case PA_CMD_DUMP_MODULES:
|
case PA_CMD_DUMP_MODULES:
|
||||||
|
|
@ -245,6 +241,8 @@ int main(int argc, char *argv[]) {
|
||||||
c->disallow_module_loading = conf->disallow_module_loading;
|
c->disallow_module_loading = conf->disallow_module_loading;
|
||||||
c->exit_idle_time = conf->exit_idle_time;
|
c->exit_idle_time = conf->exit_idle_time;
|
||||||
c->module_idle_time = conf->module_idle_time;
|
c->module_idle_time = conf->module_idle_time;
|
||||||
|
c->scache_idle_time = conf->scache_idle_time;
|
||||||
|
c->resample_method = conf->resample_method;
|
||||||
|
|
||||||
pa_log(__FILE__": Daemon startup complete.\n");
|
pa_log(__FILE__": Daemon startup complete.\n");
|
||||||
if (pa_mainloop_run(mainloop, &retval) < 0)
|
if (pa_mainloop_run(mainloop, &retval) < 0)
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,9 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "config-client.h"
|
||||||
|
|
||||||
|
#define DEFAULT_SERVER "/tmp/polypaudio/native"
|
||||||
|
|
||||||
static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
|
static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
|
||||||
[PA_COMMAND_REQUEST] = { pa_command_request },
|
[PA_COMMAND_REQUEST] = { pa_command_request },
|
||||||
|
|
@ -87,6 +90,11 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *
|
||||||
c->local = -1;
|
c->local = -1;
|
||||||
|
|
||||||
pa_check_signal_is_blocked(SIGPIPE);
|
pa_check_signal_is_blocked(SIGPIPE);
|
||||||
|
|
||||||
|
c->conf = pa_client_conf_new();
|
||||||
|
pa_client_conf_load(c->conf, NULL);
|
||||||
|
pa_client_conf_env(c->conf);
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,6 +123,9 @@ static void context_free(struct pa_context *c) {
|
||||||
|
|
||||||
pa_memblock_stat_unref(c->memblock_stat);
|
pa_memblock_stat_unref(c->memblock_stat);
|
||||||
|
|
||||||
|
if (c->conf)
|
||||||
|
pa_client_conf_free(c->conf);
|
||||||
|
|
||||||
pa_xfree(c->name);
|
pa_xfree(c->name);
|
||||||
pa_xfree(c);
|
pa_xfree(c);
|
||||||
}
|
}
|
||||||
|
|
@ -366,7 +377,7 @@ static struct sockaddr *resolve_server(const char *server, size_t *len) {
|
||||||
return sa;
|
return sa;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_running(void) {
|
static int default_server_is_running(void) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (DEFAULT_SERVER[0] != '/')
|
if (DEFAULT_SERVER[0] != '/')
|
||||||
|
|
@ -404,24 +415,39 @@ static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api
|
||||||
|
|
||||||
goto fail;
|
goto fail;
|
||||||
} else if (!pid) {
|
} else if (!pid) {
|
||||||
char t[128];
|
|
||||||
char *p;
|
|
||||||
/* Child */
|
/* Child */
|
||||||
|
|
||||||
|
char t[128];
|
||||||
|
const char *state = NULL;
|
||||||
|
#define MAX_ARGS 64
|
||||||
|
char *argv[MAX_ARGS+1];
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
close(fds[0]);
|
close(fds[0]);
|
||||||
|
|
||||||
if (api && api->atfork)
|
if (api && api->atfork)
|
||||||
api->atfork();
|
api->atfork();
|
||||||
|
|
||||||
if (!(p = getenv(ENV_DEFAULT_BINARY)))
|
|
||||||
p = POLYPAUDIO_BINARY;
|
|
||||||
|
|
||||||
snprintf(t, sizeof(t), "%s=1", ENV_AUTOSPAWNED);
|
snprintf(t, sizeof(t), "%s=1", ENV_AUTOSPAWNED);
|
||||||
putenv(t);
|
putenv(t);
|
||||||
|
|
||||||
snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]);
|
argv[n++] = c->conf->daemon_binary;
|
||||||
execl(p, p, "--daemonize=yes", "--log-target=syslog", t, NULL);
|
|
||||||
|
|
||||||
|
snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]);
|
||||||
|
argv[n++] = pa_xstrdup(t);
|
||||||
|
|
||||||
|
while (n < MAX_ARGS) {
|
||||||
|
char *a;
|
||||||
|
|
||||||
|
if (!(a = pa_split_spaces(c->conf->extra_arguments, &state)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
argv[n++] = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
argv[n++] = NULL;
|
||||||
|
|
||||||
|
execv(argv[0], argv);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -468,19 +494,12 @@ int pa_context_connect(struct pa_context *c, const char *server, int spawn, cons
|
||||||
assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED);
|
assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED);
|
||||||
|
|
||||||
if (!server)
|
if (!server)
|
||||||
if (!(server = getenv(ENV_DEFAULT_SERVER))) {
|
server = c->conf->default_server;
|
||||||
if (spawn && !is_running()) {
|
|
||||||
char *b;
|
|
||||||
|
|
||||||
if ((b = getenv(ENV_DISABLE_AUTOSPAWN)))
|
if (!server && spawn && c->conf->autospawn && !default_server_is_running())
|
||||||
if (pa_parse_boolean(b) > 1)
|
return context_connect_spawn(c, api);
|
||||||
return -1;
|
|
||||||
|
|
||||||
return context_connect_spawn(c, api);
|
server = DEFAULT_SERVER;
|
||||||
}
|
|
||||||
|
|
||||||
server = DEFAULT_SERVER;
|
|
||||||
}
|
|
||||||
|
|
||||||
pa_context_ref(c);
|
pa_context_ref(c);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
#include "polyplib-operation.h"
|
#include "polyplib-operation.h"
|
||||||
#include "llist.h"
|
#include "llist.h"
|
||||||
#include "native-common.h"
|
#include "native-common.h"
|
||||||
|
#include "config-client.h"
|
||||||
|
|
||||||
#define DEFAULT_TLENGTH (10240*8)
|
#define DEFAULT_TLENGTH (10240*8)
|
||||||
#define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2)
|
#define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2)
|
||||||
|
|
@ -41,14 +42,8 @@
|
||||||
#define DEFAULT_FRAGSIZE 1024
|
#define DEFAULT_FRAGSIZE 1024
|
||||||
|
|
||||||
#define DEFAULT_TIMEOUT (5*60)
|
#define DEFAULT_TIMEOUT (5*60)
|
||||||
#define DEFAULT_SERVER "/tmp/polypaudio/native"
|
|
||||||
#define DEFAULT_PORT "4713"
|
#define DEFAULT_PORT "4713"
|
||||||
|
|
||||||
#define ENV_DEFAULT_SINK "POLYP_SINK"
|
|
||||||
#define ENV_DEFAULT_SOURCE "POLYP_SOURCE"
|
|
||||||
#define ENV_DEFAULT_SERVER "POLYP_SERVER"
|
|
||||||
#define ENV_DEFAULT_BINARY "POLYP_BINARY"
|
|
||||||
#define ENV_DISABLE_AUTOSPAWN "POLYP_NOAUTOSPAWN"
|
|
||||||
#define ENV_AUTOSPAWNED "POLYP_AUTOSPAWNED"
|
#define ENV_AUTOSPAWNED "POLYP_AUTOSPAWNED"
|
||||||
|
|
||||||
struct pa_context {
|
struct pa_context {
|
||||||
|
|
@ -80,6 +75,8 @@ struct pa_context {
|
||||||
struct pa_memblock_stat *memblock_stat;
|
struct pa_memblock_stat *memblock_stat;
|
||||||
|
|
||||||
int local;
|
int local;
|
||||||
|
|
||||||
|
struct pa_client_conf *conf;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pa_stream {
|
struct pa_stream {
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ struct pa_operation * pa_context_play_sample(struct pa_context *c, const char *n
|
||||||
o->userdata = userdata;
|
o->userdata = userdata;
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
dev = getenv(ENV_DEFAULT_SINK);
|
dev = c->conf->default_sink;
|
||||||
|
|
||||||
t = pa_tagstruct_new(NULL, 0);
|
t = pa_tagstruct_new(NULL, 0);
|
||||||
assert(t);
|
assert(t);
|
||||||
|
|
|
||||||
|
|
@ -235,9 +235,9 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_
|
||||||
|
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
if (s->direction == PA_STREAM_PLAYBACK)
|
if (s->direction == PA_STREAM_PLAYBACK)
|
||||||
dev = getenv(ENV_DEFAULT_SINK);
|
dev = s->context->conf->default_sink;
|
||||||
else
|
else
|
||||||
dev = getenv(ENV_DEFAULT_SOURCE);
|
dev = s->context->conf->default_source;
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
|
pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ struct pa_resampler {
|
||||||
struct pa_memblock_stat *memblock_stat;
|
struct pa_memblock_stat *memblock_stat;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s) {
|
struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s, int resample_method) {
|
||||||
struct pa_resampler *r = NULL;
|
struct pa_resampler *r = NULL;
|
||||||
int err;
|
int err;
|
||||||
assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b));
|
assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b));
|
||||||
|
|
@ -67,7 +67,7 @@ struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const stru
|
||||||
r->i_buf = r->o_buf = NULL;
|
r->i_buf = r->o_buf = NULL;
|
||||||
r->i_alloc = r->o_alloc = 0;
|
r->i_alloc = r->o_alloc = 0;
|
||||||
|
|
||||||
r->src_state = src_new(SRC_SINC_FASTEST, r->channels, &err);
|
r->src_state = src_new(resample_method, r->channels, &err);
|
||||||
if (err != 0 || !r->src_state)
|
if (err != 0 || !r->src_state)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
struct pa_resampler;
|
struct pa_resampler;
|
||||||
|
|
||||||
struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s);
|
struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s, int resample_method);
|
||||||
void pa_resampler_free(struct pa_resampler *r);
|
void pa_resampler_free(struct pa_resampler *r);
|
||||||
|
|
||||||
size_t pa_resampler_request(struct pa_resampler *r, size_t out_length);
|
size_t pa_resampler_request(struct pa_resampler *r, size_t out_length);
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con
|
||||||
}
|
}
|
||||||
|
|
||||||
if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec))
|
if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec))
|
||||||
if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat)))
|
if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat, s->core->resample_method)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
i = pa_xmalloc(sizeof(struct pa_sink_input));
|
i = pa_xmalloc(sizeof(struct pa_sink_input));
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pa_sample_spec_equal(&s->sample_spec, spec))
|
if (!pa_sample_spec_equal(&s->sample_spec, spec))
|
||||||
if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat)))
|
if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat, s->core->resample_method)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
o = pa_xmalloc(sizeof(struct pa_source_output));
|
o = pa_xmalloc(sizeof(struct pa_source_output));
|
||||||
|
|
|
||||||
17
polyp/util.c
17
polyp/util.c
|
|
@ -390,6 +390,23 @@ char *pa_split(const char *c, const char *delimiter, const char**state) {
|
||||||
return pa_xstrndup(current, l);
|
return pa_xstrndup(current, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define WHITESPACE " \t\n"
|
||||||
|
|
||||||
|
char *pa_split_spaces(const char *c, const char **state) {
|
||||||
|
const char *current = *state ? *state : c;
|
||||||
|
size_t l;
|
||||||
|
|
||||||
|
if (*current)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
current += strspn(current, WHITESPACE);
|
||||||
|
l = strcspn(current, WHITESPACE);
|
||||||
|
|
||||||
|
*state = current+l;
|
||||||
|
|
||||||
|
return pa_xstrndup(current, l);
|
||||||
|
}
|
||||||
|
|
||||||
const char *pa_strsignal(int sig) {
|
const char *pa_strsignal(int sig) {
|
||||||
switch(sig) {
|
switch(sig) {
|
||||||
case SIGINT: return "SIGINT";
|
case SIGINT: return "SIGINT";
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ int pa_fd_set_cloexec(int fd, int b);
|
||||||
int pa_parse_boolean(const char *s);
|
int pa_parse_boolean(const char *s);
|
||||||
|
|
||||||
char *pa_split(const char *c, const char*delimiters, const char **state);
|
char *pa_split(const char *c, const char*delimiters, const char **state);
|
||||||
|
char *pa_split_spaces(const char *c, const char **state);
|
||||||
|
|
||||||
const char *pa_strsignal(int sig);
|
const char *pa_strsignal(int sig);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue