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@198 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
fbefe67d52
commit
829656c5fc
23 changed files with 755 additions and 231 deletions
12
Makefile.am
12
Makefile.am
|
|
@ -24,7 +24,17 @@ MAINTAINERCLEANFILES=README
|
|||
noinst_DATA = README
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc
|
||||
pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc
|
||||
|
||||
if HAVE_GLIB20
|
||||
pkgconfig_DATA += \
|
||||
polyplib-glib-mainloop.pc
|
||||
endif
|
||||
|
||||
if HAVE_GLIB12
|
||||
pkgconfig_DATA += \
|
||||
polyplib-glib12-mainloop.pc
|
||||
endif
|
||||
|
||||
README:
|
||||
rm -f README
|
||||
|
|
|
|||
|
|
@ -40,10 +40,12 @@ AC_SUBST(INCLTDL)
|
|||
AC_SUBST(LIBLTDL)
|
||||
AC_LIBTOOL_DLOPEN
|
||||
AC_PROG_LIBTOOL
|
||||
AC_PROG_LEX
|
||||
AC_PROG_YACC
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h])
|
||||
AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h syslog.h])
|
||||
|
||||
ACX_PTHREAD
|
||||
AC_PATH_XTRA
|
||||
|
|
@ -70,6 +72,7 @@ AC_FUNC_MEMCMP
|
|||
AC_FUNC_MMAP
|
||||
AC_FUNC_REALLOC
|
||||
AC_FUNC_SETPGRP
|
||||
AC_FUNC_VPRINTF
|
||||
AC_TYPE_SIGNAL
|
||||
AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul pow strcasecmp])
|
||||
AC_FUNC_STAT
|
||||
|
|
|
|||
3
doc/todo
3
doc/todo
|
|
@ -11,15 +11,14 @@
|
|||
rename streams/contexts
|
||||
- more complete pactl
|
||||
- add sample directory
|
||||
- config file for command line arguments
|
||||
- option to use default fragment size on alsa drivers
|
||||
- lazy sample cache
|
||||
- per-channel volume
|
||||
- merge pa_context_connect_*
|
||||
- input latency
|
||||
- fix tcp/native
|
||||
- suid
|
||||
- add volume to create_stream command in native protocol
|
||||
- udp based protocol
|
||||
|
||||
** later ***
|
||||
- xmlrpc/http
|
||||
|
|
|
|||
|
|
@ -24,14 +24,15 @@ modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@
|
|||
|
||||
AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS)
|
||||
AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\"
|
||||
AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/polypaudio.pa\"
|
||||
AM_CFLAGS+=-DDEFAULT_SCRIPT_FILE=\"$(polypconfdir)/default.pa\"
|
||||
AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/config\"
|
||||
AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\"
|
||||
|
||||
AM_LDADD=$(PTHREAD_LIBS) -lm
|
||||
AM_LIBADD=$(PTHREAD_LIBS) -lm
|
||||
|
||||
EXTRA_DIST = polypaudio.pa depmod.py esdcompat.sh.in
|
||||
bin_PROGRAMS = polypaudio pacat pactl pamodinfo
|
||||
EXTRA_DIST = default.pa config depmod.py esdcompat.sh.in
|
||||
bin_PROGRAMS = polypaudio pacat pactl
|
||||
bin_SCRIPTS = esdcompat.sh
|
||||
noinst_PROGRAMS = \
|
||||
mainloop-test \
|
||||
|
|
@ -40,7 +41,7 @@ noinst_PROGRAMS = \
|
|||
cpulimit-test \
|
||||
cpulimit-test2
|
||||
|
||||
polypconf_DATA=polypaudio.pa
|
||||
polypconf_DATA=default.pa config
|
||||
|
||||
BUILT_SOURCES=polyplib-version.h
|
||||
|
||||
|
|
@ -153,19 +154,15 @@ polypaudio_SOURCES = idxset.c idxset.h \
|
|||
cpulimit.c cpulimit.h \
|
||||
log.c log.h \
|
||||
gcc-printf.h \
|
||||
modinfo.c modinfo.h
|
||||
modinfo.c modinfo.h \
|
||||
conf.c conf.h \
|
||||
dumpmodules.c dumpmodules.h
|
||||
|
||||
polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
|
||||
polypaudio_INCLUDES = $(INCLTDL)
|
||||
polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS)
|
||||
polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(LEXLIB)
|
||||
polypaudio_LDFLAGS=-export-dynamic
|
||||
|
||||
pamodinfo_SOURCES = log.c log.h pamodinfo.c pamodinfo.h modinfo.c modinfo.h util.c util.h xmalloc.c xmalloc.h
|
||||
pamodinfo_CFLAGS = $(AM_CFLAGS)
|
||||
pamodinfo_INCLUDES = $(INCLTDL)
|
||||
pamodinfo_LDADD = $(AM_LDADD) $(LIBLTDL)
|
||||
pamodinfo_LDFLAGS=-export-dynamic
|
||||
|
||||
libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h
|
||||
libprotocol_simple_la_LDFLAGS = -avoid-version
|
||||
libprotocol_simple_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la
|
||||
|
|
@ -535,3 +532,7 @@ esdcompat.sh: esdcompat.sh.in Makefile
|
|||
sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \
|
||||
-e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \
|
||||
-e 's,@POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@
|
||||
|
||||
install-exec-hook:
|
||||
chown root:root $(DESTDIR)$(bindir)/polypaudio
|
||||
chmod u+s $(DESTDIR)$(bindir)/polypaudio
|
||||
|
|
|
|||
256
polyp/cmdline.c
256
polyp/cmdline.c
|
|
@ -35,29 +35,48 @@
|
|||
#include "strbuf.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
#define ENV_CONFIG_FILE "POLYP_CONFIG"
|
||||
enum {
|
||||
ARG_HELP = 256,
|
||||
ARG_VERSION,
|
||||
ARG_DUMP_CONF,
|
||||
ARG_DUMP_MODULES,
|
||||
ARG_DAEMONIZE,
|
||||
ARG_FAIL,
|
||||
ARG_VERBOSE,
|
||||
ARG_HIGH_PRIORITY,
|
||||
ARG_STAY_ROOT,
|
||||
ARG_DISALLOW_MODULE_LOADING,
|
||||
ARG_EXIT_IDLE_TIME,
|
||||
ARG_MODULE_IDLE_TIME,
|
||||
ARG_LOG_TARGET,
|
||||
ARG_LOAD,
|
||||
ARG_FILE,
|
||||
ARG_DL_SEARCH_PATH,
|
||||
};
|
||||
|
||||
char* config_file(void) {
|
||||
char *p, *h;
|
||||
static struct option long_options[] = {
|
||||
{"help", 0, 0, ARG_HELP},
|
||||
{"version", 0, 0, ARG_VERSION},
|
||||
{"dump-conf", 0, 0, ARG_DUMP_CONF},
|
||||
{"dump-modules", 0, 0, ARG_DUMP_MODULES},
|
||||
{"daemonize", 2, 0, ARG_DAEMONIZE},
|
||||
{"fail", 2, 0, ARG_FAIL},
|
||||
{"verbose", 2, 0, ARG_VERBOSE},
|
||||
{"high-priority", 2, 0, ARG_HIGH_PRIORITY},
|
||||
{"stay-root", 2, 0, ARG_STAY_ROOT},
|
||||
{"disallow-module-loading", 2, 0, ARG_DISALLOW_MODULE_LOADING},
|
||||
{"exit-idle-time", 2, 0, ARG_EXIT_IDLE_TIME},
|
||||
{"module-idle-time", 2, 0, ARG_MODULE_IDLE_TIME},
|
||||
{"log-target", 1, 0, ARG_LOG_TARGET},
|
||||
{"load", 1, 0, ARG_LOAD},
|
||||
{"file", 1, 0, ARG_FILE},
|
||||
{"dl-search-path", 1, 0, ARG_DL_SEARCH_PATH},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
if ((p = getenv(ENV_CONFIG_FILE)))
|
||||
return pa_xstrdup(p);
|
||||
|
||||
if ((h = getenv("HOME"))) {
|
||||
struct stat st;
|
||||
p = pa_sprintf_malloc("%s/.polypaudio", h);
|
||||
if (stat(p, &st) >= 0)
|
||||
return p;
|
||||
|
||||
pa_xfree(p);
|
||||
}
|
||||
|
||||
return pa_xstrdup(DEFAULT_CONFIG_FILE);
|
||||
}
|
||||
|
||||
void pa_cmdline_help(const char *argv0) {
|
||||
const char *e;
|
||||
char *cfg = config_file();
|
||||
|
||||
if ((e = strrchr(argv0, '/')))
|
||||
e++;
|
||||
|
|
@ -65,133 +84,170 @@ void pa_cmdline_help(const char *argv0) {
|
|||
e = argv0;
|
||||
|
||||
printf("%s [options]\n"
|
||||
" -r Try to set high process priority (only available as root)\n"
|
||||
" -R Don't drop root if SETUID root\n"
|
||||
" -L MODULE Load the specified plugin module with the specified argument\n"
|
||||
" -F FILE Run the specified script\n"
|
||||
" -C Open a command line on the running TTY\n"
|
||||
" -n Don't load configuration file (%s)\n"
|
||||
" -D Daemonize after loading the modules\n"
|
||||
" -d Disallow module loading after startup\n"
|
||||
" -f Dont quit when the startup fails\n"
|
||||
" -v Verbose startup\n"
|
||||
" -X SECS Terminate the daemon after the last client quit and this time passed\n"
|
||||
" -h Show this help\n"
|
||||
" -l TARGET Specify the log target (syslog, stderr, auto)\n"
|
||||
" -p DIR Append a directory to the search path for dynamic modules\n"
|
||||
" -V Show version\n", e, cfg);
|
||||
" -h, --help Show this help\n"
|
||||
" --version Show version\n"
|
||||
" --dump-conf Dump default configuration\n"
|
||||
" --dump-modules Dump list of available modules\n\n"
|
||||
|
||||
pa_xfree(cfg);
|
||||
" -D, --daemonize[=BOOL] Daemonize after startup\n"
|
||||
" --fail[=BOOL] Quit when startup fails\n"
|
||||
" --verbose[=BOOL] Be slightly more verbose\n"
|
||||
" --high-priority[=BOOL] Try to set high process priority (only available as root)\n"
|
||||
" --stay-root[=BOOL] Don't drop root if SETUID root\n"
|
||||
" --disallow-module-loading[=BOOL] Disallow module loading after startup\n"
|
||||
" --exit-idle-time=SECS Terminate the daemon when idle and this time passed\n"
|
||||
" --module-idle-time=SECS Unload autoloaded modules when idle and this time passed\n"
|
||||
" --log-target={auto,syslog,stderr} Specify the log target\n"
|
||||
" -p, --dl-search-path=PATH Set the search path for dynamic shared objects (plugins)\n\n"
|
||||
|
||||
" -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module with the specified argument\n"
|
||||
" -F, --file=FILENAME Run the specified script\n"
|
||||
" -C Open a command line on the running TTY after startup\n\n"
|
||||
|
||||
" -n Don't load default script file\n", e);
|
||||
}
|
||||
|
||||
struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) {
|
||||
char c, *cfg;
|
||||
struct pa_cmdline *cmdline = NULL;
|
||||
int pa_cmdline_parse(struct pa_conf *conf, int argc, char *const argv [], int *d) {
|
||||
struct pa_strbuf *buf = NULL;
|
||||
int no_default_config_file = 0;
|
||||
assert(argc && argv);
|
||||
|
||||
cmdline = pa_xmalloc(sizeof(struct pa_cmdline));
|
||||
cmdline->daemonize =
|
||||
cmdline->help =
|
||||
cmdline->verbose =
|
||||
cmdline->high_priority =
|
||||
cmdline->stay_root =
|
||||
cmdline->version =
|
||||
cmdline->disallow_module_loading = 0;
|
||||
cmdline->fail = cmdline->auto_log_target = 1;
|
||||
cmdline->quit_after_last_client_time = -1;
|
||||
cmdline->log_target = -1;
|
||||
cmdline->dl_search_path = NULL;
|
||||
int c;
|
||||
assert(conf && argc && argv);
|
||||
|
||||
buf = pa_strbuf_new();
|
||||
assert(buf);
|
||||
|
||||
while ((c = getopt(argc, argv, "L:F:CDhfvrRVndX:l:p:")) != -1) {
|
||||
if (conf->script_commands)
|
||||
pa_strbuf_puts(buf, conf->script_commands);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "L:F:ChDnp:", long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case ARG_HELP:
|
||||
case 'h':
|
||||
conf->help = 1;
|
||||
break;
|
||||
|
||||
case ARG_VERSION:
|
||||
conf->version = 1;
|
||||
break;
|
||||
|
||||
case ARG_DUMP_CONF:
|
||||
conf->dump_conf = 1;
|
||||
break;
|
||||
|
||||
case ARG_DUMP_MODULES:
|
||||
conf->dump_modules = 1;
|
||||
break;
|
||||
|
||||
case ARG_LOAD:
|
||||
case 'L':
|
||||
pa_strbuf_printf(buf, "load %s\n", optarg);
|
||||
break;
|
||||
|
||||
case ARG_FILE:
|
||||
case 'F':
|
||||
pa_strbuf_printf(buf, ".include %s\n", optarg);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
pa_strbuf_puts(buf, "load module-cli\n");
|
||||
break;
|
||||
|
||||
case ARG_DAEMONIZE:
|
||||
case 'D':
|
||||
cmdline->daemonize = 1;
|
||||
if ((conf->daemonize = optarg ? pa_parse_boolean(optarg) : 1) < 0) {
|
||||
pa_log(__FILE__": --daemonize expects boolean argument\n");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
cmdline->help = 1;
|
||||
|
||||
case ARG_FAIL:
|
||||
if ((conf->fail = optarg ? pa_parse_boolean(optarg) : 1) < 0) {
|
||||
pa_log(__FILE__": --fail expects boolean argument\n");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
cmdline->fail = 0;
|
||||
|
||||
case ARG_VERBOSE:
|
||||
if ((conf->verbose = optarg ? pa_parse_boolean(optarg) : 1) < 0) {
|
||||
pa_log(__FILE__": --verbose expects boolean argument\n");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
cmdline->verbose = 1;
|
||||
|
||||
case ARG_HIGH_PRIORITY:
|
||||
if ((conf->high_priority = optarg ? pa_parse_boolean(optarg) : 1) < 0) {
|
||||
pa_log(__FILE__": --high-priority expects boolean argument\n");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
cmdline->high_priority = 1;
|
||||
|
||||
case ARG_STAY_ROOT:
|
||||
if ((conf->stay_root = optarg ? pa_parse_boolean(optarg) : 1) < 0) {
|
||||
pa_log(__FILE__": --stay-root expects boolean argument\n");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
cmdline->stay_root = 1;
|
||||
break;
|
||||
case 'V':
|
||||
cmdline->version = 1;
|
||||
break;
|
||||
case 'n':
|
||||
no_default_config_file = 1;
|
||||
break;
|
||||
case 'd':
|
||||
cmdline->disallow_module_loading = 1;
|
||||
break;
|
||||
case 'X':
|
||||
cmdline->quit_after_last_client_time = atoi(optarg);
|
||||
|
||||
case ARG_DISALLOW_MODULE_LOADING:
|
||||
if ((conf->disallow_module_loading = optarg ? pa_parse_boolean(optarg) : 1) < 0) {
|
||||
pa_log(__FILE__": --disallow-module-loading expects boolean argument\n");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (cmdline->dl_search_path)
|
||||
pa_xfree(cmdline->dl_search_path);
|
||||
cmdline->dl_search_path = pa_xstrdup(optarg);
|
||||
case ARG_DL_SEARCH_PATH:
|
||||
pa_xfree(conf->dl_search_path);
|
||||
conf->dl_search_path = *optarg ? pa_xstrdup(optarg) : NULL;
|
||||
break;
|
||||
case 'l':
|
||||
|
||||
case 'n':
|
||||
pa_xfree(conf->default_script_file);
|
||||
conf->default_script_file = NULL;
|
||||
break;
|
||||
|
||||
case ARG_LOG_TARGET:
|
||||
if (!strcmp(optarg, "syslog")) {
|
||||
cmdline->auto_log_target = 0;
|
||||
cmdline->log_target = PA_LOG_SYSLOG;
|
||||
conf->auto_log_target = 0;
|
||||
conf->log_target = PA_LOG_SYSLOG;
|
||||
} else if (!strcmp(optarg, "stderr")) {
|
||||
cmdline->auto_log_target = 0;
|
||||
cmdline->log_target = PA_LOG_STDERR;
|
||||
conf->auto_log_target = 0;
|
||||
conf->log_target = PA_LOG_STDERR;
|
||||
} else if (!strcmp(optarg, "auto"))
|
||||
cmdline->auto_log_target = 1;
|
||||
conf->auto_log_target = 1;
|
||||
else {
|
||||
pa_log(__FILE__": Invalid log target: use either 'syslog', 'stderr' or 'auto'.\n");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARG_EXIT_IDLE_TIME:
|
||||
conf->exit_idle_time = atoi(optarg);
|
||||
break;
|
||||
|
||||
case ARG_MODULE_IDLE_TIME:
|
||||
conf->module_idle_time = atoi(optarg);
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!no_default_config_file) {
|
||||
cfg = config_file();
|
||||
pa_strbuf_printf(buf, ".include %s\n", cfg);
|
||||
pa_xfree(cfg);
|
||||
pa_xfree(conf->script_commands);
|
||||
conf->script_commands = pa_strbuf_tostring_free(buf);
|
||||
|
||||
if (!conf->script_commands) {
|
||||
pa_xfree(conf->script_commands);
|
||||
conf->script_commands = NULL;
|
||||
}
|
||||
|
||||
cmdline->cli_commands = pa_strbuf_tostring_free(buf);
|
||||
return cmdline;
|
||||
*d = optind;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (cmdline)
|
||||
pa_cmdline_free(cmdline);
|
||||
if (buf)
|
||||
pa_strbuf_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pa_cmdline_free(struct pa_cmdline *cmd) {
|
||||
assert(cmd);
|
||||
pa_xfree(cmd->cli_commands);
|
||||
pa_xfree(cmd->dl_search_path);
|
||||
pa_xfree(cmd);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,26 +22,9 @@
|
|||
USA.
|
||||
***/
|
||||
|
||||
#include "log.h"
|
||||
#include "conf.h"
|
||||
|
||||
struct pa_cmdline {
|
||||
int daemonize,
|
||||
help,
|
||||
fail,
|
||||
verbose,
|
||||
high_priority,
|
||||
stay_root,
|
||||
version,
|
||||
disallow_module_loading,
|
||||
quit_after_last_client_time,
|
||||
auto_log_target;
|
||||
char *cli_commands;
|
||||
char *dl_search_path;
|
||||
enum pa_log_target log_target;
|
||||
};
|
||||
|
||||
struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []);
|
||||
void pa_cmdline_free(struct pa_cmdline *cmd);
|
||||
int pa_cmdline_parse(struct pa_conf*c, int argc, char *const argv [], int *d);
|
||||
|
||||
void pa_cmdline_help(const char *argv0);
|
||||
|
||||
|
|
|
|||
285
polyp/conf.c
Normal file
285
polyp/conf.c
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
/* $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.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "conf.h"
|
||||
#include "util.h"
|
||||
#include "xmalloc.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
static const struct pa_conf default_conf = {
|
||||
.help = 0,
|
||||
.daemonize = 0,
|
||||
.dump_conf = 0,
|
||||
.dump_modules = 0,
|
||||
.fail = 1,
|
||||
.verbose = 0,
|
||||
.high_priority = 0,
|
||||
.stay_root = 0,
|
||||
.version = 0,
|
||||
.disallow_module_loading = 0,
|
||||
.exit_idle_time = -1,
|
||||
.module_idle_time = 20,
|
||||
.auto_log_target = 1,
|
||||
.script_commands = NULL,
|
||||
.dl_search_path = NULL,
|
||||
.default_script_file = NULL,
|
||||
.log_target = PA_LOG_SYSLOG,
|
||||
};
|
||||
|
||||
#define ENV_SCRIPT_FILE "POLYP_SCRIPT"
|
||||
#define ENV_CONFIG_FILE "POLYP_CONFIG"
|
||||
|
||||
#ifndef DEFAULT_SCRIPT_FILE
|
||||
#define DEFAULT_SCRIPT_FILE "/etc/polypaudio/default.pa"
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_CONFIG_FILE
|
||||
#define DEFAULT_CONFIG_FILE "/etc/polypaudio/config"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SCRIPT_FILE_LOCAL ".polypaudio.pa"
|
||||
#define DEFAULT_CONFIG_FILE_LOCAL ".polypaudio.conf"
|
||||
|
||||
char* default_file(const char *envvar, const char *global, const char *local) {
|
||||
char *p, *h;
|
||||
|
||||
assert(envvar && global && local);
|
||||
|
||||
if ((p = getenv(envvar)))
|
||||
return pa_xstrdup(p);
|
||||
|
||||
if ((h = getenv("HOME"))) {
|
||||
struct stat st;
|
||||
p = pa_sprintf_malloc("%s/%s", h, local);
|
||||
if (stat(p, &st) >= 0)
|
||||
return p;
|
||||
|
||||
pa_xfree(p);
|
||||
}
|
||||
|
||||
return pa_xstrdup(global);
|
||||
}
|
||||
|
||||
|
||||
struct pa_conf* pa_conf_new(void) {
|
||||
struct pa_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf));
|
||||
c->default_script_file = default_file(ENV_SCRIPT_FILE, DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_LOCAL);
|
||||
return c;
|
||||
}
|
||||
|
||||
void pa_conf_free(struct pa_conf *c) {
|
||||
assert(c);
|
||||
pa_xfree(c->script_commands);
|
||||
pa_xfree(c->dl_search_path);
|
||||
pa_xfree(c->default_script_file);
|
||||
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("stay-root", stay_root);
|
||||
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_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;
|
||||
}
|
||||
|
||||
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(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);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*e = 0;
|
||||
e++;
|
||||
|
||||
return next_assignment(conf, strip(b), strip(e), n);
|
||||
}
|
||||
|
||||
|
||||
int pa_conf_load(struct pa_conf *c, const char *filename) {
|
||||
FILE *f;
|
||||
int r = 0;
|
||||
unsigned n = 0;
|
||||
char *def = NULL;
|
||||
assert(c);
|
||||
|
||||
if (!filename)
|
||||
filename = def = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_LOCAL);
|
||||
|
||||
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);
|
||||
|
||||
pa_xfree(def);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
char *pa_conf_dump(struct pa_conf *c) {
|
||||
struct pa_strbuf *s = pa_strbuf_new();
|
||||
char *d;
|
||||
|
||||
d = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_LOCAL);
|
||||
pa_strbuf_printf(s, "### Default configuration file: %s ###\n\n", d);
|
||||
|
||||
pa_strbuf_printf(s, "verbose = %i\n", !!c->verbose);
|
||||
pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize);
|
||||
pa_strbuf_printf(s, "fail = %i\n", !!c->fail);
|
||||
pa_strbuf_printf(s, "high-priority = %i\n", !!c->high_priority);
|
||||
pa_strbuf_printf(s, "stay-root = %i\n", !!c->stay_root);
|
||||
pa_strbuf_printf(s, "disallow-module-loading = %i\n", !!c->disallow_module_loading);
|
||||
pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time);
|
||||
pa_strbuf_printf(s, "module-idle-time = %i\n", c->module_idle_time);
|
||||
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"));
|
||||
|
||||
pa_strbuf_printf(s, "\n### EOF ###\n");
|
||||
|
||||
pa_xfree(d);
|
||||
|
||||
return pa_strbuf_tostring_free(s);
|
||||
}
|
||||
51
polyp/conf.h
Normal file
51
polyp/conf.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef fooconfhfoo
|
||||
#define fooconfhfoo
|
||||
|
||||
/* $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 "log.h"
|
||||
|
||||
struct pa_conf {
|
||||
int help,
|
||||
version,
|
||||
dump_conf,
|
||||
dump_modules,
|
||||
daemonize,
|
||||
fail,
|
||||
verbose,
|
||||
high_priority,
|
||||
stay_root,
|
||||
disallow_module_loading,
|
||||
exit_idle_time,
|
||||
module_idle_time,
|
||||
auto_log_target;
|
||||
char *script_commands, *dl_search_path, *default_script_file;
|
||||
enum pa_log_target log_target;
|
||||
};
|
||||
|
||||
struct pa_conf* pa_conf_new(void);
|
||||
void pa_conf_free(struct pa_conf*c);
|
||||
|
||||
int pa_conf_load(struct pa_conf *c, const char *filename);
|
||||
char *pa_conf_dump(struct pa_conf *c);
|
||||
|
||||
#endif
|
||||
61
polyp/config
Normal file
61
polyp/config
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# $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. Default values are commented out.
|
||||
## Use either ; or # for commenting
|
||||
|
||||
# Extra verbositiy
|
||||
; verbose = 0
|
||||
|
||||
## Daemonize after startup
|
||||
; daemonize = 0
|
||||
|
||||
## Quit if startup fails
|
||||
; fail = 1
|
||||
|
||||
## Renice the daemon to level -15 and try to get SCHED_FIFO
|
||||
## scheduling. This a good idea if you hear annyoing noise in the
|
||||
## playback. However, this is a certain security issue.
|
||||
; high-priority = 0
|
||||
|
||||
## Don't drop root rights on startup if called SUID root.
|
||||
; stay-root = 0
|
||||
|
||||
## Disallow module loading after startup
|
||||
; disallow-module-loading = 0
|
||||
|
||||
## Terminate the daemon after the last client quit and this time
|
||||
## passed. Use a negative value to disable this feature.
|
||||
; exit-idle-time = -1
|
||||
|
||||
## 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.
|
||||
; dl-search-path =
|
||||
|
||||
## The default script file to load. Specify an empty string for not
|
||||
## loading a default script file
|
||||
; default-script-file = /etc/polyp/default.pa
|
||||
|
||||
## 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
|
||||
|
|
@ -61,7 +61,6 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
|
|||
c->default_sample_spec.rate = 44100;
|
||||
c->default_sample_spec.channels = 2;
|
||||
|
||||
c->auto_unload_time = 20;
|
||||
c->auto_unload_event = NULL;
|
||||
|
||||
c->subscription_defer_event = NULL;
|
||||
|
|
@ -73,7 +72,9 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
|
|||
c->disallow_module_loading = 0;
|
||||
|
||||
c->quit_event = NULL;
|
||||
c->quit_after_last_client_time = -1;
|
||||
|
||||
c->exit_idle_time = -1;
|
||||
c->module_idle_time = 20;
|
||||
|
||||
pa_check_for_sigpipe();
|
||||
|
||||
|
|
@ -129,10 +130,10 @@ static void quit_callback(struct pa_mainloop_api*m, struct pa_time_event *e, con
|
|||
void pa_core_check_quit(struct pa_core *c) {
|
||||
assert(c);
|
||||
|
||||
if (!c->quit_event && c->quit_after_last_client_time >= 0 && pa_idxset_ncontents(c->clients) == 0) {
|
||||
if (!c->quit_event && c->exit_idle_time >= 0 && pa_idxset_ncontents(c->clients) == 0) {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
tv.tv_sec+= c->quit_after_last_client_time;
|
||||
tv.tv_sec+= c->exit_idle_time;
|
||||
c->quit_event = c->mainloop->time_new(c->mainloop, &tv, quit_callback, c);
|
||||
} else if (c->quit_event && pa_idxset_ncontents(c->clients) > 0) {
|
||||
c->mainloop->time_free(c->quit_event);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ struct pa_core {
|
|||
char *default_source_name, *default_sink_name;
|
||||
|
||||
struct pa_sample_spec default_sample_spec;
|
||||
int auto_unload_time;
|
||||
struct pa_time_event *auto_unload_event;
|
||||
|
||||
struct pa_defer_event *subscription_defer_event;
|
||||
|
|
@ -48,7 +47,7 @@ struct pa_core {
|
|||
struct pa_memblock_stat *memblock_stat;
|
||||
|
||||
int disallow_module_loading;
|
||||
int quit_after_last_client_time;
|
||||
int exit_idle_time, module_idle_time;
|
||||
|
||||
struct pa_time_event *quit_event;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -29,12 +29,11 @@
|
|||
#include <stdio.h>
|
||||
#include <ltdl.h>
|
||||
|
||||
#include "dumpmodules.h"
|
||||
#include "modinfo.h"
|
||||
|
||||
#define PREFIX "module-"
|
||||
|
||||
static int verbose = 0;
|
||||
|
||||
static void short_info(const char *name, const char *path, struct pa_modinfo *i) {
|
||||
assert(name && i);
|
||||
printf("%-40s%s\n", name, i->description ? i->description : "n/a");
|
||||
|
|
@ -79,6 +78,7 @@ static void show_info(const char *name, const char *path, void (*info)(const cha
|
|||
|
||||
static int callback(const char *path, lt_ptr data) {
|
||||
const char *e;
|
||||
struct pa_conf *c = (data);
|
||||
|
||||
if ((e = (const char*) strrchr(path, '/')))
|
||||
e++;
|
||||
|
|
@ -86,41 +86,16 @@ static int callback(const char *path, lt_ptr data) {
|
|||
e = path;
|
||||
|
||||
if (strlen(e) > sizeof(PREFIX)-1 && !strncmp(e, PREFIX, sizeof(PREFIX)-1))
|
||||
show_info(e, path, verbose ? long_info : short_info);
|
||||
show_info(e, path, c->verbose ? long_info : short_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int r = lt_dlinit();
|
||||
char *path = NULL;
|
||||
int c;
|
||||
assert(r == 0);
|
||||
|
||||
while ((c = getopt(argc, argv, "p:v")) != -1) {
|
||||
switch (c) {
|
||||
case 'p':
|
||||
path = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (path)
|
||||
lt_dlsetsearchpath(path);
|
||||
#ifdef DLSEARCHPATH
|
||||
else
|
||||
lt_dlsetsearchpath(DLSEARCHPATH);
|
||||
#endif
|
||||
|
||||
if (argc > optind)
|
||||
show_info(argv[optind], NULL, long_info);
|
||||
else
|
||||
lt_dlforeachfile(NULL, callback, NULL);
|
||||
|
||||
lt_dlexit();
|
||||
void pa_dump_modules(struct pa_conf *c, int argc, char * const argv[]) {
|
||||
if (argc > 0) {
|
||||
int i;
|
||||
for (i = 0; i < argc; i++)
|
||||
show_info(argv[i], NULL, long_info);
|
||||
} else
|
||||
lt_dlforeachfile(NULL, callback, c);
|
||||
}
|
||||
29
polyp/dumpmodules.h
Normal file
29
polyp/dumpmodules.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef foodumpmoduleshfoo
|
||||
#define foodumpmoduleshfoo
|
||||
|
||||
/* $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 "conf.h"
|
||||
|
||||
void pa_dump_modules(struct pa_conf *c, int argc, char * const argv[]);
|
||||
|
||||
#endif
|
||||
85
polyp/main.c
85
polyp/main.c
|
|
@ -45,6 +45,8 @@
|
|||
#include "xmalloc.h"
|
||||
#include "cpulimit.h"
|
||||
#include "log.h"
|
||||
#include "conf.h"
|
||||
#include "dumpmodules.h"
|
||||
|
||||
static struct pa_mainloop *mainloop;
|
||||
|
||||
|
|
@ -99,40 +101,69 @@ static void close_pipe(int p[2]) {
|
|||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct pa_core *c;
|
||||
struct pa_cmdline *cmdline = NULL;
|
||||
struct pa_strbuf *buf = NULL;
|
||||
struct pa_conf *conf;
|
||||
char *s;
|
||||
int r, retval = 1;
|
||||
int r, retval = 1, d = 0;
|
||||
int daemon_pipe[2] = { -1, -1 };
|
||||
|
||||
r = lt_dlinit();
|
||||
assert(r == 0);
|
||||
|
||||
pa_log_set_ident("polypaudio");
|
||||
|
||||
if (!(cmdline = pa_cmdline_parse(argc, argv))) {
|
||||
conf = pa_conf_new();
|
||||
|
||||
if (pa_conf_load(conf, NULL) < 0)
|
||||
goto finish;
|
||||
|
||||
if (pa_cmdline_parse(conf, argc, argv, &d) < 0) {
|
||||
pa_log(__FILE__": failed to parse command line.\n");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
pa_log_set_target(cmdline->auto_log_target ? PA_LOG_STDERR : cmdline->log_target, NULL);
|
||||
pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target, NULL);
|
||||
|
||||
if (cmdline->help) {
|
||||
if (conf->dl_search_path)
|
||||
lt_dlsetsearchpath(conf->dl_search_path);
|
||||
#ifdef DLSEARCHPATH
|
||||
else
|
||||
lt_dlsetsearchpath(DLSEARCHPATH);
|
||||
#endif
|
||||
|
||||
if (conf->dump_modules) {
|
||||
pa_dump_modules(conf, argc-d, argv+d);
|
||||
retval = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (conf->dump_conf) {
|
||||
char *s = pa_conf_dump(conf);
|
||||
fputs(s, stdout);
|
||||
pa_xfree(s);
|
||||
retval = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (conf->help) {
|
||||
pa_cmdline_help(argv[0]);
|
||||
retval = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (cmdline->version) {
|
||||
if (conf->version) {
|
||||
printf(PACKAGE_NAME" "PACKAGE_VERSION"\n");
|
||||
retval = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (cmdline->high_priority)
|
||||
if (conf->high_priority)
|
||||
pa_raise_priority();
|
||||
|
||||
if (!cmdline->stay_root)
|
||||
if (!conf->stay_root)
|
||||
drop_root();
|
||||
|
||||
if (cmdline->daemonize) {
|
||||
if (conf->daemonize) {
|
||||
pid_t child;
|
||||
|
||||
if (pa_stdio_acquire() < 0) {
|
||||
|
|
@ -168,7 +199,7 @@ int main(int argc, char *argv[]) {
|
|||
daemon_pipe[0] = -1;
|
||||
|
||||
|
||||
if (cmdline->auto_log_target)
|
||||
if (conf->auto_log_target)
|
||||
pa_log_set_target(PA_LOG_SYSLOG, NULL);
|
||||
|
||||
setsid();
|
||||
|
|
@ -178,15 +209,6 @@ int main(int argc, char *argv[]) {
|
|||
close(1);
|
||||
}
|
||||
|
||||
r = lt_dlinit();
|
||||
assert(r == 0);
|
||||
|
||||
if (cmdline->dl_search_path)
|
||||
lt_dlsetsearchpath(cmdline->dl_search_path);
|
||||
#ifdef DLSEARCHPATH
|
||||
else
|
||||
lt_dlsetsearchpath(DLSEARCHPATH);
|
||||
#endif
|
||||
|
||||
pa_log(__FILE__": sizeof(pa_usec_t) = %u\n", sizeof(pa_usec_t));
|
||||
|
||||
|
|
@ -210,25 +232,28 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
buf = pa_strbuf_new();
|
||||
assert(buf);
|
||||
r = pa_cli_command_execute(c, cmdline->cli_commands, buf, &cmdline->fail, &cmdline->verbose);
|
||||
if (conf->default_script_file)
|
||||
pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail, &conf->verbose);
|
||||
r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail, &conf->verbose);
|
||||
pa_log(s = pa_strbuf_tostring_free(buf));
|
||||
pa_xfree(s);
|
||||
|
||||
if (r < 0 && cmdline->fail) {
|
||||
if (r < 0 && conf->fail) {
|
||||
pa_log(__FILE__": failed to initialize daemon.\n");
|
||||
if (cmdline->daemonize)
|
||||
if (conf->daemonize)
|
||||
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
||||
} else if (!c->modules || pa_idxset_ncontents(c->modules) == 0) {
|
||||
pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.\n");
|
||||
if (cmdline->daemonize)
|
||||
if (conf->daemonize)
|
||||
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
||||
} else {
|
||||
retval = 0;
|
||||
if (cmdline->daemonize)
|
||||
if (conf->daemonize)
|
||||
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
||||
|
||||
c->disallow_module_loading = cmdline->disallow_module_loading;
|
||||
c->quit_after_last_client_time = cmdline->quit_after_last_client_time;
|
||||
c->disallow_module_loading = conf->disallow_module_loading;
|
||||
c->exit_idle_time = conf->exit_idle_time;
|
||||
c->module_idle_time = conf->module_idle_time;
|
||||
|
||||
pa_log(__FILE__": Daemon startup complete.\n");
|
||||
if (pa_mainloop_run(mainloop, &retval) < 0)
|
||||
|
|
@ -242,16 +267,16 @@ int main(int argc, char *argv[]) {
|
|||
pa_signal_done();
|
||||
pa_mainloop_free(mainloop);
|
||||
|
||||
lt_dlexit();
|
||||
|
||||
pa_log(__FILE__": Daemon terminated.\n");
|
||||
|
||||
finish:
|
||||
|
||||
if (cmdline)
|
||||
pa_cmdline_free(cmdline);
|
||||
if (conf)
|
||||
pa_conf_free(conf);
|
||||
|
||||
close_pipe(daemon_pipe);
|
||||
|
||||
lt_dlexit();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "sink.h"
|
||||
#include "source.h"
|
||||
#include "xmalloc.h"
|
||||
#include "util.h"
|
||||
|
||||
struct pa_modargs;
|
||||
|
||||
|
|
@ -229,6 +230,7 @@ int pa_modargs_get_value_s32(struct pa_modargs *ma, const char *key, int32_t *va
|
|||
|
||||
int pa_modargs_get_value_boolean(struct pa_modargs *ma, const char *key, int *value) {
|
||||
const char *v;
|
||||
int r;
|
||||
assert(ma && key && value);
|
||||
|
||||
if (!(v = pa_modargs_get_value(ma, key, NULL)))
|
||||
|
|
@ -237,13 +239,10 @@ int pa_modargs_get_value_boolean(struct pa_modargs *ma, const char *key, int *va
|
|||
if (!*v)
|
||||
return -1;
|
||||
|
||||
if (!strcmp(v, "1") || !strcasecmp(v, "yes") || !strcasecmp(v, "y") || !strcasecmp(v, "on"))
|
||||
*value = 1;
|
||||
else if (!strcmp(v, "0") || !strcasecmp(v, "no") || !strcasecmp(v, "n") || !strcasecmp(v, "off"))
|
||||
*value = 0;
|
||||
else
|
||||
if ((r = pa_parse_boolean(v)) < 0)
|
||||
return -1;
|
||||
|
||||
*value = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
#define PA_SYMBOL_INIT "pa__init"
|
||||
#define PA_SYMBOL_DONE "pa__done"
|
||||
|
||||
#define UNLOAD_POLL_TIME 10
|
||||
#define UNLOAD_POLL_TIME 2
|
||||
|
||||
static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, const struct timeval *tv, void *userdata) {
|
||||
struct pa_core *c = userdata;
|
||||
|
|
@ -193,7 +193,7 @@ static int unused_callback(void *p, uint32_t index, int *del, void *userdata) {
|
|||
time_t *now = userdata;
|
||||
assert(p && del && now);
|
||||
|
||||
if (m->n_used == 0 && m->auto_unload && m->last_used_time+m->core->auto_unload_time <= *now) {
|
||||
if (m->n_used == 0 && m->auto_unload && m->last_used_time+m->core->module_idle_time <= *now) {
|
||||
pa_module_free(m);
|
||||
*del = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,7 +286,10 @@ static void stream_get_latency_callback(struct pa_stream *s, const struct pa_lat
|
|||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Current latency is %f usecs.\n", (float) (i->buffer_usec+i->sink_usec+i->transport_usec));
|
||||
fprintf(stderr, "Latency: buffer: %0.0f usec; sink: %0.0f usec; transport: %0.0f usec; total: %0.0f usec; synchronized clocks: %s.\n",
|
||||
(float) i->buffer_usec, (float) i->sink_usec, (float) i->transport_usec,
|
||||
(float) (i->buffer_usec+i->sink_usec+i->transport_usec),
|
||||
i->synchronized_clocks ? "yes" : "no");
|
||||
}
|
||||
|
||||
/* Someone requested that the latency is shown */
|
||||
|
|
|
|||
|
|
@ -145,6 +145,15 @@ struct pa_latency_info {
|
|||
pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to the daemon. \since 0.5 */
|
||||
int playing; /**< Non-zero when the stream is currently playing */
|
||||
uint32_t queue_length; /**< Queue size in bytes. */
|
||||
int synchronized_clocks; /**< Non-zero if the local and the
|
||||
* remote machine have synchronized
|
||||
* clocks. If synchronized clocks are
|
||||
* detected transport_usec becomes much
|
||||
* more reliable. However, the code that
|
||||
* detects synchronized clocks is very
|
||||
* limited und unreliable itself. \since
|
||||
* 0.5 */
|
||||
struct timeval timestamp; /**< The time when this latency info was current */
|
||||
};
|
||||
|
||||
PA_C_DECL_END
|
||||
|
|
|
|||
|
|
@ -347,12 +347,18 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman
|
|||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now))
|
||||
if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) {
|
||||
/* local and remote seem to have synchronized clocks */
|
||||
i.transport_usec = pa_timeval_diff(&remote, &local);
|
||||
else
|
||||
i.synchronized_clocks = 1;
|
||||
i.timestamp = remote;
|
||||
} else {
|
||||
/* clocks are not synchronized, let's estimate latency then */
|
||||
i.transport_usec = pa_timeval_diff(&now, &local)/2;
|
||||
i.synchronized_clocks = 0;
|
||||
i.timestamp = local;
|
||||
pa_timeval_add(&i.timestamp, i.transport_usec);
|
||||
}
|
||||
|
||||
if (o->callback) {
|
||||
void (*cb)(struct pa_stream *s, const struct pa_latency_info *i, void *userdata) = o->callback;
|
||||
|
|
|
|||
|
|
@ -101,15 +101,15 @@ int pa_socket_low_delay(int fd) {
|
|||
}
|
||||
|
||||
int pa_socket_tcp_low_delay(int fd) {
|
||||
int ret, tos;
|
||||
int ret, tos, on;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
ret = pa_socket_low_delay(fd);
|
||||
|
||||
/* on = 1; */
|
||||
/* if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) */
|
||||
/* ret = -1; */
|
||||
on = 1;
|
||||
if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
|
||||
ret = -1;
|
||||
|
||||
tos = IPTOS_LOWDELAY;
|
||||
if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0)
|
||||
|
|
@ -122,10 +122,10 @@ int pa_socket_tcp_low_delay(int fd) {
|
|||
int pa_socket_set_rcvbuf(int fd, size_t l) {
|
||||
assert(fd >= 0);
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) {
|
||||
pa_log(__FILE__": SO_RCVBUF: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
/* if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) { */
|
||||
/* pa_log(__FILE__": SO_RCVBUF: %s\n", strerror(errno)); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -133,10 +133,10 @@ int pa_socket_set_rcvbuf(int fd, size_t l) {
|
|||
int pa_socket_set_sndbuf(int fd, size_t l) {
|
||||
assert(fd >= 0);
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) {
|
||||
pa_log(__FILE__": SO_SNDBUF: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
/* if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) { */
|
||||
/* pa_log(__FILE__": SO_SNDBUF: %s\n", strerror(errno)); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
26
polyp/util.c
26
polyp/util.c
|
|
@ -268,6 +268,22 @@ pa_usec_t pa_age(const struct timeval *tv) {
|
|||
return pa_timeval_diff(&now, tv);
|
||||
}
|
||||
|
||||
void pa_timeval_add(struct timeval *tv, pa_usec_t v) {
|
||||
unsigned long secs;
|
||||
assert(tv);
|
||||
|
||||
secs = (v/1000000);
|
||||
tv->tv_sec += (unsigned long) secs;
|
||||
v -= secs*1000000;
|
||||
|
||||
tv->tv_usec += v;
|
||||
|
||||
while (tv->tv_usec >= 1000000) {
|
||||
tv->tv_sec++;
|
||||
tv->tv_usec -= 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
#define NICE_LEVEL (-15)
|
||||
|
||||
void pa_raise_priority(void) {
|
||||
|
|
@ -347,3 +363,13 @@ char *pa_path_get_filename(const char *p) {
|
|||
|
||||
return (char*) p;
|
||||
}
|
||||
|
||||
int pa_parse_boolean(const char *v) {
|
||||
|
||||
if (!strcmp(v, "1") || !strcasecmp(v, "yes") || !strcasecmp(v, "y") || !strcasecmp(v, "on"))
|
||||
return 1;
|
||||
else if (!strcmp(v, "0") || !strcasecmp(v, "no") || !strcasecmp(v, "n") || !strcasecmp(v, "off"))
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,10 +50,13 @@ char *pa_path_get_filename(const char *p);
|
|||
pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b);
|
||||
int pa_timeval_cmp(const struct timeval *a, const struct timeval *b);
|
||||
pa_usec_t pa_age(const struct timeval *tv);
|
||||
void pa_timeval_add(struct timeval *tv, pa_usec_t v);
|
||||
|
||||
void pa_raise_priority(void);
|
||||
void pa_reset_priority(void);
|
||||
|
||||
int pa_fd_set_cloexec(int fd, int b);
|
||||
|
||||
int pa_parse_boolean(const char *s);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue