mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2026-02-11 04:27:48 -05:00
merge 'lennart' branch back into trunk.
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1971 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
6687dd0131
commit
a67c21f093
294 changed files with 79057 additions and 11614 deletions
|
|
@ -26,11 +26,11 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#ifdef HAVE_SYS_CAPABILITY_H
|
||||
#include <sys/capability.h>
|
||||
|
|
@ -60,7 +60,7 @@ void pa_drop_root(void) {
|
|||
if (uid == 0 || geteuid() != 0)
|
||||
return;
|
||||
|
||||
pa_log_info("dropping root rights.");
|
||||
pa_log_info("Dropping root priviliges.");
|
||||
|
||||
#if defined(HAVE_SETRESUID)
|
||||
setresuid(uid, uid, uid);
|
||||
|
|
@ -88,8 +88,9 @@ int pa_limit_caps(void) {
|
|||
cap_value_t nice_cap = CAP_SYS_NICE;
|
||||
|
||||
caps = cap_init();
|
||||
assert(caps);
|
||||
pa_assert(caps);
|
||||
cap_clear(caps);
|
||||
cap_set_flag(caps, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET);
|
||||
cap_set_flag(caps, CAP_PERMITTED, 1, &nice_cap, CAP_SET);
|
||||
|
||||
if (cap_set_proc(caps) < 0)
|
||||
|
|
@ -98,7 +99,7 @@ int pa_limit_caps(void) {
|
|||
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0)
|
||||
goto fail;
|
||||
|
||||
pa_log_info("dropped capabilities successfully.");
|
||||
pa_log_info("Dropped capabilities successfully.");
|
||||
|
||||
r = 1;
|
||||
|
||||
|
|
@ -114,14 +115,14 @@ int pa_drop_caps(void) {
|
|||
int r = -1;
|
||||
|
||||
caps = cap_init();
|
||||
assert(caps);
|
||||
pa_assert(caps);
|
||||
|
||||
cap_clear(caps);
|
||||
|
||||
prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
|
||||
|
||||
if (cap_set_proc(caps) < 0) {
|
||||
pa_log("failed to drop capabilities: %s", pa_cstrerror(errno));
|
||||
pa_log("Failed to drop capabilities: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
|
|
@ -36,6 +35,7 @@
|
|||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/strbuf.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "cmdline.h"
|
||||
|
||||
|
|
@ -63,7 +63,9 @@ enum {
|
|||
ARG_CHECK,
|
||||
ARG_NO_CPU_LIMIT,
|
||||
ARG_DISABLE_SHM,
|
||||
ARG_SYSTEM
|
||||
ARG_DUMP_RESAMPLE_METHODS,
|
||||
ARG_SYSTEM,
|
||||
ARG_CLEANUP_SHM
|
||||
};
|
||||
|
||||
/* Tabel for getopt_long() */
|
||||
|
|
@ -92,12 +94,16 @@ static struct option long_options[] = {
|
|||
{"system", 2, 0, ARG_SYSTEM},
|
||||
{"no-cpu-limit", 2, 0, ARG_NO_CPU_LIMIT},
|
||||
{"disable-shm", 2, 0, ARG_DISABLE_SHM},
|
||||
{"dump-resample-methods", 2, 0, ARG_DUMP_RESAMPLE_METHODS},
|
||||
{"cleanup-shm", 2, 0, ARG_CLEANUP_SHM},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
void pa_cmdline_help(const char *argv0) {
|
||||
const char *e;
|
||||
|
||||
pa_assert(argv0);
|
||||
|
||||
if ((e = strrchr(argv0, '/')))
|
||||
e++;
|
||||
else
|
||||
|
|
@ -109,6 +115,8 @@ void pa_cmdline_help(const char *argv0) {
|
|||
" --version Show version\n"
|
||||
" --dump-conf Dump default configuration\n"
|
||||
" --dump-modules Dump list of available modules\n"
|
||||
" --dump-resample-methods Dump available resample methods\n"
|
||||
" --cleanup-shm Cleanup stale shared memory segments\n"
|
||||
" -k --kill Kill a running daemon\n"
|
||||
" --check Check for a running daemon\n\n"
|
||||
|
||||
|
|
@ -131,9 +139,8 @@ void pa_cmdline_help(const char *argv0) {
|
|||
" -p, --dl-search-path=PATH Set the search path for dynamic shared\n"
|
||||
" objects (plugins)\n"
|
||||
" --resample-method=[METHOD] Use the specified resampling method\n"
|
||||
" (one of src-sinc-medium-quality,\n"
|
||||
" src-sinc-best-quality,src-sinc-fastest\n"
|
||||
" src-zero-order-hold,src-linear,trivial)\n"
|
||||
" (See --dump-resample-methods for\n"
|
||||
" possible values)\n"
|
||||
" --use-pid-file[=BOOL] Create a PID file\n"
|
||||
" --no-cpu-limit[=BOOL] Do not install CPU load limiter on\n"
|
||||
" platforms that support it.\n"
|
||||
|
|
@ -152,7 +159,10 @@ void pa_cmdline_help(const char *argv0) {
|
|||
int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d) {
|
||||
pa_strbuf *buf = NULL;
|
||||
int c;
|
||||
assert(conf && argc && argv);
|
||||
|
||||
pa_assert(conf);
|
||||
pa_assert(argc > 0);
|
||||
pa_assert(argv);
|
||||
|
||||
buf = pa_strbuf_new();
|
||||
|
||||
|
|
@ -178,6 +188,14 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
|
|||
conf->cmd = PA_CMD_DUMP_MODULES;
|
||||
break;
|
||||
|
||||
case ARG_DUMP_RESAMPLE_METHODS:
|
||||
conf->cmd = PA_CMD_DUMP_RESAMPLE_METHODS;
|
||||
break;
|
||||
|
||||
case ARG_CLEANUP_SHM:
|
||||
conf->cmd = PA_CMD_CLEANUP_SHM;
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
case ARG_KILL:
|
||||
conf->cmd = PA_CMD_KILL;
|
||||
|
|
@ -193,9 +211,12 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
|
|||
break;
|
||||
|
||||
case ARG_FILE:
|
||||
case 'F':
|
||||
pa_strbuf_printf(buf, ".include %s\n", optarg);
|
||||
case 'F': {
|
||||
char *p;
|
||||
pa_strbuf_printf(buf, ".include %s\n", p = pa_make_path_absolute(optarg));
|
||||
pa_xfree(p);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'C':
|
||||
pa_strbuf_puts(buf, "load-module module-cli exit_on_eof=1\n");
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "cpulimit.h"
|
||||
|
||||
|
|
@ -38,7 +39,6 @@
|
|||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
|
@ -92,23 +92,18 @@ static enum {
|
|||
|
||||
/* Reset the SIGXCPU timer to the next t seconds */
|
||||
static void reset_cpu_time(int t) {
|
||||
int r;
|
||||
long n;
|
||||
struct rlimit rl;
|
||||
struct rusage ru;
|
||||
|
||||
/* Get the current CPU time of the current process */
|
||||
r = getrusage(RUSAGE_SELF, &ru);
|
||||
assert(r >= 0);
|
||||
pa_assert_se(getrusage(RUSAGE_SELF, &ru) >= 0);
|
||||
|
||||
n = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec + t;
|
||||
|
||||
r = getrlimit(RLIMIT_CPU, &rl);
|
||||
assert(r >= 0);
|
||||
pa_assert_se(getrlimit(RLIMIT_CPU, &rl) >= 0);
|
||||
|
||||
rl.rlim_cur = n;
|
||||
r = setrlimit(RLIMIT_CPU, &rl);
|
||||
assert(r >= 0);
|
||||
pa_assert_se(setrlimit(RLIMIT_CPU, &rl) >= 0);
|
||||
}
|
||||
|
||||
/* A simple, thread-safe puts() work-alike */
|
||||
|
|
@ -118,7 +113,7 @@ static void write_err(const char *p) {
|
|||
|
||||
/* The signal handler, called on every SIGXCPU */
|
||||
static void signal_handler(int sig) {
|
||||
assert(sig == SIGXCPU);
|
||||
pa_assert(sig == SIGXCPU);
|
||||
|
||||
if (phase == PHASE_IDLE) {
|
||||
time_t now;
|
||||
|
|
@ -130,7 +125,7 @@ static void signal_handler(int sig) {
|
|||
time(&now);
|
||||
|
||||
#ifdef PRINT_CPU_LOAD
|
||||
snprintf(t, sizeof(t), "Using %0.1f%% CPU\n", (double)CPUTIME_INTERVAL_SOFT/(now-last_time)*100);
|
||||
pa_snprintf(t, sizeof(t), "Using %0.1f%% CPU\n", (double)CPUTIME_INTERVAL_SOFT/(now-last_time)*100);
|
||||
write_err(t);
|
||||
#endif
|
||||
|
||||
|
|
@ -160,7 +155,12 @@ static void signal_handler(int sig) {
|
|||
/* Callback for IO events on the FIFO */
|
||||
static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata) {
|
||||
char c;
|
||||
assert(m && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == the_pipe[0]);
|
||||
pa_assert(m);
|
||||
pa_assert(e);
|
||||
pa_assert(f == PA_IO_EVENT_INPUT);
|
||||
pa_assert(e == io_event);
|
||||
pa_assert(fd == the_pipe[0]);
|
||||
|
||||
pa_read(the_pipe[0], &c, sizeof(c), NULL);
|
||||
m->quit(m, 1); /* Quit the main loop */
|
||||
}
|
||||
|
|
@ -168,7 +168,13 @@ static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags
|
|||
/* Initializes CPU load limiter */
|
||||
int pa_cpu_limit_init(pa_mainloop_api *m) {
|
||||
struct sigaction sa;
|
||||
assert(m && !api && !io_event && the_pipe[0] == -1 && the_pipe[1] == -1 && !installed);
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(!api);
|
||||
pa_assert(!io_event);
|
||||
pa_assert(the_pipe[0] == -1);
|
||||
pa_assert(the_pipe[1] == -1);
|
||||
pa_assert(!installed);
|
||||
|
||||
time(&last_time);
|
||||
|
||||
|
|
@ -178,10 +184,10 @@ int pa_cpu_limit_init(pa_mainloop_api *m) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
pa_make_nonblock_fd(the_pipe[0]);
|
||||
pa_make_nonblock_fd(the_pipe[1]);
|
||||
pa_fd_set_cloexec(the_pipe[0], 1);
|
||||
pa_fd_set_cloexec(the_pipe[1], 1);
|
||||
pa_make_fd_nonblock(the_pipe[0]);
|
||||
pa_make_fd_nonblock(the_pipe[1]);
|
||||
pa_make_fd_cloexec(the_pipe[0]);
|
||||
pa_make_fd_cloexec(the_pipe[1]);
|
||||
|
||||
api = m;
|
||||
io_event = api->io_new(m, the_pipe[0], PA_IO_EVENT_INPUT, callback, NULL);
|
||||
|
|
@ -208,24 +214,18 @@ int pa_cpu_limit_init(pa_mainloop_api *m) {
|
|||
|
||||
/* Shutdown CPU load limiter */
|
||||
void pa_cpu_limit_done(void) {
|
||||
int r;
|
||||
|
||||
if (io_event) {
|
||||
assert(api);
|
||||
pa_assert(api);
|
||||
api->io_free(io_event);
|
||||
io_event = NULL;
|
||||
api = NULL;
|
||||
}
|
||||
|
||||
if (the_pipe[0] >= 0)
|
||||
close(the_pipe[0]);
|
||||
if (the_pipe[1] >= 0)
|
||||
close(the_pipe[1]);
|
||||
the_pipe[0] = the_pipe[1] = -1;
|
||||
pa_close_pipe(the_pipe);
|
||||
|
||||
if (installed) {
|
||||
r = sigaction(SIGXCPU, &sigaction_prev, NULL);
|
||||
assert(r >= 0);
|
||||
pa_assert_se(sigaction(SIGXCPU, &sigaction_prev, NULL) >= 0);
|
||||
installed = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
|
@ -39,19 +38,14 @@
|
|||
#include <pulsecore/strbuf.h>
|
||||
#include <pulsecore/conf-parser.h>
|
||||
#include <pulsecore/resampler.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "daemon-conf.h"
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
# define PATH_SEP "/"
|
||||
#else
|
||||
# define PATH_SEP "\\"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "default.pa"
|
||||
#define DEFAULT_SCRIPT_FILE_USER PATH_SEP "default.pa"
|
||||
#define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf"
|
||||
#define DEFAULT_CONFIG_FILE_USER PATH_SEP "daemon.conf"
|
||||
#define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "default.pa"
|
||||
#define DEFAULT_SCRIPT_FILE_USER PA_PATH_SEP "default.pa"
|
||||
#define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "daemon.conf"
|
||||
#define DEFAULT_CONFIG_FILE_USER PA_PATH_SEP "daemon.conf"
|
||||
|
||||
#define ENV_SCRIPT_FILE "PULSE_SCRIPT"
|
||||
#define ENV_CONFIG_FILE "PULSE_CONFIG"
|
||||
|
|
@ -72,31 +66,34 @@ static const pa_daemon_conf default_conf = {
|
|||
.default_script_file = NULL,
|
||||
.log_target = PA_LOG_SYSLOG,
|
||||
.log_level = PA_LOG_NOTICE,
|
||||
.resample_method = PA_RESAMPLER_SRC_SINC_FASTEST,
|
||||
.resample_method = PA_RESAMPLER_AUTO,
|
||||
.config_file = NULL,
|
||||
.use_pid_file = 1,
|
||||
.system_instance = 0,
|
||||
.no_cpu_limit = 0,
|
||||
.disable_shm = 0
|
||||
.disable_shm = 0,
|
||||
.default_n_fragments = 4,
|
||||
.default_fragment_size_msec = 25,
|
||||
.default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 }
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
, .rlimit_as = { .value = 0, .is_set = 0 },
|
||||
.rlimit_core = { .value = 0, .is_set = 0 },
|
||||
.rlimit_data = { .value = 0, .is_set = 0 },
|
||||
.rlimit_fsize = { .value = 0, .is_set = 0 },
|
||||
.rlimit_nofile = { .value = 200, .is_set = 1 },
|
||||
.rlimit_nofile = { .value = 256, .is_set = 1 },
|
||||
.rlimit_stack = { .value = 0, .is_set = 0 }
|
||||
#ifdef RLIMIT_NPROC
|
||||
, .rlimit_nproc = { .value = 0, .is_set = 0 }
|
||||
#endif
|
||||
#ifdef RLIMIT_MEMLOCK
|
||||
, .rlimit_memlock = { .value = 0, .is_set = 1 }
|
||||
, .rlimit_memlock = { .value = 16384, .is_set = 1 }
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
pa_daemon_conf* pa_daemon_conf_new(void) {
|
||||
FILE *f;
|
||||
pa_daemon_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf));
|
||||
pa_daemon_conf *c = pa_xnewdup(pa_daemon_conf, &default_conf, 1);
|
||||
|
||||
if ((f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file, "r")))
|
||||
fclose(f);
|
||||
|
|
@ -106,7 +103,7 @@ pa_daemon_conf* pa_daemon_conf_new(void) {
|
|||
}
|
||||
|
||||
void pa_daemon_conf_free(pa_daemon_conf *c) {
|
||||
assert(c);
|
||||
pa_assert(c);
|
||||
pa_xfree(c->script_commands);
|
||||
pa_xfree(c->dl_search_path);
|
||||
pa_xfree(c->default_script_file);
|
||||
|
|
@ -115,7 +112,8 @@ void pa_daemon_conf_free(pa_daemon_conf *c) {
|
|||
}
|
||||
|
||||
int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string) {
|
||||
assert(c && string);
|
||||
pa_assert(c);
|
||||
pa_assert(string);
|
||||
|
||||
if (!strcmp(string, "auto"))
|
||||
c->auto_log_target = 1;
|
||||
|
|
@ -133,7 +131,8 @@ int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string) {
|
|||
|
||||
int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) {
|
||||
uint32_t u;
|
||||
assert(c && string);
|
||||
pa_assert(c);
|
||||
pa_assert(string);
|
||||
|
||||
if (pa_atou(string, &u) >= 0) {
|
||||
if (u >= PA_LOG_LEVEL_MAX)
|
||||
|
|
@ -158,7 +157,8 @@ int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) {
|
|||
|
||||
int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) {
|
||||
int m;
|
||||
assert(c && string);
|
||||
pa_assert(c);
|
||||
pa_assert(string);
|
||||
|
||||
if ((m = pa_parse_resample_method(string)) < 0)
|
||||
return -1;
|
||||
|
|
@ -169,7 +169,11 @@ int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) {
|
|||
|
||||
static int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
assert(filename && lvalue && rvalue && data);
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_daemon_conf_set_log_target(c, rvalue) < 0) {
|
||||
pa_log("[%s:%u] Invalid log target '%s'.", filename, line, rvalue);
|
||||
|
|
@ -181,7 +185,11 @@ static int parse_log_target(const char *filename, unsigned line, const char *lva
|
|||
|
||||
static int parse_log_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
assert(filename && lvalue && rvalue && data);
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_daemon_conf_set_log_level(c, rvalue) < 0) {
|
||||
pa_log("[%s:%u] Invalid log level '%s'.", filename, line, rvalue);
|
||||
|
|
@ -193,10 +201,14 @@ static int parse_log_level(const char *filename, unsigned line, const char *lval
|
|||
|
||||
static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
assert(filename && lvalue && rvalue && data);
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_daemon_conf_set_resample_method(c, rvalue) < 0) {
|
||||
pa_log("[%s:%u] Inavalid resample method '%s'.", filename, line, rvalue);
|
||||
pa_log("[%s:%u] Invalid resample method '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -206,10 +218,11 @@ static int parse_resample_method(const char *filename, unsigned line, const char
|
|||
static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
struct pa_rlimit *r = data;
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(r);
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(r);
|
||||
|
||||
if (rvalue[strspn(rvalue, "\t ")] == 0) {
|
||||
/* Empty string */
|
||||
|
|
@ -218,7 +231,7 @@ static int parse_rlimit(const char *filename, unsigned line, const char *lvalue,
|
|||
} else {
|
||||
int32_t k;
|
||||
if (pa_atoi(rvalue, &k) < 0) {
|
||||
pa_log("[%s:%u] Inavalid rlimit '%s'.", filename, line, rvalue);
|
||||
pa_log("[%s:%u] Invalid rlimit '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
r->is_set = k >= 0;
|
||||
|
|
@ -231,43 +244,138 @@ static int parse_rlimit(const char *filename, unsigned line, const char *lvalue,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int parse_sample_format(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
pa_sample_format_t f;
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if ((f = pa_parse_sample_format(rvalue)) < 0) {
|
||||
pa_log("[%s:%u] Invalid sample format '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->default_sample_spec.format = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_sample_rate(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t r;
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_atoi(rvalue, &r) < 0 || r > PA_RATE_MAX || r <= 0) {
|
||||
pa_log("[%s:%u] Invalid sample rate '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->default_sample_spec.rate = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_sample_channels(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t n;
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_atoi(rvalue, &n) < 0 || n > PA_CHANNELS_MAX || n <= 0) {
|
||||
pa_log("[%s:%u] Invalid sample channels '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->default_sample_spec.channels = (uint8_t) n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_fragments(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t n;
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_atoi(rvalue, &n) < 0 || n < 2) {
|
||||
pa_log("[%s:%u] Invalid number of fragments '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->default_n_fragments = (unsigned) n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_fragment_size_msec(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t n;
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_atoi(rvalue, &n) < 0 || n < 1) {
|
||||
pa_log("[%s:%u] Invalid fragment size '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->default_fragment_size_msec = (unsigned) n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
|
||||
int r = -1;
|
||||
FILE *f = NULL;
|
||||
|
||||
pa_config_item table[] = {
|
||||
{ "daemonize", pa_config_parse_bool, NULL },
|
||||
{ "fail", pa_config_parse_bool, NULL },
|
||||
{ "high-priority", pa_config_parse_bool, NULL },
|
||||
{ "disallow-module-loading", pa_config_parse_bool, NULL },
|
||||
{ "exit-idle-time", pa_config_parse_int, NULL },
|
||||
{ "module-idle-time", pa_config_parse_int, NULL },
|
||||
{ "scache-idle-time", pa_config_parse_int, NULL },
|
||||
{ "dl-search-path", pa_config_parse_string, NULL },
|
||||
{ "default-script-file", pa_config_parse_string, NULL },
|
||||
{ "log-target", parse_log_target, NULL },
|
||||
{ "log-level", parse_log_level, NULL },
|
||||
{ "verbose", parse_log_level, NULL },
|
||||
{ "resample-method", parse_resample_method, NULL },
|
||||
{ "use-pid-file", pa_config_parse_bool, NULL },
|
||||
{ "system-instance", pa_config_parse_bool, NULL },
|
||||
{ "no-cpu-limit", pa_config_parse_bool, NULL },
|
||||
{ "disable-shm", pa_config_parse_bool, NULL },
|
||||
{ "daemonize", pa_config_parse_bool, NULL },
|
||||
{ "fail", pa_config_parse_bool, NULL },
|
||||
{ "high-priority", pa_config_parse_bool, NULL },
|
||||
{ "disallow-module-loading", pa_config_parse_bool, NULL },
|
||||
{ "exit-idle-time", pa_config_parse_int, NULL },
|
||||
{ "module-idle-time", pa_config_parse_int, NULL },
|
||||
{ "scache-idle-time", pa_config_parse_int, NULL },
|
||||
{ "dl-search-path", pa_config_parse_string, NULL },
|
||||
{ "default-script-file", pa_config_parse_string, NULL },
|
||||
{ "log-target", parse_log_target, NULL },
|
||||
{ "log-level", parse_log_level, NULL },
|
||||
{ "verbose", parse_log_level, NULL },
|
||||
{ "resample-method", parse_resample_method, NULL },
|
||||
{ "use-pid-file", pa_config_parse_bool, NULL },
|
||||
{ "system-instance", pa_config_parse_bool, NULL },
|
||||
{ "no-cpu-limit", pa_config_parse_bool, NULL },
|
||||
{ "disable-shm", pa_config_parse_bool, NULL },
|
||||
{ "default-sample-format", parse_sample_format, NULL },
|
||||
{ "default-sample-rate", parse_sample_rate, NULL },
|
||||
{ "default-sample-channels", parse_sample_channels, NULL },
|
||||
{ "default-fragments", parse_fragments, NULL },
|
||||
{ "default-fragment-size-msec", parse_fragment_size_msec, NULL },
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
{ "rlimit-as", parse_rlimit, NULL },
|
||||
{ "rlimit-core", parse_rlimit, NULL },
|
||||
{ "rlimit-data", parse_rlimit, NULL },
|
||||
{ "rlimit-fsize", parse_rlimit, NULL },
|
||||
{ "rlimit-nofile", parse_rlimit, NULL },
|
||||
{ "rlimit-stack", parse_rlimit, NULL },
|
||||
{ "rlimit-as", parse_rlimit, NULL },
|
||||
{ "rlimit-core", parse_rlimit, NULL },
|
||||
{ "rlimit-data", parse_rlimit, NULL },
|
||||
{ "rlimit-fsize", parse_rlimit, NULL },
|
||||
{ "rlimit-nofile", parse_rlimit, NULL },
|
||||
{ "rlimit-stack", parse_rlimit, NULL },
|
||||
#ifdef RLIMIT_NPROC
|
||||
{ "rlimit-nproc", parse_rlimit, NULL },
|
||||
{ "rlimit-nproc", parse_rlimit, NULL },
|
||||
#endif
|
||||
#ifdef RLIMIT_MEMLOCK
|
||||
{ "rlimit-memlock", parse_rlimit, NULL },
|
||||
{ "rlimit-memlock", parse_rlimit, NULL },
|
||||
#endif
|
||||
#endif
|
||||
{ NULL, NULL, NULL },
|
||||
{ NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
table[0].data = &c->daemonize;
|
||||
|
|
@ -287,25 +395,29 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
|
|||
table[14].data = &c->system_instance;
|
||||
table[15].data = &c->no_cpu_limit;
|
||||
table[16].data = &c->disable_shm;
|
||||
table[17].data = c;
|
||||
table[18].data = c;
|
||||
table[19].data = c;
|
||||
table[20].data = c;
|
||||
table[21].data = c;
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
table[17].data = &c->rlimit_as;
|
||||
table[18].data = &c->rlimit_core;
|
||||
table[19].data = &c->rlimit_data;
|
||||
table[20].data = &c->rlimit_fsize;
|
||||
table[21].data = &c->rlimit_nofile;
|
||||
table[22].data = &c->rlimit_stack;
|
||||
table[22].data = &c->rlimit_as;
|
||||
table[23].data = &c->rlimit_core;
|
||||
table[24].data = &c->rlimit_data;
|
||||
table[25].data = &c->rlimit_fsize;
|
||||
table[26].data = &c->rlimit_nofile;
|
||||
table[27].data = &c->rlimit_stack;
|
||||
#ifdef RLIMIT_NPROC
|
||||
table[23].data = &c->rlimit_nproc;
|
||||
table[28].data = &c->rlimit_nproc;
|
||||
#endif
|
||||
#ifdef RLIMIT_MEMLOCK
|
||||
#ifndef RLIMIT_NPROC
|
||||
#error "Houston, we have a numbering problem!"
|
||||
#endif
|
||||
table[24].data = &c->rlimit_memlock;
|
||||
table[29].data = &c->rlimit_memlock;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
pa_xfree(c->config_file);
|
||||
c->config_file = NULL;
|
||||
|
||||
|
|
@ -314,7 +426,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
|
|||
pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file, "r");
|
||||
|
||||
if (!f && errno != ENOENT) {
|
||||
pa_log("WARNING: failed to open configuration file '%s': %s", c->config_file, pa_cstrerror(errno));
|
||||
pa_log_warn("Failed to open configuration file '%s': %s", c->config_file, pa_cstrerror(errno));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -351,12 +463,16 @@ static const char* const log_level_to_string[] = {
|
|||
};
|
||||
|
||||
char *pa_daemon_conf_dump(pa_daemon_conf *c) {
|
||||
pa_strbuf *s = pa_strbuf_new();
|
||||
pa_strbuf *s;
|
||||
|
||||
pa_assert(c);
|
||||
|
||||
s = pa_strbuf_new();
|
||||
|
||||
if (c->config_file)
|
||||
pa_strbuf_printf(s, "### Read from configuration file: %s ###\n", c->config_file);
|
||||
|
||||
assert(c->log_level <= PA_LOG_LEVEL_MAX);
|
||||
pa_assert(c->log_level <= PA_LOG_LEVEL_MAX);
|
||||
|
||||
pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize);
|
||||
pa_strbuf_printf(s, "fail = %i\n", !!c->fail);
|
||||
|
|
@ -373,7 +489,12 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
|
|||
pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file);
|
||||
pa_strbuf_printf(s, "system-instance = %i\n", !!c->system_instance);
|
||||
pa_strbuf_printf(s, "no-cpu-limit = %i\n", !!c->no_cpu_limit);
|
||||
pa_strbuf_printf(s, "disable_shm = %i\n", !!c->disable_shm);
|
||||
pa_strbuf_printf(s, "disable-shm = %i\n", !!c->disable_shm);
|
||||
pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format));
|
||||
pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate);
|
||||
pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels);
|
||||
pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments);
|
||||
pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec);
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1);
|
||||
pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
***/
|
||||
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulse/sample.h>
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
#include <sys/resource.h>
|
||||
|
|
@ -39,7 +40,9 @@ typedef enum pa_daemon_conf_cmd {
|
|||
PA_CMD_DUMP_CONF,
|
||||
PA_CMD_DUMP_MODULES,
|
||||
PA_CMD_KILL,
|
||||
PA_CMD_CHECK
|
||||
PA_CMD_CHECK,
|
||||
PA_CMD_DUMP_RESAMPLE_METHODS,
|
||||
PA_CMD_CLEANUP_SHM
|
||||
} pa_daemon_conf_cmd_t;
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
|
|
@ -80,6 +83,8 @@ typedef struct pa_daemon_conf {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
unsigned default_n_fragments, default_fragment_size_msec;
|
||||
pa_sample_spec default_sample_spec;
|
||||
} pa_daemon_conf;
|
||||
|
||||
/* Allocate a new structure and fill it with sane defaults */
|
||||
|
|
|
|||
|
|
@ -92,10 +92,19 @@
|
|||
; rlimit-core = -1
|
||||
; rlimit-data = -1
|
||||
; rlimit-fsize = -1
|
||||
; rlimit-nofile = 200
|
||||
; rlimit-nofile = 256
|
||||
; rlimit-stack = -1
|
||||
; rlimit-nproc = -1
|
||||
; rlimit-memlock = 25
|
||||
; rlimit-memlock = 16384
|
||||
|
||||
## Disable shared memory data transfer
|
||||
; disable-shm = 0
|
||||
|
||||
## Default sample format
|
||||
; default-sample-format = s16le
|
||||
; default-sample-rate = 44100
|
||||
; default-sample-channels = 2
|
||||
|
||||
## Default fragment settings, for device drivers that need this
|
||||
; default-fragments = 4
|
||||
; default-fragment-size-msec = 25
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#!@PA_BINARY@ -nF
|
||||
|
||||
#!@PA_BINARY@ -nF
|
||||
#
|
||||
# This file is part of PulseAudio.
|
||||
#
|
||||
|
|
@ -17,8 +16,19 @@
|
|||
# along with PulseAudio; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
.nofail
|
||||
|
||||
### Load audio drivers statically
|
||||
### Load something into the sample cache
|
||||
#load-sample-lazy x11-bell /usr/share/sounds/gtk-events/activate.wav
|
||||
load-sample-lazy pulse-hotplug /usr/share/sounds/startup3.wav
|
||||
#load-sample-lazy pulse-coldplug /usr/share/sounds/startup3.wav
|
||||
#load-sample-lazy pulse-access /usr/share/sounds/generic.wav
|
||||
|
||||
.fail
|
||||
|
||||
### Load audio drivers statically (it's probably better to not load
|
||||
### these drivers manually, but instead use module-hal-detect --
|
||||
### see below -- for doing this automatically)
|
||||
#load-module module-alsa-sink
|
||||
#load-module module-alsa-source device=hw:1,0
|
||||
#load-module module-oss device="/dev/dsp" sink_name=output source_name=input
|
||||
|
|
@ -27,19 +37,13 @@
|
|||
#load-module module-pipe-sink
|
||||
|
||||
### Automatically load driver modules depending on the hardware available
|
||||
@HAVE_HAL_TRUE@load-module module-hal-detect
|
||||
|
||||
.ifexists @PA_DLSEARCHPATH@/module-hal-detect@PA_SOEXT@
|
||||
load-module module-hal-detect
|
||||
.else
|
||||
### Alternatively use the static hardware detection module (for systems that
|
||||
### lack HAL support
|
||||
@HAVE_HAL_FALSE@load-module module-detect
|
||||
|
||||
### Load audio drivers automatically on access
|
||||
#add-autoload-sink output module-oss device="/dev/dsp" sink_name=output source_name=input
|
||||
#add-autoload-source input module-oss device="/dev/dsp" sink_name=output source_name=input
|
||||
#add-autoload-sink output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input
|
||||
#add-autoload-source input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input
|
||||
#add-autoload-sink output module-alsa-sink sink_name=output
|
||||
#add-autoload-source input module-alsa-source source_name=input
|
||||
### lack HAL support)
|
||||
load-module module-detect
|
||||
.endif
|
||||
|
||||
### Load several protocols
|
||||
load-module module-esound-protocol-unix
|
||||
|
|
@ -61,27 +65,36 @@ load-module module-native-protocol-unix
|
|||
### Automatically restore the volume of playback streams
|
||||
load-module module-volume-restore
|
||||
|
||||
### Automatically restore the default sink/source when changed by the user during runtime
|
||||
load-module module-default-device-restore
|
||||
|
||||
### Automatically move streams to the default sink if the sink they are
|
||||
### connected to dies, similar for sources
|
||||
load-module module-rescue-streams
|
||||
|
||||
### Make some devices default
|
||||
#set-default-sink output
|
||||
#set-default-source input
|
||||
|
||||
.nofail
|
||||
|
||||
### Load something to the sample cache
|
||||
load-sample x11-bell /usr/share/sounds/gtk-events/activate.wav
|
||||
#load-sample-dir-lazy /usr/share/sounds/*.wav
|
||||
### Automatically suspend sinks/sources that become idle for too long
|
||||
load-module module-suspend-on-idle
|
||||
|
||||
### Load X11 bell module
|
||||
load-module module-x11-bell sample=x11-bell
|
||||
#load-module module-x11-bell sample=x11-bell
|
||||
|
||||
### Publish connection data in the X11 root window
|
||||
.ifexists @PA_DLSEARCHPATH@/module-x11-publish@PA_SOEXT@
|
||||
load-module module-x11-publish
|
||||
.endif
|
||||
|
||||
### Register ourselves in the X11 session manager
|
||||
# Deactivated by default, to avoid deadlock when PA is started as esd from gnome-session
|
||||
# Instead we load this via /etc/xdg/autostart/ and "pactl load-module" now
|
||||
# load-module module-x11-xsmp
|
||||
|
||||
### Load additional modules from GConf settings. This can be configured with the paprefs tool.
|
||||
### Please keep in mind that the modules configured by paprefs might conflict with manually
|
||||
### loaded modules.
|
||||
.ifexists @PA_DLSEARCHPATH@/module-gconf@PA_SOEXT@
|
||||
load-module module-gconf
|
||||
.endif
|
||||
|
||||
### Make some devices default
|
||||
#set-default-sink output
|
||||
#set-default-source input
|
||||
|
|
|
|||
|
|
@ -28,26 +28,30 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <ltdl.h>
|
||||
|
||||
#include <pulse/util.h>
|
||||
|
||||
#include <pulsecore/modinfo.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "dumpmodules.h"
|
||||
|
||||
#define PREFIX "module-"
|
||||
|
||||
static void short_info(const char *name, PA_GCC_UNUSED const char *path, pa_modinfo *i) {
|
||||
assert(name && i);
|
||||
pa_assert(name);
|
||||
pa_assert(i);
|
||||
|
||||
printf("%-40s%s\n", name, i->description ? i->description : "n/a");
|
||||
}
|
||||
|
||||
static void long_info(const char *name, const char *path, pa_modinfo *i) {
|
||||
static int nl = 0;
|
||||
assert(name && i);
|
||||
pa_assert(name);
|
||||
pa_assert(i);
|
||||
|
||||
if (nl)
|
||||
printf("\n");
|
||||
|
|
@ -76,6 +80,8 @@ static void long_info(const char *name, const char *path, pa_modinfo *i) {
|
|||
static void show_info(const char *name, const char *path, void (*info)(const char *name, const char *path, pa_modinfo*i)) {
|
||||
pa_modinfo *i;
|
||||
|
||||
pa_assert(name);
|
||||
|
||||
if ((i = pa_modinfo_get_by_name(path ? path : name))) {
|
||||
info(name, path, i);
|
||||
pa_modinfo_free(i);
|
||||
|
|
@ -93,7 +99,7 @@ static int is_preloaded(const char *name) {
|
|||
if (l->address)
|
||||
continue;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s", l->name);
|
||||
pa_snprintf(buf, sizeof(buf), "%s", l->name);
|
||||
if ((e = strrchr(buf, '.')))
|
||||
*e = 0;
|
||||
|
||||
|
|
@ -121,6 +127,8 @@ static int callback(const char *path, lt_ptr data) {
|
|||
}
|
||||
|
||||
void pa_dump_modules(pa_daemon_conf *c, int argc, char * const argv[]) {
|
||||
pa_assert(c);
|
||||
|
||||
if (argc > 0) {
|
||||
int i;
|
||||
for (i = 0; i < argc; i++)
|
||||
|
|
@ -137,7 +145,7 @@ void pa_dump_modules(pa_daemon_conf *c, int argc, char * const argv[]) {
|
|||
if (strlen(l->name) <= sizeof(PREFIX)-1 || strncmp(l->name, PREFIX, sizeof(PREFIX)-1))
|
||||
continue;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s", l->name);
|
||||
pa_snprintf(buf, sizeof(buf), "%s", l->name);
|
||||
if ((e = strrchr(buf, '.')))
|
||||
*e = 0;
|
||||
|
||||
|
|
|
|||
160
src/daemon/ltdl-bind-now.c
Normal file
160
src/daemon/ltdl-bind-now.c
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/* $Id$ */
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2004-2006 Lennart Poettering
|
||||
Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio 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 Lesser General Public License
|
||||
along with PulseAudio; 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
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_DL_H
|
||||
#include <sys/dl.h>
|
||||
#endif
|
||||
|
||||
#include <ltdl.h>
|
||||
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/mutex.h>
|
||||
#include <pulsecore/thread.h>
|
||||
#include <pulsecore/log.h>
|
||||
|
||||
#include "ltdl-bind-now.h"
|
||||
|
||||
#ifdef RTLD_NOW
|
||||
#define PA_BIND_NOW RTLD_NOW
|
||||
#elif defined(DL_NOW)
|
||||
#define PA_BIND_NOW DL_NOW
|
||||
#else
|
||||
#undef PA_BIND_NOW
|
||||
#endif
|
||||
|
||||
static pa_mutex *libtool_mutex = NULL;
|
||||
|
||||
PA_STATIC_TLS_DECLARE_NO_FREE(libtool_tls);
|
||||
|
||||
static void libtool_lock(void) {
|
||||
pa_mutex_lock(libtool_mutex);
|
||||
}
|
||||
|
||||
static void libtool_unlock(void) {
|
||||
pa_mutex_unlock(libtool_mutex);
|
||||
}
|
||||
|
||||
static void libtool_set_error(const char *error) {
|
||||
PA_STATIC_TLS_SET(libtool_tls, (char*) error);
|
||||
}
|
||||
|
||||
static const char *libtool_get_error(void) {
|
||||
return PA_STATIC_TLS_GET(libtool_tls);
|
||||
}
|
||||
|
||||
#ifdef PA_BIND_NOW
|
||||
|
||||
/*
|
||||
To avoid lazy relocations during runtime in our RT threads we add
|
||||
our own shared object loader with uses RTLD_NOW if it is
|
||||
available. The standard ltdl loader prefers RTLD_LAZY.
|
||||
|
||||
Please note that this loader doesn't have any influence on
|
||||
relocations on any libraries that are already loaded into our
|
||||
process, i.e. because the pulseaudio binary links directly to
|
||||
them. To disable lazy relocations for those libraries it is possible
|
||||
to set $LT_BIND_NOW before starting the pulsaudio binary.
|
||||
*/
|
||||
|
||||
static lt_module bind_now_open(lt_user_data d, const char *fname) {
|
||||
lt_module m;
|
||||
|
||||
pa_assert(fname);
|
||||
|
||||
if (!(m = dlopen(fname, PA_BIND_NOW))) {
|
||||
libtool_set_error(dlerror());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
static int bind_now_close(lt_user_data d, lt_module m) {
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (dlclose(m) != 0){
|
||||
libtool_set_error(dlerror());
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static lt_ptr bind_now_find_sym(lt_user_data d, lt_module m, const char *symbol) {
|
||||
lt_ptr ptr;
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(symbol);
|
||||
|
||||
if (!(ptr = dlsym(m, symbol))) {
|
||||
libtool_set_error(dlerror());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void pa_ltdl_init(void) {
|
||||
|
||||
#ifdef PA_BIND_NOW
|
||||
lt_dlloader *place;
|
||||
static const struct lt_user_dlloader loader = {
|
||||
.module_open = bind_now_open,
|
||||
.module_close = bind_now_close,
|
||||
.find_sym = bind_now_find_sym
|
||||
};
|
||||
#endif
|
||||
|
||||
pa_assert_se(lt_dlinit() == 0);
|
||||
pa_assert_se(libtool_mutex = pa_mutex_new(TRUE, FALSE));
|
||||
pa_assert_se(lt_dlmutex_register(libtool_lock, libtool_unlock, libtool_set_error, libtool_get_error) == 0);
|
||||
|
||||
#ifdef PA_BIND_NOW
|
||||
|
||||
if (!(place = lt_dlloader_find("dlopen")))
|
||||
place = lt_dlloader_next(NULL);
|
||||
|
||||
/* Add our BIND_NOW loader as the default module loader. */
|
||||
if (lt_dlloader_add(place, &loader, "bind-now-loader") != 0)
|
||||
pa_log_warn("Failed to add bind-now-loader.");
|
||||
#endif
|
||||
}
|
||||
|
||||
void pa_ltdl_done(void) {
|
||||
pa_assert_se(lt_dlexit() == 0);
|
||||
pa_mutex_free(libtool_mutex);
|
||||
libtool_mutex = NULL;
|
||||
}
|
||||
|
||||
32
src/daemon/ltdl-bind-now.h
Normal file
32
src/daemon/ltdl-bind-now.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef foopulsecoreltdlbindnowhfoo
|
||||
#define foopulsecoreltdlbindnowhfoo
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2004-2006 Lennart Poettering
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio 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 Lesser General Public License
|
||||
along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
|
||||
void pa_ltdl_init(void);
|
||||
void pa_ltdl_done(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -33,7 +33,6 @@
|
|||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include <ltdl.h>
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
|
|
@ -59,13 +58,16 @@
|
|||
#include <tcpd.h>
|
||||
#endif
|
||||
|
||||
#include "../pulsecore/winsock.h"
|
||||
#ifdef HAVE_DBUS
|
||||
#include <dbus/dbus.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/mainloop.h>
|
||||
#include <pulse/mainloop-signal.h>
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/winsock.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/memblock.h>
|
||||
|
|
@ -78,12 +80,20 @@
|
|||
#include <pulsecore/pid.h>
|
||||
#include <pulsecore/namereg.h>
|
||||
#include <pulsecore/random.h>
|
||||
#include <pulsecore/rtsig.h>
|
||||
#include <pulsecore/rtclock.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/mutex.h>
|
||||
#include <pulsecore/thread.h>
|
||||
#include <pulsecore/once.h>
|
||||
#include <pulsecore/shm.h>
|
||||
|
||||
#include "cmdline.h"
|
||||
#include "cpulimit.h"
|
||||
#include "daemon-conf.h"
|
||||
#include "dumpmodules.h"
|
||||
#include "caps.h"
|
||||
#include "ltdl-bind-now.h"
|
||||
|
||||
#ifdef HAVE_LIBWRAP
|
||||
/* Only one instance of these variables */
|
||||
|
|
@ -120,7 +130,7 @@ static void message_cb(pa_mainloop_api*a, pa_time_event*e, PA_GCC_UNUSED const s
|
|||
#endif
|
||||
|
||||
static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e, int sig, void *userdata) {
|
||||
pa_log_info("Got signal %s.", pa_strsignal(sig));
|
||||
pa_log_info("Got signal %s.", pa_sig2str(sig));
|
||||
|
||||
switch (sig) {
|
||||
#ifdef SIGUSR1
|
||||
|
|
@ -153,14 +163,6 @@ static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e,
|
|||
}
|
||||
}
|
||||
|
||||
static void close_pipe(int p[2]) {
|
||||
if (p[0] != -1)
|
||||
close(p[0]);
|
||||
if (p[1] != -1)
|
||||
close(p[1]);
|
||||
p[0] = p[1] = -1;
|
||||
}
|
||||
|
||||
#define set_env(key, value) putenv(pa_sprintf_malloc("%s=%s", (key), (value)))
|
||||
|
||||
#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
|
||||
|
|
@ -281,7 +283,7 @@ static int create_runtime_dir(void) {
|
|||
|
||||
static void set_one_rlimit(const pa_rlimit *r, int resource, const char *name) {
|
||||
struct rlimit rl;
|
||||
assert(r);
|
||||
pa_assert(r);
|
||||
|
||||
if (!r->is_set)
|
||||
return;
|
||||
|
|
@ -313,13 +315,11 @@ int main(int argc, char *argv[]) {
|
|||
pa_strbuf *buf = NULL;
|
||||
pa_daemon_conf *conf = NULL;
|
||||
pa_mainloop *mainloop = NULL;
|
||||
|
||||
char *s;
|
||||
int r, retval = 1, d = 0;
|
||||
int r = 0, retval = 1, d = 0;
|
||||
int daemon_pipe[2] = { -1, -1 };
|
||||
int suid_root, real_root;
|
||||
int valid_pid_file = 0;
|
||||
|
||||
gid_t gid = (gid_t) -1;
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
|
|
@ -327,6 +327,23 @@ int main(int argc, char *argv[]) {
|
|||
struct timeval tv;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__linux__) && defined(__OPTIMIZE__)
|
||||
/*
|
||||
Disable lazy relocations to make usage of external libraries
|
||||
more deterministic for our RT threads. We abuse __OPTIMIZE__ as
|
||||
a check whether we are a debug build or not.
|
||||
*/
|
||||
|
||||
if (!getenv("LD_BIND_NOW")) {
|
||||
putenv(pa_xstrdup("LD_BIND_NOW=1"));
|
||||
|
||||
/* We have to execute ourselves, because the libc caches the
|
||||
* value of $LD_BIND_NOW on initialization. */
|
||||
pa_assert_se(execv("/proc/self/exe", argv) == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETUID
|
||||
real_root = getuid() == 0;
|
||||
suid_root = !real_root && geteuid() == 0;
|
||||
|
|
@ -336,16 +353,26 @@ int main(int argc, char *argv[]) {
|
|||
#endif
|
||||
|
||||
if (suid_root) {
|
||||
if (pa_limit_caps() > 0)
|
||||
/* We managed to drop capabilities except the needed
|
||||
* ones. Hence we can drop the uid. */
|
||||
pa_drop_root();
|
||||
/* Drop all capabilities except CAP_SYS_NICE */
|
||||
pa_limit_caps();
|
||||
|
||||
/* Drop priviliges, but keep CAP_SYS_NICE */
|
||||
pa_drop_root();
|
||||
|
||||
/* After dropping root, the effective set is reset, hence,
|
||||
* let's raise it again */
|
||||
pa_limit_caps();
|
||||
|
||||
/* When capabilities are not supported we will not be able to
|
||||
* aquire RT sched anymore. But yes, that's the way it is. It
|
||||
* is just too risky tun let PA run as root all the time. */
|
||||
}
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) {
|
||||
pa_log_warn("WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'.");
|
||||
if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0)) {
|
||||
pa_log_info("Warning: Called SUID root, but not in group '"PA_REALTIME_GROUP"'. "
|
||||
"For enabling real-time scheduling please become a member of '"PA_REALTIME_GROUP"' , or increase the RLIMIT_RTPRIO user limit.");
|
||||
pa_drop_caps();
|
||||
pa_drop_root();
|
||||
suid_root = real_root = 0;
|
||||
|
|
@ -353,8 +380,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
LTDL_SET_PRELOADED_SYMBOLS();
|
||||
|
||||
r = lt_dlinit();
|
||||
assert(r == 0);
|
||||
pa_ltdl_init();
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
{
|
||||
|
|
@ -386,7 +412,7 @@ int main(int argc, char *argv[]) {
|
|||
if (conf->high_priority && conf->cmd == PA_CMD_DAEMON)
|
||||
pa_raise_priority();
|
||||
|
||||
if (suid_root) {
|
||||
if (suid_root && (conf->cmd != PA_CMD_DAEMON || !conf->high_priority)) {
|
||||
pa_drop_caps();
|
||||
pa_drop_root();
|
||||
}
|
||||
|
|
@ -408,6 +434,16 @@ int main(int argc, char *argv[]) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
case PA_CMD_DUMP_RESAMPLE_METHODS: {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PA_RESAMPLER_MAX; i++)
|
||||
if (pa_resample_method_supported(i))
|
||||
printf("%s\n", pa_resample_method_to_string(i));
|
||||
|
||||
goto finish;
|
||||
}
|
||||
|
||||
case PA_CMD_HELP :
|
||||
pa_cmdline_help(argv[0]);
|
||||
retval = 0;
|
||||
|
|
@ -440,8 +476,15 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
goto finish;
|
||||
|
||||
case PA_CMD_CLEANUP_SHM:
|
||||
|
||||
if (pa_shm_cleanup() >= 0)
|
||||
retval = 0;
|
||||
|
||||
goto finish;
|
||||
|
||||
default:
|
||||
assert(conf->cmd == PA_CMD_DAEMON);
|
||||
pa_assert(conf->cmd == PA_CMD_DAEMON);
|
||||
}
|
||||
|
||||
if (real_root && !conf->system_instance) {
|
||||
|
|
@ -474,7 +517,7 @@ int main(int argc, char *argv[]) {
|
|||
if (child != 0) {
|
||||
/* Father */
|
||||
|
||||
close(daemon_pipe[1]);
|
||||
pa_assert_se(pa_close(daemon_pipe[1]) == 0);
|
||||
daemon_pipe[1] = -1;
|
||||
|
||||
if (pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL) != sizeof(retval)) {
|
||||
|
|
@ -490,7 +533,7 @@ int main(int argc, char *argv[]) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
close(daemon_pipe[0]);
|
||||
pa_assert_se(pa_close(daemon_pipe[0]) == 0);
|
||||
daemon_pipe[0] = -1;
|
||||
#endif
|
||||
|
||||
|
|
@ -505,9 +548,9 @@ int main(int argc, char *argv[]) {
|
|||
#endif
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
pa_close(0);
|
||||
pa_close(1);
|
||||
pa_close(2);
|
||||
|
||||
open("/dev/null", O_RDONLY);
|
||||
open("/dev/null", O_WRONLY);
|
||||
|
|
@ -529,12 +572,12 @@ int main(int argc, char *argv[]) {
|
|||
#ifdef TIOCNOTTY
|
||||
if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
|
||||
ioctl(tty_fd, TIOCNOTTY, (char*) 0);
|
||||
close(tty_fd);
|
||||
pa_assert_se(pa_close(tty_fd) == 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
chdir("/");
|
||||
pa_assert_se(chdir("/") == 0);
|
||||
umask(0022);
|
||||
|
||||
if (conf->system_instance) {
|
||||
|
|
@ -564,18 +607,37 @@ int main(int argc, char *argv[]) {
|
|||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
mainloop = pa_mainloop_new();
|
||||
assert(mainloop);
|
||||
pa_log_info("Page size is %lu bytes", (unsigned long) PA_PAGE_SIZE);
|
||||
|
||||
if (pa_rtclock_hrtimer())
|
||||
pa_log_info("Fresh high-resolution timers available! Bon appetit!");
|
||||
else
|
||||
pa_log_info("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!");
|
||||
|
||||
#ifdef SIGRTMIN
|
||||
/* Valgrind uses SIGRTMAX. To easy debugging we don't use it here */
|
||||
pa_rtsig_configure(SIGRTMIN, SIGRTMAX-1);
|
||||
#endif
|
||||
|
||||
pa_assert_se(mainloop = pa_mainloop_new());
|
||||
|
||||
if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm))) {
|
||||
pa_log("pa_core_new() failed.");
|
||||
pa_log("pa_core_new() failed.");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
c->is_system_instance = !!conf->system_instance;
|
||||
c->high_priority = !!conf->high_priority;
|
||||
c->default_sample_spec = conf->default_sample_spec;
|
||||
c->default_n_fragments = conf->default_n_fragments;
|
||||
c->default_fragment_size_msec = conf->default_fragment_size_msec;
|
||||
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;
|
||||
|
||||
r = pa_signal_init(pa_mainloop_get_api(mainloop));
|
||||
assert(r == 0);
|
||||
pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0);
|
||||
pa_signal_new(SIGINT, signal_callback, c);
|
||||
pa_signal_new(SIGTERM, signal_callback, c);
|
||||
|
||||
|
|
@ -590,9 +652,7 @@ int main(int argc, char *argv[]) {
|
|||
#endif
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
timer = pa_mainloop_get_api(mainloop)->time_new(
|
||||
pa_mainloop_get_api(mainloop), pa_gettimeofday(&tv), message_cb, NULL);
|
||||
assert(timer);
|
||||
pa_assert_se(timer = pa_mainloop_get_api(mainloop)->time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&tv), message_cb, NULL));
|
||||
#endif
|
||||
|
||||
if (conf->daemonize)
|
||||
|
|
@ -600,10 +660,8 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
oil_init();
|
||||
|
||||
if (!conf->no_cpu_limit) {
|
||||
r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop));
|
||||
assert(r == 0);
|
||||
}
|
||||
if (!conf->no_cpu_limit)
|
||||
pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0);
|
||||
|
||||
buf = pa_strbuf_new();
|
||||
if (conf->default_script_file)
|
||||
|
|
@ -634,12 +692,6 @@ int main(int argc, char *argv[]) {
|
|||
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
if (c->default_sink_name &&
|
||||
pa_namereg_get(c, c->default_sink_name, PA_NAMEREG_SINK, 1) == NULL) {
|
||||
pa_log_error("%s : Fatal error. Default sink name (%s) does not exist in name register.", __FILE__, c->default_sink_name);
|
||||
|
|
@ -656,7 +708,7 @@ int main(int argc, char *argv[]) {
|
|||
pa_mainloop_get_api(mainloop)->time_free(timer);
|
||||
#endif
|
||||
|
||||
pa_core_free(c);
|
||||
pa_core_unref(c);
|
||||
|
||||
if (!conf->no_cpu_limit)
|
||||
pa_cpu_limit_done();
|
||||
|
|
@ -676,13 +728,17 @@ finish:
|
|||
if (valid_pid_file)
|
||||
pa_pid_file_remove();
|
||||
|
||||
close_pipe(daemon_pipe);
|
||||
pa_close_pipe(daemon_pipe);
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
|
||||
lt_dlexit();
|
||||
pa_ltdl_done();
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
dbus_shutdown();
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
10
src/daemon/pulseaudio-module-xsmp.desktop
Normal file
10
src/daemon/pulseaudio-module-xsmp.desktop
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Encoding=UTF-8
|
||||
Name=PulseAudio Session Management
|
||||
Comment=Load module-x11-xsmp into PulseAudio
|
||||
Exec=pactl load-module module-x11-xsmp
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=
|
||||
GenericName=
|
||||
Loading…
Add table
Add a link
Reference in a new issue