mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -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
|
||||
- add client config file
|
||||
- remove autospawn stuff in conf.c
|
||||
- make resampler configurable
|
||||
|
||||
*** 0.6 ****
|
||||
- per-channel volume
|
||||
|
|
|
|||
|
|
@ -25,14 +25,14 @@ modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@
|
|||
AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS)
|
||||
AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\"
|
||||
AM_CFLAGS+=-DDEFAULT_SCRIPT_FILE=\"$(polypconfdir)/default.pa\"
|
||||
AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/default.conf\"
|
||||
AM_CFLAGS+=-DAUTOSPAWN_CONFIG_FILE=\"$(polypconfdir)/autospawn.conf\"
|
||||
AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/daemon.conf\"
|
||||
AM_CFLAGS+=-DDEFAULT_CLIENT_CONFIG_FILE=\"$(polypconfdir)/client.conf\"
|
||||
AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\"
|
||||
|
||||
AM_LDADD=$(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_SCRIPTS = esdcompat.sh
|
||||
noinst_PROGRAMS = \
|
||||
|
|
@ -42,7 +42,7 @@ noinst_PROGRAMS = \
|
|||
cpulimit-test \
|
||||
cpulimit-test2
|
||||
|
||||
polypconf_DATA=default.pa config
|
||||
polypconf_DATA=default.pa daemon.conf client.conf
|
||||
|
||||
BUILT_SOURCES=polyplib-version.h
|
||||
|
||||
|
|
@ -158,7 +158,8 @@ polypaudio_SOURCES = idxset.c idxset.h \
|
|||
gcc-printf.h \
|
||||
modinfo.c modinfo.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_INCLUDES = $(INCLTDL)
|
||||
|
|
@ -332,7 +333,9 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \
|
|||
cdecl.h \
|
||||
llist.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_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 <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);
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ struct pa_conf {
|
|||
auto_log_target;
|
||||
char *script_commands, *dl_search_path, *default_script_file;
|
||||
enum pa_log_target log_target;
|
||||
int resample_method;
|
||||
};
|
||||
|
||||
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 <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <samplerate.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "module.h"
|
||||
|
|
@ -79,6 +80,8 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
|
|||
c->exit_idle_time = -1;
|
||||
c->module_idle_time = 20;
|
||||
c->scache_idle_time = 20;
|
||||
|
||||
c->resample_method = SRC_SINC_FASTEST;
|
||||
|
||||
pa_check_signal_is_blocked(SIGPIPE);
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ struct pa_core {
|
|||
struct pa_time_event *quit_event;
|
||||
|
||||
struct pa_time_event *scache_auto_unload_event;
|
||||
|
||||
int resample_method;
|
||||
};
|
||||
|
||||
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
|
||||
# USA.
|
||||
|
||||
## Configuration file for polypaudio. Default values are commented out.
|
||||
## Use either ; or # for commenting
|
||||
## Configuration file for the polypaudio daemon. Default values are
|
||||
## commented out. Use either ; or # for commenting
|
||||
|
||||
# Extra verbositiy
|
||||
; verbose = 0
|
||||
|
|
@ -46,16 +46,22 @@ high-priority = 0
|
|||
## Unload autoloaded modules after being idle for this time
|
||||
module-idle-time = 20
|
||||
|
||||
## The path were to look for dynamic shared objects (DSOs aka plugins).
|
||||
## Specify an empty string for the default search path. You may specify
|
||||
## more than one path seperated by colons.
|
||||
; dl-search-path =
|
||||
## The path were to look for dynamic shared objects (DSOs aka
|
||||
## plugins). You may specify more than one path seperated by
|
||||
## colons.
|
||||
; dl-search-path = @DLSEARCHPATH@
|
||||
|
||||
## The default script file to load. Specify an empty string for not
|
||||
## loading a default script file
|
||||
; default-script-file = /etc/polyp/default.pa
|
||||
## loading a default script file. The
|
||||
; default-script-file = @DEFAULT_CONFIG_FILE@
|
||||
|
||||
## The default log target. Use either "stderr", "syslog" or
|
||||
## "auto". The latter is equivalent to "sylog" in case daemonize is
|
||||
## true, otherwise to "stderr".
|
||||
; 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)
|
||||
lt_dlsetsearchpath(conf->dl_search_path);
|
||||
#ifdef DLSEARCHPATH
|
||||
else
|
||||
lt_dlsetsearchpath(DLSEARCHPATH);
|
||||
#endif
|
||||
|
||||
switch (conf->cmd) {
|
||||
case PA_CMD_DUMP_MODULES:
|
||||
|
|
@ -245,6 +241,8 @@ int main(int argc, char *argv[]) {
|
|||
c->disallow_module_loading = conf->disallow_module_loading;
|
||||
c->exit_idle_time = conf->exit_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");
|
||||
if (pa_mainloop_run(mainloop, &retval) < 0)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@
|
|||
#include "util.h"
|
||||
#include "xmalloc.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] = {
|
||||
[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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -114,6 +122,9 @@ static void context_free(struct pa_context *c) {
|
|||
pa_dynarray_free(c->playback_streams, NULL, NULL);
|
||||
|
||||
pa_memblock_stat_unref(c->memblock_stat);
|
||||
|
||||
if (c->conf)
|
||||
pa_client_conf_free(c->conf);
|
||||
|
||||
pa_xfree(c->name);
|
||||
pa_xfree(c);
|
||||
|
|
@ -366,7 +377,7 @@ static struct sockaddr *resolve_server(const char *server, size_t *len) {
|
|||
return sa;
|
||||
}
|
||||
|
||||
static int is_running(void) {
|
||||
static int default_server_is_running(void) {
|
||||
struct stat st;
|
||||
|
||||
if (DEFAULT_SERVER[0] != '/')
|
||||
|
|
@ -404,24 +415,39 @@ static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api
|
|||
|
||||
goto fail;
|
||||
} else if (!pid) {
|
||||
char t[128];
|
||||
char *p;
|
||||
/* Child */
|
||||
|
||||
char t[128];
|
||||
const char *state = NULL;
|
||||
#define MAX_ARGS 64
|
||||
char *argv[MAX_ARGS+1];
|
||||
int n = 0;
|
||||
|
||||
close(fds[0]);
|
||||
|
||||
if (api && api->atfork)
|
||||
api->atfork();
|
||||
|
||||
if (!(p = getenv(ENV_DEFAULT_BINARY)))
|
||||
p = POLYPAUDIO_BINARY;
|
||||
|
||||
snprintf(t, sizeof(t), "%s=1", ENV_AUTOSPAWNED);
|
||||
putenv(t);
|
||||
|
||||
putenv(t);
|
||||
|
||||
argv[n++] = c->conf->daemon_binary;
|
||||
|
||||
snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]);
|
||||
execl(p, p, "--daemonize=yes", "--log-target=syslog", t, NULL);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
|
||||
if (!server)
|
||||
if (!(server = getenv(ENV_DEFAULT_SERVER))) {
|
||||
if (spawn && !is_running()) {
|
||||
char *b;
|
||||
|
||||
if ((b = getenv(ENV_DISABLE_AUTOSPAWN)))
|
||||
if (pa_parse_boolean(b) > 1)
|
||||
return -1;
|
||||
|
||||
return context_connect_spawn(c, api);
|
||||
}
|
||||
server = c->conf->default_server;
|
||||
|
||||
server = DEFAULT_SERVER;
|
||||
}
|
||||
if (!server && spawn && c->conf->autospawn && !default_server_is_running())
|
||||
return context_connect_spawn(c, api);
|
||||
|
||||
server = DEFAULT_SERVER;
|
||||
|
||||
pa_context_ref(c);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "polyplib-operation.h"
|
||||
#include "llist.h"
|
||||
#include "native-common.h"
|
||||
#include "config-client.h"
|
||||
|
||||
#define DEFAULT_TLENGTH (10240*8)
|
||||
#define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2)
|
||||
|
|
@ -41,14 +42,8 @@
|
|||
#define DEFAULT_FRAGSIZE 1024
|
||||
|
||||
#define DEFAULT_TIMEOUT (5*60)
|
||||
#define DEFAULT_SERVER "/tmp/polypaudio/native"
|
||||
#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"
|
||||
|
||||
struct pa_context {
|
||||
|
|
@ -80,6 +75,8 @@ struct pa_context {
|
|||
struct pa_memblock_stat *memblock_stat;
|
||||
|
||||
int local;
|
||||
|
||||
struct pa_client_conf *conf;
|
||||
};
|
||||
|
||||
struct pa_stream {
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ struct pa_operation * pa_context_play_sample(struct pa_context *c, const char *n
|
|||
o->userdata = userdata;
|
||||
|
||||
if (!dev)
|
||||
dev = getenv(ENV_DEFAULT_SINK);
|
||||
dev = c->conf->default_sink;
|
||||
|
||||
t = pa_tagstruct_new(NULL, 0);
|
||||
assert(t);
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_
|
|||
assert(s && s->ref >= 1 && s->state == PA_STREAM_DISCONNECTED);
|
||||
|
||||
pa_stream_ref(s);
|
||||
|
||||
|
||||
if (attr)
|
||||
s->buffer_attr = *attr;
|
||||
else {
|
||||
|
|
@ -235,9 +235,9 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_
|
|||
|
||||
if (!dev) {
|
||||
if (s->direction == PA_STREAM_PLAYBACK)
|
||||
dev = getenv(ENV_DEFAULT_SINK);
|
||||
dev = s->context->conf->default_sink;
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ struct pa_resampler {
|
|||
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;
|
||||
int err;
|
||||
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_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)
|
||||
goto fail;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
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);
|
||||
|
||||
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 (!(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;
|
||||
|
||||
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 (!(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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#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) {
|
||||
switch(sig) {
|
||||
case SIGINT: return "SIGINT";
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ int pa_fd_set_cloexec(int fd, int b);
|
|||
int pa_parse_boolean(const char *s);
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue