mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-02 09:01:46 -05:00
Merge branch 'master' of git://git.0pointer.de/pulseaudio
This commit is contained in:
commit
4282b726ee
196 changed files with 7704 additions and 3300 deletions
1
src/.gitignore
vendored
1
src/.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
|||
lock-autospawn-test
|
||||
*.lo
|
||||
*.o
|
||||
*.la
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ AM_CFLAGS += -DPA_SYSTEM_RUNTIME_PATH=\"$(PA_SYSTEM_RUNTIME_PATH)\"
|
|||
AM_CFLAGS += -DPA_SYSTEM_CONFIG_PATH=\"$(PA_SYSTEM_CONFIG_PATH)\"
|
||||
AM_CFLAGS += -DPA_SYSTEM_STATE_PATH=\"$(PA_SYSTEM_STATE_PATH)\"
|
||||
AM_CFLAGS += -DAO_REQUIRE_CAS
|
||||
AM_CFLAGS += -DPULSE_LOCALEDIR=\"$(pulselocaledir)\"
|
||||
AM_CFLAGS += -DPA_MACHINE_ID=\"$(localstatedir)/lib/dbus/machine-id\"
|
||||
|
||||
# This cool debug trap works on i386/gcc only
|
||||
AM_CFLAGS += '-DDEBUG_TRAP=__asm__("int $$3")'
|
||||
|
|
@ -260,7 +262,8 @@ noinst_PROGRAMS = \
|
|||
envelope-test \
|
||||
proplist-test \
|
||||
rtstutter \
|
||||
stripnul
|
||||
stripnul \
|
||||
lock-autospawn-test
|
||||
|
||||
if HAVE_SIGXCPU
|
||||
noinst_PROGRAMS += \
|
||||
|
|
@ -450,6 +453,11 @@ stripnul_LDADD = $(AM_LDADD) libpulsecore.la
|
|||
stripnul_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
stripnul_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
|
||||
|
||||
lock_autospawn_test_SOURCES = tests/lock-autospawn-test.c
|
||||
lock_autospawn_test_LDADD = $(AM_LDADD) libpulsecore.la
|
||||
lock_autospawn_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
lock_autospawn_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
|
||||
|
||||
###################################
|
||||
# Client library #
|
||||
###################################
|
||||
|
|
@ -479,7 +487,8 @@ pulseinclude_HEADERS = \
|
|||
pulse/volume.h \
|
||||
pulse/xmalloc.h \
|
||||
pulse/proplist.h \
|
||||
pulse/gccmacro.h
|
||||
pulse/gccmacro.h \
|
||||
pulse/ext-stream-restore.h
|
||||
|
||||
if HAVE_AVAHI
|
||||
pulseinclude_HEADERS += \
|
||||
|
|
@ -530,7 +539,10 @@ libpulse_la_SOURCES = \
|
|||
pulse/util.c pulse/util.h \
|
||||
pulse/volume.c pulse/volume.h \
|
||||
pulse/xmalloc.c pulse/xmalloc.h \
|
||||
pulse/proplist.c pulse/proplist.h
|
||||
pulse/proplist.c pulse/proplist.h \
|
||||
pulse/ext-stream-restore.c pulse/ext-stream-restore.h \
|
||||
pulse/i18n.c pulse/i18n.h \
|
||||
pulse/lock-autospawn.c pulse/lock-autospawn.h
|
||||
|
||||
# Internal stuff that is shared with libpulsecore
|
||||
libpulse_la_SOURCES += \
|
||||
|
|
@ -725,7 +737,9 @@ libpulsecore_la_SOURCES = \
|
|||
pulse/util.c pulse/util.h \
|
||||
pulse/volume.c pulse/volume.h \
|
||||
pulse/xmalloc.c pulse/xmalloc.h \
|
||||
pulse/proplist.c pulse/proplist.h
|
||||
pulse/proplist.c pulse/proplist.h \
|
||||
pulse/i18n.c pulse/i18n.h \
|
||||
pulse/lock-autospawn.c pulse/lock-autospawn.h
|
||||
|
||||
# Pure core stuff (some are shared in libpulse though).
|
||||
libpulsecore_la_SOURCES += \
|
||||
|
|
@ -1609,7 +1623,7 @@ update-ffmpeg:
|
|||
update-map-file:
|
||||
( echo "PULSE_0 {" ; \
|
||||
echo "global:" ; \
|
||||
ctags -I PA_GCC_PURE,PA_GCC_CONST -f - --c-kinds=p $(pulseinclude_HEADERS) | awk '/^pa_/ { print $$1 ";" }' | sort ; \
|
||||
ctags -I PA_GCC_PURE,PA_GCC_CONST,PA_GCC_DEPRECATED,PA_GCC_PRINTF_ATTR -f - --c-kinds=p $(pulseinclude_HEADERS) | awk '/^pa_/ { print $$1 ";" }' | sort ; \
|
||||
echo "local:" ; \
|
||||
echo "*;" ; \
|
||||
echo "};" ) > $(srcdir)/map-file
|
||||
|
|
|
|||
|
|
@ -28,7 +28,12 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/log.h>
|
||||
|
||||
#ifdef HAVE_SYS_CAPABILITY_H
|
||||
#include <sys/capability.h>
|
||||
|
|
@ -37,10 +42,6 @@
|
|||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
|
||||
#include <pulsecore/log.h>
|
||||
|
||||
#include "caps.h"
|
||||
|
||||
/* Glibc <= 2.2 has broken unistd.h */
|
||||
|
|
@ -58,7 +59,7 @@ void pa_drop_root(void) {
|
|||
if (uid == 0 || geteuid() != 0)
|
||||
return;
|
||||
|
||||
pa_log_info("Dropping root priviliges.");
|
||||
pa_log_info(_("Dropping root priviliges."));
|
||||
|
||||
#if defined(HAVE_SETRESUID)
|
||||
pa_assert_se(setresuid(uid, uid, uid) >= 0);
|
||||
|
|
@ -98,7 +99,7 @@ void pa_limit_caps(void) {
|
|||
* that */
|
||||
pa_drop_caps();
|
||||
else
|
||||
pa_log_info("Limited capabilities successfully to CAP_SYS_NICE.");
|
||||
pa_log_info(_("Limited capabilities successfully to CAP_SYS_NICE."));
|
||||
|
||||
pa_assert_se(cap_free(caps) == 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <sys/stat.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/strbuf.h>
|
||||
|
|
@ -49,6 +50,7 @@ enum {
|
|||
ARG_HIGH_PRIORITY,
|
||||
ARG_REALTIME,
|
||||
ARG_DISALLOW_MODULE_LOADING,
|
||||
ARG_DISALLOW_EXIT,
|
||||
ARG_EXIT_IDLE_TIME,
|
||||
ARG_MODULE_IDLE_TIME,
|
||||
ARG_SCACHE_IDLE_TIME,
|
||||
|
|
@ -81,6 +83,7 @@ static const struct option long_options[] = {
|
|||
{"high-priority", 2, 0, ARG_HIGH_PRIORITY},
|
||||
{"realtime", 2, 0, ARG_REALTIME},
|
||||
{"disallow-module-loading", 2, 0, ARG_DISALLOW_MODULE_LOADING},
|
||||
{"disallow-exit", 2, 0, ARG_DISALLOW_EXIT},
|
||||
{"exit-idle-time", 2, 0, ARG_EXIT_IDLE_TIME},
|
||||
{"module-idle-time", 2, 0, ARG_MODULE_IDLE_TIME},
|
||||
{"scache-idle-time", 2, 0, ARG_SCACHE_IDLE_TIME},
|
||||
|
|
@ -111,7 +114,7 @@ void pa_cmdline_help(const char *argv0) {
|
|||
else
|
||||
e = argv0;
|
||||
|
||||
printf("%s [options]\n\n"
|
||||
printf(_("%s [options]\n\n"
|
||||
"COMMANDS:\n"
|
||||
" -h, --help Show this help\n"
|
||||
" --version Show version\n"
|
||||
|
|
@ -133,7 +136,9 @@ void pa_cmdline_help(const char *argv0) {
|
|||
" --realtime[=BOOL] Try to enable realtime scheduling\n"
|
||||
" (only available as root, when SUID or\n"
|
||||
" with elevated RLIMIT_RTPRIO)\n"
|
||||
" --disallow-module-loading[=BOOL] Disallow module loading after startup\n"
|
||||
" --disallow-module-loading[=BOOL] Disallow module user requested module\n"
|
||||
" loading/unloading after startup\n"
|
||||
" --disallow-exit[=BOOL] Disallow user requested exit\n"
|
||||
" --exit-idle-time=SECS Terminate the daemon when idle and this\n"
|
||||
" time passed\n"
|
||||
" --module-idle-time=SECS Unload autoloaded modules when idle and\n"
|
||||
|
|
@ -160,7 +165,7 @@ void pa_cmdline_help(const char *argv0) {
|
|||
" -C Open a command line on the running TTY\n"
|
||||
" after startup\n\n"
|
||||
|
||||
" -n Don't load default script file\n", e);
|
||||
" -n Don't load default script file\n"), e);
|
||||
}
|
||||
|
||||
int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d) {
|
||||
|
|
@ -237,14 +242,14 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
|
|||
case ARG_DAEMONIZE:
|
||||
case 'D':
|
||||
if ((conf->daemonize = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) {
|
||||
pa_log("--daemonize expects boolean argument");
|
||||
pa_log(_("--daemonize expects boolean argument"));
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARG_FAIL:
|
||||
if ((conf->fail = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) {
|
||||
pa_log("--fail expects boolean argument");
|
||||
pa_log(_("--fail expects boolean argument"));
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
|
@ -254,7 +259,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
|
|||
|
||||
if (optarg) {
|
||||
if (pa_daemon_conf_set_log_level(conf, optarg) < 0) {
|
||||
pa_log("--log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error).");
|
||||
pa_log(_("--log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error)."));
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -266,28 +271,35 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
|
|||
|
||||
case ARG_HIGH_PRIORITY:
|
||||
if ((conf->high_priority = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) {
|
||||
pa_log("--high-priority expects boolean argument");
|
||||
pa_log(_("--high-priority expects boolean argument"));
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARG_REALTIME:
|
||||
if ((conf->realtime_scheduling = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) {
|
||||
pa_log("--realtime expects boolean argument");
|
||||
pa_log(_("--realtime expects boolean argument"));
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARG_DISALLOW_MODULE_LOADING:
|
||||
if ((conf->disallow_module_loading = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) {
|
||||
pa_log("--disallow-module-loading expects boolean argument");
|
||||
pa_log(_("--disallow-module-loading expects boolean argument"));
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARG_DISALLOW_EXIT:
|
||||
if ((conf->disallow_exit = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) {
|
||||
pa_log(_("--disallow-exit boolean argument"));
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARG_USE_PID_FILE:
|
||||
if ((conf->use_pid_file = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) {
|
||||
pa_log("--use-pid-file expects boolean argument");
|
||||
pa_log(_("--use-pid-file expects boolean argument"));
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
|
@ -304,7 +316,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
|
|||
|
||||
case ARG_LOG_TARGET:
|
||||
if (pa_daemon_conf_set_log_target(conf, optarg) < 0) {
|
||||
pa_log("Invalid log target: use either 'syslog', 'stderr' or 'auto'.");
|
||||
pa_log(_("Invalid log target: use either 'syslog', 'stderr' or 'auto'."));
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
|
@ -323,28 +335,28 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
|
|||
|
||||
case ARG_RESAMPLE_METHOD:
|
||||
if (pa_daemon_conf_set_resample_method(conf, optarg) < 0) {
|
||||
pa_log("Invalid resample method '%s'.", optarg);
|
||||
pa_log(_("Invalid resample method '%s'."), optarg);
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARG_SYSTEM:
|
||||
if ((conf->system_instance = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) {
|
||||
pa_log("--system expects boolean argument");
|
||||
pa_log(_("--system expects boolean argument"));
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARG_NO_CPU_LIMIT:
|
||||
if ((conf->no_cpu_limit = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) {
|
||||
pa_log("--no-cpu-limit expects boolean argument");
|
||||
pa_log(_("--no-cpu-limit expects boolean argument"));
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARG_DISABLE_SHM:
|
||||
if ((conf->disable_shm = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) {
|
||||
pa_log("--disable-shm expects boolean argument");
|
||||
pa_log(_("--disable-shm expects boolean argument"));
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@
|
|||
#endif
|
||||
|
||||
#include <pulse/error.h>
|
||||
#include <pulse/timeval.h>
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/rtclock.h>
|
||||
|
||||
#include "cpulimit.h"
|
||||
|
||||
|
|
@ -67,7 +69,7 @@
|
|||
#define CPUTIME_INTERVAL_HARD (5)
|
||||
|
||||
/* Time of the last CPU load check */
|
||||
static time_t last_time = 0;
|
||||
static pa_usec_t last_time = 0;
|
||||
|
||||
/* Pipe for communicating with the main loop */
|
||||
static int the_pipe[2] = {-1, -1};
|
||||
|
|
@ -100,7 +102,7 @@ static void reset_cpu_time(int t) {
|
|||
n = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec + t;
|
||||
pa_assert_se(getrlimit(RLIMIT_CPU, &rl) >= 0);
|
||||
|
||||
rl.rlim_cur = n;
|
||||
rl.rlim_cur = (rlim_t) n;
|
||||
pa_assert_se(setrlimit(RLIMIT_CPU, &rl) >= 0);
|
||||
}
|
||||
|
||||
|
|
@ -117,20 +119,21 @@ static void signal_handler(int sig) {
|
|||
pa_assert(sig == SIGXCPU);
|
||||
|
||||
if (phase == PHASE_IDLE) {
|
||||
time_t now;
|
||||
pa_usec_t now, elapsed;
|
||||
|
||||
#ifdef PRINT_CPU_LOAD
|
||||
char t[256];
|
||||
#endif
|
||||
|
||||
time(&now);
|
||||
now = pa_rtclock_usec();
|
||||
elapsed = now - last_time;
|
||||
|
||||
#ifdef PRINT_CPU_LOAD
|
||||
pa_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 * (double) PA_USEC_PER_SEC) / (double) elapsed * 100.0);
|
||||
write_err(t);
|
||||
#endif
|
||||
|
||||
if (CPUTIME_INTERVAL_SOFT >= ((now-last_time)*(double)CPUTIME_PERCENT/100)) {
|
||||
if (((double) CPUTIME_INTERVAL_SOFT * (double) PA_USEC_PER_SEC) >= ((double) elapsed * (double) CPUTIME_PERCENT / 100.0)) {
|
||||
static const char c = 'X';
|
||||
|
||||
write_err("Soft CPU time limit exhausted, terminating.\n");
|
||||
|
|
@ -179,7 +182,7 @@ int pa_cpu_limit_init(pa_mainloop_api *m) {
|
|||
pa_assert(the_pipe[1] == -1);
|
||||
pa_assert(!installed);
|
||||
|
||||
time(&last_time);
|
||||
last_time = pa_rtclock_usec();
|
||||
|
||||
/* Prepare the main loop pipe */
|
||||
if (pipe(the_pipe) < 0) {
|
||||
|
|
@ -235,7 +238,7 @@ void pa_cpu_limit_done(void) {
|
|||
|
||||
#else /* HAVE_SIGXCPU */
|
||||
|
||||
int pa_cpu_limit_init(PA_GCC_UNUSED pa_mainloop_api *m) {
|
||||
int pa_cpu_limit_init(pa_mainloop_api *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
|
|
@ -62,6 +63,7 @@ static const pa_daemon_conf default_conf = {
|
|||
.realtime_scheduling = FALSE,
|
||||
.realtime_priority = 5, /* Half of JACK's default rtprio */
|
||||
.disallow_module_loading = FALSE,
|
||||
.disallow_exit = FALSE,
|
||||
.exit_idle_time = 20,
|
||||
.module_idle_time = 20,
|
||||
.scache_idle_time = 20,
|
||||
|
|
@ -189,7 +191,7 @@ int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
static int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
|
||||
pa_assert(filename);
|
||||
|
|
@ -198,14 +200,14 @@ static int parse_log_target(const char *filename, unsigned line, const char *lva
|
|||
pa_assert(data);
|
||||
|
||||
if (pa_daemon_conf_set_log_target(c, rvalue) < 0) {
|
||||
pa_log("[%s:%u] Invalid log target '%s'.", filename, line, rvalue);
|
||||
pa_log(_("[%s:%u] Invalid log target '%s'."), filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_log_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
static int parse_log_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
|
||||
pa_assert(filename);
|
||||
|
|
@ -214,14 +216,14 @@ static int parse_log_level(const char *filename, unsigned line, const char *lval
|
|||
pa_assert(data);
|
||||
|
||||
if (pa_daemon_conf_set_log_level(c, rvalue) < 0) {
|
||||
pa_log("[%s:%u] Invalid log level '%s'.", filename, line, rvalue);
|
||||
pa_log(_("[%s:%u] Invalid log level '%s'."), filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
|
||||
pa_assert(filename);
|
||||
|
|
@ -230,14 +232,14 @@ static int parse_resample_method(const char *filename, unsigned line, const char
|
|||
pa_assert(data);
|
||||
|
||||
if (pa_daemon_conf_set_resample_method(c, rvalue) < 0) {
|
||||
pa_log("[%s:%u] Invalid resample method '%s'.", filename, line, rvalue);
|
||||
pa_log(_("[%s:%u] Invalid resample method '%s'."), filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
struct pa_rlimit *r = data;
|
||||
|
||||
|
|
@ -253,20 +255,20 @@ 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] Invalid rlimit '%s'.", filename, line, rvalue);
|
||||
pa_log(_("[%s:%u] Invalid rlimit '%s'."), filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
r->is_set = k >= 0;
|
||||
r->value = k >= 0 ? (rlim_t) k : 0;
|
||||
}
|
||||
#else
|
||||
pa_log_warn("[%s:%u] rlimit not supported on this platform.", filename, line);
|
||||
pa_log_warn(_("[%s:%u] rlimit not supported on this platform."), filename, line);
|
||||
#endif
|
||||
|
||||
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) {
|
||||
static int parse_sample_format(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
pa_sample_format_t f;
|
||||
|
||||
|
|
@ -276,7 +278,7 @@ static int parse_sample_format(const char *filename, unsigned line, const char *
|
|||
pa_assert(data);
|
||||
|
||||
if ((f = pa_parse_sample_format(rvalue)) < 0) {
|
||||
pa_log("[%s:%u] Invalid sample format '%s'.", filename, line, rvalue);
|
||||
pa_log(_("[%s:%u] Invalid sample format '%s'."), filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -284,17 +286,17 @@ static int parse_sample_format(const char *filename, unsigned line, const char *
|
|||
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) {
|
||||
static int parse_sample_rate(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t r;
|
||||
uint32_t r;
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_atoi(rvalue, &r) < 0 || r > (int32_t) PA_RATE_MAX || r <= 0) {
|
||||
pa_log("[%s:%u] Invalid sample rate '%s'.", filename, line, rvalue);
|
||||
if (pa_atou(rvalue, &r) < 0 || r > (uint32_t) PA_RATE_MAX || r <= 0) {
|
||||
pa_log(_("[%s:%u] Invalid sample rate '%s'."), filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -302,7 +304,7 @@ static int parse_sample_rate(const char *filename, unsigned line, const char *lv
|
|||
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) {
|
||||
static int parse_sample_channels(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t n;
|
||||
|
||||
|
|
@ -312,7 +314,7 @@ static int parse_sample_channels(const char *filename, unsigned line, const char
|
|||
pa_assert(data);
|
||||
|
||||
if (pa_atoi(rvalue, &n) < 0 || n > (int32_t) PA_CHANNELS_MAX || n <= 0) {
|
||||
pa_log("[%s:%u] Invalid sample channels '%s'.", filename, line, rvalue);
|
||||
pa_log(_("[%s:%u] Invalid sample channels '%s'."), filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -320,7 +322,7 @@ static int parse_sample_channels(const char *filename, unsigned line, const char
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int parse_fragments(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
static int parse_fragments(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t n;
|
||||
|
||||
|
|
@ -330,7 +332,7 @@ static int parse_fragments(const char *filename, unsigned line, const char *lval
|
|||
pa_assert(data);
|
||||
|
||||
if (pa_atoi(rvalue, &n) < 0 || n < 2) {
|
||||
pa_log("[%s:%u] Invalid number of fragments '%s'.", filename, line, rvalue);
|
||||
pa_log(_("[%s:%u] Invalid number of fragments '%s'."), filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -338,7 +340,7 @@ static int parse_fragments(const char *filename, unsigned line, const char *lval
|
|||
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) {
|
||||
static int parse_fragment_size_msec(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t n;
|
||||
|
||||
|
|
@ -348,7 +350,7 @@ static int parse_fragment_size_msec(const char *filename, unsigned line, const c
|
|||
pa_assert(data);
|
||||
|
||||
if (pa_atoi(rvalue, &n) < 0 || n < 1) {
|
||||
pa_log("[%s:%u] Invalid fragment size '%s'.", filename, line, rvalue);
|
||||
pa_log(_("[%s:%u] Invalid fragment size '%s'."), filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -356,7 +358,7 @@ static int parse_fragment_size_msec(const char *filename, unsigned line, const c
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int parse_nice_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
static int parse_nice_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t level;
|
||||
|
||||
|
|
@ -366,7 +368,7 @@ static int parse_nice_level(const char *filename, unsigned line, const char *lva
|
|||
pa_assert(data);
|
||||
|
||||
if (pa_atoi(rvalue, &level) < 0 || level < -20 || level > 19) {
|
||||
pa_log("[%s:%u] Invalid nice level '%s'.", filename, line, rvalue);
|
||||
pa_log(_("[%s:%u] Invalid nice level '%s'."), filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -374,7 +376,7 @@ static int parse_nice_level(const char *filename, unsigned line, const char *lva
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int parse_rtprio(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
static int parse_rtprio(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t rtprio;
|
||||
|
||||
|
|
@ -402,6 +404,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
|
|||
{ "high-priority", pa_config_parse_bool, NULL },
|
||||
{ "realtime-scheduling", pa_config_parse_bool, NULL },
|
||||
{ "disallow-module-loading", pa_config_parse_bool, NULL },
|
||||
{ "disallow-exit", pa_config_parse_bool, NULL },
|
||||
{ "use-pid-file", pa_config_parse_bool, NULL },
|
||||
{ "system-instance", pa_config_parse_bool, NULL },
|
||||
{ "no-cpu-limit", pa_config_parse_bool, NULL },
|
||||
|
|
@ -465,17 +468,17 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
|
|||
table[2].data = &c->high_priority;
|
||||
table[3].data = &c->realtime_scheduling;
|
||||
table[4].data = &c->disallow_module_loading;
|
||||
table[5].data = &c->use_pid_file;
|
||||
table[6].data = &c->system_instance;
|
||||
table[7].data = &c->no_cpu_limit;
|
||||
table[8].data = &c->disable_shm;
|
||||
table[9].data = &c->exit_idle_time;
|
||||
table[10].data = &c->module_idle_time;
|
||||
table[11].data = &c->scache_idle_time;
|
||||
table[12].data = c;
|
||||
table[13].data = &c->dl_search_path;
|
||||
table[14].data = &c->default_script_file;
|
||||
table[15].data = c;
|
||||
table[5].data = &c->disallow_exit;
|
||||
table[6].data = &c->use_pid_file;
|
||||
table[7].data = &c->system_instance;
|
||||
table[8].data = &c->no_cpu_limit;
|
||||
table[9].data = &c->disable_shm;
|
||||
table[10].data = &c->exit_idle_time;
|
||||
table[11].data = &c->module_idle_time;
|
||||
table[12].data = &c->scache_idle_time;
|
||||
table[13].data = c;
|
||||
table[14].data = &c->dl_search_path;
|
||||
table[15].data = &c->default_script_file;
|
||||
table[16].data = c;
|
||||
table[17].data = c;
|
||||
table[18].data = c;
|
||||
|
|
@ -485,67 +488,68 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
|
|||
table[22].data = c;
|
||||
table[23].data = c;
|
||||
table[24].data = c;
|
||||
table[25].data = &c->disable_remixing;
|
||||
table[26].data = &c->load_default_script_file;
|
||||
table[25].data = c;
|
||||
table[26].data = &c->disable_remixing;
|
||||
table[27].data = &c->load_default_script_file;
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
table[27].data = &c->rlimit_fsize;
|
||||
table[28].data = &c->rlimit_data;
|
||||
table[29].data = &c->rlimit_stack;
|
||||
table[30].data = &c->rlimit_as;
|
||||
table[31].data = &c->rlimit_core;
|
||||
table[32].data = &c->rlimit_nofile;
|
||||
table[33].data = &c->rlimit_as;
|
||||
table[28].data = &c->rlimit_fsize;
|
||||
table[29].data = &c->rlimit_data;
|
||||
table[30].data = &c->rlimit_stack;
|
||||
table[31].data = &c->rlimit_as;
|
||||
table[32].data = &c->rlimit_core;
|
||||
table[33].data = &c->rlimit_nofile;
|
||||
table[34].data = &c->rlimit_as;
|
||||
#ifdef RLIMIT_NPROC
|
||||
table[34].data = &c->rlimit_nproc;
|
||||
table[35].data = &c->rlimit_nproc;
|
||||
#endif
|
||||
|
||||
#ifdef RLIMIT_MEMLOCK
|
||||
#ifndef RLIMIT_NPROC
|
||||
#error "Houston, we have a numbering problem!"
|
||||
#endif
|
||||
table[35].data = &c->rlimit_memlock;
|
||||
table[36].data = &c->rlimit_memlock;
|
||||
#endif
|
||||
|
||||
#ifdef RLIMIT_LOCKS
|
||||
#ifndef RLIMIT_MEMLOCK
|
||||
#error "Houston, we have a numbering problem!"
|
||||
#endif
|
||||
table[36].data = &c->rlimit_locks;
|
||||
table[37].data = &c->rlimit_locks;
|
||||
#endif
|
||||
|
||||
#ifdef RLIMIT_SIGPENDING
|
||||
#ifndef RLIMIT_LOCKS
|
||||
#error "Houston, we have a numbering problem!"
|
||||
#endif
|
||||
table[37].data = &c->rlimit_sigpending;
|
||||
table[38].data = &c->rlimit_sigpending;
|
||||
#endif
|
||||
|
||||
#ifdef RLIMIT_MSGQUEUE
|
||||
#ifndef RLIMIT_SIGPENDING
|
||||
#error "Houston, we have a numbering problem!"
|
||||
#endif
|
||||
table[38].data = &c->rlimit_msgqueue;
|
||||
table[39].data = &c->rlimit_msgqueue;
|
||||
#endif
|
||||
|
||||
#ifdef RLIMIT_NICE
|
||||
#ifndef RLIMIT_MSGQUEUE
|
||||
#error "Houston, we have a numbering problem!"
|
||||
#endif
|
||||
table[39].data = &c->rlimit_nice;
|
||||
table[40].data = &c->rlimit_nice;
|
||||
#endif
|
||||
|
||||
#ifdef RLIMIT_RTPRIO
|
||||
#ifndef RLIMIT_NICE
|
||||
#error "Houston, we have a numbering problem!"
|
||||
#endif
|
||||
table[40].data = &c->rlimit_rtprio;
|
||||
table[41].data = &c->rlimit_rtprio;
|
||||
#endif
|
||||
|
||||
#ifdef RLIMIT_RTTIME
|
||||
#ifndef RLIMIT_RTTIME
|
||||
#error "Houston, we have a numbering problem!"
|
||||
#endif
|
||||
table[41].data = &c->rlimit_rttime;
|
||||
table[42].data = &c->rlimit_rttime;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
@ -557,7 +561,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);
|
||||
|
||||
if (!f && errno != ENOENT) {
|
||||
pa_log_warn("Failed to open configuration file: %s", pa_cstrerror(errno));
|
||||
pa_log_warn(_("Failed to open configuration file: %s"), pa_cstrerror(errno));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -631,7 +635,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
|
|||
s = pa_strbuf_new();
|
||||
|
||||
if (c->config_file)
|
||||
pa_strbuf_printf(s, "### Read from configuration file: %s ###\n", c->config_file);
|
||||
pa_strbuf_printf(s, _("### Read from configuration file: %s ###\n"), c->config_file);
|
||||
|
||||
pa_assert(c->log_level <= PA_LOG_LEVEL_MAX);
|
||||
|
||||
|
|
@ -642,6 +646,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
|
|||
pa_strbuf_printf(s, "realtime-scheduling = %s\n", pa_yes_no(c->realtime_scheduling));
|
||||
pa_strbuf_printf(s, "realtime-priority = %i\n", c->realtime_priority);
|
||||
pa_strbuf_printf(s, "disallow-module-loading = %s\n", pa_yes_no(c->disallow_module_loading));
|
||||
pa_strbuf_printf(s, "disallow-exit = %s\n", pa_yes_no(c->disallow_exit));
|
||||
pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file));
|
||||
pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance));
|
||||
pa_strbuf_printf(s, "no-cpu-limit = %s\n", pa_yes_no(c->no_cpu_limit));
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ typedef struct pa_daemon_conf {
|
|||
no_cpu_limit,
|
||||
disable_shm,
|
||||
disable_remixing,
|
||||
load_default_script_file;
|
||||
load_default_script_file,
|
||||
disallow_exit;
|
||||
int exit_idle_time,
|
||||
module_idle_time,
|
||||
scache_idle_time,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
; daemonize = no
|
||||
; fail = yes
|
||||
; disallow-module-loading = no
|
||||
; disallow-exit = no
|
||||
; use-pid-file = yes
|
||||
; system-instance = no
|
||||
; disable-shm = no
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
### 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-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
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <ltdl.h>
|
||||
|
||||
#include <pulse/util.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/modinfo.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
|
|
@ -39,7 +40,7 @@
|
|||
|
||||
#define PREFIX "module-"
|
||||
|
||||
static void short_info(const char *name, PA_GCC_UNUSED const char *path, pa_modinfo *i) {
|
||||
static void short_info(const char *name, const char *path, pa_modinfo *i) {
|
||||
pa_assert(name);
|
||||
pa_assert(i);
|
||||
|
||||
|
|
@ -56,24 +57,24 @@ static void long_info(const char *name, const char *path, pa_modinfo *i) {
|
|||
|
||||
nl = 1;
|
||||
|
||||
printf("Name: %s\n", name);
|
||||
printf(_("Name: %s\n"), name);
|
||||
|
||||
if (!i->description && !i->version && !i->author && !i->usage)
|
||||
printf("No module information available\n");
|
||||
printf(_("No module information available\n"));
|
||||
else {
|
||||
if (i->version)
|
||||
printf("Version: %s\n", i->version);
|
||||
printf(_("Version: %s\n"), i->version);
|
||||
if (i->description)
|
||||
printf("Description: %s\n", i->description);
|
||||
printf(_("Description: %s\n"), i->description);
|
||||
if (i->author)
|
||||
printf("Author: %s\n", i->author);
|
||||
printf(_("Author: %s\n"), i->author);
|
||||
if (i->usage)
|
||||
printf("Usage: %s\n", i->usage);
|
||||
printf("Load Once: %s\n", pa_yes_no(i->load_once));
|
||||
printf(_("Usage: %s\n"), i->usage);
|
||||
printf(_("Load Once: %s\n"), pa_yes_no(i->load_once));
|
||||
}
|
||||
|
||||
if (path)
|
||||
printf("Path: %s\n", path);
|
||||
printf(_("Path: %s\n"), path);
|
||||
}
|
||||
|
||||
static void show_info(const char *name, const char *path, void (*info)(const char *name, const char *path, pa_modinfo*i)) {
|
||||
|
|
|
|||
|
|
@ -24,21 +24,20 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
#ifdef HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_DL_H
|
||||
#ifdef HAVE_SYS_DL_H
|
||||
#include <sys/dl.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRUCT_LT_USER_DLLOADER
|
||||
/* Only used with ltdl 2.2 */
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include <ltdl.h>
|
||||
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/mutex.h>
|
||||
#include <pulsecore/thread.h>
|
||||
|
|
@ -54,9 +53,9 @@
|
|||
#undef PA_BIND_NOW
|
||||
#endif
|
||||
|
||||
static pa_mutex *libtool_mutex = NULL;
|
||||
#ifdef HAVE_LT_DLMUTEX_REGISTER
|
||||
|
||||
PA_STATIC_TLS_DECLARE_NO_FREE(libtool_tls);
|
||||
static pa_mutex *libtool_mutex = NULL;
|
||||
|
||||
static void libtool_lock(void) {
|
||||
pa_mutex_lock(libtool_mutex);
|
||||
|
|
@ -66,6 +65,10 @@ static void libtool_unlock(void) {
|
|||
pa_mutex_unlock(libtool_mutex);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
PA_STATIC_TLS_DECLARE_NO_FREE(libtool_tls);
|
||||
|
||||
static void libtool_set_error(const char *error) {
|
||||
PA_STATIC_TLS_SET(libtool_tls, (char*) error);
|
||||
}
|
||||
|
|
@ -89,16 +92,19 @@ static const char *libtool_get_error(void) {
|
|||
*/
|
||||
|
||||
#ifndef HAVE_LT_DLADVISE
|
||||
static lt_module bind_now_open(lt_user_data d, const char *fname) {
|
||||
static lt_module bind_now_open(lt_user_data d, const char *fname)
|
||||
#else
|
||||
static lt_module bind_now_open(lt_user_data d, const char *fname, lt_dladvise advise) {
|
||||
static lt_module bind_now_open(lt_user_data d, const char *fname, lt_dladvise advise)
|
||||
#endif
|
||||
{
|
||||
lt_module m;
|
||||
|
||||
pa_assert(fname);
|
||||
|
||||
if (!(m = dlopen(fname, PA_BIND_NOW))) {
|
||||
#ifdef HAVE_LT_DLMUTEX_REGISTER
|
||||
libtool_set_error(dlerror());
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +116,9 @@ static int bind_now_close(lt_user_data d, lt_module m) {
|
|||
pa_assert(m);
|
||||
|
||||
if (dlclose(m) != 0){
|
||||
#ifdef HAVE_LT_DLMUTEX_REGISTER
|
||||
libtool_set_error(dlerror());
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +132,9 @@ static lt_ptr bind_now_find_sym(lt_user_data d, lt_module m, const char *symbol)
|
|||
pa_assert(symbol);
|
||||
|
||||
if (!(ptr = dlsym(m, symbol))) {
|
||||
#ifdef HAVE_LT_DLMUTEX_REGISTER
|
||||
libtool_set_error(dlerror());
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -150,8 +160,9 @@ void pa_ltdl_init(void) {
|
|||
#endif
|
||||
|
||||
pa_assert_se(lt_dlinit() == 0);
|
||||
pa_assert_se(libtool_mutex = pa_mutex_new(TRUE, FALSE));
|
||||
|
||||
#ifdef HAVE_LT_DLMUTEX_REGISTER
|
||||
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);
|
||||
#endif
|
||||
|
||||
|
|
@ -163,14 +174,15 @@ void pa_ltdl_init(void) {
|
|||
|
||||
/* 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.");
|
||||
pa_log_warn(_("Failed to add bind-now-loader."));
|
||||
# else
|
||||
/* Already initialised */
|
||||
if ( dlopen_loader != NULL ) return;
|
||||
if (dlopen_loader)
|
||||
return;
|
||||
|
||||
if (!(dlopen_loader = lt_dlloader_find("dlopen"))) {
|
||||
pa_log_warn("Failed to find original dlopen loader.");
|
||||
return;
|
||||
pa_log_warn(_("Failed to find original dlopen loader."));
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&bindnow_loader, dlopen_loader, sizeof(bindnow_loader));
|
||||
|
|
@ -182,14 +194,16 @@ void pa_ltdl_init(void) {
|
|||
|
||||
/* Add our BIND_NOW loader as the default module loader. */
|
||||
if (lt_dlloader_add(&bindnow_loader) != 0)
|
||||
pa_log_warn("Failed to add bind-now-loader.");
|
||||
pa_log_warn(_("Failed to add bind-now-loader."));
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void pa_ltdl_done(void) {
|
||||
pa_assert_se(lt_dlexit() == 0);
|
||||
|
||||
#ifdef HAVE_LT_DLMUTEX_REGISTER
|
||||
pa_mutex_free(libtool_mutex);
|
||||
libtool_mutex = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@
|
|||
#include <pulse/mainloop-signal.h>
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/i18n.h>
|
||||
#include <pulse/lock-autospawn.h>
|
||||
|
||||
#include <pulsecore/winsock.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
|
|
@ -94,8 +96,6 @@
|
|||
#include "ltdl-bind-now.h"
|
||||
#include "polkit.h"
|
||||
|
||||
#define AUTOSPAWN_LOCK "autospawn.lock"
|
||||
|
||||
#ifdef HAVE_LIBWRAP
|
||||
/* Only one instance of these variables */
|
||||
int allow_severity = LOG_INFO;
|
||||
|
|
@ -111,7 +111,7 @@ int __padsp_disabled__ = 7;
|
|||
|
||||
#ifdef OS_IS_WIN32
|
||||
|
||||
static void message_cb(pa_mainloop_api*a, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) {
|
||||
static void message_cb(pa_mainloop_api*a, pa_time_event*e, const struct timeval *tv, void *userdata) {
|
||||
MSG msg;
|
||||
struct timeval tvnext;
|
||||
|
||||
|
|
@ -130,8 +130,8 @@ 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_sig2str(sig));
|
||||
static void signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) {
|
||||
pa_log_info(_("Got signal %s."), pa_sig2str(sig));
|
||||
|
||||
switch (sig) {
|
||||
#ifdef SIGUSR1
|
||||
|
|
@ -158,7 +158,7 @@ static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e,
|
|||
case SIGINT:
|
||||
case SIGTERM:
|
||||
default:
|
||||
pa_log_info("Exiting.");
|
||||
pa_log_info(_("Exiting."));
|
||||
m->quit(m, 1);
|
||||
break;
|
||||
}
|
||||
|
|
@ -176,41 +176,41 @@ static int change_user(void) {
|
|||
* afterwards. */
|
||||
|
||||
if (!(pw = getpwnam(PA_SYSTEM_USER))) {
|
||||
pa_log("Failed to find user '%s'.", PA_SYSTEM_USER);
|
||||
pa_log(_("Failed to find user '%s'."), PA_SYSTEM_USER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(gr = getgrnam(PA_SYSTEM_GROUP))) {
|
||||
pa_log("Failed to find group '%s'.", PA_SYSTEM_GROUP);
|
||||
pa_log(_("Failed to find group '%s'."), PA_SYSTEM_GROUP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pa_log_info("Found user '%s' (UID %lu) and group '%s' (GID %lu).",
|
||||
pa_log_info(_("Found user '%s' (UID %lu) and group '%s' (GID %lu)."),
|
||||
PA_SYSTEM_USER, (unsigned long) pw->pw_uid,
|
||||
PA_SYSTEM_GROUP, (unsigned long) gr->gr_gid);
|
||||
|
||||
if (pw->pw_gid != gr->gr_gid) {
|
||||
pa_log("GID of user '%s' and of group '%s' don't match.", PA_SYSTEM_USER, PA_SYSTEM_GROUP);
|
||||
pa_log(_("GID of user '%s' and of group '%s' don't match."), PA_SYSTEM_USER, PA_SYSTEM_GROUP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(pw->pw_dir, PA_SYSTEM_RUNTIME_PATH) != 0)
|
||||
pa_log_warn("Warning: home directory of user '%s' is not '%s', ignoring.", PA_SYSTEM_USER, PA_SYSTEM_RUNTIME_PATH);
|
||||
pa_log_warn(_("Home directory of user '%s' is not '%s', ignoring."), PA_SYSTEM_USER, PA_SYSTEM_RUNTIME_PATH);
|
||||
|
||||
if (pa_make_secure_dir(PA_SYSTEM_RUNTIME_PATH, 0755, pw->pw_uid, gr->gr_gid) < 0) {
|
||||
pa_log("Failed to create '%s': %s", PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno));
|
||||
pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pa_make_secure_dir(PA_SYSTEM_STATE_PATH, 0700, pw->pw_uid, gr->gr_gid) < 0) {
|
||||
pa_log("Failed to create '%s': %s", PA_SYSTEM_STATE_PATH, pa_cstrerror(errno));
|
||||
pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_STATE_PATH, pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We don't create the config dir here, because we don't need to write to it */
|
||||
|
||||
if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) {
|
||||
pa_log("Failed to change group list: %s", pa_cstrerror(errno));
|
||||
pa_log(_("Failed to change group list: %s"), pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -226,7 +226,7 @@ static int change_user(void) {
|
|||
#endif
|
||||
|
||||
if (r < 0) {
|
||||
pa_log("Failed to change GID: %s", pa_cstrerror(errno));
|
||||
pa_log(_("Failed to change GID: %s"), pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -242,7 +242,7 @@ static int change_user(void) {
|
|||
#endif
|
||||
|
||||
if (r < 0) {
|
||||
pa_log("Failed to change UID: %s", pa_cstrerror(errno));
|
||||
pa_log(_("Failed to change UID: %s"), pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -256,7 +256,7 @@ static int change_user(void) {
|
|||
pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_CONFIG_PATH);
|
||||
pa_set_env("PULSE_STATE_PATH", PA_SYSTEM_STATE_PATH);
|
||||
|
||||
pa_log_info("Successfully dropped root privileges.");
|
||||
pa_log_info(_("Successfully dropped root privileges."));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -264,7 +264,7 @@ static int change_user(void) {
|
|||
#else /* HAVE_PWD_H && HAVE_GRP_H */
|
||||
|
||||
static int change_user(void) {
|
||||
pa_log("System wide mode unsupported on this platform.");
|
||||
pa_log(_("System wide mode unsupported on this platform."));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -282,7 +282,7 @@ static int set_one_rlimit(const pa_rlimit *r, int resource, const char *name) {
|
|||
rl.rlim_cur = rl.rlim_max = r->value;
|
||||
|
||||
if (setrlimit(resource, &rl) < 0) {
|
||||
pa_log_info("setrlimit(%s, (%u, %u)) failed: %s", name, (unsigned) r->value, (unsigned) r->value, pa_cstrerror(errno));
|
||||
pa_log_info(_("setrlimit(%s, (%u, %u)) failed: %s"), name, (unsigned) r->value, (unsigned) r->value, pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -345,7 +345,8 @@ int main(int argc, char *argv[]) {
|
|||
struct timeval win32_tv;
|
||||
#endif
|
||||
char *lf = NULL;
|
||||
int autospawn_lock_fd = -1;
|
||||
int autospawn_fd = -1;
|
||||
pa_bool_t autospawn_locked = FALSE;
|
||||
|
||||
#if defined(__linux__) && defined(__OPTIMIZE__)
|
||||
/*
|
||||
|
|
@ -407,6 +408,8 @@ int main(int argc, char *argv[]) {
|
|||
* still are normal root. */
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
pa_init_i18n();
|
||||
|
||||
pa_log_set_maximal_level(PA_LOG_INFO);
|
||||
pa_log_set_ident("pulseaudio");
|
||||
|
||||
|
|
@ -419,7 +422,7 @@ int main(int argc, char *argv[]) {
|
|||
goto finish;
|
||||
|
||||
if (pa_cmdline_parse(conf, argc, argv, &d) < 0) {
|
||||
pa_log("Failed to parse command line.");
|
||||
pa_log(_("Failed to parse command line."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -435,14 +438,14 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
if (conf->high_priority && !allow_high_priority) {
|
||||
if (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) > 0) {
|
||||
pa_log_info("We're in the group '"PA_REALTIME_GROUP"', allowing high-priority scheduling.");
|
||||
pa_log_info(_("We're in the group '%s', allowing high-priority scheduling."), PA_REALTIME_GROUP);
|
||||
allow_high_priority = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (conf->realtime_scheduling && !allow_realtime) {
|
||||
if (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) > 0) {
|
||||
pa_log_info("We're in the group '"PA_REALTIME_GROUP"', allowing real-time scheduling.");
|
||||
pa_log_info(_("We're in the group '%s', allowing real-time scheduling."), PA_REALTIME_GROUP);
|
||||
allow_realtime = TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -450,18 +453,18 @@ int main(int argc, char *argv[]) {
|
|||
#ifdef HAVE_POLKIT
|
||||
if (conf->high_priority && !allow_high_priority) {
|
||||
if (pa_polkit_check("org.pulseaudio.acquire-high-priority") > 0) {
|
||||
pa_log_info("PolicyKit grants us acquire-high-priority privilege.");
|
||||
pa_log_info(_("PolicyKit grants us acquire-high-priority privilege."));
|
||||
allow_high_priority = TRUE;
|
||||
} else
|
||||
pa_log_info("PolicyKit refuses acquire-high-priority privilege.");
|
||||
pa_log_info(_("PolicyKit refuses acquire-high-priority privilege."));
|
||||
}
|
||||
|
||||
if (conf->realtime_scheduling && !allow_realtime) {
|
||||
if (pa_polkit_check("org.pulseaudio.acquire-real-time") > 0) {
|
||||
pa_log_info("PolicyKit grants us acquire-real-time privilege.");
|
||||
pa_log_info(_("PolicyKit grants us acquire-real-time privilege."));
|
||||
allow_realtime = TRUE;
|
||||
} else
|
||||
pa_log_info("PolicyKit refuses acquire-real-time privilege.");
|
||||
pa_log_info(_("PolicyKit refuses acquire-real-time privilege."));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -473,9 +476,9 @@ int main(int argc, char *argv[]) {
|
|||
pa_drop_caps();
|
||||
|
||||
if (conf->high_priority || conf->realtime_scheduling)
|
||||
pa_log_notice("Called SUID root and real-time/high-priority scheduling was requested in the configuration. However, we lack the necessary priviliges:\n"
|
||||
"We are not in group '"PA_REALTIME_GROUP"' and PolicyKit refuse to grant us priviliges. Dropping SUID again.\n"
|
||||
"For enabling real-time scheduling please acquire the appropriate PolicyKit priviliges, or become a member of '"PA_REALTIME_GROUP"', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user.");
|
||||
pa_log_notice(_("Called SUID root and real-time/high-priority scheduling was requested in the configuration. However, we lack the necessary priviliges:\n"
|
||||
"We are not in group '"PA_REALTIME_GROUP"' and PolicyKit refuse to grant us priviliges. Dropping SUID again.\n"
|
||||
"For enabling real-time scheduling please acquire the appropriate PolicyKit priviliges, or become a member of '"PA_REALTIME_GROUP"', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user."));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -491,7 +494,7 @@ int main(int argc, char *argv[]) {
|
|||
#endif
|
||||
|
||||
if (conf->high_priority && !pa_can_high_priority())
|
||||
pa_log_warn("High-priority scheduling enabled in configuration but not allowed by policy.");
|
||||
pa_log_warn(_("High-priority scheduling enabled in configuration but not allowed by policy."));
|
||||
|
||||
if (conf->high_priority && (conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START))
|
||||
pa_raise_priority(conf->nice_level);
|
||||
|
|
@ -516,24 +519,24 @@ int main(int argc, char *argv[]) {
|
|||
rl.rlim_max = rl.rlim_cur = 9;
|
||||
|
||||
if (setrlimit(RLIMIT_RTPRIO, &rl) >= 0) {
|
||||
pa_log_info("Successfully increased RLIMIT_RTPRIO");
|
||||
pa_log_info(_("Successfully increased RLIMIT_RTPRIO"));
|
||||
drop = TRUE;
|
||||
} else
|
||||
pa_log_warn("RLIMIT_RTPRIO failed: %s", pa_cstrerror(errno));
|
||||
pa_log_warn(_("RLIMIT_RTPRIO failed: %s"), pa_cstrerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (drop) {
|
||||
pa_log_info("Giving up CAP_NICE");
|
||||
pa_log_info(_("Giving up CAP_NICE"));
|
||||
pa_drop_caps();
|
||||
suid_root = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (conf->realtime_scheduling && !pa_can_realtime())
|
||||
pa_log_warn("Real-time scheduling enabled in configuration but not allowed by policy.");
|
||||
pa_log_warn(_("Real-time scheduling enabled in configuration but not allowed by policy."));
|
||||
|
||||
pa_log_debug("Can realtime: %s, can high-priority: %s", pa_yes_no(pa_can_realtime()), pa_yes_no(pa_can_high_priority()));
|
||||
|
||||
|
|
@ -591,9 +594,9 @@ int main(int argc, char *argv[]) {
|
|||
pid_t pid;
|
||||
|
||||
if (pa_pid_file_check_running(&pid, "pulseaudio") < 0)
|
||||
pa_log_info("Daemon not running");
|
||||
pa_log_info(_("Daemon not running"));
|
||||
else {
|
||||
pa_log_info("Daemon running as PID %u", pid);
|
||||
pa_log_info(_("Daemon running as PID %u"), pid);
|
||||
retval = 0;
|
||||
}
|
||||
|
||||
|
|
@ -603,7 +606,7 @@ int main(int argc, char *argv[]) {
|
|||
case PA_CMD_KILL:
|
||||
|
||||
if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0)
|
||||
pa_log("Failed to kill daemon.");
|
||||
pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno));
|
||||
else
|
||||
retval = 0;
|
||||
|
||||
|
|
@ -621,24 +624,49 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
if (real_root && !conf->system_instance)
|
||||
pa_log_warn("This program is not intended to be run as root (unless --system is specified).");
|
||||
pa_log_warn(_("This program is not intended to be run as root (unless --system is specified)."));
|
||||
else if (!real_root && conf->system_instance) {
|
||||
pa_log("Root priviliges required.");
|
||||
pa_log(_("Root priviliges required."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (conf->cmd == PA_CMD_START && conf->system_instance) {
|
||||
pa_log("--start not supported for system instances.");
|
||||
pa_log(_("--start not supported for system instances."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (conf->system_instance && !conf->disallow_exit)
|
||||
pa_log_warn(_("Running in system mode, but --disallow-exit not set!"));
|
||||
|
||||
if (conf->system_instance && !conf->disallow_module_loading)
|
||||
pa_log_warn(_("Running in system mode, but --disallow-module-loading not set!"));
|
||||
|
||||
if (conf->system_instance && !conf->disable_shm) {
|
||||
pa_log_notice(_("Running in system mode, forcibly disabling SHM mode!"));
|
||||
conf->disable_shm = TRUE;
|
||||
}
|
||||
|
||||
if (conf->system_instance && conf->exit_idle_time > 0) {
|
||||
pa_log_notice(_("Running in system mode, forcibly disabling exit idle time!"));
|
||||
conf->exit_idle_time = 0;
|
||||
}
|
||||
|
||||
if (conf->cmd == PA_CMD_START) {
|
||||
/* If we shall start PA only when it is not running yet, we
|
||||
* first take the autospawn lock to make things
|
||||
* synchronous. */
|
||||
|
||||
lf = pa_runtime_path(AUTOSPAWN_LOCK);
|
||||
autospawn_lock_fd = pa_lock_lockfile(lf);
|
||||
if ((autospawn_fd = pa_autospawn_lock_init()) < 0) {
|
||||
pa_log("Failed to initialize autospawn lock");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((pa_autospawn_lock_acquire(TRUE) < 0)) {
|
||||
pa_log("Failed to acquire autospawn lock");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
autospawn_locked = TRUE;
|
||||
}
|
||||
|
||||
if (conf->daemonize) {
|
||||
|
|
@ -646,18 +674,18 @@ int main(int argc, char *argv[]) {
|
|||
int tty_fd;
|
||||
|
||||
if (pa_stdio_acquire() < 0) {
|
||||
pa_log("Failed to acquire stdio.");
|
||||
pa_log(_("Failed to acquire stdio."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FORK
|
||||
if (pipe(daemon_pipe) < 0) {
|
||||
pa_log("pipe failed: %s", pa_cstrerror(errno));
|
||||
pa_log(_("pipe failed: %s"), pa_cstrerror(errno));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((child = fork()) < 0) {
|
||||
pa_log("fork() failed: %s", pa_cstrerror(errno));
|
||||
pa_log(_("fork() failed: %s"), pa_cstrerror(errno));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -671,25 +699,28 @@ int main(int argc, char *argv[]) {
|
|||
if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) {
|
||||
|
||||
if (n < 0)
|
||||
pa_log("read() failed: %s", pa_cstrerror(errno));
|
||||
pa_log(_("read() failed: %s"), pa_cstrerror(errno));
|
||||
|
||||
retval = 1;
|
||||
}
|
||||
|
||||
if (retval)
|
||||
pa_log("Daemon startup failed.");
|
||||
pa_log(_("Daemon startup failed."));
|
||||
else
|
||||
pa_log_info("Daemon startup successful.");
|
||||
pa_log_info(_("Daemon startup successful."));
|
||||
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (autospawn_lock_fd >= 0) {
|
||||
if (autospawn_fd >= 0) {
|
||||
/* The lock file is unlocked from the parent, so we need
|
||||
* to close it in the child */
|
||||
|
||||
pa_close(autospawn_lock_fd);
|
||||
autospawn_lock_fd = -1;
|
||||
pa_autospawn_lock_release();
|
||||
pa_autospawn_lock_done(TRUE);
|
||||
|
||||
autospawn_locked = FALSE;
|
||||
autospawn_fd = -1;
|
||||
}
|
||||
|
||||
pa_assert_se(pa_close(daemon_pipe[0]) == 0);
|
||||
|
|
@ -746,17 +777,27 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
pa_set_env("PULSE_SYSTEM", conf->system_instance ? "1" : "0");
|
||||
|
||||
pa_log_info("This is PulseAudio " PACKAGE_VERSION);
|
||||
pa_log_info("Page size is %lu bytes", (unsigned long) PA_PAGE_SIZE);
|
||||
if (!(s = pa_get_runtime_dir()))
|
||||
pa_log_info(_("This is PulseAudio %s"), PACKAGE_VERSION);
|
||||
pa_log_info(_("Page size is %lu bytes"), (unsigned long) PA_PAGE_SIZE);
|
||||
|
||||
if (!(s = pa_machine_id())) {
|
||||
pa_log(_("Failed to get machine ID"));
|
||||
goto finish;
|
||||
pa_log_info("Using runtime directory %s.", s);
|
||||
pa_xfree(s);
|
||||
if (!(s = pa_get_state_dir()))
|
||||
pa_log_info("Using state directory %s.", s);
|
||||
}
|
||||
pa_log_info(_("Machine ID is %s."), s);
|
||||
pa_xfree(s);
|
||||
|
||||
pa_log_info("Running in system mode: %s", pa_yes_no(pa_in_system_mode()));
|
||||
if (!(s = pa_get_runtime_dir()))
|
||||
goto finish;
|
||||
pa_log_info(_("Using runtime directory %s."), s);
|
||||
pa_xfree(s);
|
||||
|
||||
if (!(s = pa_get_state_dir()))
|
||||
goto finish;
|
||||
pa_log_info(_("Using state directory %s."), s);
|
||||
pa_xfree(s);
|
||||
|
||||
pa_log_info(_("Running in system mode: %s"), pa_yes_no(pa_in_system_mode()));
|
||||
|
||||
if (conf->use_pid_file) {
|
||||
int z;
|
||||
|
|
@ -771,7 +812,7 @@ int main(int argc, char *argv[]) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
pa_log("pa_pid_file_create() failed.");
|
||||
pa_log(_("pa_pid_file_create() failed."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -783,9 +824,9 @@ int main(int argc, char *argv[]) {
|
|||
#endif
|
||||
|
||||
if (pa_rtclock_hrtimer())
|
||||
pa_log_info("Fresh high-resolution timers available! Bon appetit!");
|
||||
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!");
|
||||
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 */
|
||||
|
|
@ -795,7 +836,7 @@ int main(int argc, char *argv[]) {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -810,6 +851,7 @@ int main(int argc, char *argv[]) {
|
|||
c->realtime_scheduling = !!conf->realtime_scheduling;
|
||||
c->disable_remixing = !!conf->disable_remixing;
|
||||
c->running_as_daemon = !!conf->daemonize;
|
||||
c->disallow_exit = conf->disallow_exit;
|
||||
|
||||
pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0);
|
||||
pa_signal_new(SIGINT, signal_callback, c);
|
||||
|
|
@ -854,17 +896,17 @@ int main(int argc, char *argv[]) {
|
|||
c->disallow_module_loading = !!conf->disallow_module_loading;
|
||||
|
||||
if (r < 0 && conf->fail) {
|
||||
pa_log("Failed to initialize daemon.");
|
||||
pa_log(_("Failed to initialize daemon."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!c->modules || pa_idxset_size(c->modules) == 0) {
|
||||
pa_log("Daemon startup without any loaded modules, refusing to work.");
|
||||
pa_log(_("Daemon startup without any loaded modules, refusing to work."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (c->default_sink_name && !pa_namereg_get(c, c->default_sink_name, PA_NAMEREG_SINK, TRUE) && conf->fail) {
|
||||
pa_log_error("Default sink name (%s) does not exist in name register.", c->default_sink_name);
|
||||
pa_log_error(_("Default sink name (%s) does not exist in name register."), c->default_sink_name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -877,18 +919,22 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
#endif
|
||||
|
||||
pa_log_info("Daemon startup complete.");
|
||||
pa_log_info(_("Daemon startup complete."));
|
||||
|
||||
retval = 0;
|
||||
if (pa_mainloop_run(mainloop, &retval) < 0)
|
||||
goto finish;
|
||||
|
||||
pa_log_info("Daemon shutdown initiated.");
|
||||
pa_log_info(_("Daemon shutdown initiated."));
|
||||
|
||||
finish:
|
||||
|
||||
if (autospawn_lock_fd >= 0)
|
||||
pa_unlock_lockfile(lf, autospawn_lock_fd);
|
||||
if (autospawn_fd >= 0) {
|
||||
if (autospawn_locked)
|
||||
pa_autospawn_lock_release();
|
||||
|
||||
pa_autospawn_lock_done(FALSE);
|
||||
}
|
||||
|
||||
if (lf)
|
||||
pa_xfree(lf);
|
||||
|
|
@ -900,7 +946,7 @@ finish:
|
|||
|
||||
if (c) {
|
||||
pa_core_unref(c);
|
||||
pa_log_info("Daemon terminated.");
|
||||
pa_log_info(_("Daemon terminated."));
|
||||
}
|
||||
|
||||
if (!conf->no_cpu_limit)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
#include <dbus/dbus.h>
|
||||
#include <polkit-dbus/polkit-dbus.h>
|
||||
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
|
|
@ -50,7 +52,7 @@ int pa_polkit_check(const char *action_id) {
|
|||
dbus_error_init(&dbus_error);
|
||||
|
||||
if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error))) {
|
||||
pa_log_error("Cannot connect to system bus: %s", dbus_error.message);
|
||||
pa_log_error(_("Cannot connect to system bus: %s"), dbus_error.message);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +62,7 @@ int pa_polkit_check(const char *action_id) {
|
|||
dbus_connection_set_exit_on_disconnect(bus, FALSE);
|
||||
|
||||
if (!(caller = polkit_caller_new_from_pid(bus, getpid(), &dbus_error))) {
|
||||
pa_log_error("Cannot get caller from PID: %s", dbus_error.message);
|
||||
pa_log_error(_("Cannot get caller from PID: %s"), dbus_error.message);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -72,12 +74,12 @@ int pa_polkit_check(const char *action_id) {
|
|||
* -- an not the EUID or any other user id. */
|
||||
|
||||
if (!(polkit_caller_set_uid(caller, getuid()))) {
|
||||
pa_log_error("Cannot set UID on caller object.");
|
||||
pa_log_error(_("Cannot set UID on caller object."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!(polkit_caller_get_ck_session(caller, &session))) {
|
||||
pa_log_error("Failed to get CK session.");
|
||||
pa_log_error(_("Failed to get CK session."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -85,27 +87,27 @@ int pa_polkit_check(const char *action_id) {
|
|||
* object */
|
||||
|
||||
if (!(polkit_session_set_uid(session, getuid()))) {
|
||||
pa_log_error("Cannot set UID on session object.");
|
||||
pa_log_error(_("Cannot set UID on session object."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!(action = polkit_action_new())) {
|
||||
pa_log_error("Cannot allocate PolKitAction.");
|
||||
pa_log_error(_("Cannot allocate PolKitAction."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!polkit_action_set_action_id(action, action_id)) {
|
||||
pa_log_error("Cannot set action_id");
|
||||
pa_log_error(_("Cannot set action_id"));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!(context = polkit_context_new())) {
|
||||
pa_log_error("Cannot allocate PolKitContext.");
|
||||
pa_log_error(_("Cannot allocate PolKitContext."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!polkit_context_init(context, &polkit_error)) {
|
||||
pa_log_error("Cannot initialize PolKitContext: %s", polkit_error_get_error_message(polkit_error));
|
||||
pa_log_error(_("Cannot initialize PolKitContext: %s"), polkit_error_get_error_message(polkit_error));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +116,7 @@ int pa_polkit_check(const char *action_id) {
|
|||
polkit_result = polkit_context_is_caller_authorized(context, action, caller, TRUE, &polkit_error);
|
||||
|
||||
if (polkit_error_is_set(polkit_error)) {
|
||||
pa_log_error("Could not determine whether caller is authorized: %s", polkit_error_get_error_message(polkit_error));
|
||||
pa_log_error(_("Could not determine whether caller is authorized: %s"), polkit_error_get_error_message(polkit_error));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +136,7 @@ int pa_polkit_check(const char *action_id) {
|
|||
}
|
||||
|
||||
if (dbus_error_is_set(&dbus_error)) {
|
||||
pa_log_error("Cannot obtain auth: %s", dbus_error.message);
|
||||
pa_log_error(_("Cannot obtain auth: %s"), dbus_error.message);
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
|
@ -143,7 +145,7 @@ int pa_polkit_check(const char *action_id) {
|
|||
}
|
||||
|
||||
if (polkit_result != POLKIT_RESULT_YES && polkit_result != POLKIT_RESULT_NO)
|
||||
pa_log_warn("PolicyKit responded with '%s'", polkit_result_to_string_representation(polkit_result));
|
||||
pa_log_warn(_("PolicyKit responded with '%s'"), polkit_result_to_string_representation(polkit_result));
|
||||
|
||||
ret = polkit_result == POLKIT_RESULT_YES;
|
||||
|
||||
|
|
|
|||
19
src/map-file
19
src/map-file
|
|
@ -98,9 +98,16 @@ pa_context_unref;
|
|||
pa_cvolume_avg;
|
||||
pa_cvolume_channels_equal_to;
|
||||
pa_cvolume_equal;
|
||||
pa_cvolume_remap;
|
||||
pa_cvolume_set;
|
||||
pa_cvolume_snprint;
|
||||
pa_cvolume_valid;
|
||||
pa_ext_stream_restore_delete;
|
||||
pa_ext_stream_restore_read;
|
||||
pa_ext_stream_restore_set_subscribe_cb;
|
||||
pa_ext_stream_restore_subscribe;
|
||||
pa_ext_stream_restore_test;
|
||||
pa_ext_stream_restore_write;
|
||||
pa_frame_size;
|
||||
pa_get_binary_name;
|
||||
pa_get_fqdn;
|
||||
|
|
@ -133,21 +140,21 @@ pa_operation_ref;
|
|||
pa_operation_unref;
|
||||
pa_parse_sample_format;
|
||||
pa_path_get_filename;
|
||||
pa_proplist_free;
|
||||
pa_proplist_contains;
|
||||
pa_proplist_clear;
|
||||
pa_proplist_contains;
|
||||
pa_proplist_copy;
|
||||
pa_proplist_free;
|
||||
pa_proplist_get;
|
||||
pa_proplist_gets;
|
||||
pa_proplist_iterate;
|
||||
pa_proplist_update;
|
||||
pa_proplist_new;
|
||||
pa_proplist_set;
|
||||
pa_proplist_sets;
|
||||
pa_proplist_setf;
|
||||
pa_proplist_sets;
|
||||
pa_proplist_to_string;
|
||||
pa_proplist_unset;
|
||||
pa_proplist_unset_many;
|
||||
pa_proplist_to_string;
|
||||
pa_proplist_update;
|
||||
pa_sample_format_to_string;
|
||||
pa_sample_size;
|
||||
pa_sample_spec_equal;
|
||||
|
|
@ -198,8 +205,8 @@ pa_stream_readable_size;
|
|||
pa_stream_ref;
|
||||
pa_stream_set_buffer_attr;
|
||||
pa_stream_set_latency_update_callback;
|
||||
pa_stream_set_moved_callback;
|
||||
pa_stream_set_monitor_stream;
|
||||
pa_stream_set_moved_callback;
|
||||
pa_stream_set_name;
|
||||
pa_stream_set_overflow_callback;
|
||||
pa_stream_set_read_callback;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
#include "alsa-util.h"
|
||||
|
||||
struct pa_alsa_fdlist {
|
||||
int num_fds;
|
||||
unsigned num_fds;
|
||||
struct pollfd *fds;
|
||||
/* This is a temporary buffer used to avoid lots of mallocs */
|
||||
struct pollfd *work_fds;
|
||||
|
|
@ -50,16 +50,17 @@ struct pa_alsa_fdlist {
|
|||
pa_defer_event *defer;
|
||||
pa_io_event **ios;
|
||||
|
||||
int polled;
|
||||
pa_bool_t polled;
|
||||
|
||||
void (*cb)(void *userdata);
|
||||
void *userdata;
|
||||
};
|
||||
|
||||
static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void *userdata) {
|
||||
static void io_cb(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
|
||||
|
||||
struct pa_alsa_fdlist *fdl = userdata;
|
||||
int err, i;
|
||||
int err;
|
||||
unsigned i;
|
||||
unsigned short revents;
|
||||
|
||||
pa_assert(a);
|
||||
|
|
@ -71,11 +72,11 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io
|
|||
if (fdl->polled)
|
||||
return;
|
||||
|
||||
fdl->polled = 1;
|
||||
fdl->polled = TRUE;
|
||||
|
||||
memcpy(fdl->work_fds, fdl->fds, sizeof(struct pollfd) * fdl->num_fds);
|
||||
|
||||
for (i = 0;i < fdl->num_fds; i++) {
|
||||
for (i = 0; i < fdl->num_fds; i++) {
|
||||
if (e == fdl->ios[i]) {
|
||||
if (events & PA_IO_EVENT_INPUT)
|
||||
fdl->work_fds[i].revents |= POLLIN;
|
||||
|
|
@ -102,9 +103,10 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io
|
|||
snd_mixer_handle_events(fdl->mixer);
|
||||
}
|
||||
|
||||
static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *userdata) {
|
||||
static void defer_cb(pa_mainloop_api*a, pa_defer_event* e, void *userdata) {
|
||||
struct pa_alsa_fdlist *fdl = userdata;
|
||||
int num_fds, i, err;
|
||||
unsigned num_fds, i;
|
||||
int err;
|
||||
struct pollfd *temp;
|
||||
|
||||
pa_assert(a);
|
||||
|
|
@ -113,8 +115,7 @@ static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *u
|
|||
|
||||
a->defer_enable(fdl->defer, 0);
|
||||
|
||||
num_fds = snd_mixer_poll_descriptors_count(fdl->mixer);
|
||||
pa_assert(num_fds > 0);
|
||||
num_fds = (unsigned) snd_mixer_poll_descriptors_count(fdl->mixer);
|
||||
|
||||
if (num_fds != fdl->num_fds) {
|
||||
if (fdl->fds)
|
||||
|
|
@ -132,7 +133,7 @@ static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *u
|
|||
return;
|
||||
}
|
||||
|
||||
fdl->polled = 0;
|
||||
fdl->polled = FALSE;
|
||||
|
||||
if (memcmp(fdl->fds, fdl->work_fds, sizeof(struct pollfd) * num_fds) == 0)
|
||||
return;
|
||||
|
|
@ -176,7 +177,7 @@ struct pa_alsa_fdlist *pa_alsa_fdlist_new(void) {
|
|||
fdl->m = NULL;
|
||||
fdl->defer = NULL;
|
||||
fdl->ios = NULL;
|
||||
fdl->polled = 0;
|
||||
fdl->polled = FALSE;
|
||||
|
||||
return fdl;
|
||||
}
|
||||
|
|
@ -190,9 +191,9 @@ void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl) {
|
|||
}
|
||||
|
||||
if (fdl->ios) {
|
||||
int i;
|
||||
unsigned i;
|
||||
pa_assert(fdl->m);
|
||||
for (i = 0;i < fdl->num_fds;i++)
|
||||
for (i = 0; i < fdl->num_fds; i++)
|
||||
fdl->m->io_free(fdl->ios[i]);
|
||||
pa_xfree(fdl->ios);
|
||||
}
|
||||
|
|
@ -403,7 +404,7 @@ int pa_alsa_set_hw_params(
|
|||
/* If the sample rate deviates too much, we need to resample */
|
||||
if (r < ss->rate*.95 || r > ss->rate*1.05)
|
||||
ss->rate = r;
|
||||
ss->channels = c;
|
||||
ss->channels = (uint8_t) c;
|
||||
ss->format = f;
|
||||
|
||||
pa_assert(_periods > 0);
|
||||
|
|
@ -808,7 +809,7 @@ int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel
|
|||
if (channel_map->channels > 1 &&
|
||||
((playback && snd_mixer_selem_has_playback_volume_joined(elem)) ||
|
||||
(!playback && snd_mixer_selem_has_capture_volume_joined(elem)))) {
|
||||
pa_log_info("ALSA device lacks independant volume controls for each channel, falling back to software volume control.");
|
||||
pa_log_info("ALSA device lacks independant volume controls for each channel.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -820,7 +821,7 @@ int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel
|
|||
id = alsa_channel_ids[channel_map->map[i]];
|
||||
|
||||
if (!is_mono && id == SND_MIXER_SCHN_UNKNOWN) {
|
||||
pa_log_info("Configured channel map contains channel '%s' that is unknown to the ALSA mixer. Falling back to software volume control.", pa_channel_position_to_string(channel_map->map[i]));
|
||||
pa_log_info("Configured channel map contains channel '%s' that is unknown to the ALSA mixer.", pa_channel_position_to_string(channel_map->map[i]));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -832,7 +833,7 @@ int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel
|
|||
if ((playback && (!snd_mixer_selem_has_playback_channel(elem, id) || (is_mono && !snd_mixer_selem_is_playback_mono(elem)))) ||
|
||||
(!playback && (!snd_mixer_selem_has_capture_channel(elem, id) || (is_mono && !snd_mixer_selem_is_capture_mono(elem))))) {
|
||||
|
||||
pa_log_info("ALSA device lacks separate volumes control for channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map->map[i]));
|
||||
pa_log_info("ALSA device lacks separate volumes control for channel '%s'", pa_channel_position_to_string(channel_map->map[i]));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -850,56 +851,6 @@ int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel
|
|||
return 0;
|
||||
}
|
||||
|
||||
void pa_alsa_0dB_playback(snd_mixer_elem_t *elem) {
|
||||
long min, max, v;
|
||||
|
||||
pa_assert(elem);
|
||||
|
||||
/* Try to enable 0 dB if possible. If ALSA cannot do dB, then use
|
||||
* raw volume levels and fix them to 75% */
|
||||
|
||||
if (snd_mixer_selem_set_playback_dB_all(elem, 0, -1) >= 0)
|
||||
return;
|
||||
|
||||
if (snd_mixer_selem_set_playback_dB_all(elem, 0, 1) >= 0)
|
||||
return;
|
||||
|
||||
if (snd_mixer_selem_get_playback_volume_range(elem, &min, &max) < 0)
|
||||
return;
|
||||
|
||||
v = min + ((max - min) * 3) / 4; /* 75% */
|
||||
|
||||
if (v <= min)
|
||||
v = max;
|
||||
|
||||
snd_mixer_selem_set_playback_volume_all(elem, v);
|
||||
}
|
||||
|
||||
void pa_alsa_0dB_capture(snd_mixer_elem_t *elem) {
|
||||
long min, max, v;
|
||||
|
||||
pa_assert(elem);
|
||||
|
||||
/* Try to enable 0 dB if possible. If ALSA cannot do dB, then use
|
||||
* raw volume levels and fix them to 75% */
|
||||
|
||||
if (snd_mixer_selem_set_capture_dB_all(elem, 0, -1) >= 0)
|
||||
return;
|
||||
|
||||
if (snd_mixer_selem_set_capture_dB_all(elem, 0, 1) >= 0)
|
||||
return;
|
||||
|
||||
if (snd_mixer_selem_get_capture_volume_range(elem, &min, &max) < 0)
|
||||
return;
|
||||
|
||||
v = min + ((max - min) * 3) / 4; /* 75% */
|
||||
|
||||
if (v <= min)
|
||||
v = max;
|
||||
|
||||
snd_mixer_selem_set_capture_volume_all(elem, v);
|
||||
}
|
||||
|
||||
void pa_alsa_dump(snd_pcm_t *pcm) {
|
||||
int err;
|
||||
snd_output_t *out;
|
||||
|
|
@ -1106,10 +1057,10 @@ pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, n);
|
||||
item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
|
||||
pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
|
||||
|
||||
if ((err = snd_pcm_poll_descriptors(pcm, pollfd, n)) < 0) {
|
||||
if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
|
||||
pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err));
|
||||
pa_rtpoll_item_free(item);
|
||||
return NULL;
|
||||
|
|
@ -1117,3 +1068,27 @@ pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
|
|||
|
||||
return item;
|
||||
}
|
||||
|
||||
pa_cvolume *pa_alsa_volume_divide(pa_cvolume *r, const pa_cvolume *t) {
|
||||
unsigned i;
|
||||
|
||||
pa_assert(r);
|
||||
pa_assert(t);
|
||||
pa_assert(r->channels == t->channels);
|
||||
|
||||
for (i = 0; i < r->channels; i++) {
|
||||
double a, b, c;
|
||||
|
||||
a = pa_sw_volume_to_linear(r->values[i]); /* the hw volume */
|
||||
b = pa_sw_volume_to_linear(t->values[i]); /* the intended volume */
|
||||
|
||||
if (a <= 0)
|
||||
c = 0;
|
||||
else
|
||||
c = b / a;
|
||||
|
||||
r->values[i] = pa_sw_volume_from_linear(c);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <asoundlib.h>
|
||||
|
||||
#include <pulse/sample.h>
|
||||
#include <pulse/volume.h>
|
||||
#include <pulse/mainloop-api.h>
|
||||
#include <pulse/channelmap.h>
|
||||
#include <pulse/proplist.h>
|
||||
|
|
@ -79,9 +80,6 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
|||
|
||||
int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel_map, snd_mixer_selem_channel_id_t mixer_map[], pa_bool_t playback);
|
||||
|
||||
void pa_alsa_0dB_playback(snd_mixer_elem_t *elem);
|
||||
void pa_alsa_0dB_capture(snd_mixer_elem_t *elem);
|
||||
|
||||
void pa_alsa_dump(snd_pcm_t *pcm);
|
||||
void pa_alsa_dump_status(snd_pcm_t *pcm);
|
||||
|
||||
|
|
@ -94,4 +92,6 @@ int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents);
|
|||
|
||||
pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll);
|
||||
|
||||
pa_cvolume *pa_alsa_volume_divide(pa_cvolume *r, const pa_cvolume *t);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ static pa_io_event_flags_t get_watch_flags(DBusWatch *watch) {
|
|||
}
|
||||
|
||||
/* pa_io_event_cb_t IO event handler */
|
||||
static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
|
||||
static void handle_io_event(pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
|
||||
unsigned int flags = 0;
|
||||
DBusWatch *watch = userdata;
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, const struc
|
|||
dbus_timeout_handle(timeout);
|
||||
|
||||
/* restart it for the next scheduled time */
|
||||
pa_timeval_add(&next, dbus_timeout_get_interval(timeout) * 1000);
|
||||
pa_timeval_add(&next, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000);
|
||||
ea->time_restart(e, &next);
|
||||
}
|
||||
}
|
||||
|
|
@ -192,7 +192,7 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) {
|
|||
return FALSE;
|
||||
|
||||
pa_gettimeofday(&tv);
|
||||
pa_timeval_add(&tv, dbus_timeout_get_interval(timeout) * 1000);
|
||||
pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000);
|
||||
|
||||
ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event, timeout);
|
||||
|
||||
|
|
@ -227,7 +227,7 @@ static void toggle_timeout(DBusTimeout *timeout, void *data) {
|
|||
struct timeval tv;
|
||||
|
||||
pa_gettimeofday(&tv);
|
||||
pa_timeval_add(&tv, dbus_timeout_get_interval(timeout) * 1000);
|
||||
pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000);
|
||||
|
||||
c->mainloop->time_restart(ev, &tv);
|
||||
} else
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ static int fill_buf(struct userdata *u) {
|
|||
if ((r = pa_read(u->fd, u->buf + u->buf_fill, BUF_MAX - u->buf_fill, &u->fd_type)) <= 0)
|
||||
return -1;
|
||||
|
||||
u->buf_fill += r;
|
||||
u->buf_fill += (size_t) r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ static char *read_string(struct userdata *u) {
|
|||
|
||||
if ((e = memchr(u->buf, 0, u->buf_fill))) {
|
||||
char *ret = pa_xstrdup(u->buf);
|
||||
u->buf_fill -= e - u->buf +1;
|
||||
u->buf_fill -= (size_t) (e - u->buf +1);
|
||||
memmove(u->buf, e+1, u->buf_fill);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -142,7 +142,7 @@ static void unload_one_module(struct userdata *u, struct module_info*m, unsigned
|
|||
return;
|
||||
|
||||
pa_log_debug("Unloading module #%i", m->items[i].index);
|
||||
pa_module_unload_by_index(u->core, m->items[i].index);
|
||||
pa_module_unload_by_index(u->core, m->items[i].index, TRUE);
|
||||
m->items[i].index = PA_INVALID_INDEX;
|
||||
pa_xfree(m->items[i].name);
|
||||
pa_xfree(m->items[i].args);
|
||||
|
|
@ -164,10 +164,10 @@ static void unload_all_modules(struct userdata *u, struct module_info*m) {
|
|||
static void load_module(
|
||||
struct userdata *u,
|
||||
struct module_info *m,
|
||||
int i,
|
||||
unsigned i,
|
||||
const char *name,
|
||||
const char *args,
|
||||
int is_new) {
|
||||
pa_bool_t is_new) {
|
||||
|
||||
pa_module *mod;
|
||||
|
||||
|
|
@ -324,7 +324,7 @@ static void io_event_cb(
|
|||
u->io_event = NULL;
|
||||
}
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@
|
|||
|
||||
#include <asoundlib.h>
|
||||
|
||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
#include <valgrind/memcheck.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/util.h>
|
||||
#include <pulse/timeval.h>
|
||||
|
|
@ -68,8 +72,7 @@ PA_MODULE_USAGE(
|
|||
"mmap=<enable memory mapping?> "
|
||||
"tsched=<enable system timer based scheduling mode?> "
|
||||
"tsched_buffer_size=<buffer size when using timer based scheduling> "
|
||||
"tsched_buffer_watermark=<lower fill watermark> "
|
||||
"mixer_reset=<reset hw volume and mute settings to sane defaults when falling back to software?>");
|
||||
"tsched_buffer_watermark=<lower fill watermark>");
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"sink_name",
|
||||
|
|
@ -85,7 +88,6 @@ static const char* const valid_modargs[] = {
|
|||
"tsched",
|
||||
"tsched_buffer_size",
|
||||
"tsched_buffer_watermark",
|
||||
"mixer_reset",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -112,6 +114,8 @@ struct userdata {
|
|||
long hw_volume_max, hw_volume_min;
|
||||
long hw_dB_max, hw_dB_min;
|
||||
pa_bool_t hw_dB_supported;
|
||||
pa_bool_t mixer_seperate_channels;
|
||||
pa_cvolume hardware_volume;
|
||||
|
||||
size_t frame_size, fragment_size, hwbuf_size, tsched_watermark;
|
||||
unsigned nfragments;
|
||||
|
|
@ -139,7 +143,7 @@ static void fix_tsched_watermark(struct userdata *u) {
|
|||
size_t min_sleep, min_wakeup;
|
||||
pa_assert(u);
|
||||
|
||||
max_use = u->hwbuf_size - u->hwbuf_unused_frames * u->frame_size;
|
||||
max_use = u->hwbuf_size - (size_t) u->hwbuf_unused_frames * u->frame_size;
|
||||
|
||||
min_sleep = pa_usec_to_bytes(TSCHED_MIN_SLEEP_USEC, &u->sink->sample_spec);
|
||||
min_wakeup = pa_usec_to_bytes(TSCHED_MIN_WAKEUP_USEC, &u->sink->sample_spec);
|
||||
|
|
@ -212,8 +216,8 @@ static int try_recover(struct userdata *u, const char *call, int err) {
|
|||
static size_t check_left_to_play(struct userdata *u, snd_pcm_sframes_t n) {
|
||||
size_t left_to_play;
|
||||
|
||||
if (n*u->frame_size < u->hwbuf_size)
|
||||
left_to_play = u->hwbuf_size - (n*u->frame_size);
|
||||
if ((size_t) n*u->frame_size < u->hwbuf_size)
|
||||
left_to_play = u->hwbuf_size - ((size_t) n*u->frame_size);
|
||||
else
|
||||
left_to_play = 0;
|
||||
|
||||
|
|
@ -239,7 +243,7 @@ static size_t check_left_to_play(struct userdata *u, snd_pcm_sframes_t n) {
|
|||
|
||||
static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) {
|
||||
int work_done = 0;
|
||||
pa_usec_t max_sleep_usec, process_usec;
|
||||
pa_usec_t max_sleep_usec = 0, process_usec = 0;
|
||||
size_t left_to_play;
|
||||
|
||||
pa_assert(u);
|
||||
|
|
@ -259,7 +263,7 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
|
||||
if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
|
||||
|
||||
if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
|
||||
if ((r = try_recover(u, "snd_pcm_avail_update", (int) n)) == 0)
|
||||
continue;
|
||||
|
||||
return r;
|
||||
|
|
@ -291,6 +295,7 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
int err;
|
||||
const snd_pcm_channel_area_t *areas;
|
||||
snd_pcm_uframes_t offset, frames = (snd_pcm_uframes_t) n;
|
||||
snd_pcm_sframes_t sframes;
|
||||
|
||||
/* pa_log_debug("%lu frames to write", (unsigned long) frames); */
|
||||
|
||||
|
|
@ -326,9 +331,9 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
* a little bit longer around? */
|
||||
pa_memblock_unref_fixed(chunk.memblock);
|
||||
|
||||
if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
|
||||
if (PA_UNLIKELY((sframes = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
|
||||
|
||||
if ((r = try_recover(u, "snd_pcm_mmap_commit", err)) == 0)
|
||||
if ((r = try_recover(u, "snd_pcm_mmap_commit", (int) sframes)) == 0)
|
||||
continue;
|
||||
|
||||
return r;
|
||||
|
|
@ -336,7 +341,7 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
|
||||
work_done = 1;
|
||||
|
||||
u->frame_index += frames;
|
||||
u->frame_index += (int64_t) frames;
|
||||
u->since_start += frames * u->frame_size;
|
||||
|
||||
/* pa_log_debug("wrote %lu frames", (unsigned long) frames); */
|
||||
|
|
@ -344,7 +349,7 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
if (frames >= (snd_pcm_uframes_t) n)
|
||||
break;
|
||||
|
||||
n -= frames;
|
||||
n -= (snd_pcm_sframes_t) frames;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -354,7 +359,7 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
|
||||
static int unix_write(struct userdata *u, pa_usec_t *sleep_usec) {
|
||||
int work_done = 0;
|
||||
pa_usec_t max_sleep_usec, process_usec;
|
||||
pa_usec_t max_sleep_usec = 0, process_usec = 0;
|
||||
size_t left_to_play;
|
||||
|
||||
pa_assert(u);
|
||||
|
|
@ -371,7 +376,7 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
|
||||
if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
|
||||
|
||||
if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
|
||||
if ((r = try_recover(u, "snd_pcm_avail_update", (int) n)) == 0)
|
||||
continue;
|
||||
|
||||
return r;
|
||||
|
|
@ -402,31 +407,31 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
/* pa_log_debug("%lu frames to write", (unsigned long) frames); */
|
||||
|
||||
if (u->memchunk.length <= 0)
|
||||
pa_sink_render(u->sink, n * u->frame_size, &u->memchunk);
|
||||
pa_sink_render(u->sink, (size_t) n * u->frame_size, &u->memchunk);
|
||||
|
||||
pa_assert(u->memchunk.length > 0);
|
||||
|
||||
frames = u->memchunk.length / u->frame_size;
|
||||
frames = (snd_pcm_sframes_t) (u->memchunk.length / u->frame_size);
|
||||
|
||||
if (frames > n)
|
||||
frames = n;
|
||||
|
||||
p = pa_memblock_acquire(u->memchunk.memblock);
|
||||
frames = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, frames);
|
||||
frames = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, (snd_pcm_uframes_t) frames);
|
||||
pa_memblock_release(u->memchunk.memblock);
|
||||
|
||||
pa_assert(frames != 0);
|
||||
|
||||
if (PA_UNLIKELY(frames < 0)) {
|
||||
|
||||
if ((r = try_recover(u, "snd_pcm_writei", n)) == 0)
|
||||
if ((r = try_recover(u, "snd_pcm_writei", (int) frames)) == 0)
|
||||
continue;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
u->memchunk.index += frames * u->frame_size;
|
||||
u->memchunk.length -= frames * u->frame_size;
|
||||
u->memchunk.index += (size_t) frames * u->frame_size;
|
||||
u->memchunk.length -= (size_t) frames * u->frame_size;
|
||||
|
||||
if (u->memchunk.length <= 0) {
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
|
|
@ -436,7 +441,7 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
work_done = 1;
|
||||
|
||||
u->frame_index += frames;
|
||||
u->since_start += frames * u->frame_size;
|
||||
u->since_start += (size_t) frames * u->frame_size;
|
||||
|
||||
/* pa_log_debug("wrote %lu frames", (unsigned long) frames); */
|
||||
|
||||
|
|
@ -490,7 +495,7 @@ static void update_smoother(struct userdata *u) {
|
|||
/* now1 = pa_timeval_load(×tamp); */
|
||||
|
||||
now1 = pa_rtclock_usec();
|
||||
now2 = pa_bytes_to_usec(frames * u->frame_size, &u->sink->sample_spec);
|
||||
now2 = pa_bytes_to_usec((uint64_t) frames * u->frame_size, &u->sink->sample_spec);
|
||||
pa_smoother_put(u->smoother, now1, now2);
|
||||
}
|
||||
|
||||
|
|
@ -504,7 +509,7 @@ static pa_usec_t sink_get_latency(struct userdata *u) {
|
|||
now1 = pa_rtclock_usec();
|
||||
now2 = pa_smoother_get(u->smoother, now1);
|
||||
|
||||
delay = (int64_t) pa_bytes_to_usec(u->frame_index * u->frame_size, &u->sink->sample_spec) - (int64_t) now2;
|
||||
delay = (int64_t) pa_bytes_to_usec((uint64_t) u->frame_index * u->frame_size, &u->sink->sample_spec) - (int64_t) now2;
|
||||
|
||||
if (delay > 0)
|
||||
r = (pa_usec_t) delay;
|
||||
|
|
@ -573,9 +578,9 @@ static int update_sw_params(struct userdata *u) {
|
|||
if (PA_UNLIKELY(b < u->frame_size))
|
||||
b = u->frame_size;
|
||||
|
||||
u->hwbuf_unused_frames =
|
||||
PA_LIKELY(b < u->hwbuf_size) ?
|
||||
((u->hwbuf_size - b) / u->frame_size) : 0;
|
||||
u->hwbuf_unused_frames = (snd_pcm_sframes_t)
|
||||
(PA_LIKELY(b < u->hwbuf_size) ?
|
||||
((u->hwbuf_size - b) / u->frame_size) : 0);
|
||||
|
||||
fix_tsched_watermark(u);
|
||||
}
|
||||
|
|
@ -584,7 +589,7 @@ static int update_sw_params(struct userdata *u) {
|
|||
pa_log_debug("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames);
|
||||
|
||||
/* We need at last one frame in the used part of the buffer */
|
||||
avail_min = u->hwbuf_unused_frames + 1;
|
||||
avail_min = (snd_pcm_uframes_t) u->hwbuf_unused_frames + 1;
|
||||
|
||||
if (u->use_tsched) {
|
||||
pa_usec_t sleep_usec, process_usec;
|
||||
|
|
@ -600,7 +605,7 @@ static int update_sw_params(struct userdata *u) {
|
|||
return err;
|
||||
}
|
||||
|
||||
pa_sink_set_max_request(u->sink, u->hwbuf_size - u->hwbuf_unused_frames * u->frame_size);
|
||||
pa_sink_set_max_request(u->sink, u->hwbuf_size - (size_t) u->hwbuf_unused_frames * u->frame_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -737,8 +742,8 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
|
|||
return 0;
|
||||
|
||||
if (mask & SND_CTL_EVENT_MASK_VALUE) {
|
||||
pa_sink_get_volume(u->sink);
|
||||
pa_sink_get_mute(u->sink);
|
||||
pa_sink_get_volume(u->sink, TRUE);
|
||||
pa_sink_get_mute(u->sink, TRUE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -747,30 +752,68 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
|
|||
static int sink_get_volume_cb(pa_sink *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
int err;
|
||||
int i;
|
||||
unsigned i;
|
||||
pa_cvolume r;
|
||||
char t[PA_CVOLUME_SNPRINT_MAX];
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(u->mixer_elem);
|
||||
|
||||
for (i = 0; i < s->sample_spec.channels; i++) {
|
||||
long alsa_vol;
|
||||
if (u->mixer_seperate_channels) {
|
||||
|
||||
pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, u->mixer_map[i]));
|
||||
r.channels = s->sample_spec.channels;
|
||||
|
||||
if (u->hw_dB_supported) {
|
||||
for (i = 0; i < s->sample_spec.channels; i++) {
|
||||
long alsa_vol;
|
||||
|
||||
if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) >= 0) {
|
||||
s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0);
|
||||
continue;
|
||||
if (u->hw_dB_supported) {
|
||||
|
||||
if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
|
||||
#endif
|
||||
|
||||
r.values[i] = pa_sw_volume_from_dB((double) alsa_vol / 100.0);
|
||||
} else {
|
||||
|
||||
if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
r.values[i] = (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (double) (u->hw_volume_max - u->hw_volume_min));
|
||||
}
|
||||
|
||||
u->hw_dB_supported = FALSE;
|
||||
}
|
||||
|
||||
if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
|
||||
} else {
|
||||
long alsa_vol;
|
||||
|
||||
pa_assert(u->hw_dB_supported);
|
||||
|
||||
if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
|
||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
|
||||
#endif
|
||||
|
||||
pa_cvolume_set(&r, s->sample_spec.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
|
||||
}
|
||||
|
||||
pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &r));
|
||||
|
||||
if (!pa_cvolume_equal(&u->hardware_volume, &r)) {
|
||||
|
||||
u->hardware_volume = s->volume = r;
|
||||
|
||||
if (u->hw_dB_supported) {
|
||||
pa_cvolume reset;
|
||||
|
||||
/* Hmm, so the hardware volume changed, let's reset our software volume */
|
||||
|
||||
pa_cvolume_reset(&reset, s->sample_spec.channels);
|
||||
pa_sink_set_soft_volume(s, &reset);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -784,45 +827,90 @@ fail:
|
|||
static int sink_set_volume_cb(pa_sink *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
int err;
|
||||
int i;
|
||||
unsigned i;
|
||||
pa_cvolume r;
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(u->mixer_elem);
|
||||
|
||||
for (i = 0; i < s->sample_spec.channels; i++) {
|
||||
long alsa_vol;
|
||||
pa_volume_t vol;
|
||||
if (u->mixer_seperate_channels) {
|
||||
|
||||
pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, u->mixer_map[i]));
|
||||
r.channels = s->sample_spec.channels;
|
||||
|
||||
vol = PA_MIN(s->volume.values[i], PA_VOLUME_NORM);
|
||||
for (i = 0; i < s->sample_spec.channels; i++) {
|
||||
long alsa_vol;
|
||||
pa_volume_t vol;
|
||||
|
||||
if (u->hw_dB_supported) {
|
||||
alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
|
||||
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
|
||||
vol = s->volume.values[i];
|
||||
|
||||
if ((err = snd_mixer_selem_set_playback_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, -1)) >= 0) {
|
||||
if (u->hw_dB_supported) {
|
||||
|
||||
if (snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0)
|
||||
s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0);
|
||||
alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
|
||||
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
|
||||
|
||||
continue;
|
||||
if ((err = snd_mixer_selem_set_playback_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, 1)) < 0)
|
||||
goto fail;
|
||||
|
||||
if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
r.values[i] = pa_sw_volume_from_dB((double) alsa_vol / 100.0);
|
||||
} else {
|
||||
|
||||
alsa_vol = (long) round(((double) vol * (double) (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
|
||||
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
|
||||
|
||||
if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
r.values[i] = (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (double) (u->hw_volume_max - u->hw_volume_min));
|
||||
}
|
||||
|
||||
u->hw_dB_supported = FALSE;
|
||||
|
||||
}
|
||||
|
||||
alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
|
||||
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
|
||||
} else {
|
||||
pa_volume_t vol;
|
||||
long alsa_vol;
|
||||
|
||||
if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
|
||||
pa_assert(u->hw_dB_supported);
|
||||
|
||||
vol = pa_cvolume_max(&s->volume);
|
||||
|
||||
alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
|
||||
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
|
||||
|
||||
if ((err = snd_mixer_selem_set_playback_dB_all(u->mixer_elem, alsa_vol, 1)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0)
|
||||
s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
|
||||
if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
pa_cvolume_set(&r, s->volume.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
|
||||
}
|
||||
|
||||
u->hardware_volume = r;
|
||||
|
||||
if (u->hw_dB_supported) {
|
||||
char t[PA_CVOLUME_SNPRINT_MAX];
|
||||
|
||||
/* Match exactly what the user requested by software */
|
||||
|
||||
pa_alsa_volume_divide(&r, &s->volume);
|
||||
pa_sink_set_soft_volume(s, &r);
|
||||
|
||||
pa_log_debug("Requested volume: %s", pa_cvolume_snprint(t, sizeof(t), &s->volume));
|
||||
pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &u->hardware_volume));
|
||||
pa_log_debug("Calculated software volume: %s", pa_cvolume_snprint(t, sizeof(t), &r));
|
||||
|
||||
} else
|
||||
|
||||
/* We can't match exactly what the user requested, hence let's
|
||||
* at least tell the user about it */
|
||||
|
||||
s->volume = r;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
|
@ -903,7 +991,7 @@ static int process_rewind(struct userdata *u) {
|
|||
|
||||
snd_pcm_hwsync(u->pcm_handle);
|
||||
if ((unused = snd_pcm_avail_update(u->pcm_handle)) < 0) {
|
||||
pa_log("snd_pcm_avail_update() failed: %s", snd_strerror(unused));
|
||||
pa_log("snd_pcm_avail_update() failed: %s", snd_strerror((int) unused));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -922,15 +1010,15 @@ static int process_rewind(struct userdata *u) {
|
|||
|
||||
pa_log_debug("Limited to %lu bytes.", (unsigned long) rewind_nbytes);
|
||||
|
||||
in_frames = (snd_pcm_sframes_t) rewind_nbytes / u->frame_size;
|
||||
in_frames = (snd_pcm_sframes_t) (rewind_nbytes / u->frame_size);
|
||||
pa_log_debug("before: %lu", (unsigned long) in_frames);
|
||||
if ((out_frames = snd_pcm_rewind(u->pcm_handle, in_frames)) < 0) {
|
||||
pa_log("snd_pcm_rewind() failed: %s", snd_strerror(out_frames));
|
||||
if ((out_frames = snd_pcm_rewind(u->pcm_handle, (snd_pcm_uframes_t) in_frames)) < 0) {
|
||||
pa_log("snd_pcm_rewind() failed: %s", snd_strerror((int) out_frames));
|
||||
return -1;
|
||||
}
|
||||
pa_log_debug("after: %lu", (unsigned long) out_frames);
|
||||
|
||||
rewind_nbytes = out_frames * u->frame_size;
|
||||
rewind_nbytes = (size_t) out_frames * u->frame_size;
|
||||
|
||||
if (rewind_nbytes <= 0)
|
||||
pa_log_info("Tried rewind, but was apparently not possible.");
|
||||
|
|
@ -974,7 +1062,7 @@ static void thread_func(void *userdata) {
|
|||
/* Render some data and write it to the dsp */
|
||||
if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
|
||||
int work_done;
|
||||
pa_usec_t sleep_usec;
|
||||
pa_usec_t sleep_usec = 0;
|
||||
|
||||
if (u->sink->thread_info.rewind_requested)
|
||||
if (process_rewind(u) < 0)
|
||||
|
|
@ -1100,7 +1188,7 @@ int pa__init(pa_module*m) {
|
|||
const char *name;
|
||||
char *name_buf = NULL;
|
||||
pa_bool_t namereg_fail;
|
||||
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, mixer_reset = TRUE;
|
||||
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d;
|
||||
pa_usec_t usec;
|
||||
pa_sink_new_data data;
|
||||
|
||||
|
|
@ -1124,11 +1212,11 @@ int pa__init(pa_module*m) {
|
|||
frame_size = pa_frame_size(&ss);
|
||||
|
||||
nfrags = m->core->default_n_fragments;
|
||||
frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss);
|
||||
frag_size = (uint32_t) pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss);
|
||||
if (frag_size <= 0)
|
||||
frag_size = frame_size;
|
||||
tsched_size = pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC, &ss);
|
||||
tsched_watermark = pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC, &ss);
|
||||
frag_size = (uint32_t) frame_size;
|
||||
tsched_size = (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC, &ss);
|
||||
tsched_watermark = (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC, &ss);
|
||||
|
||||
if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 ||
|
||||
pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 ||
|
||||
|
|
@ -1157,11 +1245,6 @@ int pa__init(pa_module*m) {
|
|||
use_tsched = FALSE;
|
||||
}
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "mixer_reset", &mixer_reset) < 0) {
|
||||
pa_log("Failed to parse mixer_reset argument.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u = pa_xnew0(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
|
|
@ -1313,7 +1396,7 @@ int pa__init(pa_module*m) {
|
|||
pa_sink_set_rtpoll(u->sink, u->rtpoll);
|
||||
|
||||
u->frame_size = frame_size;
|
||||
u->fragment_size = frag_size = period_frames * frame_size;
|
||||
u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size);
|
||||
u->nfragments = nfrags;
|
||||
u->hwbuf_size = u->fragment_size * nfrags;
|
||||
u->hwbuf_unused_frames = 0;
|
||||
|
|
@ -1322,6 +1405,8 @@ int pa__init(pa_module*m) {
|
|||
u->hw_dB_supported = FALSE;
|
||||
u->hw_dB_min = u->hw_dB_max = 0;
|
||||
u->hw_volume_min = u->hw_volume_max = 0;
|
||||
u->mixer_seperate_channels = FALSE;
|
||||
pa_cvolume_mute(&u->hardware_volume, u->sink->sample_spec.channels);
|
||||
|
||||
if (use_tsched)
|
||||
fix_tsched_watermark(u);
|
||||
|
|
@ -1349,76 +1434,56 @@ int pa__init(pa_module*m) {
|
|||
if (u->mixer_handle) {
|
||||
pa_assert(u->mixer_elem);
|
||||
|
||||
if (snd_mixer_selem_has_playback_volume(u->mixer_elem))
|
||||
|
||||
if (pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, TRUE) >= 0 &&
|
||||
snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) >= 0) {
|
||||
|
||||
pa_bool_t suitable = TRUE;
|
||||
if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) {
|
||||
pa_bool_t suitable = TRUE;
|
||||
|
||||
if (snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) < 0) {
|
||||
pa_log_info("Failed to get volume range. Falling back to software volume control.");
|
||||
suitable = FALSE;
|
||||
} else {
|
||||
pa_log_info("Volume ranges from %li to %li.", u->hw_volume_min, u->hw_volume_max);
|
||||
|
||||
if (u->hw_volume_min > u->hw_volume_max) {
|
||||
|
||||
pa_log_info("Minimal volume %li larger than maximum volume %li. Strange stuff Falling back to software volume control.", u->hw_volume_min, u->hw_volume_max);
|
||||
suitable = FALSE;
|
||||
|
||||
} else if (u->hw_volume_max - u->hw_volume_min < 3) {
|
||||
|
||||
pa_log_info("Device has less than 4 volume levels. Falling back to software volume control.");
|
||||
suitable = FALSE;
|
||||
|
||||
} else if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) >= 0) {
|
||||
|
||||
/* u->hw_dB_max = 0; u->hw_dB_min = -3000; Use this to make valgrind shut up */
|
||||
|
||||
pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", u->hw_dB_min/100.0, u->hw_dB_max/100.0);
|
||||
|
||||
/* Let's see if this thing actually is useful for muting */
|
||||
if (u->hw_dB_min > -6000) {
|
||||
pa_log_info("Device cannot attenuate for more than -60 dB (only %0.2f dB supported), falling back to software volume control.", ((double) u->hw_dB_min) / 100);
|
||||
|
||||
suitable = FALSE;
|
||||
} else if (u->hw_dB_max < 0) {
|
||||
|
||||
pa_log_info("Device is still attenuated at maximum volume setting (%0.2f dB is maximum). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_max) / 100);
|
||||
suitable = FALSE;
|
||||
|
||||
} else if (u->hw_dB_min >= u->hw_dB_max) {
|
||||
|
||||
pa_log_info("Minimal dB (%0.2f) larger or equal to maximum dB (%0.2f). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_min) / 100, ((double) u->hw_dB_max) / 100);
|
||||
suitable = FALSE;
|
||||
|
||||
} else {
|
||||
|
||||
if (u->hw_dB_max > 0) {
|
||||
/* dB > 0 means overamplification, and clipping, we don't want that here */
|
||||
pa_log_info("Device can do overamplification for %0.2f dB. Limiting to 0 db", ((double) u->hw_dB_max) / 100);
|
||||
u->hw_dB_max = 0;
|
||||
}
|
||||
|
||||
u->hw_dB_supported = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (suitable) {
|
||||
u->sink->get_volume = sink_get_volume_cb;
|
||||
u->sink->set_volume = sink_set_volume_cb;
|
||||
u->sink->flags |= PA_SINK_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SINK_DECIBEL_VOLUME : 0);
|
||||
pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported");
|
||||
|
||||
} else if (mixer_reset) {
|
||||
pa_log_info("Using software volume control. Trying to reset sound card to 0 dB.");
|
||||
pa_alsa_0dB_playback(u->mixer_elem);
|
||||
} else
|
||||
pa_log_info("Using software volume control. Leaving hw mixer controls untouched.");
|
||||
pa_assert(u->hw_volume_min < u->hw_volume_max);
|
||||
}
|
||||
|
||||
if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) < 0)
|
||||
pa_log_info("Mixer doesn't support dB information.");
|
||||
else {
|
||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_min, sizeof(u->hw_dB_min));
|
||||
VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_max, sizeof(u->hw_dB_max));
|
||||
#endif
|
||||
|
||||
pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
|
||||
pa_assert(u->hw_dB_min < u->hw_dB_max);
|
||||
u->hw_dB_supported = TRUE;
|
||||
}
|
||||
|
||||
if (suitable &&
|
||||
!u->hw_dB_supported &&
|
||||
u->hw_volume_max - u->hw_volume_min < 3) {
|
||||
|
||||
pa_log_info("Device doesn't do dB volume and has less than 4 volume levels. Falling back to software volume control.");
|
||||
suitable = FALSE;
|
||||
}
|
||||
|
||||
if (suitable) {
|
||||
u->mixer_seperate_channels = pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, TRUE) >= 0;
|
||||
|
||||
u->sink->get_volume = sink_get_volume_cb;
|
||||
u->sink->set_volume = sink_set_volume_cb;
|
||||
u->sink->flags |= PA_SINK_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SINK_DECIBEL_VOLUME : 0);
|
||||
pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported");
|
||||
|
||||
} else
|
||||
pa_log_info("Using software volume control.");
|
||||
}
|
||||
|
||||
if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) {
|
||||
u->sink->get_mute = sink_get_mute_cb;
|
||||
u->sink->set_mute = sink_set_mute_cb;
|
||||
u->sink->flags |= PA_SINK_HW_MUTE_CTRL;
|
||||
}
|
||||
} else
|
||||
pa_log_info("Using software mute control.");
|
||||
|
||||
u->mixer_fdl = pa_alsa_fdlist_new();
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@
|
|||
|
||||
#include <asoundlib.h>
|
||||
|
||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
#include <valgrind/memcheck.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/util.h>
|
||||
#include <pulse/timeval.h>
|
||||
|
|
@ -69,8 +73,7 @@ PA_MODULE_USAGE(
|
|||
"mmap=<enable memory mapping?> "
|
||||
"tsched=<enable system timer based scheduling mode?> "
|
||||
"tsched_buffer_size=<buffer size when using timer based scheduling> "
|
||||
"tsched_buffer_watermark=<upper fill watermark> "
|
||||
"mixer_reset=<reset hw volume and mute settings to sane defaults when falling back to software?>");
|
||||
"tsched_buffer_watermark=<upper fill watermark>");
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"source_name",
|
||||
|
|
@ -86,7 +89,6 @@ static const char* const valid_modargs[] = {
|
|||
"tsched",
|
||||
"tsched_buffer_size",
|
||||
"tsched_buffer_watermark",
|
||||
"mixer_reset",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -113,6 +115,9 @@ struct userdata {
|
|||
long hw_volume_max, hw_volume_min;
|
||||
long hw_dB_max, hw_dB_min;
|
||||
pa_bool_t hw_dB_supported;
|
||||
pa_bool_t mixer_seperate_channels;
|
||||
|
||||
pa_cvolume hardware_volume;
|
||||
|
||||
size_t frame_size, fragment_size, hwbuf_size, tsched_watermark;
|
||||
unsigned nfragments;
|
||||
|
|
@ -136,7 +141,7 @@ static void fix_tsched_watermark(struct userdata *u) {
|
|||
size_t min_sleep, min_wakeup;
|
||||
pa_assert(u);
|
||||
|
||||
max_use = u->hwbuf_size - u->hwbuf_unused_frames * u->frame_size;
|
||||
max_use = u->hwbuf_size - (size_t) u->hwbuf_unused_frames * u->frame_size;
|
||||
|
||||
min_sleep = pa_usec_to_bytes(TSCHED_MIN_SLEEP_USEC, &u->source->sample_spec);
|
||||
min_wakeup = pa_usec_to_bytes(TSCHED_MIN_WAKEUP_USEC, &u->source->sample_spec);
|
||||
|
|
@ -207,8 +212,8 @@ static int try_recover(struct userdata *u, const char *call, int err) {
|
|||
static size_t check_left_to_record(struct userdata *u, snd_pcm_sframes_t n) {
|
||||
size_t left_to_record;
|
||||
|
||||
if (n*u->frame_size < u->hwbuf_size)
|
||||
left_to_record = u->hwbuf_size - (n*u->frame_size);
|
||||
if ((size_t) n*u->frame_size < u->hwbuf_size)
|
||||
left_to_record = u->hwbuf_size - ((size_t) n*u->frame_size);
|
||||
else
|
||||
left_to_record = 0;
|
||||
|
||||
|
|
@ -234,7 +239,7 @@ static size_t check_left_to_record(struct userdata *u, snd_pcm_sframes_t n) {
|
|||
|
||||
static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) {
|
||||
int work_done = 0;
|
||||
pa_usec_t max_sleep_usec, process_usec;
|
||||
pa_usec_t max_sleep_usec = 0, process_usec = 0;
|
||||
size_t left_to_record;
|
||||
|
||||
pa_assert(u);
|
||||
|
|
@ -251,7 +256,7 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
|
||||
if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
|
||||
|
||||
if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
|
||||
if ((r = try_recover(u, "snd_pcm_avail_update", (int) n)) == 0)
|
||||
continue;
|
||||
|
||||
return r;
|
||||
|
|
@ -272,6 +277,7 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
snd_pcm_uframes_t offset, frames = (snd_pcm_uframes_t) n;
|
||||
pa_memchunk chunk;
|
||||
void *p;
|
||||
snd_pcm_sframes_t sframes;
|
||||
|
||||
/* pa_log_debug("%lu frames to read", (unsigned long) frames); */
|
||||
|
||||
|
|
@ -304,9 +310,9 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
pa_source_post(u->source, &chunk);
|
||||
pa_memblock_unref_fixed(chunk.memblock);
|
||||
|
||||
if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
|
||||
if (PA_UNLIKELY((sframes = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
|
||||
|
||||
if ((r = try_recover(u, "snd_pcm_mmap_commit", err)) == 0)
|
||||
if ((r = try_recover(u, "snd_pcm_mmap_commit", (int) sframes)) == 0)
|
||||
continue;
|
||||
|
||||
return r;
|
||||
|
|
@ -314,14 +320,14 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
|
||||
work_done = 1;
|
||||
|
||||
u->frame_index += frames;
|
||||
u->frame_index += (int64_t) frames;
|
||||
|
||||
/* pa_log_debug("read %lu frames", (unsigned long) frames); */
|
||||
|
||||
if (frames >= (snd_pcm_uframes_t) n)
|
||||
break;
|
||||
|
||||
n -= frames;
|
||||
n -= (snd_pcm_sframes_t) frames;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -331,7 +337,7 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
|
||||
static int unix_read(struct userdata *u, pa_usec_t *sleep_usec) {
|
||||
int work_done = 0;
|
||||
pa_usec_t max_sleep_usec, process_usec;
|
||||
pa_usec_t max_sleep_usec = 0, process_usec = 0;
|
||||
size_t left_to_record;
|
||||
|
||||
pa_assert(u);
|
||||
|
|
@ -348,7 +354,7 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
|
||||
if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
|
||||
|
||||
if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
|
||||
if ((r = try_recover(u, "snd_pcm_avail_update", (int) n)) == 0)
|
||||
continue;
|
||||
|
||||
return r;
|
||||
|
|
@ -370,7 +376,7 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
|
||||
chunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1);
|
||||
|
||||
frames = pa_memblock_get_length(chunk.memblock) / u->frame_size;
|
||||
frames = (snd_pcm_sframes_t) (pa_memblock_get_length(chunk.memblock) / u->frame_size);
|
||||
|
||||
if (frames > n)
|
||||
frames = n;
|
||||
|
|
@ -378,7 +384,7 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
/* pa_log_debug("%lu frames to read", (unsigned long) n); */
|
||||
|
||||
p = pa_memblock_acquire(chunk.memblock);
|
||||
frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, frames);
|
||||
frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, (snd_pcm_uframes_t) frames);
|
||||
pa_memblock_release(chunk.memblock);
|
||||
|
||||
pa_assert(frames != 0);
|
||||
|
|
@ -386,14 +392,14 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec) {
|
|||
if (PA_UNLIKELY(frames < 0)) {
|
||||
pa_memblock_unref(chunk.memblock);
|
||||
|
||||
if ((r = try_recover(u, "snd_pcm_readi", n)) == 0)
|
||||
if ((r = try_recover(u, "snd_pcm_readi", (int) (frames))) == 0)
|
||||
continue;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
chunk.index = 0;
|
||||
chunk.length = frames * u->frame_size;
|
||||
chunk.length = (size_t) frames * u->frame_size;
|
||||
|
||||
pa_source_post(u->source, &chunk);
|
||||
pa_memblock_unref(chunk.memblock);
|
||||
|
|
@ -437,7 +443,7 @@ static void update_smoother(struct userdata *u) {
|
|||
frames = u->frame_index + delay;
|
||||
|
||||
now1 = pa_rtclock_usec();
|
||||
now2 = pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec);
|
||||
now2 = pa_bytes_to_usec((uint64_t) frames * u->frame_size, &u->source->sample_spec);
|
||||
|
||||
pa_smoother_put(u->smoother, now1, now2);
|
||||
}
|
||||
|
|
@ -452,7 +458,7 @@ static pa_usec_t source_get_latency(struct userdata *u) {
|
|||
now1 = pa_rtclock_usec();
|
||||
now2 = pa_smoother_get(u->smoother, now1);
|
||||
|
||||
delay = (int64_t) now2 - pa_bytes_to_usec(u->frame_index * u->frame_size, &u->source->sample_spec);
|
||||
delay = (int64_t) now2 - (int64_t) pa_bytes_to_usec((uint64_t) u->frame_index * u->frame_size, &u->source->sample_spec);
|
||||
|
||||
if (delay > 0)
|
||||
r = (pa_usec_t) delay;
|
||||
|
|
@ -517,9 +523,9 @@ static int update_sw_params(struct userdata *u) {
|
|||
if (PA_UNLIKELY(b < u->frame_size))
|
||||
b = u->frame_size;
|
||||
|
||||
u->hwbuf_unused_frames =
|
||||
PA_LIKELY(b < u->hwbuf_size) ?
|
||||
((u->hwbuf_size - b) / u->frame_size) : 0;
|
||||
u->hwbuf_unused_frames = (snd_pcm_sframes_t)
|
||||
(PA_LIKELY(b < u->hwbuf_size) ?
|
||||
((u->hwbuf_size - b) / u->frame_size) : 0);
|
||||
|
||||
fix_tsched_watermark(u);
|
||||
}
|
||||
|
|
@ -680,8 +686,8 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
|
|||
return 0;
|
||||
|
||||
if (mask & SND_CTL_EVENT_MASK_VALUE) {
|
||||
pa_source_get_volume(u->source);
|
||||
pa_source_get_mute(u->source);
|
||||
pa_source_get_volume(u->source, TRUE);
|
||||
pa_source_get_mute(u->source, TRUE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -690,30 +696,68 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
|
|||
static int source_get_volume_cb(pa_source *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
int err;
|
||||
int i;
|
||||
unsigned i;
|
||||
pa_cvolume r;
|
||||
char t[PA_CVOLUME_SNPRINT_MAX];
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(u->mixer_elem);
|
||||
|
||||
for (i = 0; i < s->sample_spec.channels; i++) {
|
||||
long alsa_vol;
|
||||
if (u->mixer_seperate_channels) {
|
||||
|
||||
pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, u->mixer_map[i]));
|
||||
r.channels = s->sample_spec.channels;
|
||||
|
||||
if (u->hw_dB_supported) {
|
||||
for (i = 0; i < s->sample_spec.channels; i++) {
|
||||
long alsa_vol;
|
||||
|
||||
if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) >= 0) {
|
||||
s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0);
|
||||
continue;
|
||||
if (u->hw_dB_supported) {
|
||||
|
||||
if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
|
||||
#endif
|
||||
|
||||
r.values[i] = pa_sw_volume_from_dB((double) alsa_vol / 100.0);
|
||||
} else {
|
||||
|
||||
if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
r.values[i] = (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (double) (u->hw_volume_max - u->hw_volume_min));
|
||||
}
|
||||
|
||||
u->hw_dB_supported = FALSE;
|
||||
}
|
||||
|
||||
if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
|
||||
} else {
|
||||
long alsa_vol;
|
||||
|
||||
pa_assert(u->hw_dB_supported);
|
||||
|
||||
if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
|
||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
|
||||
#endif
|
||||
|
||||
pa_cvolume_set(&r, s->sample_spec.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
|
||||
}
|
||||
|
||||
pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &r));
|
||||
|
||||
if (!pa_cvolume_equal(&u->hardware_volume, &r)) {
|
||||
|
||||
u->hardware_volume = s->volume = r;
|
||||
|
||||
if (u->hw_dB_supported) {
|
||||
pa_cvolume reset;
|
||||
|
||||
/* Hmm, so the hardware volume changed, let's reset our software volume */
|
||||
|
||||
pa_cvolume_reset(&reset, s->sample_spec.channels);
|
||||
pa_source_set_soft_volume(s, &reset);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -727,45 +771,90 @@ fail:
|
|||
static int source_set_volume_cb(pa_source *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
int err;
|
||||
int i;
|
||||
unsigned i;
|
||||
pa_cvolume r;
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(u->mixer_elem);
|
||||
|
||||
for (i = 0; i < s->sample_spec.channels; i++) {
|
||||
long alsa_vol;
|
||||
pa_volume_t vol;
|
||||
if (u->mixer_seperate_channels) {
|
||||
|
||||
pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, u->mixer_map[i]));
|
||||
r.channels = s->sample_spec.channels;
|
||||
|
||||
vol = PA_MIN(s->volume.values[i], PA_VOLUME_NORM);
|
||||
for (i = 0; i < s->sample_spec.channels; i++) {
|
||||
long alsa_vol;
|
||||
pa_volume_t vol;
|
||||
|
||||
if (u->hw_dB_supported) {
|
||||
alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
|
||||
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
|
||||
vol = s->volume.values[i];
|
||||
|
||||
if (u->hw_dB_supported) {
|
||||
|
||||
if ((err = snd_mixer_selem_set_capture_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, -1)) >= 0) {
|
||||
alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
|
||||
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
|
||||
|
||||
if (snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0)
|
||||
s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0);
|
||||
if ((err = snd_mixer_selem_set_capture_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, 1)) < 0)
|
||||
goto fail;
|
||||
|
||||
continue;
|
||||
if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
r.values[i] = pa_sw_volume_from_dB((double) alsa_vol / 100.0);
|
||||
} else {
|
||||
|
||||
alsa_vol = (long) round(((double) vol * (double) (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
|
||||
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
|
||||
|
||||
if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
r.values[i] = (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (double) (u->hw_volume_max - u->hw_volume_min));
|
||||
}
|
||||
|
||||
u->hw_dB_supported = FALSE;
|
||||
}
|
||||
|
||||
alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
|
||||
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
|
||||
} else {
|
||||
pa_volume_t vol;
|
||||
long alsa_vol;
|
||||
|
||||
if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
|
||||
pa_assert(u->hw_dB_supported);
|
||||
|
||||
vol = pa_cvolume_max(&s->volume);
|
||||
|
||||
alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
|
||||
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
|
||||
|
||||
if ((err = snd_mixer_selem_set_capture_dB_all(u->mixer_elem, alsa_vol, 1)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0)
|
||||
s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
|
||||
if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
|
||||
goto fail;
|
||||
|
||||
pa_cvolume_set(&r, s->volume.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
|
||||
}
|
||||
|
||||
u->hardware_volume = r;
|
||||
|
||||
if (u->hw_dB_supported) {
|
||||
char t[PA_CVOLUME_SNPRINT_MAX];
|
||||
|
||||
/* Match exactly what the user requested by software */
|
||||
|
||||
pa_alsa_volume_divide(&r, &s->volume);
|
||||
pa_source_set_soft_volume(s, &r);
|
||||
|
||||
pa_log_debug("Requested volume: %s", pa_cvolume_snprint(t, sizeof(t), &s->volume));
|
||||
pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &u->hardware_volume));
|
||||
pa_log_debug("Calculated software volume: %s", pa_cvolume_snprint(t, sizeof(t), &r));
|
||||
|
||||
} else
|
||||
|
||||
/* We can't match exactly what the user requested, hence let's
|
||||
* at least tell the user about it */
|
||||
|
||||
s->volume = r;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
|
@ -837,7 +926,7 @@ static void thread_func(void *userdata) {
|
|||
/* Read some data and pass it to the sources */
|
||||
if (PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
|
||||
int work_done = 0;
|
||||
pa_usec_t sleep_usec;
|
||||
pa_usec_t sleep_usec = 0;
|
||||
|
||||
if (u->use_mmap)
|
||||
work_done = mmap_read(u, &sleep_usec);
|
||||
|
|
@ -932,7 +1021,7 @@ int pa__init(pa_module*m) {
|
|||
const char *name;
|
||||
char *name_buf = NULL;
|
||||
pa_bool_t namereg_fail;
|
||||
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, mixer_reset = TRUE;
|
||||
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d;
|
||||
pa_source_new_data data;
|
||||
|
||||
snd_pcm_info_alloca(&pcm_info);
|
||||
|
|
@ -955,11 +1044,11 @@ int pa__init(pa_module*m) {
|
|||
frame_size = pa_frame_size(&ss);
|
||||
|
||||
nfrags = m->core->default_n_fragments;
|
||||
frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss);
|
||||
frag_size = (uint32_t) pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss);
|
||||
if (frag_size <= 0)
|
||||
frag_size = frame_size;
|
||||
tsched_size = pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC, &ss);
|
||||
tsched_watermark = pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC, &ss);
|
||||
frag_size = (uint32_t) frame_size;
|
||||
tsched_size = (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC, &ss);
|
||||
tsched_watermark = (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC, &ss);
|
||||
|
||||
if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 ||
|
||||
pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 ||
|
||||
|
|
@ -988,11 +1077,6 @@ int pa__init(pa_module*m) {
|
|||
use_tsched = FALSE;
|
||||
}
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "mixer_reset", &mixer_reset) < 0) {
|
||||
pa_log("Failed to parse mixer_reset argument.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u = pa_xnew0(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
|
|
@ -1137,7 +1221,7 @@ int pa__init(pa_module*m) {
|
|||
pa_source_set_rtpoll(u->source, u->rtpoll);
|
||||
|
||||
u->frame_size = frame_size;
|
||||
u->fragment_size = frag_size = period_frames * frame_size;
|
||||
u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size);
|
||||
u->nfragments = nfrags;
|
||||
u->hwbuf_size = u->fragment_size * nfrags;
|
||||
u->hwbuf_unused_frames = 0;
|
||||
|
|
@ -1146,6 +1230,8 @@ int pa__init(pa_module*m) {
|
|||
u->hw_dB_supported = FALSE;
|
||||
u->hw_dB_min = u->hw_dB_max = 0;
|
||||
u->hw_volume_min = u->hw_volume_max = 0;
|
||||
u->mixer_seperate_channels = FALSE;
|
||||
pa_cvolume_mute(&u->hardware_volume, u->source->sample_spec.channels);
|
||||
|
||||
if (use_tsched)
|
||||
fix_tsched_watermark(u);
|
||||
|
|
@ -1168,67 +1254,56 @@ int pa__init(pa_module*m) {
|
|||
if (u->mixer_handle) {
|
||||
pa_assert(u->mixer_elem);
|
||||
|
||||
if (snd_mixer_selem_has_capture_volume(u->mixer_elem))
|
||||
if (pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, FALSE) >= 0 &&
|
||||
snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) >= 0) {
|
||||
|
||||
pa_bool_t suitable = TRUE;
|
||||
if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) {
|
||||
pa_bool_t suitable = TRUE;
|
||||
|
||||
if (snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) < 0) {
|
||||
pa_log_info("Failed to get volume range. Falling back to software volume control.");
|
||||
suitable = FALSE;
|
||||
} else {
|
||||
pa_log_info("Volume ranges from %li to %li.", u->hw_volume_min, u->hw_volume_max);
|
||||
|
||||
if (u->hw_volume_min > u->hw_volume_max) {
|
||||
|
||||
pa_log_info("Minimal volume %li larger than maximum volume %li. Strange stuff Falling back to software volume control.", u->hw_volume_min, u->hw_volume_max);
|
||||
suitable = FALSE;
|
||||
|
||||
} else if (u->hw_volume_max - u->hw_volume_min < 3) {
|
||||
|
||||
pa_log_info("Device has less than 4 volume levels. Falling back to software volume control.");
|
||||
suitable = FALSE;
|
||||
|
||||
} else if (snd_mixer_selem_get_capture_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) >= 0) {
|
||||
|
||||
pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", u->hw_dB_min/100.0, u->hw_dB_max/100.0);
|
||||
|
||||
/* Let's see if this thing actually is useful for muting */
|
||||
if (u->hw_dB_min > -6000) {
|
||||
pa_log_info("Device cannot attenuate for more than -60 dB (only %0.2f dB supported), falling back to software volume control.", ((double) u->hw_dB_min) / 100);
|
||||
|
||||
suitable = FALSE;
|
||||
} else if (u->hw_dB_max < 0) {
|
||||
|
||||
pa_log_info("Device is still attenuated at maximum volume setting (%0.2f dB is maximum). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_max) / 100);
|
||||
suitable = FALSE;
|
||||
|
||||
} else if (u->hw_dB_min >= u->hw_dB_max) {
|
||||
|
||||
pa_log_info("Minimal dB (%0.2f) larger or equal to maximum dB (%0.2f). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_min) / 100, ((double) u->hw_dB_max) / 100);
|
||||
suitable = FALSE;
|
||||
|
||||
} else
|
||||
u->hw_dB_supported = TRUE;
|
||||
}
|
||||
|
||||
if (suitable) {
|
||||
u->source->get_volume = source_get_volume_cb;
|
||||
u->source->set_volume = source_set_volume_cb;
|
||||
u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SOURCE_DECIBEL_VOLUME : 0);
|
||||
pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported");
|
||||
|
||||
} else if (mixer_reset) {
|
||||
pa_log_info("Using software volume control. Trying to reset sound card to 0 dB.");
|
||||
pa_alsa_0dB_capture(u->mixer_elem);
|
||||
} else
|
||||
pa_log_info("Using software volume control. Leaving hw mixer controls untouched.");
|
||||
|
||||
pa_assert(u->hw_volume_min < u->hw_volume_max);
|
||||
}
|
||||
|
||||
if (snd_mixer_selem_get_capture_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) < 0)
|
||||
pa_log_info("Mixer doesn't support dB information.");
|
||||
else {
|
||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_min, sizeof(u->hw_dB_min));
|
||||
VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_max, sizeof(u->hw_dB_max));
|
||||
#endif
|
||||
|
||||
pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
|
||||
pa_assert(u->hw_dB_min < u->hw_dB_max);
|
||||
u->hw_dB_supported = TRUE;
|
||||
}
|
||||
|
||||
if (suitable &&
|
||||
!u->hw_dB_supported &&
|
||||
u->hw_volume_max - u->hw_volume_min < 3) {
|
||||
|
||||
pa_log_info("Device has less than 4 volume levels. Falling back to software volume control.");
|
||||
suitable = FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (suitable) {
|
||||
u->mixer_seperate_channels = pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, FALSE) >= 0;
|
||||
|
||||
u->source->get_volume = source_get_volume_cb;
|
||||
u->source->set_volume = source_set_volume_cb;
|
||||
u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SOURCE_DECIBEL_VOLUME : 0);
|
||||
pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported");
|
||||
} else
|
||||
pa_log_info("Using software volume control.");
|
||||
}
|
||||
|
||||
if (snd_mixer_selem_has_capture_switch(u->mixer_elem)) {
|
||||
u->source->get_mute = source_get_mute_cb;
|
||||
u->source->set_mute = source_set_mute_cb;
|
||||
u->source->flags |= PA_SOURCE_HW_MUTE_CTRL;
|
||||
}
|
||||
} else
|
||||
pa_log_info("Using software mute control.");
|
||||
|
||||
u->mixer_fdl = pa_alsa_fdlist_new();
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ static pa_hook_result_t put_hook_callback(pa_core *c, pa_sink *sink, void* userd
|
|||
|
||||
pa_log_info("A new sink has been discovered. Unloading null-sink.");
|
||||
|
||||
pa_module_unload_request(u->null_module);
|
||||
pa_module_unload_request(u->null_module, TRUE);
|
||||
u->null_module = NULL;
|
||||
|
||||
return PA_HOOK_OK;
|
||||
|
|
@ -171,7 +171,7 @@ void pa__done(pa_module*m) {
|
|||
if (u->unlink_slot)
|
||||
pa_hook_slot_free(u->unlink_slot);
|
||||
if (u->null_module)
|
||||
pa_module_unload_request(u->null_module);
|
||||
pa_module_unload_request(u->null_module, TRUE);
|
||||
|
||||
pa_xfree(u->sink_name);
|
||||
pa_xfree(u);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ static void eof_and_unload_cb(pa_cli*c, void *userdata) {
|
|||
pa_assert(c);
|
||||
pa_assert(m);
|
||||
|
||||
pa_module_unload_request(m);
|
||||
pa_module_unload_request(m, TRUE);
|
||||
}
|
||||
|
||||
static void eof_and_exit_cb(pa_cli*c, void *userdata) {
|
||||
|
|
@ -62,7 +62,7 @@ static void eof_and_exit_cb(pa_cli*c, void *userdata) {
|
|||
pa_assert(c);
|
||||
pa_assert(m);
|
||||
|
||||
m->core->mainloop->quit(m->core->mainloop, 0);
|
||||
pa_core_exit(m->core, FALSE, 0);
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
|
|
|
|||
|
|
@ -206,9 +206,9 @@ static void adjust_rates(struct userdata *u) {
|
|||
continue;
|
||||
|
||||
if (o->total_latency < target_latency)
|
||||
r -= (uint32_t) (((((double) target_latency - o->total_latency))/u->adjust_time)*r/PA_USEC_PER_SEC);
|
||||
r -= (uint32_t) ((((double) (target_latency - o->total_latency))/(double)u->adjust_time)*(double)r/PA_USEC_PER_SEC);
|
||||
else if (o->total_latency > target_latency)
|
||||
r += (uint32_t) (((((double) o->total_latency - target_latency))/u->adjust_time)*r/PA_USEC_PER_SEC);
|
||||
r += (uint32_t) ((((double) (o->total_latency - target_latency))/(double)u->adjust_time)*(double)r/PA_USEC_PER_SEC);
|
||||
|
||||
if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1)) {
|
||||
pa_log_warn("[%s] sample rates too different, not adjusting (%u vs. %u).", pa_proplist_gets(o->sink_input->proplist, PA_PROP_MEDIA_NAME), base_rate, r);
|
||||
|
|
@ -233,7 +233,7 @@ static void time_callback(pa_mainloop_api*a, pa_time_event* e, const struct time
|
|||
adjust_rates(u);
|
||||
|
||||
pa_gettimeofday(&n);
|
||||
n.tv_sec += u->adjust_time;
|
||||
n.tv_sec += (time_t) u->adjust_time;
|
||||
u->sink->core->mainloop->time_restart(e, &n);
|
||||
}
|
||||
|
||||
|
|
@ -389,7 +389,7 @@ static void request_memblock(struct output *o, size_t length) {
|
|||
|
||||
/* OK, we need to prepare new data, but only if the sink is actually running */
|
||||
if (pa_atomic_load(&o->userdata->thread_info.running))
|
||||
pa_asyncmsgq_send(o->outq, PA_MSGOBJECT(o->userdata->sink), SINK_MESSAGE_NEED, o, length, NULL);
|
||||
pa_asyncmsgq_send(o->outq, PA_MSGOBJECT(o->userdata->sink), SINK_MESSAGE_NEED, o, (int64_t) length, NULL);
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
|
|
@ -489,7 +489,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
|
|||
pa_sink_input_assert_ref(i);
|
||||
pa_assert(o = i->userdata);
|
||||
|
||||
pa_module_unload_request(o->userdata->module);
|
||||
pa_module_unload_request(o->userdata->module, TRUE);
|
||||
output_free(o);
|
||||
}
|
||||
|
||||
|
|
@ -1159,7 +1159,7 @@ int pa__init(pa_module*m) {
|
|||
if (u->adjust_time > 0) {
|
||||
struct timeval tv;
|
||||
pa_gettimeofday(&tv);
|
||||
tv.tv_sec += u->adjust_time;
|
||||
tv.tv_sec += (time_t) u->adjust_time;
|
||||
u->time_event = m->core->mainloop->time_new(m->core->mainloop, &tv, time_callback, u);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulse/util.h>
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/module.h>
|
||||
|
|
@ -41,8 +42,6 @@ PA_MODULE_DESCRIPTION("Automatically restore the default sink and source");
|
|||
PA_MODULE_VERSION(PACKAGE_VERSION);
|
||||
PA_MODULE_LOAD_ONCE(TRUE);
|
||||
|
||||
#define DEFAULT_SINK_FILE "default-sink"
|
||||
#define DEFAULT_SOURCE_FILE "default-source"
|
||||
#define DEFAULT_SAVE_INTERVAL 5
|
||||
|
||||
struct userdata {
|
||||
|
|
@ -161,10 +160,10 @@ int pa__init(pa_module *m) {
|
|||
m->userdata = u = pa_xnew0(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
|
||||
if (!(u->sink_filename = pa_state_path(DEFAULT_SINK_FILE)))
|
||||
if (!(u->sink_filename = pa_state_path("default-sink", TRUE)))
|
||||
goto fail;
|
||||
|
||||
if (!(u->source_filename = pa_state_path(DEFAULT_SOURCE_FILE)))
|
||||
if (!(u->source_filename = pa_state_path("default-source", TRUE)))
|
||||
goto fail;
|
||||
|
||||
load(u);
|
||||
|
|
|
|||
|
|
@ -236,16 +236,16 @@ int pa__init(pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
#if HAVE_ALSA
|
||||
#ifdef HAVE_ALSA
|
||||
if ((n = detect_alsa(m->core, just_one)) <= 0)
|
||||
#endif
|
||||
#if HAVE_OSS
|
||||
if ((n = detect_oss(m->core, just_one)) <= 0)
|
||||
#endif
|
||||
#if HAVE_SOLARIS
|
||||
#ifdef HAVE_SOLARIS
|
||||
if ((n = detect_solaris(m->core, just_one)) <= 0)
|
||||
#endif
|
||||
#if OS_IS_WIN32
|
||||
#ifdef OS_IS_WIN32
|
||||
if ((n = detect_waveout(m->core, just_one)) <= 0)
|
||||
#endif
|
||||
{
|
||||
|
|
@ -256,7 +256,7 @@ int pa__init(pa_module*m) {
|
|||
pa_log_info("loaded %i modules.", n);
|
||||
|
||||
/* We were successful and can unload ourselves now. */
|
||||
pa_module_unload_request(m);
|
||||
pa_module_unload_request(m, TRUE);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2006 Lennart Poettering
|
||||
Copyright 2006-2008 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
|
||||
|
|
@ -64,6 +64,7 @@ static const char* const valid_modargs[] = {
|
|||
|
||||
struct userdata {
|
||||
pa_core *core;
|
||||
pa_module *module;
|
||||
pa_subscription *subscription;
|
||||
pa_hook_slot
|
||||
*sink_fixate_hook_slot,
|
||||
|
|
@ -76,6 +77,7 @@ struct userdata {
|
|||
};
|
||||
|
||||
struct entry {
|
||||
pa_channel_map channel_map;
|
||||
pa_cvolume volume;
|
||||
pa_bool_t muted:1;
|
||||
};
|
||||
|
|
@ -104,7 +106,7 @@ static struct entry* read_entry(struct userdata *u, char *name) {
|
|||
pa_assert(name);
|
||||
|
||||
key.dptr = name;
|
||||
key.dsize = strlen(name);
|
||||
key.dsize = (int) strlen(name);
|
||||
|
||||
data = gdbm_fetch(u->gdbm_file, key);
|
||||
|
||||
|
|
@ -123,6 +125,16 @@ static struct entry* read_entry(struct userdata *u, char *name) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!(pa_channel_map_valid(&e->channel_map))) {
|
||||
pa_log_warn("Invalid channel map stored in database for device %s", name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (e->volume.channels != e->channel_map.channels) {
|
||||
pa_log_warn("Volume and channel map don't match in database entry for device %s", name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return e;
|
||||
|
||||
fail:
|
||||
|
|
@ -131,6 +143,17 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void trigger_save(struct userdata *u) {
|
||||
struct timeval tv;
|
||||
|
||||
if (u->save_time_event)
|
||||
return;
|
||||
|
||||
pa_gettimeofday(&tv);
|
||||
tv.tv_sec += SAVE_INTERVAL;
|
||||
u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u);
|
||||
}
|
||||
|
||||
static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
struct entry entry, *old;
|
||||
|
|
@ -146,6 +169,8 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE))
|
||||
return;
|
||||
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
|
||||
if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK) {
|
||||
pa_sink *sink;
|
||||
|
||||
|
|
@ -153,8 +178,9 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
return;
|
||||
|
||||
name = pa_sprintf_malloc("sink:%s", sink->name);
|
||||
entry.volume = *pa_sink_get_volume(sink);
|
||||
entry.muted = pa_sink_get_mute(sink);
|
||||
entry.channel_map = sink->channel_map;
|
||||
entry.volume = *pa_sink_get_volume(sink, FALSE);
|
||||
entry.muted = pa_sink_get_mute(sink, FALSE);
|
||||
|
||||
} else {
|
||||
pa_source *source;
|
||||
|
|
@ -165,13 +191,14 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
return;
|
||||
|
||||
name = pa_sprintf_malloc("source:%s", source->name);
|
||||
entry.volume = *pa_source_get_volume(source);
|
||||
entry.muted = pa_source_get_mute(source);
|
||||
entry.channel_map = source->channel_map;
|
||||
entry.volume = *pa_source_get_volume(source, FALSE);
|
||||
entry.muted = pa_source_get_mute(source, FALSE);
|
||||
}
|
||||
|
||||
if ((old = read_entry(u, name))) {
|
||||
|
||||
if (pa_cvolume_equal(&old->volume, &entry.volume) &&
|
||||
if (pa_cvolume_equal(pa_cvolume_remap(&old->volume, &old->channel_map, &entry.channel_map), &entry.volume) &&
|
||||
!old->muted == !entry.muted) {
|
||||
|
||||
pa_xfree(old);
|
||||
|
|
@ -183,7 +210,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
}
|
||||
|
||||
key.dptr = name;
|
||||
key.dsize = strlen(name);
|
||||
key.dsize = (int) strlen(name);
|
||||
|
||||
data.dptr = (void*) &entry;
|
||||
data.dsize = sizeof(entry);
|
||||
|
|
@ -192,14 +219,9 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
|
||||
gdbm_store(u->gdbm_file, key, data, GDBM_REPLACE);
|
||||
|
||||
if (!u->save_time_event) {
|
||||
struct timeval tv;
|
||||
pa_gettimeofday(&tv);
|
||||
tv.tv_sec += SAVE_INTERVAL;
|
||||
u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u);
|
||||
}
|
||||
|
||||
pa_xfree(name);
|
||||
|
||||
trigger_save(u);
|
||||
}
|
||||
|
||||
static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *new_data, struct userdata *u) {
|
||||
|
|
@ -212,11 +234,9 @@ static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *
|
|||
|
||||
if ((e = read_entry(u, name))) {
|
||||
|
||||
if (u->restore_volume &&
|
||||
e->volume.channels == new_data->sample_spec.channels) {
|
||||
|
||||
if (u->restore_volume) {
|
||||
pa_log_info("Restoring volume for sink %s.", new_data->name);
|
||||
pa_sink_new_data_set_volume(new_data, &e->volume);
|
||||
pa_sink_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map));
|
||||
}
|
||||
|
||||
if (u->restore_muted) {
|
||||
|
|
@ -242,11 +262,9 @@ static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_da
|
|||
|
||||
if ((e = read_entry(u, name))) {
|
||||
|
||||
if (u->restore_volume &&
|
||||
e->volume.channels == new_data->sample_spec.channels) {
|
||||
|
||||
if (u->restore_volume) {
|
||||
pa_log_info("Restoring volume for source %s.", new_data->name);
|
||||
pa_source_new_data_set_volume(new_data, &e->volume);
|
||||
pa_source_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map));
|
||||
}
|
||||
|
||||
if (u->restore_muted) {
|
||||
|
|
@ -266,7 +284,6 @@ int pa__init(pa_module*m) {
|
|||
pa_modargs *ma = NULL;
|
||||
struct userdata *u;
|
||||
char *fname, *fn;
|
||||
char hn[256];
|
||||
pa_sink *sink;
|
||||
pa_source *source;
|
||||
uint32_t idx;
|
||||
|
|
@ -290,9 +307,11 @@ int pa__init(pa_module*m) {
|
|||
|
||||
m->userdata = u = pa_xnew(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
u->save_time_event = NULL;
|
||||
u->restore_volume = restore_volume;
|
||||
u->restore_muted = restore_muted;
|
||||
u->gdbm_file = NULL;
|
||||
|
||||
u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK|PA_SUBSCRIPTION_MASK_SOURCE, subscribe_callback, u);
|
||||
|
||||
|
|
@ -301,11 +320,12 @@ int pa__init(pa_module*m) {
|
|||
u->source_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) source_fixate_hook_callback, u);
|
||||
}
|
||||
|
||||
if (!pa_get_host_name(hn, sizeof(hn)))
|
||||
goto fail;
|
||||
/* We include the host identifier in the file name because gdbm
|
||||
* files are CPU dependant, and we don't want things to go wrong
|
||||
* if we are on a multiarch system. */
|
||||
|
||||
fn = pa_sprintf_malloc("device-volumes.%s."CANONICAL_HOST".gdbm", hn);
|
||||
fname = pa_state_path(fn);
|
||||
fn = pa_sprintf_malloc("device-volumes."CANONICAL_HOST".gdbm");
|
||||
fname = pa_state_path(fn, TRUE);
|
||||
pa_xfree(fn);
|
||||
|
||||
if (!fname)
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ int pa__init(pa_module*m) {
|
|||
|
||||
pa_assert_se(pa_close(fd) == 0);
|
||||
|
||||
pa_module_unload_request(m);
|
||||
pa_module_unload_request(m, TRUE);
|
||||
|
||||
ret = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -62,10 +62,10 @@ int pa__init(pa_module*m) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if (kill(pid, SIGUSR1) < 0)
|
||||
if (kill((pid_t) pid, SIGUSR1) < 0)
|
||||
pa_log_warn("kill(%u) failed: %s", pid, pa_cstrerror(errno));
|
||||
|
||||
pa_module_unload_request(m);
|
||||
pa_module_unload_request(m, TRUE);
|
||||
|
||||
ret = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
|
|||
pa_usec_t w, r;
|
||||
|
||||
r = pa_smoother_get(u->smoother, pa_rtclock_usec());
|
||||
w = pa_bytes_to_usec(u->offset + u->memchunk.length, &u->sink->sample_spec);
|
||||
w = pa_bytes_to_usec((uint64_t) u->offset + u->memchunk.length, &u->sink->sample_spec);
|
||||
|
||||
*((pa_usec_t*) data) = w > r ? w - r : 0;
|
||||
break;
|
||||
|
|
@ -250,8 +250,8 @@ static void thread_func(void *userdata) {
|
|||
} else {
|
||||
u->offset += l;
|
||||
|
||||
u->memchunk.index += l;
|
||||
u->memchunk.length -= l;
|
||||
u->memchunk.index += (size_t) l;
|
||||
u->memchunk.length -= (size_t) l;
|
||||
|
||||
if (u->memchunk.length <= 0) {
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
|
|
@ -285,7 +285,7 @@ static void thread_func(void *userdata) {
|
|||
}
|
||||
#endif
|
||||
|
||||
usec = pa_bytes_to_usec(n, &u->sink->sample_spec);
|
||||
usec = pa_bytes_to_usec((uint64_t) n, &u->sink->sample_spec);
|
||||
|
||||
if (usec > u->latency)
|
||||
usec -= u->latency;
|
||||
|
|
@ -296,7 +296,7 @@ static void thread_func(void *userdata) {
|
|||
}
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
|
||||
pollfd->events = (short) (PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0);
|
||||
}
|
||||
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||
|
|
@ -342,7 +342,7 @@ static int do_write(struct userdata *u) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
u->write_index += r;
|
||||
u->write_index += (size_t) r;
|
||||
pa_assert(u->write_index <= u->write_length);
|
||||
|
||||
if (u->write_index == u->write_length) {
|
||||
|
|
@ -458,7 +458,7 @@ static int do_read(struct userdata *u) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
u->read_index += r;
|
||||
u->read_index += (size_t) r;
|
||||
pa_assert(u->read_index <= u->read_length);
|
||||
|
||||
if (u->read_index == u->read_length)
|
||||
|
|
@ -468,7 +468,7 @@ static int do_read(struct userdata *u) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
|
||||
static void io_callback(pa_iochannel *io, void*userdata) {
|
||||
struct userdata *u = userdata;
|
||||
pa_assert(u);
|
||||
|
||||
|
|
@ -479,11 +479,11 @@ static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
|
|||
u->io = NULL;
|
||||
}
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, void *userdata) {
|
||||
static void on_connection(pa_socket_client *c, pa_iochannel*io, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
|
||||
pa_socket_client_unref(u->client);
|
||||
|
|
@ -491,7 +491,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, vo
|
|||
|
||||
if (!io) {
|
||||
pa_log("Connection failed: %s", pa_cstrerror(errno));
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -545,7 +545,7 @@ int pa__init(pa_module*m) {
|
|||
u->format =
|
||||
(ss.format == PA_SAMPLE_U8 ? ESD_BITS8 : ESD_BITS16) |
|
||||
(ss.channels == 2 ? ESD_STEREO : ESD_MONO);
|
||||
u->rate = ss.rate;
|
||||
u->rate = (int32_t) ss.rate;
|
||||
u->block_size = pa_usec_to_bytes(PA_USEC_PER_SEC/20, &ss);
|
||||
|
||||
u->read_data = u->write_data = NULL;
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ static void hal_device_free(struct device* d) {
|
|||
pa_xfree(d);
|
||||
}
|
||||
|
||||
static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) {
|
||||
static void hal_device_free_cb(void *d, void *data) {
|
||||
hal_device_free(d);
|
||||
}
|
||||
|
||||
|
|
@ -405,7 +405,7 @@ static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, const s
|
|||
dbus_error_init(&error);
|
||||
|
||||
if (!pa_hashmap_get(td->u->devices, td->udi)) {
|
||||
int b;
|
||||
dbus_bool_t b;
|
||||
struct device *d;
|
||||
|
||||
b = libhal_device_exists(td->u->context, td->udi, &error);
|
||||
|
|
@ -433,7 +433,7 @@ static void device_added_cb(LibHalContext *context, const char *udi) {
|
|||
struct timeval tv;
|
||||
struct timerdata *t;
|
||||
struct userdata *u;
|
||||
int good = 0;
|
||||
pa_bool_t good = FALSE;
|
||||
|
||||
pa_assert_se(u = libhal_ctx_get_user_data(context));
|
||||
|
||||
|
|
@ -511,7 +511,7 @@ static void device_removed_cb(LibHalContext* context, const char *udi) {
|
|||
pa_log_debug("Device removed: %s", udi);
|
||||
|
||||
if ((d = pa_hashmap_remove(u->devices, udi))) {
|
||||
pa_module_unload_by_index(u->core, d->index);
|
||||
pa_module_unload_by_index(u->core, d->index, TRUE);
|
||||
hal_device_free(d);
|
||||
}
|
||||
}
|
||||
|
|
@ -749,17 +749,17 @@ int pa__init(pa_module*m) {
|
|||
}
|
||||
|
||||
if ((api = pa_modargs_get_value(ma, "api", NULL))) {
|
||||
int good = 0;
|
||||
pa_bool_t good = FALSE;
|
||||
|
||||
#ifdef HAVE_ALSA
|
||||
if (strcmp(api, CAPABILITY_ALSA) == 0) {
|
||||
good = 1;
|
||||
good = TRUE;
|
||||
api = CAPABILITY_ALSA;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_OSS
|
||||
if (strcmp(api, CAPABILITY_OSS) == 0) {
|
||||
good = 1;
|
||||
good = TRUE;
|
||||
api = CAPABILITY_OSS;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -130,12 +130,12 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
|
|||
void *p;
|
||||
|
||||
pa_assert(offset > 0);
|
||||
nbytes = offset * pa_frame_size(&u->sink->sample_spec);
|
||||
nbytes = (size_t) offset * pa_frame_size(&u->sink->sample_spec);
|
||||
|
||||
pa_sink_render_full(u->sink, nbytes, &chunk);
|
||||
|
||||
p = (uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index;
|
||||
pa_deinterleave(p, u->buffer, u->channels, sizeof(float), offset);
|
||||
pa_deinterleave(p, u->buffer, u->channels, sizeof(float), (unsigned) offset);
|
||||
pa_memblock_release(chunk.memblock);
|
||||
|
||||
pa_memblock_unref(chunk.memblock);
|
||||
|
|
@ -149,10 +149,10 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
|
|||
ss.channels = 1;
|
||||
|
||||
for (c = 0; c < u->channels; c++)
|
||||
pa_silence_memory(u->buffer[c], offset * pa_sample_size(&ss), &ss);
|
||||
pa_silence_memory(u->buffer[c], (size_t) offset * pa_sample_size(&ss), &ss);
|
||||
}
|
||||
|
||||
u->frames_in_buffer = offset;
|
||||
u->frames_in_buffer = (jack_nframes_t) offset;
|
||||
u->saved_frame_time = * (jack_nframes_t*) data;
|
||||
u->saved_frame_time_valid = TRUE;
|
||||
|
||||
|
|
@ -342,7 +342,7 @@ int pa__init(pa_module*m) {
|
|||
|
||||
pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client));
|
||||
|
||||
ss.channels = u->channels = channels;
|
||||
u->channels = ss.channels = (uint8_t) channels;
|
||||
ss.rate = jack_get_sample_rate(u->client);
|
||||
ss.format = PA_SAMPLE_FLOAT32NE;
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
|
|||
if (u->source->thread_info.state == PA_SOURCE_RUNNING)
|
||||
pa_source_post(u->source, chunk);
|
||||
|
||||
u->saved_frame_time = offset;
|
||||
u->saved_frame_time = (jack_nframes_t) offset;
|
||||
u->saved_frame_time_valid = TRUE;
|
||||
|
||||
return 0;
|
||||
|
|
@ -309,7 +309,7 @@ int pa__init(pa_module*m) {
|
|||
|
||||
pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client));
|
||||
|
||||
ss.channels = u->channels = channels;
|
||||
u->channels = ss.channels = (uint8_t) channels;
|
||||
ss.rate = jack_get_sample_rate(u->client);
|
||||
ss.format = PA_SAMPLE_FLOAT32NE;
|
||||
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
|
|||
pa_assert(tchunk.length > 0);
|
||||
|
||||
fs = pa_frame_size(&i->sample_spec);
|
||||
n = PA_MIN(tchunk.length, u->block_size) / fs;
|
||||
n = (unsigned) (PA_MIN(tchunk.length, u->block_size) / fs);
|
||||
|
||||
pa_assert(n > 0);
|
||||
|
||||
|
|
@ -340,7 +340,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
|
|||
pa_sink_input_unref(u->sink_input);
|
||||
u->sink_input = NULL;
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
|
||||
/* Called from IO thread context */
|
||||
|
|
@ -502,9 +502,9 @@ int pa__init(pa_module*m) {
|
|||
|
||||
u->block_size = pa_frame_align(pa_mempool_block_size_max(m->core->mempool), &ss);
|
||||
|
||||
u->input = (LADSPA_Data*) pa_xnew(uint8_t, u->block_size);
|
||||
u->input = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size);
|
||||
if (LADSPA_IS_INPLACE_BROKEN(d->Properties))
|
||||
u->output = (LADSPA_Data*) pa_xnew(uint8_t, u->block_size);
|
||||
u->output = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size);
|
||||
else
|
||||
u->output = u->input;
|
||||
|
||||
|
|
@ -530,8 +530,8 @@ int pa__init(pa_module*m) {
|
|||
char *k;
|
||||
unsigned long h;
|
||||
|
||||
u->control = pa_xnew(LADSPA_Data, n_control);
|
||||
use_default = pa_xnew(pa_bool_t, n_control);
|
||||
u->control = pa_xnew(LADSPA_Data, (unsigned) n_control);
|
||||
use_default = pa_xnew(pa_bool_t, (unsigned) n_control);
|
||||
p = 0;
|
||||
|
||||
while ((k = pa_split(cdata, ",", &state)) && p < n_control) {
|
||||
|
|
@ -552,7 +552,7 @@ int pa__init(pa_module*m) {
|
|||
pa_xfree(k);
|
||||
|
||||
use_default[p] = FALSE;
|
||||
u->control[p++] = f;
|
||||
u->control[p++] = (LADSPA_Data) f;
|
||||
}
|
||||
|
||||
/* The previous loop doesn't take the last control value into account
|
||||
|
|
@ -601,8 +601,8 @@ int pa__init(pa_module*m) {
|
|||
upper = d->PortRangeHints[p].UpperBound;
|
||||
|
||||
if (LADSPA_IS_HINT_SAMPLE_RATE(hint)) {
|
||||
lower *= ss.rate;
|
||||
upper *= ss.rate;
|
||||
lower *= (LADSPA_Data) ss.rate;
|
||||
upper *= (LADSPA_Data) ss.rate;
|
||||
}
|
||||
|
||||
switch (hint & LADSPA_HINT_DEFAULT_MASK) {
|
||||
|
|
@ -617,23 +617,23 @@ int pa__init(pa_module*m) {
|
|||
|
||||
case LADSPA_HINT_DEFAULT_LOW:
|
||||
if (LADSPA_IS_HINT_LOGARITHMIC(hint))
|
||||
u->control[h] = exp(log(lower) * 0.75 + log(upper) * 0.25);
|
||||
u->control[h] = (LADSPA_Data) exp(log(lower) * 0.75 + log(upper) * 0.25);
|
||||
else
|
||||
u->control[h] = lower * 0.75 + upper * 0.25;
|
||||
u->control[h] = (LADSPA_Data) (lower * 0.75 + upper * 0.25);
|
||||
break;
|
||||
|
||||
case LADSPA_HINT_DEFAULT_MIDDLE:
|
||||
if (LADSPA_IS_HINT_LOGARITHMIC(hint))
|
||||
u->control[h] = exp(log(lower) * 0.5 + log(upper) * 0.5);
|
||||
u->control[h] = (LADSPA_Data) exp(log(lower) * 0.5 + log(upper) * 0.5);
|
||||
else
|
||||
u->control[h] = lower * 0.5 + upper * 0.5;
|
||||
u->control[h] = (LADSPA_Data) (lower * 0.5 + upper * 0.5);
|
||||
break;
|
||||
|
||||
case LADSPA_HINT_DEFAULT_HIGH:
|
||||
if (LADSPA_IS_HINT_LOGARITHMIC(hint))
|
||||
u->control[h] = exp(log(lower) * 0.25 + log(upper) * 0.75);
|
||||
u->control[h] = (LADSPA_Data) exp(log(lower) * 0.25 + log(upper) * 0.75);
|
||||
else
|
||||
u->control[h] = lower * 0.25 + upper * 0.75;
|
||||
u->control[h] = (LADSPA_Data) (lower * 0.25 + upper * 0.75);
|
||||
break;
|
||||
|
||||
case LADSPA_HINT_DEFAULT_0:
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ struct userdata {
|
|||
|
||||
static int lirc_in_use = 0;
|
||||
|
||||
static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) {
|
||||
static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) {
|
||||
struct userdata *u = userdata;
|
||||
char *name = NULL, *code = NULL;
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
|
|||
pa_log("Failed to get sink '%s'", u->sink_name);
|
||||
else {
|
||||
int i;
|
||||
pa_cvolume cv = *pa_sink_get_volume(s);
|
||||
pa_cvolume cv = *pa_sink_get_volume(s, FALSE);
|
||||
|
||||
#define DELTA (PA_VOLUME_NORM/20)
|
||||
|
||||
|
|
@ -159,7 +159,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
|
|||
|
||||
case MUTE_TOGGLE:
|
||||
|
||||
pa_sink_set_mute(s, !pa_sink_get_mute(s));
|
||||
pa_sink_set_mute(s, !pa_sink_get_mute(s, FALSE));
|
||||
break;
|
||||
|
||||
case INVALID:
|
||||
|
|
@ -178,7 +178,7 @@ fail:
|
|||
u->module->core->mainloop->io_free(u->io);
|
||||
u->io = NULL;
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
|
||||
pa_xfree(code);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ struct userdata {
|
|||
pa_module *module;
|
||||
};
|
||||
|
||||
static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) {
|
||||
static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) {
|
||||
struct userdata *u = userdata;
|
||||
|
||||
pa_assert(io);
|
||||
|
|
@ -113,7 +113,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
|
|||
pa_log("Failed to get sink '%s'", u->sink_name);
|
||||
else {
|
||||
int i;
|
||||
pa_cvolume cv = *pa_sink_get_volume(s);
|
||||
pa_cvolume cv = *pa_sink_get_volume(s, FALSE);
|
||||
|
||||
#define DELTA (PA_VOLUME_NORM/20)
|
||||
|
||||
|
|
@ -142,7 +142,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
|
|||
|
||||
case MUTE_TOGGLE:
|
||||
|
||||
pa_sink_set_mute(s, !pa_sink_get_mute(s));
|
||||
pa_sink_set_mute(s, !pa_sink_get_mute(s, FALSE));
|
||||
break;
|
||||
|
||||
case INVALID:
|
||||
|
|
@ -159,7 +159,7 @@ fail:
|
|||
u->module->core->mainloop->io_free(u->io);
|
||||
u->io = NULL;
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
|
||||
#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
|
||||
|
|
|
|||
|
|
@ -48,7 +48,8 @@ static const char* const valid_modargs[] = {
|
|||
int pa__init(pa_module*m) {
|
||||
pa_iochannel *io;
|
||||
pa_modargs *ma;
|
||||
int fd, r = -1;
|
||||
int32_t fd;
|
||||
int r = -1;
|
||||
pa_native_options *options = NULL;
|
||||
|
||||
pa_assert(m);
|
||||
|
|
@ -63,18 +64,16 @@ int pa__init(pa_module*m) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
m->userdata = pa_native_protocol_get(m->core);
|
||||
|
||||
io = pa_iochannel_new(m->core->mainloop, fd, fd);
|
||||
|
||||
options = pa_native_options_new();
|
||||
options->module = m;
|
||||
options->auth_anonymous = TRUE;
|
||||
|
||||
io = pa_iochannel_new(m->core->mainloop, fd, fd);
|
||||
|
||||
m->userdata = pa_native_protocol_get(m->core);
|
||||
|
||||
pa_native_protocol_connect(m->userdata, io, options);
|
||||
|
||||
pa_native_options_unref(options);
|
||||
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ static int mmap_write(struct userdata *u) {
|
|||
u->out_mmap_saved_nfrags = 0;
|
||||
|
||||
if (info.blocks > 0)
|
||||
mmap_fill_memblocks(u, info.blocks);
|
||||
mmap_fill_memblocks(u, (unsigned) info.blocks);
|
||||
|
||||
return info.blocks;
|
||||
}
|
||||
|
|
@ -336,7 +336,7 @@ static int mmap_read(struct userdata *u) {
|
|||
u->in_mmap_saved_nfrags = 0;
|
||||
|
||||
if (info.blocks > 0) {
|
||||
mmap_post_memblocks(u, info.blocks);
|
||||
mmap_post_memblocks(u, (unsigned) info.blocks);
|
||||
mmap_clear_memblocks(u, u->in_nfrags/2);
|
||||
}
|
||||
|
||||
|
|
@ -356,12 +356,12 @@ static pa_usec_t mmap_sink_get_latency(struct userdata *u) {
|
|||
|
||||
u->out_mmap_saved_nfrags += info.blocks;
|
||||
|
||||
bpos = ((u->out_mmap_current + u->out_mmap_saved_nfrags) * u->out_fragment_size) % u->out_hwbuf_size;
|
||||
bpos = ((u->out_mmap_current + (unsigned) u->out_mmap_saved_nfrags) * u->out_fragment_size) % u->out_hwbuf_size;
|
||||
|
||||
if (bpos <= (size_t) info.ptr)
|
||||
n = u->out_hwbuf_size - (info.ptr - bpos);
|
||||
n = u->out_hwbuf_size - ((size_t) info.ptr - bpos);
|
||||
else
|
||||
n = bpos - info.ptr;
|
||||
n = bpos - (size_t) info.ptr;
|
||||
|
||||
/* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->out_fragment_size, u->out_fragments); */
|
||||
|
||||
|
|
@ -380,12 +380,12 @@ static pa_usec_t mmap_source_get_latency(struct userdata *u) {
|
|||
}
|
||||
|
||||
u->in_mmap_saved_nfrags += info.blocks;
|
||||
bpos = ((u->in_mmap_current + u->in_mmap_saved_nfrags) * u->in_fragment_size) % u->in_hwbuf_size;
|
||||
bpos = ((u->in_mmap_current + (unsigned) u->in_mmap_saved_nfrags) * u->in_fragment_size) % u->in_hwbuf_size;
|
||||
|
||||
if (bpos <= (size_t) info.ptr)
|
||||
n = info.ptr - bpos;
|
||||
n = (size_t) info.ptr - bpos;
|
||||
else
|
||||
n = u->in_hwbuf_size - bpos + info.ptr;
|
||||
n = u->in_hwbuf_size - bpos + (size_t) info.ptr;
|
||||
|
||||
/* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->in_fragment_size, u->in_fragments); */
|
||||
|
||||
|
|
@ -404,7 +404,7 @@ static pa_usec_t io_sink_get_latency(struct userdata *u) {
|
|||
pa_log_info("Device doesn't support SNDCTL_DSP_GETODELAY: %s", pa_cstrerror(errno));
|
||||
u->use_getodelay = 0;
|
||||
} else
|
||||
r = pa_bytes_to_usec(arg, &u->sink->sample_spec);
|
||||
r = pa_bytes_to_usec((size_t) arg, &u->sink->sample_spec);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -415,7 +415,7 @@ static pa_usec_t io_sink_get_latency(struct userdata *u) {
|
|||
pa_log_info("Device doesn't support SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno));
|
||||
u->use_getospace = 0;
|
||||
} else
|
||||
r = pa_bytes_to_usec(info.bytes, &u->sink->sample_spec);
|
||||
r = pa_bytes_to_usec((size_t) info.bytes, &u->sink->sample_spec);
|
||||
}
|
||||
|
||||
if (u->memchunk.memblock)
|
||||
|
|
@ -437,7 +437,7 @@ static pa_usec_t io_source_get_latency(struct userdata *u) {
|
|||
pa_log_info("Device doesn't support SNDCTL_DSP_GETISPACE: %s", pa_cstrerror(errno));
|
||||
u->use_getispace = 0;
|
||||
} else
|
||||
r = pa_bytes_to_usec(info.bytes, &u->source->sample_spec);
|
||||
r = pa_bytes_to_usec((size_t) info.bytes, &u->source->sample_spec);
|
||||
}
|
||||
|
||||
return r;
|
||||
|
|
@ -528,8 +528,9 @@ static int unsuspend(struct userdata *u) {
|
|||
if ((u->fd = pa_oss_open(u->device_name, &m, NULL)) < 0) {
|
||||
pa_log_warn("Resume failed, device busy (%s)", pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (m != u->mode)
|
||||
if (m != u->mode) {
|
||||
pa_log_warn("Resume failed, couldn't open device with original access mode.");
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -859,7 +860,7 @@ static int source_set_volume(pa_source *s) {
|
|||
static void thread_func(void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
int write_type = 0, read_type = 0;
|
||||
unsigned short revents = 0;
|
||||
short revents = 0;
|
||||
|
||||
pa_assert(u);
|
||||
|
||||
|
|
@ -898,7 +899,7 @@ static void thread_func(void *userdata) {
|
|||
ssize_t l;
|
||||
pa_bool_t loop = FALSE, work_done = FALSE;
|
||||
|
||||
l = u->out_fragment_size;
|
||||
l = (ssize_t) u->out_fragment_size;
|
||||
|
||||
if (u->use_getospace) {
|
||||
audio_buf_info info;
|
||||
|
|
@ -919,14 +920,14 @@ static void thread_func(void *userdata) {
|
|||
/* Round down to multiples of the fragment size,
|
||||
* because OSS needs that (at least some versions
|
||||
* do) */
|
||||
l = (l/u->out_fragment_size) * u->out_fragment_size;
|
||||
l = (l/(ssize_t) u->out_fragment_size) * (ssize_t) u->out_fragment_size;
|
||||
|
||||
/* Hmm, so poll() signalled us that we can read
|
||||
* something, but GETOSPACE told us there was nothing?
|
||||
* Hmm, make the best of it, try to read some data, to
|
||||
* avoid spinning forever. */
|
||||
if (l <= 0 && (revents & POLLOUT)) {
|
||||
l = u->out_fragment_size;
|
||||
l = (ssize_t) u->out_fragment_size;
|
||||
loop = FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -935,7 +936,7 @@ static void thread_func(void *userdata) {
|
|||
ssize_t t;
|
||||
|
||||
if (u->memchunk.length <= 0)
|
||||
pa_sink_render(u->sink, l, &u->memchunk);
|
||||
pa_sink_render(u->sink, (size_t) l, &u->memchunk);
|
||||
|
||||
pa_assert(u->memchunk.length > 0);
|
||||
|
||||
|
|
@ -965,8 +966,8 @@ static void thread_func(void *userdata) {
|
|||
|
||||
} else {
|
||||
|
||||
u->memchunk.index += t;
|
||||
u->memchunk.length -= t;
|
||||
u->memchunk.index += (size_t) t;
|
||||
u->memchunk.length -= (size_t) t;
|
||||
|
||||
if (u->memchunk.length <= 0) {
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
|
|
@ -1009,7 +1010,7 @@ static void thread_func(void *userdata) {
|
|||
pa_memchunk memchunk;
|
||||
pa_bool_t loop = FALSE, work_done = FALSE;
|
||||
|
||||
l = u->in_fragment_size;
|
||||
l = (ssize_t) u->in_fragment_size;
|
||||
|
||||
if (u->use_getispace) {
|
||||
audio_buf_info info;
|
||||
|
|
@ -1023,15 +1024,16 @@ static void thread_func(void *userdata) {
|
|||
}
|
||||
}
|
||||
|
||||
l = (l/u->in_fragment_size) * u->in_fragment_size;
|
||||
l = (l/(ssize_t) u->in_fragment_size) * (ssize_t) u->in_fragment_size;
|
||||
|
||||
if (l <= 0 && (revents & POLLIN)) {
|
||||
l = u->in_fragment_size;
|
||||
l = (ssize_t) u->in_fragment_size;
|
||||
loop = FALSE;
|
||||
}
|
||||
|
||||
while (l > 0) {
|
||||
ssize_t t, k;
|
||||
ssize_t t;
|
||||
size_t k;
|
||||
|
||||
pa_assert(l > 0);
|
||||
|
||||
|
|
@ -1039,8 +1041,8 @@ static void thread_func(void *userdata) {
|
|||
|
||||
k = pa_memblock_get_length(memchunk.memblock);
|
||||
|
||||
if (k > l)
|
||||
k = l;
|
||||
if (k > (size_t) l)
|
||||
k = (size_t) l;
|
||||
|
||||
k = (k/u->frame_size)*u->frame_size;
|
||||
|
||||
|
|
@ -1071,7 +1073,7 @@ static void thread_func(void *userdata) {
|
|||
|
||||
} else {
|
||||
memchunk.index = 0;
|
||||
memchunk.length = t;
|
||||
memchunk.length = (size_t) t;
|
||||
|
||||
pa_source_post(u->source, &memchunk);
|
||||
pa_memblock_unref(memchunk.memblock);
|
||||
|
|
@ -1099,9 +1101,9 @@ static void thread_func(void *userdata) {
|
|||
pa_assert(u->fd >= 0);
|
||||
|
||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||
pollfd->events =
|
||||
((u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) ? POLLIN : 0) |
|
||||
((u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) ? POLLOUT : 0);
|
||||
pollfd->events = (short)
|
||||
(((u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) ? POLLIN : 0) |
|
||||
((u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) ? POLLOUT : 0));
|
||||
}
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
|
|
@ -1179,10 +1181,10 @@ int pa__init(pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
nfrags = m->core->default_n_fragments;
|
||||
frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*1000, &ss);
|
||||
nfrags = (int) m->core->default_n_fragments;
|
||||
frag_size = (int) pa_usec_to_bytes(m->core->default_fragment_size_msec*1000, &ss);
|
||||
if (frag_size <= 0)
|
||||
frag_size = pa_frame_size(&ss);
|
||||
frag_size = (int) pa_frame_size(&ss);
|
||||
|
||||
if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) {
|
||||
pa_log("Failed to parse fragments arguments");
|
||||
|
|
@ -1238,8 +1240,8 @@ int pa__init(pa_module*m) {
|
|||
u->mode = mode;
|
||||
u->frame_size = pa_frame_size(&ss);
|
||||
u->device_name = pa_xstrdup(dev);
|
||||
u->in_nfrags = u->out_nfrags = u->nfrags = nfrags;
|
||||
u->out_fragment_size = u->in_fragment_size = u->frag_size = frag_size;
|
||||
u->in_nfrags = u->out_nfrags = (uint32_t) (u->nfrags = nfrags);
|
||||
u->out_fragment_size = u->in_fragment_size = (uint32_t) (u->frag_size = frag_size);
|
||||
u->use_mmap = use_mmap;
|
||||
u->rtpoll = pa_rtpoll_new();
|
||||
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
|
||||
|
|
@ -1248,15 +1250,15 @@ int pa__init(pa_module*m) {
|
|||
|
||||
if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
|
||||
pa_log_info("Input -- %u fragments of size %u.", info.fragstotal, info.fragsize);
|
||||
u->in_fragment_size = info.fragsize;
|
||||
u->in_nfrags = info.fragstotal;
|
||||
u->in_fragment_size = (uint32_t) info.fragsize;
|
||||
u->in_nfrags = (uint32_t) info.fragstotal;
|
||||
u->use_getispace = TRUE;
|
||||
}
|
||||
|
||||
if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) {
|
||||
pa_log_info("Output -- %u fragments of size %u.", info.fragstotal, info.fragsize);
|
||||
u->out_fragment_size = info.fragsize;
|
||||
u->out_nfrags = info.fragstotal;
|
||||
u->out_fragment_size = (uint32_t) info.fragsize;
|
||||
u->out_nfrags = (uint32_t) info.fragstotal;
|
||||
u->use_getospace = TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,8 +145,8 @@ static int process_render(struct userdata *u) {
|
|||
|
||||
} else {
|
||||
|
||||
u->memchunk.index += l;
|
||||
u->memchunk.length -= l;
|
||||
u->memchunk.index += (size_t) l;
|
||||
u->memchunk.length -= (size_t) l;
|
||||
|
||||
if (u->memchunk.length <= 0) {
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
|
|
@ -189,7 +189,7 @@ static void thread_func(void *userdata) {
|
|||
}
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
pollfd->events = u->sink->thread_info.state == PA_SINK_RUNNING ? POLLOUT : 0;
|
||||
pollfd->events = (short) (u->sink->thread_info.state == PA_SINK_RUNNING ? POLLOUT : 0);
|
||||
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -135,9 +135,9 @@ static void thread_func(void *userdata) {
|
|||
|
||||
} else {
|
||||
|
||||
u->memchunk.length = l;
|
||||
u->memchunk.length = (size_t) l;
|
||||
pa_source_post(u->source, &u->memchunk);
|
||||
u->memchunk.index += l;
|
||||
u->memchunk.index += (size_t) l;
|
||||
|
||||
if (u->memchunk.index >= pa_memblock_get_length(u->memchunk.memblock)) {
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
|
|
@ -149,7 +149,7 @@ static void thread_func(void *userdata) {
|
|||
}
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
pollfd->events = u->source->thread_info.state == PA_SOURCE_RUNNING ? POLLIN : 0;
|
||||
pollfd->events = (short) (u->source->thread_info.state == PA_SOURCE_RUNNING ? POLLIN : 0);
|
||||
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ int pa__init(pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
u = pa_xnew0(struct userdata, 1);
|
||||
m->userdata = u = pa_xnew0(struct userdata, 1);
|
||||
u->module = m;
|
||||
|
||||
#if defined(USE_PROTOCOL_SIMPLE)
|
||||
|
|
@ -299,11 +299,11 @@ int pa__init(pa_module*m) {
|
|||
listen_on = pa_modargs_get_value(ma, "listen", NULL);
|
||||
|
||||
if (listen_on) {
|
||||
u->socket_server_ipv6 = pa_socket_server_new_ipv6_string(m->core->mainloop, listen_on, port, TCPWRAP_SERVICE);
|
||||
u->socket_server_ipv4 = pa_socket_server_new_ipv4_string(m->core->mainloop, listen_on, port, TCPWRAP_SERVICE);
|
||||
u->socket_server_ipv6 = pa_socket_server_new_ipv6_string(m->core->mainloop, listen_on, (uint16_t) port, TCPWRAP_SERVICE);
|
||||
u->socket_server_ipv4 = pa_socket_server_new_ipv4_string(m->core->mainloop, listen_on, (uint16_t) port, TCPWRAP_SERVICE);
|
||||
} else {
|
||||
u->socket_server_ipv6 = pa_socket_server_new_ipv6_any(m->core->mainloop, port, TCPWRAP_SERVICE);
|
||||
u->socket_server_ipv4 = pa_socket_server_new_ipv4_any(m->core->mainloop, port, TCPWRAP_SERVICE);
|
||||
u->socket_server_ipv6 = pa_socket_server_new_ipv6_any(m->core->mainloop, (uint16_t) port, TCPWRAP_SERVICE);
|
||||
u->socket_server_ipv4 = pa_socket_server_new_ipv4_any(m->core->mainloop, (uint16_t) port, TCPWRAP_SERVICE);
|
||||
}
|
||||
|
||||
if (!u->socket_server_ipv4 && !u->socket_server_ipv6)
|
||||
|
|
@ -327,7 +327,7 @@ int pa__init(pa_module*m) {
|
|||
/* This socket doesn't reside in our own runtime dir but in
|
||||
* /tmp/.esd/, hence we have to create the dir first */
|
||||
|
||||
if (pa_make_secure_parent_dir(u->socket_path, pa_in_system_mode() ? 0755 : 0700, (uid_t)-1, (gid_t)-1) < 0) {
|
||||
if (pa_make_secure_parent_dir(u->socket_path, pa_in_system_mode() ? 0755U : 0700U, (uid_t)-1, (gid_t)-1) < 0) {
|
||||
pa_log("Failed to create socket directory '%s': %s\n", u->socket_path, pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -368,8 +368,6 @@ int pa__init(pa_module*m) {
|
|||
# endif
|
||||
#endif
|
||||
|
||||
m->userdata = u;
|
||||
|
||||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
|
|
@ -390,7 +388,8 @@ void pa__done(pa_module*m) {
|
|||
|
||||
pa_assert(m);
|
||||
|
||||
u = m->userdata;
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
#if defined(USE_PROTOCOL_SIMPLE)
|
||||
if (u->simple_protocol) {
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
|
|||
pa_sink_input_unref(u->sink_input);
|
||||
u->sink_input = NULL;
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
|
||||
/* Called from IO thread context */
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
|
|||
pa_sink_input_unref(u->sink_input);
|
||||
u->sink_input = NULL;
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
|
||||
/* Called from IO thread context */
|
||||
|
|
@ -116,13 +116,13 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s
|
|||
pa_sink_input_request_rewind(i, 0, FALSE, TRUE);
|
||||
}
|
||||
|
||||
static void calc_sine(float *f, size_t l, float freq) {
|
||||
static void calc_sine(float *f, size_t l, double freq) {
|
||||
size_t i;
|
||||
|
||||
l /= sizeof(float);
|
||||
|
||||
for (i = 0; i < l; i++)
|
||||
f[i] = (float) sin((double) i/l*M_PI*2*freq)/2;
|
||||
f[i] = (float) sin((double) i/(double)l*M_PI*2*freq)/2;
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
|
|
@ -163,7 +163,7 @@ int pa__init(pa_module*m) {
|
|||
|
||||
u->memblock = pa_memblock_new(m->core->mempool, pa_bytes_per_second(&ss));
|
||||
p = pa_memblock_acquire(u->memblock);
|
||||
calc_sine(p, pa_memblock_get_length(u->memblock), frequency);
|
||||
calc_sine(p, pa_memblock_get_length(u->memblock), (double) frequency);
|
||||
pa_memblock_release(u->memblock);
|
||||
|
||||
pa_sink_input_new_data_init(&data);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@
|
|||
#include <pulsecore/sink-input.h>
|
||||
#include <pulsecore/source-output.h>
|
||||
#include <pulsecore/namereg.h>
|
||||
#include <pulsecore/protocol-native.h>
|
||||
#include <pulsecore/pstream.h>
|
||||
#include <pulsecore/pstream-util.h>
|
||||
|
||||
#include "module-stream-restore-symdef.h"
|
||||
|
||||
|
|
@ -65,25 +68,41 @@ static const char* const valid_modargs[] = {
|
|||
|
||||
struct userdata {
|
||||
pa_core *core;
|
||||
pa_module *module;
|
||||
pa_subscription *subscription;
|
||||
pa_hook_slot
|
||||
*sink_input_new_hook_slot,
|
||||
*sink_input_fixate_hook_slot,
|
||||
*source_output_new_hook_slot;
|
||||
*source_output_new_hook_slot,
|
||||
*connection_unlink_hook_slot;
|
||||
pa_time_event *save_time_event;
|
||||
GDBM_FILE gdbm_file;
|
||||
|
||||
pa_bool_t restore_device:1;
|
||||
pa_bool_t restore_volume:1;
|
||||
pa_bool_t restore_muted:1;
|
||||
|
||||
pa_native_protocol *protocol;
|
||||
pa_idxset *subscribed;
|
||||
};
|
||||
|
||||
struct entry {
|
||||
pa_cvolume volume;
|
||||
char device[PA_NAME_MAX];
|
||||
pa_channel_map channel_map;
|
||||
pa_cvolume volume;
|
||||
pa_bool_t muted:1;
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
SUBCOMMAND_TEST,
|
||||
SUBCOMMAND_READ,
|
||||
SUBCOMMAND_WRITE,
|
||||
SUBCOMMAND_DELETE,
|
||||
SUBCOMMAND_SUBSCRIBE,
|
||||
SUBCOMMAND_EVENT
|
||||
};
|
||||
|
||||
static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
|
||||
|
|
@ -126,7 +145,7 @@ static struct entry* read_entry(struct userdata *u, char *name) {
|
|||
pa_assert(name);
|
||||
|
||||
key.dptr = name;
|
||||
key.dsize = strlen(name);
|
||||
key.dsize = (int) strlen(name);
|
||||
|
||||
data = gdbm_fetch(u->gdbm_file, key);
|
||||
|
||||
|
|
@ -146,7 +165,17 @@ static struct entry* read_entry(struct userdata *u, char *name) {
|
|||
}
|
||||
|
||||
if (!(pa_cvolume_valid(&e->volume))) {
|
||||
pa_log_warn("Invalid volume stored in database for device %s", name);
|
||||
pa_log_warn("Invalid volume stored in database for stream %s", name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(pa_channel_map_valid(&e->channel_map))) {
|
||||
pa_log_warn("Invalid channel map stored in database for stream %s", name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (e->volume.channels != e->channel_map.channels) {
|
||||
pa_log_warn("Volume and channel map don't match in database entry for stream %s", name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -158,6 +187,32 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void trigger_save(struct userdata *u) {
|
||||
struct timeval tv;
|
||||
pa_native_connection *c;
|
||||
uint32_t idx;
|
||||
|
||||
for (c = pa_idxset_first(u->subscribed, &idx); c; c = pa_idxset_next(u->subscribed, &idx)) {
|
||||
pa_tagstruct *t;
|
||||
|
||||
t = pa_tagstruct_new(NULL, 0);
|
||||
pa_tagstruct_putu32(t, PA_COMMAND_EXTENSION);
|
||||
pa_tagstruct_putu32(t, 0);
|
||||
pa_tagstruct_putu32(t, u->module->index);
|
||||
pa_tagstruct_puts(t, u->module->name);
|
||||
pa_tagstruct_putu32(t, SUBCOMMAND_EVENT);
|
||||
|
||||
pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), t);
|
||||
}
|
||||
|
||||
if (u->save_time_event)
|
||||
return;
|
||||
|
||||
pa_gettimeofday(&tv);
|
||||
tv.tv_sec += SAVE_INTERVAL;
|
||||
u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u);
|
||||
}
|
||||
|
||||
static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
struct entry entry, *old;
|
||||
|
|
@ -173,6 +228,8 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE))
|
||||
return;
|
||||
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
|
||||
if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
|
||||
pa_sink_input *sink_input;
|
||||
|
||||
|
|
@ -182,6 +239,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
if (!(name = get_name(sink_input->proplist, "sink-input")))
|
||||
return;
|
||||
|
||||
entry.channel_map = sink_input->channel_map;
|
||||
entry.volume = *pa_sink_input_get_volume(sink_input);
|
||||
entry.muted = pa_sink_input_get_mute(sink_input);
|
||||
pa_strlcpy(entry.device, sink_input->sink->name, sizeof(entry.device));
|
||||
|
|
@ -197,15 +255,16 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
if (!(name = get_name(source_output->proplist, "source-output")))
|
||||
return;
|
||||
|
||||
memset(&entry.volume, 0, sizeof(entry.volume));
|
||||
entry.muted = FALSE;
|
||||
|
||||
/* The following fields are filled in to make the entry valid
|
||||
* according to read_entry(). They are otherwise useless */
|
||||
entry.channel_map = source_output->channel_map;
|
||||
pa_cvolume_reset(&entry.volume, entry.channel_map.channels);
|
||||
pa_strlcpy(entry.device, source_output->source->name, sizeof(entry.device));
|
||||
}
|
||||
|
||||
if ((old = read_entry(u, name))) {
|
||||
|
||||
if (pa_cvolume_equal(&old->volume, &entry.volume) &&
|
||||
if (pa_cvolume_equal(pa_cvolume_remap(&old->volume, &old->channel_map, &entry.channel_map), &entry.volume) &&
|
||||
!old->muted == !entry.muted &&
|
||||
strcmp(old->device, entry.device) == 0) {
|
||||
|
||||
|
|
@ -218,7 +277,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
}
|
||||
|
||||
key.dptr = name;
|
||||
key.dsize = strlen(name);
|
||||
key.dsize = (int) strlen(name);
|
||||
|
||||
data.dptr = (void*) &entry;
|
||||
data.dsize = sizeof(entry);
|
||||
|
|
@ -227,14 +286,9 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
|
||||
gdbm_store(u->gdbm_file, key, data, GDBM_REPLACE);
|
||||
|
||||
if (!u->save_time_event) {
|
||||
struct timeval tv;
|
||||
pa_gettimeofday(&tv);
|
||||
tv.tv_sec += SAVE_INTERVAL;
|
||||
u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u);
|
||||
}
|
||||
|
||||
pa_xfree(name);
|
||||
|
||||
trigger_save(u);
|
||||
}
|
||||
|
||||
static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
|
||||
|
|
@ -250,11 +304,13 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n
|
|||
pa_sink *s;
|
||||
|
||||
if (u->restore_device &&
|
||||
e->device[0] &&
|
||||
(s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK, TRUE))) {
|
||||
|
||||
pa_log_info("Restoring device for stream %s.", name);
|
||||
new_data->sink = s;
|
||||
if (!new_data->sink) {
|
||||
pa_log_info("Restoring device for stream %s.", name);
|
||||
new_data->sink = s;
|
||||
} else
|
||||
pa_log_info("Not restore device for stream %s, because already set.", name);
|
||||
}
|
||||
|
||||
pa_xfree(e);
|
||||
|
|
@ -276,16 +332,21 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu
|
|||
|
||||
if ((e = read_entry(u, name))) {
|
||||
|
||||
if (u->restore_volume &&
|
||||
e->volume.channels == new_data->sample_spec.channels) {
|
||||
if (u->restore_volume) {
|
||||
|
||||
pa_log_info("Restoring volume for sink input %s.", name);
|
||||
pa_sink_input_new_data_set_volume(new_data, &e->volume);
|
||||
if (!new_data->volume_is_set) {
|
||||
pa_log_info("Restoring volume for sink input %s.", name);
|
||||
pa_sink_input_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map));
|
||||
} else
|
||||
pa_log_debug("Not restoring volume for sink input %s, because already set.", name);
|
||||
}
|
||||
|
||||
if (u->restore_muted) {
|
||||
pa_log_info("Restoring mute state for sink input %s.", name);
|
||||
pa_sink_input_new_data_set_muted(new_data, e->muted);
|
||||
if (!new_data->muted_is_set) {
|
||||
pa_log_info("Restoring mute state for sink input %s.", name);
|
||||
pa_sink_input_new_data_set_muted(new_data, e->muted);
|
||||
} else
|
||||
pa_log_debug("Not restoring mute state for sink input %s, because already set.", name);
|
||||
}
|
||||
|
||||
pa_xfree(e);
|
||||
|
|
@ -309,11 +370,14 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou
|
|||
pa_source *s;
|
||||
|
||||
if (u->restore_device &&
|
||||
e->device[0] &&
|
||||
!new_data->direct_on_input &&
|
||||
(s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE, TRUE))) {
|
||||
|
||||
pa_log_info("Restoring device for stream %s.", name);
|
||||
new_data->source = s;
|
||||
if (!new_data->source) {
|
||||
pa_log_info("Restoring device for stream %s.", name);
|
||||
new_data->source = s;
|
||||
} else
|
||||
pa_log_info("Not restroing device for stream %s, because already set", name);
|
||||
}
|
||||
|
||||
pa_xfree(e);
|
||||
|
|
@ -324,11 +388,300 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou
|
|||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
#define EXT_VERSION 1
|
||||
|
||||
static void clear_db(struct userdata *u) {
|
||||
datum key;
|
||||
|
||||
pa_assert(u);
|
||||
|
||||
key = gdbm_firstkey(u->gdbm_file);
|
||||
while (key.dptr) {
|
||||
datum next_key;
|
||||
next_key = gdbm_nextkey(u->gdbm_file, key);
|
||||
|
||||
gdbm_delete(u->gdbm_file, key);
|
||||
pa_xfree(key.dptr);
|
||||
|
||||
key = next_key;
|
||||
}
|
||||
|
||||
gdbm_reorganize(u->gdbm_file);
|
||||
}
|
||||
|
||||
static void apply_entry(struct userdata *u, const char *name, struct entry *e) {
|
||||
pa_sink_input *si;
|
||||
pa_source_output *so;
|
||||
uint32_t idx;
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(name);
|
||||
pa_assert(e);
|
||||
|
||||
for (si = pa_idxset_first(u->core->sink_inputs, &idx); si; si = pa_idxset_next(u->core->sink_inputs, &idx)) {
|
||||
char *n;
|
||||
pa_sink *s;
|
||||
|
||||
if (!(n = get_name(si->proplist, "sink-input")))
|
||||
continue;
|
||||
|
||||
if (strcmp(name, n)) {
|
||||
pa_xfree(n);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (u->restore_volume) {
|
||||
pa_cvolume v = e->volume;
|
||||
pa_log_info("Restoring volume for sink input %s.", name);
|
||||
pa_sink_input_set_volume(si, pa_cvolume_remap(&v, &e->channel_map, &si->channel_map));
|
||||
}
|
||||
|
||||
if (u->restore_muted) {
|
||||
pa_log_info("Restoring mute state for sink input %s.", name);
|
||||
pa_sink_input_set_mute(si, e->muted);
|
||||
}
|
||||
|
||||
if (u->restore_device &&
|
||||
(s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SOURCE, TRUE))) {
|
||||
|
||||
pa_log_info("Restoring device for stream %s.", name);
|
||||
pa_sink_input_move_to(si, s);
|
||||
}
|
||||
}
|
||||
|
||||
for (so = pa_idxset_first(u->core->source_outputs, &idx); so; so = pa_idxset_next(u->core->source_outputs, &idx)) {
|
||||
char *n;
|
||||
pa_source *s;
|
||||
|
||||
if (!(n = get_name(so->proplist, "source-output")))
|
||||
continue;
|
||||
|
||||
if (strcmp(name, n)) {
|
||||
pa_xfree(n);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (u->restore_device &&
|
||||
(s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SOURCE, TRUE))) {
|
||||
|
||||
pa_log_info("Restoring device for stream %s.", name);
|
||||
pa_source_output_move_to(so, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void dump_database(struct userdata *u) {
|
||||
datum key;
|
||||
|
||||
key = gdbm_firstkey(u->gdbm_file);
|
||||
while (key.dptr) {
|
||||
datum next_key;
|
||||
struct entry *e;
|
||||
char *name;
|
||||
|
||||
next_key = gdbm_nextkey(u->gdbm_file, key);
|
||||
|
||||
name = pa_xstrndup(key.dptr, key.dsize);
|
||||
pa_xfree(key.dptr);
|
||||
|
||||
if ((e = read_entry(u, name))) {
|
||||
char t[256];
|
||||
pa_log("name=%s", name);
|
||||
pa_log("device=%s", e->device);
|
||||
pa_log("channel_map=%s", pa_channel_map_snprint(t, sizeof(t), &e->channel_map));
|
||||
pa_log("volume=%s", pa_cvolume_snprint(t, sizeof(t), &e->volume));
|
||||
pa_log("mute=%s", pa_yes_no(e->muted));
|
||||
pa_xfree(e);
|
||||
}
|
||||
|
||||
pa_xfree(name);
|
||||
|
||||
key = next_key;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
|
||||
struct userdata *u;
|
||||
uint32_t command;
|
||||
pa_tagstruct *reply = NULL;
|
||||
|
||||
pa_assert(p);
|
||||
pa_assert(m);
|
||||
pa_assert(c);
|
||||
pa_assert(t);
|
||||
|
||||
u = m->userdata;
|
||||
|
||||
if (pa_tagstruct_getu32(t, &command) < 0)
|
||||
goto fail;
|
||||
|
||||
reply = pa_tagstruct_new(NULL, 0);
|
||||
pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
|
||||
pa_tagstruct_putu32(reply, tag);
|
||||
|
||||
switch (command) {
|
||||
case SUBCOMMAND_TEST: {
|
||||
if (!pa_tagstruct_eof(t))
|
||||
goto fail;
|
||||
|
||||
pa_tagstruct_putu32(reply, EXT_VERSION);
|
||||
break;
|
||||
}
|
||||
|
||||
case SUBCOMMAND_READ: {
|
||||
datum key;
|
||||
|
||||
if (!pa_tagstruct_eof(t))
|
||||
goto fail;
|
||||
|
||||
key = gdbm_firstkey(u->gdbm_file);
|
||||
while (key.dptr) {
|
||||
datum next_key;
|
||||
struct entry *e;
|
||||
char *name;
|
||||
|
||||
next_key = gdbm_nextkey(u->gdbm_file, key);
|
||||
|
||||
name = pa_xstrndup(key.dptr, (size_t) key.dsize);
|
||||
pa_xfree(key.dptr);
|
||||
|
||||
if ((e = read_entry(u, name))) {
|
||||
pa_tagstruct_puts(reply, name);
|
||||
pa_tagstruct_put_channel_map(reply, &e->channel_map);
|
||||
pa_tagstruct_put_cvolume(reply, &e->volume);
|
||||
pa_tagstruct_puts(reply, e->device);
|
||||
pa_tagstruct_put_boolean(reply, e->muted);
|
||||
|
||||
pa_xfree(e);
|
||||
}
|
||||
|
||||
pa_xfree(name);
|
||||
|
||||
key = next_key;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SUBCOMMAND_WRITE: {
|
||||
uint32_t mode;
|
||||
pa_bool_t apply_immediately = FALSE;
|
||||
|
||||
if (pa_tagstruct_getu32(t, &mode) < 0 ||
|
||||
pa_tagstruct_get_boolean(t, &apply_immediately) < 0)
|
||||
goto fail;
|
||||
|
||||
if (mode != PA_UPDATE_MERGE &&
|
||||
mode != PA_UPDATE_REPLACE &&
|
||||
mode != PA_UPDATE_SET)
|
||||
goto fail;
|
||||
|
||||
if (mode == PA_UPDATE_SET)
|
||||
clear_db(u);
|
||||
|
||||
while (!pa_tagstruct_eof(t)) {
|
||||
const char *name, *device;
|
||||
pa_bool_t muted;
|
||||
struct entry entry;
|
||||
datum key, data;
|
||||
int k;
|
||||
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
|
||||
if (pa_tagstruct_gets(t, &name) < 0 ||
|
||||
pa_tagstruct_get_channel_map(t, &entry.channel_map) ||
|
||||
pa_tagstruct_get_cvolume(t, &entry.volume) < 0 ||
|
||||
pa_tagstruct_gets(t, &device) < 0 ||
|
||||
pa_tagstruct_get_boolean(t, &muted) < 0)
|
||||
goto fail;
|
||||
|
||||
if (entry.channel_map.channels != entry.volume.channels)
|
||||
goto fail;
|
||||
|
||||
entry.muted = muted;
|
||||
pa_strlcpy(entry.device, device, sizeof(entry.device));
|
||||
|
||||
key.dptr = (void*) name;
|
||||
key.dsize = (int) strlen(name);
|
||||
|
||||
data.dptr = (void*) &entry;
|
||||
data.dsize = sizeof(entry);
|
||||
|
||||
if ((k = gdbm_store(u->gdbm_file, key, data, mode == PA_UPDATE_REPLACE ? GDBM_REPLACE : GDBM_INSERT)) == 0)
|
||||
if (apply_immediately)
|
||||
apply_entry(u, name, &entry);
|
||||
}
|
||||
|
||||
trigger_save(u);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SUBCOMMAND_DELETE:
|
||||
|
||||
while (!pa_tagstruct_eof(t)) {
|
||||
const char *name;
|
||||
datum key;
|
||||
|
||||
if (pa_tagstruct_gets(t, &name) < 0)
|
||||
goto fail;
|
||||
|
||||
key.dptr = (void*) name;
|
||||
key.dsize = (int) strlen(name);
|
||||
|
||||
gdbm_delete(u->gdbm_file, key);
|
||||
}
|
||||
|
||||
trigger_save(u);
|
||||
|
||||
break;
|
||||
|
||||
case SUBCOMMAND_SUBSCRIBE: {
|
||||
|
||||
pa_bool_t enabled;
|
||||
|
||||
if (pa_tagstruct_get_boolean(t, &enabled) < 0 ||
|
||||
!pa_tagstruct_eof(t))
|
||||
goto fail;
|
||||
|
||||
if (enabled)
|
||||
pa_idxset_put(u->subscribed, c, NULL);
|
||||
else
|
||||
pa_idxset_remove_by_data(u->subscribed, c, NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
||||
if (reply)
|
||||
pa_tagstruct_free(reply);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) {
|
||||
pa_assert(p);
|
||||
pa_assert(c);
|
||||
pa_assert(u);
|
||||
|
||||
pa_idxset_remove_by_data(u->subscribed, c, NULL);
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
pa_modargs *ma = NULL;
|
||||
struct userdata *u;
|
||||
char *fname, *fn;
|
||||
char hn[256];
|
||||
pa_sink_input *si;
|
||||
pa_source_output *so;
|
||||
uint32_t idx;
|
||||
|
|
@ -353,10 +706,18 @@ int pa__init(pa_module*m) {
|
|||
|
||||
m->userdata = u = pa_xnew(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
u->save_time_event = NULL;
|
||||
u->restore_device = restore_device;
|
||||
u->restore_volume = restore_volume;
|
||||
u->restore_muted = restore_muted;
|
||||
u->gdbm_file = NULL;
|
||||
u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
|
||||
|
||||
u->protocol = pa_native_protocol_get(m->core);
|
||||
pa_native_protocol_install_ext(u->protocol, m, extension_cb);
|
||||
|
||||
u->connection_unlink_hook_slot = pa_hook_connect(&pa_native_protocol_hooks(u->protocol)[PA_NATIVE_HOOK_CONNECTION_UNLINK], PA_HOOK_NORMAL, (pa_hook_cb_t) connection_unlink_hook_cb, u);
|
||||
|
||||
u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
|
||||
|
||||
|
|
@ -368,11 +729,12 @@ int pa__init(pa_module*m) {
|
|||
if (restore_volume || restore_muted)
|
||||
u->sink_input_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_fixate_hook_callback, u);
|
||||
|
||||
if (!pa_get_host_name(hn, sizeof(hn)))
|
||||
goto fail;
|
||||
/* We include the host identifier in the file name because gdbm
|
||||
* files are CPU dependant, and we don't want things to go wrong
|
||||
* if we are on a multiarch system. */
|
||||
|
||||
fn = pa_sprintf_malloc("stream-volumes.%s."CANONICAL_HOST".gdbm", hn);
|
||||
fname = pa_state_path(fn);
|
||||
fn = pa_sprintf_malloc("stream-volumes."CANONICAL_HOST".gdbm");
|
||||
fname = pa_state_path(fn, TRUE);
|
||||
pa_xfree(fn);
|
||||
|
||||
if (!fname)
|
||||
|
|
@ -423,11 +785,22 @@ void pa__done(pa_module*m) {
|
|||
if (u->source_output_new_hook_slot)
|
||||
pa_hook_slot_free(u->source_output_new_hook_slot);
|
||||
|
||||
if (u->connection_unlink_hook_slot)
|
||||
pa_hook_slot_free(u->connection_unlink_hook_slot);
|
||||
|
||||
if (u->save_time_event)
|
||||
u->core->mainloop->time_free(u->save_time_event);
|
||||
|
||||
if (u->gdbm_file)
|
||||
gdbm_close(u->gdbm_file);
|
||||
|
||||
if (u->protocol) {
|
||||
pa_native_protocol_remove_ext(u->protocol, m);
|
||||
pa_native_protocol_unref(u->protocol);
|
||||
}
|
||||
|
||||
if (u->subscribed)
|
||||
pa_idxset_free(u->subscribed, NULL, NULL);
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ struct userdata {
|
|||
#ifdef TUNNEL_SINK
|
||||
char *sink_name;
|
||||
pa_sink *sink;
|
||||
int32_t requested_bytes;
|
||||
size_t requested_bytes;
|
||||
#else
|
||||
char *source_name;
|
||||
pa_source *source;
|
||||
|
|
@ -231,7 +231,7 @@ static void command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t
|
|||
pa_assert(u->pdispatch == pd);
|
||||
|
||||
pa_log_warn("Stream killed");
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
|
|
@ -262,7 +262,7 @@ static void command_suspended(pa_pdispatch *pd, uint32_t command, uint32_t tag
|
|||
pa_tagstruct_get_boolean(t, &suspended) < 0 ||
|
||||
!pa_tagstruct_eof(t)) {
|
||||
pa_log("Invalid packet");
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -389,7 +389,7 @@ static void send_data(struct userdata *u) {
|
|||
|
||||
u->requested_bytes -= memchunk.length;
|
||||
|
||||
u->counter += memchunk.length;
|
||||
u->counter += (int64_t) memchunk.length;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -417,7 +417,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
|
|||
case PA_SINK_MESSAGE_GET_LATENCY: {
|
||||
pa_usec_t yl, yr, *usec = data;
|
||||
|
||||
yl = pa_bytes_to_usec(u->counter, &u->sink->sample_spec);
|
||||
yl = pa_bytes_to_usec((uint64_t) u->counter, &u->sink->sample_spec);
|
||||
yr = pa_smoother_get(u->smoother, pa_rtclock_usec());
|
||||
|
||||
*usec = yl > yr ? yl - yr : 0;
|
||||
|
|
@ -444,10 +444,10 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
|
|||
case SINK_MESSAGE_UPDATE_LATENCY: {
|
||||
pa_usec_t y;
|
||||
|
||||
y = pa_bytes_to_usec(u->counter, &u->sink->sample_spec);
|
||||
y = pa_bytes_to_usec((uint64_t) u->counter, &u->sink->sample_spec);
|
||||
|
||||
if (y > (pa_usec_t) offset || offset < 0)
|
||||
y -= offset;
|
||||
y -= (pa_usec_t) offset;
|
||||
else
|
||||
y = 0;
|
||||
|
||||
|
|
@ -465,7 +465,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
|
|||
|
||||
pa_pstream_send_memblock(u->pstream, u->channel, 0, PA_SEEK_RELATIVE, chunk);
|
||||
|
||||
u->counter_delta += chunk->length;
|
||||
u->counter_delta += (int64_t) chunk->length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -520,7 +520,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
|
|||
case PA_SOURCE_MESSAGE_GET_LATENCY: {
|
||||
pa_usec_t yr, yl, *usec = data;
|
||||
|
||||
yl = pa_bytes_to_usec(u->counter, &PA_SINK(o)->sample_spec);
|
||||
yl = pa_bytes_to_usec((uint64_t) u->counter, &PA_SINK(o)->sample_spec);
|
||||
yr = pa_smoother_get(u->smoother, pa_rtclock_usec());
|
||||
|
||||
*usec = yr > yl ? yr - yl : 0;
|
||||
|
|
@ -532,7 +532,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
|
|||
if (PA_SOURCE_IS_OPENED(u->source->thread_info.state))
|
||||
pa_source_post(u->source, chunk);
|
||||
|
||||
u->counter += chunk->length;
|
||||
u->counter += (int64_t) chunk->length;
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -544,10 +544,10 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
|
|||
case SOURCE_MESSAGE_UPDATE_LATENCY: {
|
||||
pa_usec_t y;
|
||||
|
||||
y = pa_bytes_to_usec(u->counter, &u->source->sample_spec);
|
||||
y = pa_bytes_to_usec((uint64_t) u->counter, &u->source->sample_spec);
|
||||
|
||||
if (offset >= 0 || y > (pa_usec_t) -offset)
|
||||
y += offset;
|
||||
y += (pa_usec_t) offset;
|
||||
else
|
||||
y = 0;
|
||||
|
||||
|
|
@ -652,7 +652,7 @@ static void command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, p
|
|||
return;
|
||||
|
||||
fail:
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -736,9 +736,9 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint
|
|||
|
||||
/* Add the length of our server-side buffer */
|
||||
if (write_index >= read_index)
|
||||
delay += (int64_t) pa_bytes_to_usec(write_index-read_index, ss);
|
||||
delay += (int64_t) pa_bytes_to_usec((uint64_t) (write_index-read_index), ss);
|
||||
else
|
||||
delay -= (int64_t) pa_bytes_to_usec(read_index-write_index, ss);
|
||||
delay -= (int64_t) pa_bytes_to_usec((uint64_t) (read_index-write_index), ss);
|
||||
|
||||
/* Our measurements are already out of date, hence correct by the *
|
||||
* transport latency */
|
||||
|
|
@ -750,9 +750,9 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint
|
|||
|
||||
/* Now correct by what we have have read/written since we requested the update */
|
||||
#ifdef TUNNEL_SINK
|
||||
delay += (int64_t) pa_bytes_to_usec(u->counter_delta, ss);
|
||||
delay += (int64_t) pa_bytes_to_usec((uint64_t) u->counter_delta, ss);
|
||||
#else
|
||||
delay -= (int64_t) pa_bytes_to_usec(u->counter_delta, ss);
|
||||
delay -= (int64_t) pa_bytes_to_usec((uint64_t) u->counter_delta, ss);
|
||||
#endif
|
||||
|
||||
#ifdef TUNNEL_SINK
|
||||
|
|
@ -765,7 +765,7 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint
|
|||
|
||||
fail:
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
|
|
@ -902,7 +902,7 @@ static void server_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
|
|||
return;
|
||||
|
||||
fail:
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
|
||||
#ifdef TUNNEL_SINK
|
||||
|
|
@ -979,7 +979,7 @@ static void sink_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_t
|
|||
return;
|
||||
|
||||
fail:
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
pa_proplist_free(pl);
|
||||
}
|
||||
|
||||
|
|
@ -1066,7 +1066,7 @@ static void sink_input_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag
|
|||
return;
|
||||
|
||||
fail:
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
pa_proplist_free(pl);
|
||||
}
|
||||
|
||||
|
|
@ -1142,7 +1142,7 @@ static void source_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
|
|||
return;
|
||||
|
||||
fail:
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
pa_proplist_free(pl);
|
||||
}
|
||||
|
||||
|
|
@ -1204,7 +1204,7 @@ static void command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32
|
|||
if (pa_tagstruct_getu32(t, &e) < 0 ||
|
||||
pa_tagstruct_getu32(t, &idx) < 0) {
|
||||
pa_log("Invalid protocol reply");
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1344,7 +1344,7 @@ parse_error:
|
|||
pa_log("Invalid reply. (Create stream)");
|
||||
|
||||
fail:
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1425,11 +1425,11 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
|
|||
u->maxlength = 4*1024*1024;
|
||||
|
||||
#ifdef TUNNEL_SINK
|
||||
u->tlength = pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_TLENGTH_MSEC, &u->sink->sample_spec);
|
||||
u->minreq = pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_MINREQ_MSEC, &u->sink->sample_spec);
|
||||
u->tlength = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_TLENGTH_MSEC, &u->sink->sample_spec);
|
||||
u->minreq = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_MINREQ_MSEC, &u->sink->sample_spec);
|
||||
u->prebuf = u->tlength;
|
||||
#else
|
||||
u->fragsize = pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_FRAGSIZE_MSEC, &u->source->sample_spec);
|
||||
u->fragsize = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_FRAGSIZE_MSEC, &u->source->sample_spec);
|
||||
#endif
|
||||
|
||||
#ifdef TUNNEL_SINK
|
||||
|
|
@ -1502,7 +1502,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
|
|||
return;
|
||||
|
||||
fail:
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
|
|
@ -1513,7 +1513,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) {
|
|||
pa_assert(u);
|
||||
|
||||
pa_log_warn("Stream died.");
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
|
|
@ -1526,7 +1526,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_c
|
|||
|
||||
if (pa_pdispatch_run(u->pdispatch, packet, creds, u) < 0) {
|
||||
pa_log("Invalid packet");
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1542,13 +1542,13 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
|
|||
|
||||
if (channel != u->channel) {
|
||||
pa_log("Recieved memory block on bad channel.");
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
pa_asyncmsgq_send(u->source->asyncmsgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_POST, PA_UINT_TO_PTR(seek), offset, chunk);
|
||||
|
||||
u->counter_delta += chunk->length;
|
||||
u->counter_delta += (int64_t) chunk->length;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1568,7 +1568,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata
|
|||
|
||||
if (!io) {
|
||||
pa_log("Connection failed: %s", pa_cstrerror(errno));
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) {
|
|||
if (k <= 0 || k > (long) PA_CHANNELS_MAX)
|
||||
return NULL;
|
||||
|
||||
v->channels = (unsigned) k;
|
||||
v->channels = (uint8_t) k;
|
||||
|
||||
for (i = 0; i < v->channels; i++) {
|
||||
p += strspn(p, WHITESPACE);
|
||||
|
|
@ -493,7 +493,7 @@ int pa__init(pa_module*m) {
|
|||
|
||||
m->userdata = u;
|
||||
|
||||
if (!(u->table_file = pa_state_path(pa_modargs_get_value(ma, "table", DEFAULT_VOLUME_TABLE_FILE))))
|
||||
if (!(u->table_file = pa_state_path(pa_modargs_get_value(ma, "table", DEFAULT_VOLUME_TABLE_FILE), TRUE)))
|
||||
goto fail;
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 ||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ static int x11_event_cb(pa_x11_wrapper *w, XEvent *e, void *userdata) {
|
|||
|
||||
bne = (XkbBellNotifyEvent*) e;
|
||||
|
||||
if (pa_scache_play_item_by_name(u->core, u->scache_item, u->sink_name, TRUE, (bne->percent*PA_VOLUME_NORM)/100, NULL, NULL) < 0) {
|
||||
if (pa_scache_play_item_by_name(u->core, u->scache_item, u->sink_name, TRUE, ((pa_volume_t) bne->percent*PA_VOLUME_NORM)/100U, NULL, NULL) < 0) {
|
||||
pa_log_info("Ringing bell failed, reverting to X11 device bell.");
|
||||
XkbForceDeviceBell(pa_x11_wrapper_get_display(w), bne->device, bne->bell_class, bne->bell_id, bne->percent);
|
||||
}
|
||||
|
|
@ -106,7 +106,7 @@ static void x11_kill_cb(pa_x11_wrapper *w, void *userdata) {
|
|||
u->x11_client = NULL;
|
||||
u->x11_wrapper = NULL;
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ static void x11_kill_cb(pa_x11_wrapper *w, void *userdata) {
|
|||
u->x11_client = NULL;
|
||||
u->x11_wrapper = NULL;
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
|
|
@ -152,7 +152,7 @@ int pa__init(pa_module*m) {
|
|||
u->x11_client = NULL;
|
||||
u->x11_wrapper = NULL;
|
||||
|
||||
u->hook_slot = pa_hook_connect(pa_native_protocol_servers_changed(u->protocol), PA_HOOK_NORMAL, servers_changed_cb, u);
|
||||
u->hook_slot = pa_hook_connect(&pa_native_protocol_hooks(u->protocol)[PA_NATIVE_HOOK_SERVERS_CHANGED], PA_HOOK_NORMAL, servers_changed_cb, u);
|
||||
|
||||
if (!(u->auth_cookie = pa_auth_cookie_get(m->core, pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), PA_NATIVE_COOKIE_LENGTH)))
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ static void die_cb(SmcConn connection, SmPointer client_data){
|
|||
pa_x11_wrapper_unref(u->x11);
|
||||
u->x11 = NULL;
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
|
||||
static void save_complete_cb(SmcConn connection, SmPointer client_data) {
|
||||
|
|
@ -181,7 +181,7 @@ int pa__init(pa_module*m) {
|
|||
prop_program.name = (char*) SmProgram;
|
||||
prop_program.type = (char*) SmARRAY8;
|
||||
val_program.value = (char*) PACKAGE_NAME;
|
||||
val_program.length = strlen(val_program.value);
|
||||
val_program.length = (int) strlen(val_program.value);
|
||||
prop_program.num_vals = 1;
|
||||
prop_program.vals = &val_program;
|
||||
prop_list[0] = &prop_program;
|
||||
|
|
@ -190,7 +190,7 @@ int pa__init(pa_module*m) {
|
|||
prop_user.type = (char*) SmARRAY8;
|
||||
pa_get_user_name(t, sizeof(t));
|
||||
val_user.value = t;
|
||||
val_user.length = strlen(val_user.value);
|
||||
val_user.length = (int) strlen(val_user.value);
|
||||
prop_user.num_vals = 1;
|
||||
prop_user.vals = &val_user;
|
||||
prop_list[1] = &prop_user;
|
||||
|
|
|
|||
|
|
@ -173,9 +173,9 @@ static void resolver_cb(
|
|||
device = value;
|
||||
value = NULL;
|
||||
} else if (strcmp(key, "rate") == 0)
|
||||
ss.rate = atoi(value);
|
||||
ss.rate = (uint32_t) atoi(value);
|
||||
else if (strcmp(key, "channels") == 0)
|
||||
ss.channels = atoi(value);
|
||||
ss.channels = (uint8_t) atoi(value);
|
||||
else if (strcmp(key, "format") == 0)
|
||||
ss.format = pa_parse_sample_format(value);
|
||||
else if (strcmp(key, "channel_map") == 0) {
|
||||
|
|
@ -286,7 +286,7 @@ static void browser_cb(
|
|||
struct tunnel *t2;
|
||||
|
||||
if ((t2 = pa_hashmap_get(u->tunnels, t))) {
|
||||
pa_module_unload_by_index(u->core, t2->module_index);
|
||||
pa_module_unload_by_index(u->core, t2->module_index, TRUE);
|
||||
pa_hashmap_remove(u->tunnels, t2);
|
||||
tunnel_free(t2);
|
||||
}
|
||||
|
|
@ -319,7 +319,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda
|
|||
browser_cb, u))) {
|
||||
|
||||
pa_log("avahi_service_browser_new() failed: %s", avahi_strerror(avahi_client_errno(c)));
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -334,7 +334,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda
|
|||
browser_cb, u))) {
|
||||
|
||||
pa_log("avahi_service_browser_new() failed: %s", avahi_strerror(avahi_client_errno(c)));
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -348,7 +348,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda
|
|||
|
||||
if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) {
|
||||
pa_log("avahi_client_new() failed: %s", avahi_strerror(error));
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -427,7 +427,7 @@ void pa__done(pa_module*m) {
|
|||
struct tunnel *t;
|
||||
|
||||
while ((t = pa_hashmap_steal_first(u->tunnels))) {
|
||||
pa_module_unload_by_index(u->core, t->module_index);
|
||||
pa_module_unload_by_index(u->core, t->module_index, TRUE);
|
||||
tunnel_free(t);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -539,7 +539,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda
|
|||
|
||||
if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) {
|
||||
pa_log("avahi_client_new() failed: %s", avahi_strerror(error));
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -204,10 +204,10 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) {
|
|||
|
||||
if (ss->channels != channels) {
|
||||
pa_log_warn("device doesn't support %i channels, using %i channels.", ss->channels, channels);
|
||||
ss->channels = channels;
|
||||
ss->channels = (uint8_t) channels;
|
||||
}
|
||||
|
||||
speed = ss->rate;
|
||||
speed = (int) ss->rate;
|
||||
if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0) {
|
||||
pa_log("SNDCTL_DSP_SPEED: %s", pa_cstrerror(errno));
|
||||
return -1;
|
||||
|
|
@ -219,7 +219,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) {
|
|||
|
||||
/* If the sample rate deviates too much, we need to resample */
|
||||
if (speed < ss->rate*.95 || speed > ss->rate*1.05)
|
||||
ss->rate = speed;
|
||||
ss->rate = (uint32_t) speed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -238,15 +238,15 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
|
|||
else
|
||||
delta = j;
|
||||
|
||||
pa_memblockq_seek(s->memblockq, delta * s->rtp_context.frame_size, PA_SEEK_RELATIVE);
|
||||
pa_memblockq_seek(s->memblockq, delta * (int64_t) s->rtp_context.frame_size, PA_SEEK_RELATIVE);
|
||||
|
||||
pa_rtclock_get(&now);
|
||||
|
||||
pa_smoother_put(s->smoother, pa_timeval_load(&now), pa_bytes_to_usec(pa_memblockq_get_write_index(s->memblockq), &s->sink_input->sample_spec));
|
||||
pa_smoother_put(s->smoother, pa_timeval_load(&now), pa_bytes_to_usec((uint64_t) pa_memblockq_get_write_index(s->memblockq), &s->sink_input->sample_spec));
|
||||
|
||||
if (pa_memblockq_push(s->memblockq, &chunk) < 0) {
|
||||
pa_log_warn("Queue overrun");
|
||||
pa_memblockq_seek(s->memblockq, chunk.length, PA_SEEK_RELATIVE);
|
||||
pa_memblockq_seek(s->memblockq, (int64_t) chunk.length, PA_SEEK_RELATIVE);
|
||||
}
|
||||
|
||||
pa_log("blocks in q: %u", pa_memblockq_get_nblocks(s->memblockq));
|
||||
|
|
@ -254,9 +254,9 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
|
|||
pa_memblock_unref(chunk.memblock);
|
||||
|
||||
/* The next timestamp we expect */
|
||||
s->offset = s->rtp_context.timestamp + (chunk.length / s->rtp_context.frame_size);
|
||||
s->offset = s->rtp_context.timestamp + (uint32_t) (chunk.length / s->rtp_context.frame_size);
|
||||
|
||||
pa_atomic_store(&s->timestamp, now.tv_sec);
|
||||
pa_atomic_store(&s->timestamp, (int) now.tv_sec);
|
||||
|
||||
if (s->last_rate_update + RATE_UPDATE_INTERVAL < pa_timeval_load(&now)) {
|
||||
pa_usec_t wi, ri, render_delay, sink_delay = 0, latency, fix;
|
||||
|
|
@ -265,7 +265,7 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
|
|||
pa_log("Updating sample rate");
|
||||
|
||||
wi = pa_smoother_get(s->smoother, pa_timeval_load(&now));
|
||||
ri = pa_bytes_to_usec(pa_memblockq_get_read_index(s->memblockq), &s->sink_input->sample_spec);
|
||||
ri = pa_bytes_to_usec((uint64_t) pa_memblockq_get_read_index(s->memblockq), &s->sink_input->sample_spec);
|
||||
|
||||
if (PA_MSGOBJECT(s->sink_input->sink)->process_msg(PA_MSGOBJECT(s->sink_input->sink), PA_SINK_MESSAGE_GET_LATENCY, &sink_delay, 0, NULL) < 0)
|
||||
sink_delay = 0;
|
||||
|
|
@ -291,7 +291,7 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
|
|||
fix = latency - s->intended_latency;
|
||||
|
||||
/* How many samples is this per second? */
|
||||
fix_samples = fix * s->sink_input->thread_info.sample_spec.rate / RATE_UPDATE_INTERVAL;
|
||||
fix_samples = (unsigned) (fix * (pa_usec_t) s->sink_input->thread_info.sample_spec.rate / (pa_usec_t) RATE_UPDATE_INTERVAL);
|
||||
|
||||
/* Check if deviation is in bounds */
|
||||
if (fix_samples > s->sink_input->sample_spec.rate*.20)
|
||||
|
|
@ -431,7 +431,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
|
|||
s->smoother = pa_smoother_new(PA_USEC_PER_SEC*5, PA_USEC_PER_SEC*2, TRUE, 10);
|
||||
pa_smoother_set_time_offset(s->smoother, pa_timeval_load(&now));
|
||||
s->last_rate_update = pa_timeval_load(&now);
|
||||
pa_atomic_store(&s->timestamp, now.tv_sec);
|
||||
pa_atomic_store(&s->timestamp, (int) now.tv_sec);
|
||||
|
||||
if ((fd = mcast_socket((const struct sockaddr*) &sdp_info->sa, sdp_info->salen)) < 0)
|
||||
goto fail;
|
||||
|
|
@ -566,7 +566,7 @@ static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event
|
|||
} else {
|
||||
struct timeval now;
|
||||
pa_rtclock_get(&now);
|
||||
pa_atomic_store(&s->timestamp, now.tv_sec);
|
||||
pa_atomic_store(&s->timestamp, (int) now.tv_sec);
|
||||
|
||||
pa_sdp_info_destroy(&info);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,10 +67,12 @@ PA_MODULE_USAGE(
|
|||
"destination=<destination IP address> "
|
||||
"port=<port number> "
|
||||
"mtu=<maximum transfer unit> "
|
||||
"loop=<loopback to local host?>"
|
||||
"loop=<loopback to local host?> "
|
||||
"ttl=<ttl value>"
|
||||
);
|
||||
|
||||
#define DEFAULT_PORT 46000
|
||||
#define DEFAULT_TTL 1
|
||||
#define SAP_PORT 9875
|
||||
#define DEFAULT_DESTINATION "224.0.0.56"
|
||||
#define MEMBLOCKQ_MAXLENGTH (1024*170)
|
||||
|
|
@ -86,6 +88,7 @@ static const char* const valid_modargs[] = {
|
|||
"port",
|
||||
"mtu" ,
|
||||
"loop",
|
||||
"ttl",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -139,7 +142,7 @@ static void source_output_kill(pa_source_output* o) {
|
|||
pa_source_output_assert_ref(o);
|
||||
pa_assert_se(u = o->userdata);
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
pa_module_unload_request(u->module, TRUE);
|
||||
|
||||
pa_source_output_unlink(u->source_output);
|
||||
pa_source_output_unref(u->source_output);
|
||||
|
|
@ -167,7 +170,9 @@ int pa__init(pa_module*m) {
|
|||
pa_modargs *ma = NULL;
|
||||
const char *dest;
|
||||
uint32_t port = DEFAULT_PORT, mtu;
|
||||
int af, fd = -1, sap_fd = -1;
|
||||
uint32_t ttl = DEFAULT_TTL;
|
||||
sa_family_t af;
|
||||
int fd = -1, sap_fd = -1;
|
||||
pa_source *s;
|
||||
pa_sample_spec ss;
|
||||
pa_channel_map cm;
|
||||
|
|
@ -219,14 +224,14 @@ int pa__init(pa_module*m) {
|
|||
|
||||
payload = pa_rtp_payload_from_sample_spec(&ss);
|
||||
|
||||
mtu = pa_frame_align(DEFAULT_MTU, &ss);
|
||||
mtu = (uint32_t) pa_frame_align(DEFAULT_MTU, &ss);
|
||||
|
||||
if (pa_modargs_get_value_u32(ma, "mtu", &mtu) < 0 || mtu < 1 || mtu % pa_frame_size(&ss) != 0) {
|
||||
pa_log("Invalid MTU.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
port = DEFAULT_PORT + ((rand() % 512) << 1);
|
||||
port = DEFAULT_PORT + ((uint32_t) (rand() % 512) << 1);
|
||||
if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) {
|
||||
pa_log("port= expects a numerical argument between 1 and 65535.");
|
||||
goto fail;
|
||||
|
|
@ -235,16 +240,21 @@ int pa__init(pa_module*m) {
|
|||
if (port & 1)
|
||||
pa_log_warn("Port number not even as suggested in RFC3550!");
|
||||
|
||||
if (pa_modargs_get_value_u32(ma, "ttl", &ttl) < 0 || ttl < 1 || ttl > 0xFF) {
|
||||
pa_log("ttl= expects a numerical argument between 1 and 255.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dest = pa_modargs_get_value(ma, "destination", DEFAULT_DESTINATION);
|
||||
|
||||
if (inet_pton(AF_INET6, dest, &sa6.sin6_addr) > 0) {
|
||||
sa6.sin6_family = af = AF_INET6;
|
||||
sa6.sin6_port = htons(port);
|
||||
sa6.sin6_port = htons((uint16_t) port);
|
||||
sap_sa6 = sa6;
|
||||
sap_sa6.sin6_port = htons(SAP_PORT);
|
||||
} else if (inet_pton(AF_INET, dest, &sa4.sin_addr) > 0) {
|
||||
sa4.sin_family = af = AF_INET;
|
||||
sa4.sin_port = htons(port);
|
||||
sa4.sin_port = htons((uint16_t) port);
|
||||
sap_sa4 = sa4;
|
||||
sap_sa4.sin_port = htons(SAP_PORT);
|
||||
} else {
|
||||
|
|
@ -257,7 +267,7 @@ int pa__init(pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (connect(fd, af == AF_INET ? (struct sockaddr*) &sa4 : (struct sockaddr*) &sa6, af == AF_INET ? sizeof(sa4) : sizeof(sa6)) < 0) {
|
||||
if (connect(fd, af == AF_INET ? (struct sockaddr*) &sa4 : (struct sockaddr*) &sa6, (socklen_t) (af == AF_INET ? sizeof(sa4) : sizeof(sa6))) < 0) {
|
||||
pa_log("connect() failed: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -267,7 +277,7 @@ int pa__init(pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (connect(sap_fd, af == AF_INET ? (struct sockaddr*) &sap_sa4 : (struct sockaddr*) &sap_sa6, af == AF_INET ? sizeof(sap_sa4) : sizeof(sap_sa6)) < 0) {
|
||||
if (connect(sap_fd, af == AF_INET ? (struct sockaddr*) &sap_sa4 : (struct sockaddr*) &sap_sa6, (socklen_t) (af == AF_INET ? sizeof(sap_sa4) : sizeof(sap_sa6))) < 0) {
|
||||
pa_log("connect() failed: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -279,6 +289,15 @@ int pa__init(pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (ttl != DEFAULT_TTL) {
|
||||
int _ttl = (int) ttl;
|
||||
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &_ttl, sizeof(_ttl)) < 0) {
|
||||
pa_log("IP_MULTICAST_TTL failed: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the socket queue is full, let's drop packets */
|
||||
pa_make_fd_nonblock(fd);
|
||||
pa_make_udp_socket_low_delay(fd);
|
||||
|
|
@ -290,6 +309,7 @@ int pa__init(pa_module*m) {
|
|||
pa_proplist_sets(data.proplist, "rtp.destination", dest);
|
||||
pa_proplist_setf(data.proplist, "rtp.mtu", "%lu", (unsigned long) mtu);
|
||||
pa_proplist_setf(data.proplist, "rtp.port", "%lu", (unsigned long) port);
|
||||
pa_proplist_setf(data.proplist, "rtp.ttl", "%lu", (unsigned long) ttl);
|
||||
data.driver = __FILE__;
|
||||
data.module = m;
|
||||
data.source = s;
|
||||
|
|
@ -335,14 +355,14 @@ int pa__init(pa_module*m) {
|
|||
p = pa_sdp_build(af,
|
||||
af == AF_INET ? (void*) &((struct sockaddr_in*) &sa_dst)->sin_addr : (void*) &((struct sockaddr_in6*) &sa_dst)->sin6_addr,
|
||||
af == AF_INET ? (void*) &sa4.sin_addr : (void*) &sa6.sin6_addr,
|
||||
n, port, payload, &ss);
|
||||
n, (uint16_t) port, payload, &ss);
|
||||
|
||||
pa_xfree(n);
|
||||
|
||||
pa_rtp_context_init_send(&u->rtp_context, fd, m->core->cookie, payload, pa_frame_size(&ss));
|
||||
pa_sap_context_init_send(&u->sap_context, sap_fd, p);
|
||||
|
||||
pa_log_info("RTP stream initialized with mtu %u on %s:%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, u->rtp_context.ssrc, payload, u->rtp_context.sequence);
|
||||
pa_log_info("RTP stream initialized with mtu %u on %s:%u ttl=%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, ttl, u->rtp_context.ssrc, payload, u->rtp_context.sequence);
|
||||
pa_log_info("SDP-Data:\n%s\nEOF", p);
|
||||
|
||||
pa_sap_send(&u->sap_context, 0);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssr
|
|||
c->sequence = (uint16_t) (rand()*rand());
|
||||
c->timestamp = 0;
|
||||
c->ssrc = ssrc ? ssrc : (uint32_t) (rand()*rand());
|
||||
c->payload = payload & 127;
|
||||
c->payload = (uint8_t) (payload & 127U);
|
||||
c->frame_size = frame_size;
|
||||
|
||||
pa_memchunk_reset(&c->memchunk);
|
||||
|
|
@ -99,7 +99,8 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
|
|||
if (r < 0 || n >= size || iov_idx >= MAX_IOVECS) {
|
||||
uint32_t header[3];
|
||||
struct msghdr m;
|
||||
int k, i;
|
||||
ssize_t k;
|
||||
int i;
|
||||
|
||||
if (n > 0) {
|
||||
header[0] = htonl(((uint32_t) 2 << 30) | ((uint32_t) c->payload << 16) | ((uint32_t) c->sequence));
|
||||
|
|
@ -112,7 +113,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
|
|||
m.msg_name = NULL;
|
||||
m.msg_namelen = 0;
|
||||
m.msg_iov = iov;
|
||||
m.msg_iovlen = iov_idx;
|
||||
m.msg_iovlen = (size_t) iov_idx;
|
||||
m.msg_control = NULL;
|
||||
m.msg_controllen = 0;
|
||||
m.msg_flags = 0;
|
||||
|
|
@ -128,7 +129,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
|
|||
} else
|
||||
k = 0;
|
||||
|
||||
c->timestamp += n/c->frame_size;
|
||||
c->timestamp += (unsigned) (n/c->frame_size);
|
||||
|
||||
if (k < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) /* If the queue is full, just ignore it */
|
||||
|
|
@ -162,7 +163,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
|
|||
struct msghdr m;
|
||||
struct iovec iov;
|
||||
uint32_t header;
|
||||
int cc;
|
||||
unsigned cc;
|
||||
ssize_t r;
|
||||
|
||||
pa_assert(c);
|
||||
|
|
@ -197,7 +198,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
|
|||
chunk->index = c->memchunk.index;
|
||||
|
||||
iov.iov_base = (uint8_t*) pa_memblock_acquire(chunk->memblock) + chunk->index;
|
||||
iov.iov_len = size;
|
||||
iov.iov_len = (size_t) size;
|
||||
|
||||
m.msg_name = NULL;
|
||||
m.msg_namelen = 0;
|
||||
|
|
@ -246,16 +247,16 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
|
|||
}
|
||||
|
||||
cc = (header >> 24) & 0xF;
|
||||
c->payload = (header >> 16) & 127;
|
||||
c->sequence = header & 0xFFFF;
|
||||
c->payload = (uint8_t) ((header >> 16) & 127U);
|
||||
c->sequence = (uint16_t) (header & 0xFFFFU);
|
||||
|
||||
if (12 + cc*4 > size) {
|
||||
if (12 + cc*4 > (unsigned) size) {
|
||||
pa_log_warn("RTP packet too short. (CSRC)");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
chunk->index += 12 + cc*4;
|
||||
chunk->length = size - 12 + cc*4;
|
||||
chunk->length = (size_t) size - 12 + cc*4;
|
||||
|
||||
if (chunk->length % c->frame_size != 0) {
|
||||
pa_log_warn("Bad RTP packet size.");
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ int pa_sap_send(pa_sap_context *c, pa_bool_t goodbye) {
|
|||
socklen_t salen = sizeof(sa_buf);
|
||||
struct iovec iov[4];
|
||||
struct msghdr m;
|
||||
int k;
|
||||
ssize_t k;
|
||||
|
||||
if (getsockname(c->fd, sa, &salen) < 0) {
|
||||
pa_log("getsockname() failed: %s\n", pa_cstrerror(errno));
|
||||
|
|
@ -94,7 +94,7 @@ int pa_sap_send(pa_sap_context *c, pa_bool_t goodbye) {
|
|||
iov[0].iov_len = sizeof(header);
|
||||
|
||||
iov[1].iov_base = sa->sa_family == AF_INET ? (void*) &((struct sockaddr_in*) sa)->sin_addr : (void*) &((struct sockaddr_in6*) sa)->sin6_addr;
|
||||
iov[1].iov_len = sa->sa_family == AF_INET ? 4 : 16;
|
||||
iov[1].iov_len = sa->sa_family == AF_INET ? 4U : 16U;
|
||||
|
||||
iov[2].iov_base = (char*) MIME_TYPE;
|
||||
iov[2].iov_len = sizeof(MIME_TYPE);
|
||||
|
|
@ -113,7 +113,7 @@ int pa_sap_send(pa_sap_context *c, pa_bool_t goodbye) {
|
|||
if ((k = sendmsg(c->fd, &m, MSG_DONTWAIT)) < 0)
|
||||
pa_log_warn("sendmsg() failed: %s\n", pa_cstrerror(errno));
|
||||
|
||||
return k;
|
||||
return (int) k;
|
||||
}
|
||||
|
||||
pa_sap_context* pa_sap_context_init_recv(pa_sap_context *c, int fd) {
|
||||
|
|
@ -128,10 +128,10 @@ pa_sap_context* pa_sap_context_init_recv(pa_sap_context *c, int fd) {
|
|||
int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye) {
|
||||
struct msghdr m;
|
||||
struct iovec iov;
|
||||
int size, k;
|
||||
int size;
|
||||
char *buf = NULL, *e;
|
||||
uint32_t header;
|
||||
int six, ac;
|
||||
unsigned six, ac, k;
|
||||
ssize_t r;
|
||||
|
||||
pa_assert(c);
|
||||
|
|
@ -142,11 +142,11 @@ int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
buf = pa_xnew(char, size+1);
|
||||
buf = pa_xnew(char, (unsigned) size+1);
|
||||
buf[size] = 0;
|
||||
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = size;
|
||||
iov.iov_len = (size_t) size;
|
||||
|
||||
m.msg_name = NULL;
|
||||
m.msg_namelen = 0;
|
||||
|
|
@ -184,21 +184,21 @@ int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
six = (header >> 28) & 1;
|
||||
ac = (header >> 16) & 0xFF;
|
||||
six = (header >> 28) & 1U;
|
||||
ac = (header >> 16) & 0xFFU;
|
||||
|
||||
k = 4 + (six ? 16 : 4) + ac*4;
|
||||
if (size < k) {
|
||||
k = 4 + (six ? 16U : 4U) + ac*4U;
|
||||
if ((unsigned) size < k) {
|
||||
pa_log_warn("SAP packet too short (AD).");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
e = buf + k;
|
||||
size -= k;
|
||||
size -= (int) k;
|
||||
|
||||
if ((unsigned) size >= sizeof(MIME_TYPE) && !strcmp(e, MIME_TYPE)) {
|
||||
e += sizeof(MIME_TYPE);
|
||||
size -= sizeof(MIME_TYPE);
|
||||
size -= (int) sizeof(MIME_TYPE);
|
||||
} else if ((unsigned) size < sizeof(PA_SDP_HEADER)-1 || strncmp(e, PA_SDP_HEADER, sizeof(PA_SDP_HEADER)-1)) {
|
||||
pa_log_warn("Invalid SDP header.");
|
||||
goto fail;
|
||||
|
|
@ -207,7 +207,7 @@ int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye) {
|
|||
if (c->sdp_data)
|
||||
pa_xfree(c->sdp_data);
|
||||
|
||||
c->sdp_data = pa_xstrndup(e, size);
|
||||
c->sdp_data = pa_xstrndup(e, (unsigned) size);
|
||||
pa_xfree(buf);
|
||||
|
||||
*goodbye = !!((header >> 26) & 1);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, u
|
|||
if (!(u = pa_get_user_name(un, sizeof(un))))
|
||||
u = "-";
|
||||
|
||||
ntp = time(NULL) + 2208988800U;
|
||||
ntp = (uint32_t) time(NULL) + 2208988800U;
|
||||
|
||||
pa_assert_se(a = inet_ntop(af, src, buf_src, sizeof(buf_src)));
|
||||
pa_assert_se(a = inet_ntop(af, dst, buf_dst, sizeof(buf_dst)));
|
||||
|
|
@ -99,10 +99,10 @@ static pa_sample_spec *parse_sdp_sample_spec(pa_sample_spec *ss, char *c) {
|
|||
return NULL;
|
||||
|
||||
if (sscanf(c, "%u/%u", &rate, &channels) == 2) {
|
||||
ss->rate = rate;
|
||||
ss->channels = channels;
|
||||
ss->rate = (uint32_t) rate;
|
||||
ss->channels = (uint8_t) channels;
|
||||
} else if (sscanf(c, "%u", &rate) == 2) {
|
||||
ss->rate = rate;
|
||||
ss->rate = (uint32_t) rate;
|
||||
ss->channels = 1;
|
||||
} else
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/i18n.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
|
|
@ -98,66 +99,66 @@ const char *const table[PA_CHANNEL_POSITION_MAX] = {
|
|||
};
|
||||
|
||||
const char *const pretty_table[PA_CHANNEL_POSITION_MAX] = {
|
||||
[PA_CHANNEL_POSITION_MONO] = "Mono",
|
||||
[PA_CHANNEL_POSITION_MONO] = N_("Mono"),
|
||||
|
||||
[PA_CHANNEL_POSITION_FRONT_CENTER] = "Front Center",
|
||||
[PA_CHANNEL_POSITION_FRONT_LEFT] = "Front Left",
|
||||
[PA_CHANNEL_POSITION_FRONT_RIGHT] = "Front Right",
|
||||
[PA_CHANNEL_POSITION_FRONT_CENTER] = N_("Front Center"),
|
||||
[PA_CHANNEL_POSITION_FRONT_LEFT] = N_("Front Left"),
|
||||
[PA_CHANNEL_POSITION_FRONT_RIGHT] = N_("Front Right"),
|
||||
|
||||
[PA_CHANNEL_POSITION_REAR_CENTER] = "Rear Center",
|
||||
[PA_CHANNEL_POSITION_REAR_LEFT] = "Rear Left",
|
||||
[PA_CHANNEL_POSITION_REAR_RIGHT] = "Rear Right",
|
||||
[PA_CHANNEL_POSITION_REAR_CENTER] = N_("Rear Center"),
|
||||
[PA_CHANNEL_POSITION_REAR_LEFT] = N_("Rear Left"),
|
||||
[PA_CHANNEL_POSITION_REAR_RIGHT] = N_("Rear Right"),
|
||||
|
||||
[PA_CHANNEL_POSITION_LFE] = "Low Frequency Emmiter",
|
||||
[PA_CHANNEL_POSITION_LFE] = N_("Low Frequency Emmiter"),
|
||||
|
||||
[PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = "Front Left-of-center",
|
||||
[PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = "Front Right-of-center",
|
||||
[PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = N_("Front Left-of-center"),
|
||||
[PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = N_("Front Right-of-center"),
|
||||
|
||||
[PA_CHANNEL_POSITION_SIDE_LEFT] = "Side Left",
|
||||
[PA_CHANNEL_POSITION_SIDE_RIGHT] = "Side Right",
|
||||
[PA_CHANNEL_POSITION_SIDE_LEFT] = N_("Side Left"),
|
||||
[PA_CHANNEL_POSITION_SIDE_RIGHT] = N_("Side Right"),
|
||||
|
||||
[PA_CHANNEL_POSITION_AUX0] = "Auxiliary 0",
|
||||
[PA_CHANNEL_POSITION_AUX1] = "Auxiliary 1",
|
||||
[PA_CHANNEL_POSITION_AUX2] = "Auxiliary 2",
|
||||
[PA_CHANNEL_POSITION_AUX3] = "Auxiliary 3",
|
||||
[PA_CHANNEL_POSITION_AUX4] = "Auxiliary 4",
|
||||
[PA_CHANNEL_POSITION_AUX5] = "Auxiliary 5",
|
||||
[PA_CHANNEL_POSITION_AUX6] = "Auxiliary 6",
|
||||
[PA_CHANNEL_POSITION_AUX7] = "Auxiliary 7",
|
||||
[PA_CHANNEL_POSITION_AUX8] = "Auxiliary 8",
|
||||
[PA_CHANNEL_POSITION_AUX9] = "Auxiliary 9",
|
||||
[PA_CHANNEL_POSITION_AUX10] = "Auxiliary 10",
|
||||
[PA_CHANNEL_POSITION_AUX11] = "Auxiliary 11",
|
||||
[PA_CHANNEL_POSITION_AUX12] = "Auxiliary 12",
|
||||
[PA_CHANNEL_POSITION_AUX13] = "Auxiliary 13",
|
||||
[PA_CHANNEL_POSITION_AUX14] = "Auxiliary 14",
|
||||
[PA_CHANNEL_POSITION_AUX15] = "Auxiliary 15",
|
||||
[PA_CHANNEL_POSITION_AUX16] = "Auxiliary 16",
|
||||
[PA_CHANNEL_POSITION_AUX17] = "Auxiliary 17",
|
||||
[PA_CHANNEL_POSITION_AUX18] = "Auxiliary 18",
|
||||
[PA_CHANNEL_POSITION_AUX19] = "Auxiliary 19",
|
||||
[PA_CHANNEL_POSITION_AUX20] = "Auxiliary 20",
|
||||
[PA_CHANNEL_POSITION_AUX21] = "Auxiliary 21",
|
||||
[PA_CHANNEL_POSITION_AUX22] = "Auxiliary 22",
|
||||
[PA_CHANNEL_POSITION_AUX23] = "Auxiliary 23",
|
||||
[PA_CHANNEL_POSITION_AUX24] = "Auxiliary 24",
|
||||
[PA_CHANNEL_POSITION_AUX25] = "Auxiliary 25",
|
||||
[PA_CHANNEL_POSITION_AUX26] = "Auxiliary 26",
|
||||
[PA_CHANNEL_POSITION_AUX27] = "Auxiliary 27",
|
||||
[PA_CHANNEL_POSITION_AUX28] = "Auxiliary 28",
|
||||
[PA_CHANNEL_POSITION_AUX29] = "Auxiliary 29",
|
||||
[PA_CHANNEL_POSITION_AUX30] = "Auxiliary 30",
|
||||
[PA_CHANNEL_POSITION_AUX31] = "Auxiliary 31",
|
||||
[PA_CHANNEL_POSITION_AUX0] = N_("Auxiliary 0"),
|
||||
[PA_CHANNEL_POSITION_AUX1] = N_("Auxiliary 1"),
|
||||
[PA_CHANNEL_POSITION_AUX2] = N_("Auxiliary 2"),
|
||||
[PA_CHANNEL_POSITION_AUX3] = N_("Auxiliary 3"),
|
||||
[PA_CHANNEL_POSITION_AUX4] = N_("Auxiliary 4"),
|
||||
[PA_CHANNEL_POSITION_AUX5] = N_("Auxiliary 5"),
|
||||
[PA_CHANNEL_POSITION_AUX6] = N_("Auxiliary 6"),
|
||||
[PA_CHANNEL_POSITION_AUX7] = N_("Auxiliary 7"),
|
||||
[PA_CHANNEL_POSITION_AUX8] = N_("Auxiliary 8"),
|
||||
[PA_CHANNEL_POSITION_AUX9] = N_("Auxiliary 9"),
|
||||
[PA_CHANNEL_POSITION_AUX10] = N_("Auxiliary 10"),
|
||||
[PA_CHANNEL_POSITION_AUX11] = N_("Auxiliary 11"),
|
||||
[PA_CHANNEL_POSITION_AUX12] = N_("Auxiliary 12"),
|
||||
[PA_CHANNEL_POSITION_AUX13] = N_("Auxiliary 13"),
|
||||
[PA_CHANNEL_POSITION_AUX14] = N_("Auxiliary 14"),
|
||||
[PA_CHANNEL_POSITION_AUX15] = N_("Auxiliary 15"),
|
||||
[PA_CHANNEL_POSITION_AUX16] = N_("Auxiliary 16"),
|
||||
[PA_CHANNEL_POSITION_AUX17] = N_("Auxiliary 17"),
|
||||
[PA_CHANNEL_POSITION_AUX18] = N_("Auxiliary 18"),
|
||||
[PA_CHANNEL_POSITION_AUX19] = N_("Auxiliary 19"),
|
||||
[PA_CHANNEL_POSITION_AUX20] = N_("Auxiliary 20"),
|
||||
[PA_CHANNEL_POSITION_AUX21] = N_("Auxiliary 21"),
|
||||
[PA_CHANNEL_POSITION_AUX22] = N_("Auxiliary 22"),
|
||||
[PA_CHANNEL_POSITION_AUX23] = N_("Auxiliary 23"),
|
||||
[PA_CHANNEL_POSITION_AUX24] = N_("Auxiliary 24"),
|
||||
[PA_CHANNEL_POSITION_AUX25] = N_("Auxiliary 25"),
|
||||
[PA_CHANNEL_POSITION_AUX26] = N_("Auxiliary 26"),
|
||||
[PA_CHANNEL_POSITION_AUX27] = N_("Auxiliary 27"),
|
||||
[PA_CHANNEL_POSITION_AUX28] = N_("Auxiliary 28"),
|
||||
[PA_CHANNEL_POSITION_AUX29] = N_("Auxiliary 29"),
|
||||
[PA_CHANNEL_POSITION_AUX30] = N_("Auxiliary 30"),
|
||||
[PA_CHANNEL_POSITION_AUX31] = N_("Auxiliary 31"),
|
||||
|
||||
[PA_CHANNEL_POSITION_TOP_CENTER] = "Top Center",
|
||||
[PA_CHANNEL_POSITION_TOP_CENTER] = N_("Top Center"),
|
||||
|
||||
[PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "Top Front Center",
|
||||
[PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = "Top Front Left",
|
||||
[PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = "Top Front Right",
|
||||
[PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = N_("Top Front Center"),
|
||||
[PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = N_("Top Front Left"),
|
||||
[PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = N_("Top Front Right"),
|
||||
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_CENTER] = "Top Rear Center",
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_LEFT] = "Top Rear left",
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = "Top Rear Right"
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_CENTER] = N_("Top Rear Center"),
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_LEFT] = N_("Top Rear Left"),
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = N_("Top Rear Right")
|
||||
};
|
||||
|
||||
pa_channel_map* pa_channel_map_init(pa_channel_map *m) {
|
||||
|
|
@ -200,7 +201,7 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p
|
|||
|
||||
pa_channel_map_init(m);
|
||||
|
||||
m->channels = channels;
|
||||
m->channels = (uint8_t) channels;
|
||||
|
||||
switch (def) {
|
||||
case PA_CHANNEL_MAP_AIFF:
|
||||
|
|
@ -414,7 +415,7 @@ pa_channel_map* pa_channel_map_init_extend(pa_channel_map *m, unsigned channels,
|
|||
i++;
|
||||
}
|
||||
|
||||
m->channels = channels;
|
||||
m->channels = (uint8_t) channels;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
|
@ -432,10 +433,13 @@ const char* pa_channel_position_to_string(pa_channel_position_t pos) {
|
|||
}
|
||||
|
||||
const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos) {
|
||||
|
||||
pa_init_i18n();
|
||||
|
||||
if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
|
||||
return NULL;
|
||||
|
||||
return pretty_table[pos];
|
||||
return _(pretty_table[pos]);
|
||||
}
|
||||
|
||||
int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) {
|
||||
|
|
@ -456,7 +460,7 @@ int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) {
|
|||
|
||||
char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
|
||||
unsigned channel;
|
||||
int first = 1;
|
||||
pa_bool_t first = TRUE;
|
||||
char *e;
|
||||
|
||||
pa_assert(s);
|
||||
|
|
@ -471,7 +475,7 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
|
|||
pa_channel_position_to_string(map->map[channel]));
|
||||
|
||||
e = strchr(e, 0);
|
||||
first = 0;
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
return s;
|
||||
|
|
@ -552,7 +556,6 @@ int pa_channel_map_valid(const pa_channel_map *map) {
|
|||
|
||||
if (map->map[c] < 0 ||map->map[c] >= PA_CHANNEL_POSITION_MAX)
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <X11/Xatom.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/x11prop.h>
|
||||
#include <pulsecore/log.h>
|
||||
|
|
@ -51,7 +52,7 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) {
|
|||
goto finish;
|
||||
|
||||
if (!(d = XOpenDisplay(dname))) {
|
||||
pa_log("XOpenDisplay() failed");
|
||||
pa_log(_("XOpenDisplay() failed"));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +75,7 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) {
|
|||
uint8_t cookie[PA_NATIVE_COOKIE_LENGTH];
|
||||
|
||||
if (pa_parsehex(t, cookie, sizeof(cookie)) != sizeof(cookie)) {
|
||||
pa_log("failed to parse cookie data");
|
||||
pa_log(_("Failed to parse cookie data"));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
|
|
@ -113,7 +114,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
|
|||
if (filename) {
|
||||
|
||||
if (!(f = fopen(filename, "r"))) {
|
||||
pa_log("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
|
||||
pa_log(_("Failed to open configuration file '%s': %s"), fn, pa_cstrerror(errno));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@
|
|||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/utf8.h>
|
||||
#include <pulse/util.h>
|
||||
#include <pulse/i18n.h>
|
||||
#include <pulse/lock-autospawn.h>
|
||||
|
||||
#include <pulsecore/winsock.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
|
|
@ -80,7 +82,7 @@
|
|||
|
||||
#include "context.h"
|
||||
|
||||
#define AUTOSPAWN_LOCK "autospawn.lock"
|
||||
void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
|
||||
|
||||
static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
|
||||
[PA_COMMAND_REQUEST] = pa_command_request,
|
||||
|
|
@ -93,23 +95,27 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
|
|||
[PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = pa_command_stream_suspended,
|
||||
[PA_COMMAND_RECORD_STREAM_SUSPENDED] = pa_command_stream_suspended,
|
||||
[PA_COMMAND_STARTED] = pa_command_stream_started,
|
||||
[PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event
|
||||
[PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event,
|
||||
[PA_COMMAND_EXTENSION] = pa_command_extension
|
||||
};
|
||||
|
||||
static void unlock_autospawn_lock_file(pa_context *c) {
|
||||
static void unlock_autospawn(pa_context *c) {
|
||||
pa_assert(c);
|
||||
|
||||
if (c->autospawn_lock_fd >= 0) {
|
||||
char *lf;
|
||||
if (c->autospawn_fd >= 0) {
|
||||
|
||||
if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK)))
|
||||
pa_log_warn("Cannot unlock autospawn because runtime path is no more.");
|
||||
if (c->autospawn_locked)
|
||||
pa_autospawn_lock_release();
|
||||
|
||||
pa_unlock_lockfile(lf, c->autospawn_lock_fd);
|
||||
pa_xfree(lf);
|
||||
if (c->autospawn_event)
|
||||
c->mainloop->io_free(c->autospawn_event);
|
||||
|
||||
c->autospawn_lock_fd = -1;
|
||||
pa_autospawn_lock_done(FALSE);
|
||||
}
|
||||
|
||||
c->autospawn_locked = FALSE;
|
||||
c->autospawn_fd = -1;
|
||||
c->autospawn_event = NULL;
|
||||
}
|
||||
|
||||
static void context_free(pa_context *c);
|
||||
|
|
@ -126,6 +132,9 @@ static void reset_callbacks(pa_context *c) {
|
|||
|
||||
c->subscribe_callback = NULL;
|
||||
c->subscribe_userdata = NULL;
|
||||
|
||||
c->ext_stream_restore.callback = NULL;
|
||||
c->ext_stream_restore.userdata = NULL;
|
||||
}
|
||||
|
||||
pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *p) {
|
||||
|
|
@ -133,6 +142,8 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
|
|||
|
||||
pa_assert(mainloop);
|
||||
|
||||
pa_init_i18n();
|
||||
|
||||
if (!name && !pa_proplist_contains(p, PA_PROP_APPLICATION_NAME))
|
||||
return NULL;
|
||||
|
||||
|
|
@ -165,11 +176,15 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
|
|||
c->is_local = FALSE;
|
||||
c->server_list = NULL;
|
||||
c->server = NULL;
|
||||
c->autospawn_lock_fd = -1;
|
||||
memset(&c->spawn_api, 0, sizeof(c->spawn_api));
|
||||
c->do_autospawn = FALSE;
|
||||
|
||||
c->do_shm = FALSE;
|
||||
|
||||
c->do_autospawn = FALSE;
|
||||
c->autospawn_fd = -1;
|
||||
c->autospawn_locked = FALSE;
|
||||
c->autospawn_event = NULL;
|
||||
memset(&c->spawn_api, 0, sizeof(c->spawn_api));
|
||||
|
||||
#ifndef MSG_NOSIGNAL
|
||||
#ifdef SIGPIPE
|
||||
pa_check_signal_is_blocked(SIGPIPE);
|
||||
|
|
@ -237,7 +252,7 @@ static void context_free(pa_context *c) {
|
|||
|
||||
context_unlink(c);
|
||||
|
||||
unlock_autospawn_lock_file(c);
|
||||
unlock_autospawn(c);
|
||||
|
||||
if (c->record_streams)
|
||||
pa_dynarray_free(c->record_streams, NULL, NULL);
|
||||
|
|
@ -398,11 +413,11 @@ int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t, pa
|
|||
err = PA_ERR_UNKNOWN;
|
||||
|
||||
if (fail) {
|
||||
pa_context_fail(c, err);
|
||||
pa_context_fail(c, (int) err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pa_context_set_error(c, err);
|
||||
pa_context_set_error(c, (int) err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -424,7 +439,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
|
|||
switch(c->state) {
|
||||
case PA_CONTEXT_AUTHORIZING: {
|
||||
pa_tagstruct *reply;
|
||||
pa_bool_t shm_on_remote;
|
||||
pa_bool_t shm_on_remote = FALSE;
|
||||
|
||||
if (pa_tagstruct_getu32(t, &c->version) < 0 ||
|
||||
!pa_tagstruct_eof(t)) {
|
||||
|
|
@ -524,7 +539,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) {
|
|||
c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
|
||||
|
||||
if (!c->conf->cookie_valid)
|
||||
pa_log_info("No cookie loaded. Attempting to connect without.");
|
||||
pa_log_info(_("No cookie loaded. Attempting to connect without."));
|
||||
|
||||
t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag);
|
||||
|
||||
|
|
@ -578,7 +593,7 @@ static int context_connect_spawn(pa_context *c) {
|
|||
pa_context_ref(c);
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
|
||||
pa_log_error("socketpair(): %s", pa_cstrerror(errno));
|
||||
pa_log_error(_("socketpair(): %s"), pa_cstrerror(errno));
|
||||
pa_context_fail(c, PA_ERR_INTERNAL);
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -592,7 +607,7 @@ static int context_connect_spawn(pa_context *c) {
|
|||
c->spawn_api.prefork();
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
pa_log_error("fork(): %s", pa_cstrerror(errno));
|
||||
pa_log_error(_("fork(): %s"), pa_cstrerror(errno));
|
||||
pa_context_fail(c, PA_ERR_INTERNAL);
|
||||
|
||||
if (c->spawn_api.postfork)
|
||||
|
|
@ -655,7 +670,7 @@ static int context_connect_spawn(pa_context *c) {
|
|||
c->spawn_api.postfork();
|
||||
|
||||
if (r < 0) {
|
||||
pa_log("waitpid(): %s", pa_cstrerror(errno));
|
||||
pa_log(_("waitpid(): %s"), pa_cstrerror(errno));
|
||||
pa_context_fail(c, PA_ERR_INTERNAL);
|
||||
goto fail;
|
||||
} else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
||||
|
|
@ -665,7 +680,7 @@ static int context_connect_spawn(pa_context *c) {
|
|||
|
||||
c->is_local = TRUE;
|
||||
|
||||
unlock_autospawn_lock_file(c);
|
||||
unlock_autospawn(c);
|
||||
|
||||
io = pa_iochannel_new(c->mainloop, fds[0], fds[0]);
|
||||
setup_context(c, io);
|
||||
|
|
@ -677,7 +692,7 @@ static int context_connect_spawn(pa_context *c) {
|
|||
fail:
|
||||
pa_close_pipe(fds);
|
||||
|
||||
unlock_autospawn_lock_file(c);
|
||||
unlock_autospawn(c);
|
||||
|
||||
pa_context_unref(c);
|
||||
|
||||
|
|
@ -759,15 +774,48 @@ static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userd
|
|||
goto finish;
|
||||
}
|
||||
|
||||
unlock_autospawn_lock_file(c);
|
||||
unlock_autospawn(c);
|
||||
setup_context(c, io);
|
||||
|
||||
finish:
|
||||
pa_context_unref(c);
|
||||
}
|
||||
|
||||
static void autospawn_cb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
|
||||
pa_context *c = userdata;
|
||||
int k;
|
||||
|
||||
static char *get_legacy_runtime_dir(void) {
|
||||
pa_assert(a);
|
||||
pa_assert(e);
|
||||
pa_assert(fd >= 0);
|
||||
pa_assert(events == PA_IO_EVENT_INPUT);
|
||||
pa_assert(c);
|
||||
pa_assert(e == c->autospawn_event);
|
||||
pa_assert(fd == c->autospawn_fd);
|
||||
|
||||
pa_context_ref(c);
|
||||
|
||||
/* Check whether we can get the lock right now*/
|
||||
if ((k = pa_autospawn_lock_acquire(FALSE)) < 0) {
|
||||
pa_context_fail(c, PA_ERR_ACCESS);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (k > 0) {
|
||||
/* So we got it, rock on! */
|
||||
c->autospawn_locked = TRUE;
|
||||
try_next_connection(c);
|
||||
|
||||
c->mainloop->io_free(c->autospawn_event);
|
||||
c->autospawn_event = NULL;
|
||||
}
|
||||
|
||||
finish:
|
||||
|
||||
pa_context_unref(c);
|
||||
}
|
||||
|
||||
static char *get_old_legacy_runtime_dir(void) {
|
||||
char *p, u[128];
|
||||
struct stat st;
|
||||
|
||||
|
|
@ -789,6 +837,28 @@ static char *get_legacy_runtime_dir(void) {
|
|||
return p;
|
||||
}
|
||||
|
||||
static char *get_very_old_legacy_runtime_dir(void) {
|
||||
char *p, h[128];
|
||||
struct stat st;
|
||||
|
||||
if (!pa_get_home_dir(h, sizeof(h)))
|
||||
return NULL;
|
||||
|
||||
p = pa_sprintf_malloc("%s/.pulse", h);
|
||||
|
||||
if (stat(p, &st) < 0) {
|
||||
pa_xfree(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (st.st_uid != getuid()) {
|
||||
pa_xfree(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int pa_context_connect(
|
||||
pa_context *c,
|
||||
const char *server,
|
||||
|
|
@ -816,6 +886,7 @@ int pa_context_connect(
|
|||
pa_context_fail(c, PA_ERR_INVALIDSERVER);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
} else {
|
||||
char *d, *ufn;
|
||||
static char *legacy_dir;
|
||||
|
|
@ -840,8 +911,16 @@ int pa_context_connect(
|
|||
/* The system wide instance */
|
||||
c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET);
|
||||
|
||||
/* The old per-user instance path. This is supported only to ease upgrades */
|
||||
if ((legacy_dir = get_legacy_runtime_dir())) {
|
||||
/* The very old per-user instance path (< 0.9.11). This is supported only to ease upgrades */
|
||||
if ((legacy_dir = get_very_old_legacy_runtime_dir())) {
|
||||
char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir);
|
||||
c->server_list = pa_strlist_prepend(c->server_list, p);
|
||||
pa_xfree(p);
|
||||
pa_xfree(legacy_dir);
|
||||
}
|
||||
|
||||
/* The old per-user instance path (< 0.9.12). This is supported only to ease upgrades */
|
||||
if ((legacy_dir = get_old_legacy_runtime_dir())) {
|
||||
char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir);
|
||||
c->server_list = pa_strlist_prepend(c->server_list, p);
|
||||
pa_xfree(p);
|
||||
|
|
@ -856,21 +935,40 @@ int pa_context_connect(
|
|||
|
||||
/* Wrap the connection attempts in a single transaction for sane autospawn locking */
|
||||
if (!(flags & PA_CONTEXT_NOAUTOSPAWN) && c->conf->autospawn) {
|
||||
char *lf;
|
||||
int k;
|
||||
|
||||
if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK))) {
|
||||
pa_assert(c->autospawn_fd < 0);
|
||||
pa_assert(!c->autospawn_locked);
|
||||
|
||||
/* Start the locking procedure */
|
||||
if ((c->autospawn_fd = pa_autospawn_lock_init()) < 0) {
|
||||
pa_context_fail(c, PA_ERR_ACCESS);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
pa_assert(c->autospawn_lock_fd <= 0);
|
||||
c->autospawn_lock_fd = pa_lock_lockfile(lf);
|
||||
pa_xfree(lf);
|
||||
|
||||
if (api)
|
||||
c->spawn_api = *api;
|
||||
|
||||
c->do_autospawn = TRUE;
|
||||
|
||||
/* Check whether we can get the lock right now*/
|
||||
if ((k = pa_autospawn_lock_acquire(FALSE)) < 0) {
|
||||
pa_context_fail(c, PA_ERR_ACCESS);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (k > 0)
|
||||
/* So we got it, rock on! */
|
||||
c->autospawn_locked = TRUE;
|
||||
else {
|
||||
/* Hmm, we didn't get it, so let's wait for it */
|
||||
c->autospawn_event = c->mainloop->io_new(c->mainloop, c->autospawn_fd, PA_IO_EVENT_INPUT, autospawn_cb, c);
|
||||
|
||||
pa_context_set_state(c, PA_CONTEXT_CONNECTING);
|
||||
r = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -929,11 +1027,11 @@ int pa_context_is_pending(pa_context *c) {
|
|||
|
||||
static void set_dispatch_callbacks(pa_operation *o);
|
||||
|
||||
static void pdispatch_drain_callback(PA_GCC_UNUSED pa_pdispatch*pd, void *userdata) {
|
||||
static void pdispatch_drain_callback(pa_pdispatch*pd, void *userdata) {
|
||||
set_dispatch_callbacks(userdata);
|
||||
}
|
||||
|
||||
static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream *s, void *userdata) {
|
||||
static void pstream_drain_callback(pa_pstream *s, void *userdata) {
|
||||
set_dispatch_callbacks(userdata);
|
||||
}
|
||||
|
||||
|
|
@ -985,7 +1083,7 @@ pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *u
|
|||
return o;
|
||||
}
|
||||
|
||||
void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int success = 1;
|
||||
|
||||
|
|
@ -1137,7 +1235,7 @@ const char* pa_context_get_server(pa_context *c) {
|
|||
return c->server;
|
||||
}
|
||||
|
||||
uint32_t pa_context_get_protocol_version(PA_GCC_UNUSED pa_context *c) {
|
||||
uint32_t pa_context_get_protocol_version(pa_context *c) {
|
||||
return PA_PROTOCOL_VERSION;
|
||||
}
|
||||
|
||||
|
|
@ -1230,3 +1328,31 @@ pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[]
|
|||
|
||||
return o;
|
||||
}
|
||||
|
||||
void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_context *c = userdata;
|
||||
uint32_t idx;
|
||||
const char *name;
|
||||
|
||||
pa_assert(pd);
|
||||
pa_assert(command == PA_COMMAND_EXTENSION);
|
||||
pa_assert(t);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
pa_context_ref(c);
|
||||
|
||||
if (pa_tagstruct_getu32(t, &idx) < 0 ||
|
||||
pa_tagstruct_gets(t, &name) < 0) {
|
||||
pa_context_fail(c, PA_ERR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!strcmp(name, "module-stream-restore"))
|
||||
pa_ext_stream_restore_command(c, tag, t);
|
||||
else
|
||||
pa_log(_("Received message for unknown extension '%s'"), name);
|
||||
|
||||
finish:
|
||||
pa_context_unref(c);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/native-common.h>
|
||||
|
|
@ -39,32 +40,34 @@
|
|||
const char*pa_strerror(int error) {
|
||||
|
||||
static const char* const errortab[PA_ERR_MAX] = {
|
||||
[PA_OK] = "OK",
|
||||
[PA_ERR_ACCESS] = "Access denied",
|
||||
[PA_ERR_COMMAND] = "Unknown command",
|
||||
[PA_ERR_INVALID] = "Invalid argument",
|
||||
[PA_ERR_EXIST] = "Entity exists",
|
||||
[PA_ERR_NOENTITY] = "No such entity",
|
||||
[PA_ERR_CONNECTIONREFUSED] = "Connection refused",
|
||||
[PA_ERR_PROTOCOL] = "Protocol error",
|
||||
[PA_ERR_TIMEOUT] = "Timeout",
|
||||
[PA_ERR_AUTHKEY] = "No authorization key",
|
||||
[PA_ERR_INTERNAL] = "Internal error",
|
||||
[PA_ERR_CONNECTIONTERMINATED] = "Connection terminated",
|
||||
[PA_ERR_KILLED] = "Entity killed",
|
||||
[PA_ERR_INVALIDSERVER] = "Invalid server",
|
||||
[PA_ERR_MODINITFAILED] = "Module initalization failed",
|
||||
[PA_ERR_BADSTATE] = "Bad state",
|
||||
[PA_ERR_NODATA] = "No data",
|
||||
[PA_ERR_VERSION] = "Incompatible protocol version",
|
||||
[PA_ERR_TOOLARGE] = "Too large",
|
||||
[PA_ERR_NOTSUPPORTED] = "Not supported",
|
||||
[PA_ERR_UNKNOWN] = "Unknown error code",
|
||||
[PA_ERR_NOEXTENSION] = "No such extension"
|
||||
[PA_OK] = N_("OK"),
|
||||
[PA_ERR_ACCESS] = N_("Access denied"),
|
||||
[PA_ERR_COMMAND] = N_("Unknown command"),
|
||||
[PA_ERR_INVALID] = N_("Invalid argument"),
|
||||
[PA_ERR_EXIST] = N_("Entity exists"),
|
||||
[PA_ERR_NOENTITY] = N_("No such entity"),
|
||||
[PA_ERR_CONNECTIONREFUSED] = N_("Connection refused"),
|
||||
[PA_ERR_PROTOCOL] = N_("Protocol error"),
|
||||
[PA_ERR_TIMEOUT] = N_("Timeout"),
|
||||
[PA_ERR_AUTHKEY] = N_("No authorization key"),
|
||||
[PA_ERR_INTERNAL] = N_("Internal error"),
|
||||
[PA_ERR_CONNECTIONTERMINATED] = N_("Connection terminated"),
|
||||
[PA_ERR_KILLED] = N_("Entity killed"),
|
||||
[PA_ERR_INVALIDSERVER] = N_("Invalid server"),
|
||||
[PA_ERR_MODINITFAILED] = N_("Module initalization failed"),
|
||||
[PA_ERR_BADSTATE] = N_("Bad state"),
|
||||
[PA_ERR_NODATA] = N_("No data"),
|
||||
[PA_ERR_VERSION] = N_("Incompatible protocol version"),
|
||||
[PA_ERR_TOOLARGE] = N_("Too large"),
|
||||
[PA_ERR_NOTSUPPORTED] = N_("Not supported"),
|
||||
[PA_ERR_UNKNOWN] = N_("Unknown error code"),
|
||||
[PA_ERR_NOEXTENSION] = N_("No such extension")
|
||||
};
|
||||
|
||||
pa_init_i18n();
|
||||
|
||||
if (error < 0 || error >= PA_ERR_MAX)
|
||||
return NULL;
|
||||
|
||||
return errortab[error];
|
||||
return _(errortab[error]);
|
||||
}
|
||||
|
|
|
|||
326
src/pulse/ext-stream-restore.c
Normal file
326
src/pulse/ext-stream-restore.c
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2008 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.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/context.h>
|
||||
#include <pulse/gccmacro.h>
|
||||
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/pstream-util.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include "ext-stream-restore.h"
|
||||
|
||||
enum {
|
||||
SUBCOMMAND_TEST,
|
||||
SUBCOMMAND_READ,
|
||||
SUBCOMMAND_WRITE,
|
||||
SUBCOMMAND_DELETE,
|
||||
SUBCOMMAND_SUBSCRIBE,
|
||||
SUBCOMMAND_EVENT
|
||||
};
|
||||
|
||||
static void ext_stream_restore_test_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
uint32_t version = PA_INVALID_INDEX;
|
||||
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
||||
if (command != PA_COMMAND_REPLY) {
|
||||
if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
|
||||
goto finish;
|
||||
|
||||
} else if (pa_tagstruct_getu32(t, &version) < 0 ||
|
||||
!pa_tagstruct_eof(t)) {
|
||||
|
||||
pa_context_fail(o->context, PA_ERR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (o->callback) {
|
||||
pa_ext_stream_restore_test_cb_t cb = (pa_ext_stream_restore_test_cb_t) o->callback;
|
||||
cb(o->context, version, o->userdata);
|
||||
}
|
||||
|
||||
finish:
|
||||
pa_operation_done(o);
|
||||
pa_operation_unref(o);
|
||||
}
|
||||
|
||||
pa_operation *pa_ext_stream_restore_test(
|
||||
pa_context *c,
|
||||
pa_ext_stream_restore_test_cb_t cb,
|
||||
void *userdata) {
|
||||
|
||||
uint32_t tag;
|
||||
pa_operation *o;
|
||||
pa_tagstruct *t;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
|
||||
|
||||
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
|
||||
|
||||
t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
|
||||
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
|
||||
pa_tagstruct_puts(t, "module-stream-restore");
|
||||
pa_tagstruct_putu32(t, SUBCOMMAND_TEST);
|
||||
pa_pstream_send_tagstruct(c->pstream, t);
|
||||
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_stream_restore_test_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
static void ext_stream_restore_read_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
||||
if (command != PA_COMMAND_REPLY) {
|
||||
if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
|
||||
goto finish;
|
||||
|
||||
eol = -1;
|
||||
} else {
|
||||
|
||||
while (!pa_tagstruct_eof(t)) {
|
||||
pa_ext_stream_restore_info i;
|
||||
pa_bool_t mute = FALSE;
|
||||
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
||||
if (pa_tagstruct_gets(t, &i.name) < 0 ||
|
||||
pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
|
||||
pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.device) < 0 ||
|
||||
pa_tagstruct_get_boolean(t, &mute) < 0) {
|
||||
|
||||
pa_context_fail(o->context, PA_ERR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
i.mute = (int) mute;
|
||||
|
||||
if (o->callback) {
|
||||
pa_ext_stream_restore_read_cb_t cb = (pa_ext_stream_restore_read_cb_t) o->callback;
|
||||
cb(o->context, &i, 0, o->userdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (o->callback) {
|
||||
pa_ext_stream_restore_read_cb_t cb = (pa_ext_stream_restore_read_cb_t) o->callback;
|
||||
cb(o->context, NULL, eol, o->userdata);
|
||||
}
|
||||
|
||||
finish:
|
||||
pa_operation_done(o);
|
||||
pa_operation_unref(o);
|
||||
}
|
||||
|
||||
pa_operation *pa_ext_stream_restore_read(
|
||||
pa_context *c,
|
||||
pa_ext_stream_restore_read_cb_t cb,
|
||||
void *userdata) {
|
||||
|
||||
uint32_t tag;
|
||||
pa_operation *o;
|
||||
pa_tagstruct *t;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
|
||||
|
||||
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
|
||||
|
||||
t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
|
||||
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
|
||||
pa_tagstruct_puts(t, "module-stream-restore");
|
||||
pa_tagstruct_putu32(t, SUBCOMMAND_READ);
|
||||
pa_pstream_send_tagstruct(c->pstream, t);
|
||||
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_stream_restore_read_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
pa_operation *pa_ext_stream_restore_write(
|
||||
pa_context *c,
|
||||
pa_update_mode_t mode,
|
||||
const pa_ext_stream_restore_info data[],
|
||||
unsigned n,
|
||||
int apply_immediately,
|
||||
pa_context_success_cb_t cb,
|
||||
void *userdata) {
|
||||
|
||||
uint32_t tag;
|
||||
pa_operation *o;
|
||||
pa_tagstruct *t;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE || mode == PA_UPDATE_SET);
|
||||
pa_assert(data);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
|
||||
|
||||
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
|
||||
|
||||
t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
|
||||
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
|
||||
pa_tagstruct_puts(t, "module-stream-restore");
|
||||
pa_tagstruct_putu32(t, SUBCOMMAND_WRITE);
|
||||
|
||||
pa_tagstruct_putu32(t, mode);
|
||||
pa_tagstruct_put_boolean(t, apply_immediately);
|
||||
|
||||
for (; n > 0; n--, data++) {
|
||||
pa_tagstruct_puts(t, data->name);
|
||||
pa_tagstruct_put_channel_map(t, &data->channel_map);
|
||||
pa_tagstruct_put_cvolume(t, &data->volume);
|
||||
pa_tagstruct_puts(t, data->device);
|
||||
pa_tagstruct_put_boolean(t, data->mute);
|
||||
}
|
||||
|
||||
pa_pstream_send_tagstruct(c->pstream, t);
|
||||
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
pa_operation *pa_ext_stream_restore_delete(
|
||||
pa_context *c,
|
||||
const char *const s[],
|
||||
pa_context_success_cb_t cb,
|
||||
void *userdata) {
|
||||
|
||||
uint32_t tag;
|
||||
pa_operation *o;
|
||||
pa_tagstruct *t;
|
||||
const char *const *k;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(s);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
|
||||
|
||||
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
|
||||
|
||||
t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
|
||||
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
|
||||
pa_tagstruct_puts(t, "module-stream-restore");
|
||||
pa_tagstruct_putu32(t, SUBCOMMAND_DELETE);
|
||||
|
||||
for (k = s; *k; k++)
|
||||
pa_tagstruct_puts(t, *k);
|
||||
|
||||
pa_pstream_send_tagstruct(c->pstream, t);
|
||||
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
pa_operation *pa_ext_stream_restore_subscribe(
|
||||
pa_context *c,
|
||||
int enable,
|
||||
pa_context_success_cb_t cb,
|
||||
void *userdata) {
|
||||
|
||||
uint32_t tag;
|
||||
pa_operation *o;
|
||||
pa_tagstruct *t;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
|
||||
|
||||
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
|
||||
|
||||
t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
|
||||
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
|
||||
pa_tagstruct_puts(t, "module-stream-restore");
|
||||
pa_tagstruct_putu32(t, SUBCOMMAND_SUBSCRIBE);
|
||||
pa_tagstruct_put_boolean(t, enable);
|
||||
pa_pstream_send_tagstruct(c->pstream, t);
|
||||
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
void pa_ext_stream_restore_set_subscribe_cb(
|
||||
pa_context *c,
|
||||
pa_ext_stream_restore_subscribe_cb_t cb,
|
||||
void *userdata) {
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
c->ext_stream_restore.callback = cb;
|
||||
c->ext_stream_restore.userdata = userdata;
|
||||
}
|
||||
|
||||
void pa_ext_stream_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t) {
|
||||
uint32_t subcommand;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(t);
|
||||
|
||||
if (pa_tagstruct_getu32(t, &subcommand) < 0 ||
|
||||
!pa_tagstruct_eof(t)) {
|
||||
|
||||
pa_context_fail(c, PA_ERR_PROTOCOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (subcommand != SUBCOMMAND_EVENT) {
|
||||
pa_context_fail(c, PA_ERR_PROTOCOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->ext_stream_restore.callback)
|
||||
c->ext_stream_restore.callback(c, c->ext_stream_restore.userdata);
|
||||
|
||||
}
|
||||
107
src/pulse/ext-stream-restore.h
Normal file
107
src/pulse/ext-stream-restore.h
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
#ifndef foopulseextstreamrestorehfoo
|
||||
#define foopulseextstreamrestorehfoo
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2008 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.
|
||||
***/
|
||||
|
||||
#include <pulse/context.h>
|
||||
|
||||
/** \file
|
||||
*
|
||||
* Routines for controlling module-stream-restore
|
||||
*/
|
||||
|
||||
PA_C_DECL_BEGIN
|
||||
|
||||
/** Stores information about one entry in the stream database that is
|
||||
* maintained by module-stream-restore. \since 0.9.12 */
|
||||
typedef struct pa_ext_stream_restore_info {
|
||||
const char *name; /**< Identifier string of the stream. A string like "sink-input-by-role:" or similar followed by some arbitrary property value. */
|
||||
pa_channel_map channel_map; /**< The channel map for the volume field */
|
||||
pa_cvolume volume; /**< The volume of the stream when it was seen last, if applicable */
|
||||
const char *device; /**< The sink/source of the stream when it was last seen */
|
||||
int mute; /**< The boolean mute state of the stream when it was last seen, if applicable */
|
||||
} pa_ext_stream_restore_info;
|
||||
|
||||
/** Callback prototype for pa_ext_stream_restore_test(). \since 0.9.12 */
|
||||
typedef void (*pa_ext_stream_restore_test_cb_t)(
|
||||
pa_context *c,
|
||||
uint32_t version,
|
||||
void *userdata);
|
||||
|
||||
/** Test if this extension module is available in the server. \since 0.9.12 */
|
||||
pa_operation *pa_ext_stream_restore_test(
|
||||
pa_context *c,
|
||||
pa_ext_stream_restore_test_cb_t cb,
|
||||
void *userdata);
|
||||
|
||||
/** Callback prototype for pa_ext_stream_restore_read(). \since 0.9.12 */
|
||||
typedef void (*pa_ext_stream_restore_read_cb_t)(
|
||||
pa_context *c,
|
||||
const pa_ext_stream_restore_info *info,
|
||||
int eol,
|
||||
void *userdata);
|
||||
|
||||
/** Read all entries from the stream database. \since 0.9.12 */
|
||||
pa_operation *pa_ext_stream_restore_read(
|
||||
pa_context *c,
|
||||
pa_ext_stream_restore_read_cb_t cb,
|
||||
void *userdata);
|
||||
|
||||
/** Store entries in the stream database. \since 0.9.12 */
|
||||
pa_operation *pa_ext_stream_restore_write(
|
||||
pa_context *c,
|
||||
pa_update_mode_t mode,
|
||||
const pa_ext_stream_restore_info data[],
|
||||
unsigned n,
|
||||
int apply_immediately,
|
||||
pa_context_success_cb_t cb,
|
||||
void *userdata);
|
||||
|
||||
/** Delete entries from the stream database. \since 0.9.12 */
|
||||
pa_operation *pa_ext_stream_restore_delete(
|
||||
pa_context *c,
|
||||
const char *const s[],
|
||||
pa_context_success_cb_t cb,
|
||||
void *userdata);
|
||||
|
||||
/** Subscribe to changes in the stream database. \since 0.9.12 */
|
||||
pa_operation *pa_ext_stream_restore_subscribe(
|
||||
pa_context *c,
|
||||
int enable,
|
||||
pa_context_success_cb_t cb,
|
||||
void *userdata);
|
||||
|
||||
/** Callback prototype for pa_ext_stream_restore_set_subscribe_cb(). \since 0.9.12 */
|
||||
typedef void (*pa_ext_stream_restore_subscribe_cb_t)(
|
||||
pa_context *c,
|
||||
void *userdata);
|
||||
|
||||
/** Set the subscription callback that is called when
|
||||
* pa_ext_stream_restore_subscribe() was called. \since 0.9.12 */
|
||||
void pa_ext_stream_restore_set_subscribe_cb(
|
||||
pa_context *c,
|
||||
pa_ext_stream_restore_subscribe_cb_t cb,
|
||||
void *userdata);
|
||||
|
||||
PA_C_DECL_END
|
||||
|
||||
#endif
|
||||
|
|
@ -195,11 +195,11 @@ static void cleanup_defer_events(pa_glib_mainloop *g, int force) {
|
|||
}
|
||||
|
||||
static gushort map_flags_to_glib(pa_io_event_flags_t flags) {
|
||||
return
|
||||
(flags & PA_IO_EVENT_INPUT ? G_IO_IN : 0) |
|
||||
(flags & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0) |
|
||||
(flags & PA_IO_EVENT_ERROR ? G_IO_ERR : 0) |
|
||||
(flags & PA_IO_EVENT_HANGUP ? G_IO_HUP : 0);
|
||||
return (gushort)
|
||||
((flags & PA_IO_EVENT_INPUT ? G_IO_IN : 0) |
|
||||
(flags & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0) |
|
||||
(flags & PA_IO_EVENT_ERROR ? G_IO_ERR : 0) |
|
||||
(flags & PA_IO_EVENT_HANGUP ? G_IO_HUP : 0));
|
||||
}
|
||||
|
||||
static pa_io_event_flags_t map_flags_from_glib(gushort flags) {
|
||||
|
|
@ -425,7 +425,7 @@ static void glib_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_
|
|||
|
||||
/* quit() */
|
||||
|
||||
static void glib_quit(pa_mainloop_api*a, PA_GCC_UNUSED int retval) {
|
||||
static void glib_quit(pa_mainloop_api*a, int retval) {
|
||||
|
||||
g_warning("quit() ignored");
|
||||
|
||||
|
|
@ -536,7 +536,7 @@ static gboolean check_func(GSource *source) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean dispatch_func(GSource *source, PA_GCC_UNUSED GSourceFunc callback, PA_GCC_UNUSED gpointer userdata) {
|
||||
static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer userdata) {
|
||||
pa_glib_mainloop *g = (pa_glib_mainloop*) source;
|
||||
pa_io_event *e;
|
||||
|
||||
|
|
|
|||
38
src/pulse/i18n.c
Normal file
38
src/pulse/i18n.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2008 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.1 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
|
||||
Lesser 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
|
||||
|
||||
#include <pulsecore/once.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
void pa_init_i18n(void) {
|
||||
|
||||
PA_ONCE_BEGIN {
|
||||
|
||||
bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
|
||||
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
|
||||
|
||||
} PA_ONCE_END;
|
||||
}
|
||||
62
src/pulse/i18n.h
Normal file
62
src/pulse/i18n.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef foopulsei18nhfoo
|
||||
#define foopulsei18nhfoo
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2008 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.1 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
|
||||
Lesser 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.
|
||||
***/
|
||||
|
||||
#include <pulse/cdecl.h>
|
||||
#include <pulse/gccmacro.h>
|
||||
|
||||
PA_C_DECL_BEGIN
|
||||
|
||||
#if !defined(GETTEXT_PACKAGE)
|
||||
#error "Something is very wrong here, config.h needs to be included first"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
|
||||
#include <libintl.h>
|
||||
|
||||
#define _(String) dgettext(GETTEXT_PACKAGE, String)
|
||||
#ifdef gettext_noop
|
||||
#define N_(String) gettext_noop(String)
|
||||
#else
|
||||
#define N_(String) (String)
|
||||
#endif
|
||||
|
||||
#else /* NLS is disabled */
|
||||
|
||||
#define _(String) (String)
|
||||
#define N_(String) (String)
|
||||
#define textdomain(String) (String)
|
||||
#define gettext(String) (String)
|
||||
#define dgettext(Domain,String) (String)
|
||||
#define dcgettext(Domain,String,Type) (String)
|
||||
#define bindtextdomain(Domain,Directory) (Domain)
|
||||
#define bind_textdomain_codeset(Domain,Codeset) (Codeset)
|
||||
|
||||
#endif /* ENABLE_NLS */
|
||||
|
||||
void pa_init_i18n(void);
|
||||
|
||||
PA_C_DECL_END
|
||||
|
||||
#endif
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
#include <pulse/stream.h>
|
||||
#include <pulse/operation.h>
|
||||
#include <pulse/subscribe.h>
|
||||
#include <pulse/ext-stream-restore.h>
|
||||
|
||||
#include <pulsecore/socket-client.h>
|
||||
#include <pulsecore/pstream.h>
|
||||
|
|
@ -63,7 +64,7 @@ struct pa_context {
|
|||
uint32_t version;
|
||||
uint32_t ctag;
|
||||
uint32_t csyncid;
|
||||
uint32_t error;
|
||||
int error;
|
||||
pa_context_state_t state;
|
||||
|
||||
pa_context_notify_cb_t state_callback;
|
||||
|
|
@ -74,9 +75,12 @@ struct pa_context {
|
|||
pa_mempool *mempool;
|
||||
|
||||
pa_bool_t is_local:1;
|
||||
pa_bool_t do_autospawn:1;
|
||||
pa_bool_t do_shm:1;
|
||||
int autospawn_lock_fd;
|
||||
|
||||
pa_bool_t do_autospawn:1;
|
||||
pa_bool_t autospawn_locked:1;
|
||||
int autospawn_fd;
|
||||
pa_io_event *autospawn_event;
|
||||
pa_spawn_api spawn_api;
|
||||
|
||||
pa_strlist *server_list;
|
||||
|
|
@ -86,6 +90,12 @@ struct pa_context {
|
|||
pa_client_conf *conf;
|
||||
|
||||
uint32_t client_index;
|
||||
|
||||
/* Extension specific data */
|
||||
struct {
|
||||
pa_ext_stream_restore_subscribe_cb_t callback;
|
||||
void *userdata;
|
||||
} ext_stream_restore;
|
||||
};
|
||||
|
||||
#define PA_MAX_WRITE_INDEX_CORRECTIONS 32
|
||||
|
|
@ -233,4 +243,6 @@ pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *ta
|
|||
|
||||
#define PA_CHECK_VALIDITY_RETURN_NULL(context, expression, error) PA_CHECK_VALIDITY_RETURN_ANY(context, expression, error, NULL)
|
||||
|
||||
void pa_ext_stream_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
/*** Statistics ***/
|
||||
|
||||
static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
static void context_stat_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
pa_stat_info i, *p = &i;
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ pa_operation* pa_context_stat(pa_context *c, pa_stat_info_cb_t cb, void *userdat
|
|||
|
||||
/*** Server Info ***/
|
||||
|
||||
static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
pa_server_info i, *p = &i;
|
||||
|
||||
|
|
@ -127,7 +127,7 @@ pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb,
|
|||
|
||||
/*** Sink Info ***/
|
||||
|
||||
static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
|
|
@ -248,7 +248,7 @@ pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name,
|
|||
|
||||
/*** Source info ***/
|
||||
|
||||
static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
|
|
@ -369,7 +369,7 @@ pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name
|
|||
|
||||
/*** Client info ***/
|
||||
|
||||
static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
|
|
@ -451,7 +451,7 @@ pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t
|
|||
|
||||
/*** Module info ***/
|
||||
|
||||
static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
|
|
@ -530,7 +530,7 @@ pa_operation* pa_context_get_module_info_list(pa_context *c, pa_module_info_cb_t
|
|||
|
||||
/*** Sink input info ***/
|
||||
|
||||
static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
|
|
@ -624,7 +624,7 @@ pa_operation* pa_context_get_sink_input_info_list(pa_context *c, void (*cb)(pa_c
|
|||
|
||||
/*** Source output info ***/
|
||||
|
||||
static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
|
|
@ -954,7 +954,7 @@ pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name
|
|||
|
||||
/** Sample Cache **/
|
||||
|
||||
static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
|
|
@ -1098,7 +1098,7 @@ pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_cont
|
|||
return command_kill(c, PA_COMMAND_KILL_SOURCE_OUTPUT, idx, cb, userdata);
|
||||
}
|
||||
|
||||
static void context_index_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
static void context_index_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
uint32_t idx;
|
||||
|
||||
|
|
@ -1159,7 +1159,7 @@ pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_s
|
|||
|
||||
/*** Autoload stuff ***/
|
||||
|
||||
static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -52,14 +52,14 @@
|
|||
* Some objects can have multiple entries at the server. When requesting all
|
||||
* of these at once, the callback will be called multiple times, once for
|
||||
* each object. When the list has been exhausted, the callback will be called
|
||||
* without an information structure and the eol parameter set to a non-zero
|
||||
* without an information structure and the eol parameter set to a positive
|
||||
* value.
|
||||
*
|
||||
* Note that even if a single object is requested, and not the entire list,
|
||||
* the terminating call will still be made.
|
||||
*
|
||||
* If an error occurs, the callback will be called without and information
|
||||
* structure and eol set to zero.
|
||||
* structure and eol set to a negative value..
|
||||
*
|
||||
* Data members in the information structures are only valid during the
|
||||
* duration of the callback. If they are required after the callback is
|
||||
|
|
@ -210,11 +210,6 @@
|
|||
|
||||
PA_C_DECL_BEGIN
|
||||
|
||||
#define PA_PORT_DIGITAL "spdif"
|
||||
#define PA_PORT_ANALOG_STEREO "analog-stereo"
|
||||
#define PA_PORT_ANALOG_5_1 "analog-5-1"
|
||||
#define PA_PORT_ANALOG_4_0 "analog-4-0"
|
||||
|
||||
/** @{ \name Sinks */
|
||||
|
||||
/** Stores information about sinks. Please note that this structure
|
||||
|
|
|
|||
330
src/pulse/lock-autospawn.c
Normal file
330
src/pulse/lock-autospawn.c
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2008 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.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/poll.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <pulse/i18n.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/mutex.h>
|
||||
#include <pulsecore/thread.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
|
||||
#include "lock-autospawn.h"
|
||||
|
||||
/* So, why do we have this complex code here with threads and pipes
|
||||
* and stuff? For two reasons: POSIX file locks are per-process, not
|
||||
* per-file descriptor. That means that two contexts within the same
|
||||
* process that try to create the autospawn lock might end up assuming
|
||||
* they both managed to lock the file. And then, POSIX locking
|
||||
* operations are synchronous. If two contexts run from the same event
|
||||
* loop it must be made sure that they do not block each other, but
|
||||
* that the locking operation can happen asynchronously. */
|
||||
|
||||
#define AUTOSPAWN_LOCK "autospawn.lock"
|
||||
|
||||
static pa_mutex *mutex;
|
||||
|
||||
static unsigned n_ref = 0;
|
||||
static int lock_fd = -1;
|
||||
static pa_mutex *lock_fd_mutex = NULL;
|
||||
static pa_bool_t taken = FALSE;
|
||||
static pa_thread *thread;
|
||||
static int pipe_fd[2] = { -1, -1 };
|
||||
|
||||
static void destroy_mutex(void) PA_GCC_DESTRUCTOR;
|
||||
|
||||
static int ref(void) {
|
||||
|
||||
if (n_ref > 0) {
|
||||
|
||||
pa_assert(pipe_fd[0] >= 0);
|
||||
pa_assert(pipe_fd[1] >= 0);
|
||||
|
||||
n_ref++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pa_assert(lock_fd < 0);
|
||||
pa_assert(!lock_fd_mutex);
|
||||
pa_assert(!taken);
|
||||
pa_assert(!thread);
|
||||
pa_assert(pipe_fd[0] < 0);
|
||||
pa_assert(pipe_fd[1] < 0);
|
||||
|
||||
if (pipe(pipe_fd) < 0)
|
||||
return -1;
|
||||
|
||||
lock_fd_mutex = pa_mutex_new(FALSE, FALSE);
|
||||
|
||||
pa_make_fd_cloexec(pipe_fd[0]);
|
||||
pa_make_fd_cloexec(pipe_fd[1]);
|
||||
|
||||
pa_make_fd_nonblock(pipe_fd[1]);
|
||||
pa_make_fd_nonblock(pipe_fd[0]);
|
||||
|
||||
n_ref = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void unref(pa_bool_t after_fork) {
|
||||
|
||||
pa_assert(n_ref > 0);
|
||||
pa_assert(pipe_fd[0] >= 0);
|
||||
pa_assert(pipe_fd[1] >= 0);
|
||||
pa_assert(lock_fd_mutex);
|
||||
|
||||
n_ref--;
|
||||
|
||||
if (n_ref > 0)
|
||||
return;
|
||||
|
||||
pa_assert(!taken);
|
||||
|
||||
if (thread) {
|
||||
pa_thread_free(thread);
|
||||
thread = NULL;
|
||||
}
|
||||
|
||||
pa_mutex_lock(lock_fd_mutex);
|
||||
if (lock_fd >= 0) {
|
||||
|
||||
if (after_fork)
|
||||
pa_close(lock_fd);
|
||||
else {
|
||||
char *lf;
|
||||
|
||||
if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK)))
|
||||
pa_log_warn(_("Cannot access autospawn lock."));
|
||||
|
||||
pa_unlock_lockfile(lf, lock_fd);
|
||||
pa_xfree(lf);
|
||||
|
||||
lock_fd = -1;
|
||||
}
|
||||
}
|
||||
pa_mutex_unlock(lock_fd_mutex);
|
||||
|
||||
pa_mutex_free(lock_fd_mutex);
|
||||
lock_fd_mutex = NULL;
|
||||
|
||||
pa_close(pipe_fd[0]);
|
||||
pa_close(pipe_fd[1]);
|
||||
pipe_fd[0] = pipe_fd[1] = -1;
|
||||
}
|
||||
|
||||
static void ping(void) {
|
||||
ssize_t s;
|
||||
|
||||
pa_assert(pipe_fd[1] >= 0);
|
||||
|
||||
for (;;) {
|
||||
char x = 'x';
|
||||
|
||||
if ((s = write(pipe_fd[1], &x, 1)) == 1)
|
||||
break;
|
||||
|
||||
pa_assert(s < 0);
|
||||
|
||||
if (errno == EAGAIN)
|
||||
break;
|
||||
|
||||
pa_assert(errno == EINTR);
|
||||
}
|
||||
}
|
||||
|
||||
static void wait_for_ping(void) {
|
||||
ssize_t s;
|
||||
char x;
|
||||
struct pollfd pfd;
|
||||
int k;
|
||||
|
||||
pa_assert(pipe_fd[0] >= 0);
|
||||
|
||||
memset(&pfd, 0, sizeof(pfd));
|
||||
pfd.fd = pipe_fd[0];
|
||||
pfd.events = POLLIN;
|
||||
|
||||
if ((k = poll(&pfd, 1, -1)) != 1) {
|
||||
pa_assert(k < 0);
|
||||
pa_assert(errno == EINTR);
|
||||
} else if ((s = read(pipe_fd[0], &x, 1)) != 1) {
|
||||
pa_assert(s < 0);
|
||||
pa_assert(errno == EAGAIN);
|
||||
}
|
||||
}
|
||||
|
||||
static void empty_pipe(void) {
|
||||
char x[16];
|
||||
ssize_t s;
|
||||
|
||||
pa_assert(pipe_fd[0] >= 0);
|
||||
|
||||
if ((s = read(pipe_fd[0], &x, sizeof(x))) < 1) {
|
||||
pa_assert(s < 0);
|
||||
pa_assert(errno == EAGAIN);
|
||||
}
|
||||
}
|
||||
|
||||
static void thread_func(void *u) {
|
||||
int fd;
|
||||
char *lf;
|
||||
sigset_t fullset;
|
||||
|
||||
/* No signals in this thread please */
|
||||
sigfillset(&fullset);
|
||||
pthread_sigmask(SIG_BLOCK, &fullset, NULL);
|
||||
|
||||
if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK))) {
|
||||
pa_log_warn(_("Cannot access autospawn lock."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((fd = pa_lock_lockfile(lf)) < 0)
|
||||
goto finish;
|
||||
|
||||
pa_mutex_lock(lock_fd_mutex);
|
||||
pa_assert(lock_fd < 0);
|
||||
lock_fd = fd;
|
||||
pa_mutex_unlock(lock_fd_mutex);
|
||||
|
||||
finish:
|
||||
pa_xfree(lf);
|
||||
|
||||
ping();
|
||||
}
|
||||
|
||||
static int start_thread(void) {
|
||||
|
||||
if (!thread)
|
||||
if (!(thread = pa_thread_new(thread_func, NULL)))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void create_mutex(void) {
|
||||
PA_ONCE_BEGIN {
|
||||
mutex = pa_mutex_new(FALSE, FALSE);
|
||||
} PA_ONCE_END;
|
||||
}
|
||||
|
||||
static void destroy_mutex(void) {
|
||||
|
||||
if (mutex)
|
||||
pa_mutex_free(mutex);
|
||||
}
|
||||
|
||||
|
||||
int pa_autospawn_lock_init(void) {
|
||||
int ret = -1;
|
||||
|
||||
create_mutex();
|
||||
pa_mutex_lock(mutex);
|
||||
|
||||
if (ref() < 0)
|
||||
ret = -1;
|
||||
else
|
||||
ret = pipe_fd[0];
|
||||
|
||||
pa_mutex_unlock(mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pa_autospawn_lock_acquire(pa_bool_t block) {
|
||||
int ret = -1;
|
||||
|
||||
create_mutex();
|
||||
pa_mutex_lock(mutex);
|
||||
pa_assert(n_ref >= 1);
|
||||
|
||||
pa_mutex_lock(lock_fd_mutex);
|
||||
|
||||
for (;;) {
|
||||
|
||||
empty_pipe();
|
||||
|
||||
if (lock_fd >= 0 && !taken) {
|
||||
taken = TRUE;
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lock_fd < 0)
|
||||
if (start_thread() < 0)
|
||||
break;
|
||||
|
||||
if (!block) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
pa_mutex_unlock(lock_fd_mutex);
|
||||
pa_mutex_unlock(mutex);
|
||||
|
||||
wait_for_ping();
|
||||
|
||||
pa_mutex_lock(mutex);
|
||||
pa_mutex_lock(lock_fd_mutex);
|
||||
}
|
||||
|
||||
pa_mutex_unlock(lock_fd_mutex);
|
||||
|
||||
pa_mutex_unlock(mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pa_autospawn_lock_release(void) {
|
||||
|
||||
create_mutex();
|
||||
pa_mutex_lock(mutex);
|
||||
pa_assert(n_ref >= 1);
|
||||
|
||||
pa_assert(taken);
|
||||
taken = FALSE;
|
||||
|
||||
ping();
|
||||
|
||||
pa_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
void pa_autospawn_lock_done(pa_bool_t after_fork) {
|
||||
|
||||
create_mutex();
|
||||
pa_mutex_lock(mutex);
|
||||
pa_assert(n_ref >= 1);
|
||||
|
||||
unref(after_fork);
|
||||
|
||||
pa_mutex_unlock(mutex);
|
||||
}
|
||||
32
src/pulse/lock-autospawn.h
Normal file
32
src/pulse/lock-autospawn.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef foopulselockautospawnhfoo
|
||||
#define foopulselockautospawnhfoo
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2008 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.1 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
|
||||
Lesser 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.
|
||||
***/
|
||||
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
int pa_autospawn_lock_init(void);
|
||||
int pa_autospawn_lock_acquire(pa_bool_t block);
|
||||
void pa_autospawn_lock_release(void);
|
||||
void pa_autospawn_lock_done(pa_bool_t after_fork);
|
||||
|
||||
#endif
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/gccmacro.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
|
|
@ -50,7 +51,7 @@ static void once_callback(pa_mainloop_api *m, pa_defer_event *e, void *userdata)
|
|||
m->defer_free(e);
|
||||
}
|
||||
|
||||
static void free_callback(pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event *e, void *userdata) {
|
||||
static void free_callback(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
|
||||
struct once_info *i = userdata;
|
||||
|
||||
pa_assert(m);
|
||||
|
|
@ -65,6 +66,8 @@ void pa_mainloop_api_once(pa_mainloop_api* m, void (*callback)(pa_mainloop_api *
|
|||
pa_assert(m);
|
||||
pa_assert(callback);
|
||||
|
||||
pa_init_i18n();
|
||||
|
||||
i = pa_xnew(struct once_info, 1);
|
||||
i->callback = callback;
|
||||
i->userdata = userdata;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/gccmacro.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
|
|
@ -89,7 +90,7 @@ static void dispatch(pa_mainloop_api*a, int sig) {
|
|||
}
|
||||
}
|
||||
|
||||
static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t f, PA_GCC_UNUSED void *userdata) {
|
||||
static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata) {
|
||||
ssize_t r;
|
||||
int sig;
|
||||
|
||||
|
|
@ -165,6 +166,8 @@ pa_signal_event* pa_signal_new(int sig, pa_signal_cb_t _callback, void *userdata
|
|||
pa_assert(sig > 0);
|
||||
pa_assert(_callback);
|
||||
|
||||
pa_init_i18n();
|
||||
|
||||
for (e = signals; e; e = e->next)
|
||||
if (e->sig == sig)
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/llist.h>
|
||||
|
|
@ -56,7 +57,7 @@
|
|||
|
||||
struct pa_io_event {
|
||||
pa_mainloop *mainloop;
|
||||
int dead;
|
||||
pa_bool_t dead:1;
|
||||
|
||||
int fd;
|
||||
pa_io_event_flags_t events;
|
||||
|
|
@ -71,9 +72,9 @@ struct pa_io_event {
|
|||
|
||||
struct pa_time_event {
|
||||
pa_mainloop *mainloop;
|
||||
int dead;
|
||||
pa_bool_t dead:1;
|
||||
|
||||
int enabled;
|
||||
pa_bool_t enabled:1;
|
||||
struct timeval timeval;
|
||||
|
||||
pa_time_event_cb_t callback;
|
||||
|
|
@ -85,9 +86,9 @@ struct pa_time_event {
|
|||
|
||||
struct pa_defer_event {
|
||||
pa_mainloop *mainloop;
|
||||
int dead;
|
||||
pa_bool_t dead:1;
|
||||
|
||||
int enabled;
|
||||
pa_bool_t enabled:1;
|
||||
|
||||
pa_defer_event_cb_t callback;
|
||||
void *userdata;
|
||||
|
|
@ -101,22 +102,24 @@ struct pa_mainloop {
|
|||
PA_LLIST_HEAD(pa_time_event, time_events);
|
||||
PA_LLIST_HEAD(pa_defer_event, defer_events);
|
||||
|
||||
int n_enabled_defer_events, n_enabled_time_events, n_io_events;
|
||||
int io_events_please_scan, time_events_please_scan, defer_events_please_scan;
|
||||
unsigned n_enabled_defer_events, n_enabled_time_events, n_io_events;
|
||||
unsigned io_events_please_scan, time_events_please_scan, defer_events_please_scan;
|
||||
|
||||
pa_bool_t rebuild_pollfds:1;
|
||||
struct pollfd *pollfds;
|
||||
unsigned max_pollfds, n_pollfds;
|
||||
int rebuild_pollfds;
|
||||
|
||||
int prepared_timeout;
|
||||
pa_time_event *cached_next_time_event;
|
||||
|
||||
int quit, retval;
|
||||
pa_mainloop_api api;
|
||||
|
||||
int retval;
|
||||
pa_bool_t quit:1;
|
||||
|
||||
pa_bool_t wakeup_requested:1;
|
||||
int wakeup_pipe[2];
|
||||
int wakeup_pipe_type;
|
||||
int wakeup_requested;
|
||||
|
||||
enum {
|
||||
STATE_PASSIVE,
|
||||
|
|
@ -132,11 +135,11 @@ struct pa_mainloop {
|
|||
};
|
||||
|
||||
static short map_flags_to_libc(pa_io_event_flags_t flags) {
|
||||
return
|
||||
(flags & PA_IO_EVENT_INPUT ? POLLIN : 0) |
|
||||
(flags & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) |
|
||||
(flags & PA_IO_EVENT_ERROR ? POLLERR : 0) |
|
||||
(flags & PA_IO_EVENT_HANGUP ? POLLHUP : 0);
|
||||
return (short)
|
||||
((flags & PA_IO_EVENT_INPUT ? POLLIN : 0) |
|
||||
(flags & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) |
|
||||
(flags & PA_IO_EVENT_ERROR ? POLLERR : 0) |
|
||||
(flags & PA_IO_EVENT_HANGUP ? POLLHUP : 0));
|
||||
}
|
||||
|
||||
static pa_io_event_flags_t map_flags_from_libc(short flags) {
|
||||
|
|
@ -168,7 +171,7 @@ static pa_io_event* mainloop_io_new(
|
|||
|
||||
e = pa_xnew(pa_io_event, 1);
|
||||
e->mainloop = m;
|
||||
e->dead = 0;
|
||||
e->dead = FALSE;
|
||||
|
||||
e->fd = fd;
|
||||
e->events = events;
|
||||
|
|
@ -193,13 +196,13 @@ static pa_io_event* mainloop_io_new(
|
|||
SELECT_TYPE_ARG5 &tv) == -1) &&
|
||||
(WSAGetLastError() == WSAENOTSOCK)) {
|
||||
pa_log_warn("Cannot monitor non-socket file descriptors.");
|
||||
e->dead = 1;
|
||||
e->dead = TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
PA_LLIST_PREPEND(pa_io_event, m->io_events, e);
|
||||
m->rebuild_pollfds = 1;
|
||||
m->rebuild_pollfds = TRUE;
|
||||
m->n_io_events ++;
|
||||
|
||||
pa_mainloop_wakeup(m);
|
||||
|
|
@ -219,7 +222,7 @@ static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) {
|
|||
if (e->pollfd)
|
||||
e->pollfd->events = map_flags_to_libc(events);
|
||||
else
|
||||
e->mainloop->rebuild_pollfds = 1;
|
||||
e->mainloop->rebuild_pollfds = TRUE;
|
||||
|
||||
pa_mainloop_wakeup(e->mainloop);
|
||||
}
|
||||
|
|
@ -228,11 +231,11 @@ static void mainloop_io_free(pa_io_event *e) {
|
|||
pa_assert(e);
|
||||
pa_assert(!e->dead);
|
||||
|
||||
e->dead = 1;
|
||||
e->dead = TRUE;
|
||||
e->mainloop->io_events_please_scan ++;
|
||||
|
||||
e->mainloop->n_io_events --;
|
||||
e->mainloop->rebuild_pollfds = 1;
|
||||
e->mainloop->rebuild_pollfds = TRUE;
|
||||
|
||||
pa_mainloop_wakeup(e->mainloop);
|
||||
}
|
||||
|
|
@ -261,9 +264,9 @@ static pa_defer_event* mainloop_defer_new(
|
|||
|
||||
e = pa_xnew(pa_defer_event, 1);
|
||||
e->mainloop = m;
|
||||
e->dead = 0;
|
||||
e->dead = FALSE;
|
||||
|
||||
e->enabled = 1;
|
||||
e->enabled = TRUE;
|
||||
m->n_enabled_defer_events++;
|
||||
|
||||
e->callback = callback;
|
||||
|
|
@ -296,13 +299,13 @@ static void mainloop_defer_free(pa_defer_event *e) {
|
|||
pa_assert(e);
|
||||
pa_assert(!e->dead);
|
||||
|
||||
e->dead = 1;
|
||||
e->dead = TRUE;
|
||||
e->mainloop->defer_events_please_scan ++;
|
||||
|
||||
if (e->enabled) {
|
||||
pa_assert(e->mainloop->n_enabled_defer_events > 0);
|
||||
e->mainloop->n_enabled_defer_events--;
|
||||
e->enabled = 0;
|
||||
e->enabled = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -332,7 +335,7 @@ static pa_time_event* mainloop_time_new(
|
|||
|
||||
e = pa_xnew(pa_time_event, 1);
|
||||
e->mainloop = m;
|
||||
e->dead = 0;
|
||||
e->dead = FALSE;
|
||||
|
||||
if ((e->enabled = !!tv)) {
|
||||
e->timeval = *tv;
|
||||
|
|
@ -387,13 +390,13 @@ static void mainloop_time_free(pa_time_event *e) {
|
|||
pa_assert(e);
|
||||
pa_assert(!e->dead);
|
||||
|
||||
e->dead = 1;
|
||||
e->dead = TRUE;
|
||||
e->mainloop->time_events_please_scan ++;
|
||||
|
||||
if (e->enabled) {
|
||||
pa_assert(e->mainloop->n_enabled_time_events > 0);
|
||||
e->mainloop->n_enabled_time_events--;
|
||||
e->enabled = 0;
|
||||
e->enabled = FALSE;
|
||||
}
|
||||
|
||||
if (e->mainloop->cached_next_time_event == e)
|
||||
|
|
@ -446,6 +449,8 @@ static const pa_mainloop_api vtable = {
|
|||
pa_mainloop *pa_mainloop_new(void) {
|
||||
pa_mainloop *m;
|
||||
|
||||
pa_init_i18n();
|
||||
|
||||
m = pa_xnew(pa_mainloop, 1);
|
||||
|
||||
m->wakeup_pipe_type = 0;
|
||||
|
|
@ -459,7 +464,7 @@ pa_mainloop *pa_mainloop_new(void) {
|
|||
pa_make_fd_nonblock(m->wakeup_pipe[1]);
|
||||
pa_make_fd_cloexec(m->wakeup_pipe[0]);
|
||||
pa_make_fd_cloexec(m->wakeup_pipe[1]);
|
||||
m->wakeup_requested = 0;
|
||||
m->wakeup_requested = FALSE;
|
||||
|
||||
PA_LLIST_HEAD_INIT(pa_io_event, m->io_events);
|
||||
PA_LLIST_HEAD_INIT(pa_time_event, m->time_events);
|
||||
|
|
@ -473,9 +478,10 @@ pa_mainloop *pa_mainloop_new(void) {
|
|||
|
||||
m->pollfds = NULL;
|
||||
m->max_pollfds = m->n_pollfds = 0;
|
||||
m->rebuild_pollfds = 1;
|
||||
m->rebuild_pollfds = TRUE;
|
||||
|
||||
m->quit = m->retval = 0;
|
||||
m->quit = FALSE;
|
||||
m->retval = 0;
|
||||
|
||||
m->api = vtable;
|
||||
m->api.userdata = m;
|
||||
|
|
@ -489,7 +495,7 @@ pa_mainloop *pa_mainloop_new(void) {
|
|||
return m;
|
||||
}
|
||||
|
||||
static void cleanup_io_events(pa_mainloop *m, int force) {
|
||||
static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) {
|
||||
pa_io_event *e;
|
||||
|
||||
e = m->io_events;
|
||||
|
|
@ -512,7 +518,7 @@ static void cleanup_io_events(pa_mainloop *m, int force) {
|
|||
|
||||
pa_xfree(e);
|
||||
|
||||
m->rebuild_pollfds = 1;
|
||||
m->rebuild_pollfds = TRUE;
|
||||
}
|
||||
|
||||
e = n;
|
||||
|
|
@ -521,7 +527,7 @@ static void cleanup_io_events(pa_mainloop *m, int force) {
|
|||
pa_assert(m->io_events_please_scan == 0);
|
||||
}
|
||||
|
||||
static void cleanup_time_events(pa_mainloop *m, int force) {
|
||||
static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) {
|
||||
pa_time_event *e;
|
||||
|
||||
e = m->time_events;
|
||||
|
|
@ -542,7 +548,7 @@ static void cleanup_time_events(pa_mainloop *m, int force) {
|
|||
if (!e->dead && e->enabled) {
|
||||
pa_assert(m->n_enabled_time_events > 0);
|
||||
m->n_enabled_time_events--;
|
||||
e->enabled = 0;
|
||||
e->enabled = FALSE;
|
||||
}
|
||||
|
||||
if (e->destroy_callback)
|
||||
|
|
@ -557,7 +563,7 @@ static void cleanup_time_events(pa_mainloop *m, int force) {
|
|||
pa_assert(m->time_events_please_scan == 0);
|
||||
}
|
||||
|
||||
static void cleanup_defer_events(pa_mainloop *m, int force) {
|
||||
static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) {
|
||||
pa_defer_event *e;
|
||||
|
||||
e = m->defer_events;
|
||||
|
|
@ -578,7 +584,7 @@ static void cleanup_defer_events(pa_mainloop *m, int force) {
|
|||
if (!e->dead && e->enabled) {
|
||||
pa_assert(m->n_enabled_defer_events > 0);
|
||||
m->n_enabled_defer_events--;
|
||||
e->enabled = 0;
|
||||
e->enabled = FALSE;
|
||||
}
|
||||
|
||||
if (e->destroy_callback)
|
||||
|
|
@ -597,9 +603,9 @@ static void cleanup_defer_events(pa_mainloop *m, int force) {
|
|||
void pa_mainloop_free(pa_mainloop* m) {
|
||||
pa_assert(m);
|
||||
|
||||
cleanup_io_events(m, 1);
|
||||
cleanup_defer_events(m, 1);
|
||||
cleanup_time_events(m, 1);
|
||||
cleanup_io_events(m, TRUE);
|
||||
cleanup_defer_events(m, TRUE);
|
||||
cleanup_time_events(m, TRUE);
|
||||
|
||||
pa_xfree(m->pollfds);
|
||||
|
||||
|
|
@ -612,13 +618,13 @@ static void scan_dead(pa_mainloop *m) {
|
|||
pa_assert(m);
|
||||
|
||||
if (m->io_events_please_scan)
|
||||
cleanup_io_events(m, 0);
|
||||
cleanup_io_events(m, FALSE);
|
||||
|
||||
if (m->time_events_please_scan)
|
||||
cleanup_time_events(m, 0);
|
||||
cleanup_time_events(m, FALSE);
|
||||
|
||||
if (m->defer_events_please_scan)
|
||||
cleanup_defer_events(m, 0);
|
||||
cleanup_defer_events(m, FALSE);
|
||||
}
|
||||
|
||||
static void rebuild_pollfds(pa_mainloop *m) {
|
||||
|
|
@ -659,7 +665,7 @@ static void rebuild_pollfds(pa_mainloop *m) {
|
|||
m->n_pollfds++;
|
||||
}
|
||||
|
||||
m->rebuild_pollfds = 0;
|
||||
m->rebuild_pollfds = FALSE;
|
||||
}
|
||||
|
||||
static int dispatch_pollfds(pa_mainloop *m) {
|
||||
|
|
@ -945,7 +951,7 @@ int pa_mainloop_run(pa_mainloop *m, int *retval) {
|
|||
void pa_mainloop_quit(pa_mainloop *m, int retval) {
|
||||
pa_assert(m);
|
||||
|
||||
m->quit = 1;
|
||||
m->quit = TRUE;
|
||||
m->retval = retval;
|
||||
pa_mainloop_wakeup(m);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/utf8.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/hashmap.h>
|
||||
#include <pulsecore/strbuf.h>
|
||||
|
|
@ -63,6 +64,8 @@ static void property_free(struct property *prop) {
|
|||
}
|
||||
|
||||
pa_proplist* pa_proplist_new(void) {
|
||||
pa_init_i18n();
|
||||
|
||||
return MAKE_PROPLIST(pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func));
|
||||
}
|
||||
|
||||
|
|
@ -277,7 +280,7 @@ char *pa_proplist_to_string(pa_proplist *p) {
|
|||
char *c;
|
||||
|
||||
pa_assert_se(pa_proplist_get(p, key, &value, &nbytes) == 0);
|
||||
c = pa_xnew(char, nbytes*2+1);
|
||||
c = pa_xmalloc(nbytes*2+1);
|
||||
pa_hexstr((const uint8_t*) value, nbytes, c, nbytes*2+1);
|
||||
|
||||
pa_strbuf_printf(buf, "%s = hex:%s\n", key, c);
|
||||
|
|
|
|||
|
|
@ -28,9 +28,11 @@
|
|||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulse/timeval.h>
|
||||
|
||||
#include "sample.h"
|
||||
|
||||
|
|
@ -126,8 +128,10 @@ char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
|
|||
pa_assert(l);
|
||||
pa_assert(spec);
|
||||
|
||||
pa_init_i18n();
|
||||
|
||||
if (!pa_sample_spec_valid(spec))
|
||||
pa_snprintf(s, l, "Invalid");
|
||||
pa_snprintf(s, l, _("Invalid"));
|
||||
else
|
||||
pa_snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate);
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) {
|
|||
|
||||
PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY(s->context, length > 0, PA_ERR_INVALID);
|
||||
PA_CHECK_VALIDITY(s->context, length == (size_t) (uint32_t) length, PA_ERR_INVALID);
|
||||
|
||||
if (!(name = pa_proplist_gets(s->proplist, PA_PROP_EVENT_ID)))
|
||||
name = pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME);
|
||||
|
|
@ -63,7 +64,7 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) {
|
|||
pa_tagstruct_puts(t, name);
|
||||
pa_tagstruct_put_sample_spec(t, &s->sample_spec);
|
||||
pa_tagstruct_put_channel_map(t, &s->channel_map);
|
||||
pa_tagstruct_putu32(t, length);
|
||||
pa_tagstruct_putu32(t, (uint32_t) length);
|
||||
|
||||
if (s->context->version >= 13) {
|
||||
pa_init_proplist(s->proplist);
|
||||
|
|
|
|||
|
|
@ -453,4 +453,3 @@ unlock_and_fail:
|
|||
pa_threaded_mainloop_unlock(p->mainloop);
|
||||
return (pa_usec_t) -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ pa_stream *pa_stream_new_with_proplist(
|
|||
* what older PA versions provided. */
|
||||
|
||||
s->buffer_attr.maxlength = (uint32_t) -1;
|
||||
s->buffer_attr.tlength = pa_usec_to_bytes(250*PA_USEC_PER_MSEC, ss); /* 250ms of buffering */
|
||||
s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes(250*PA_USEC_PER_MSEC, ss); /* 250ms of buffering */
|
||||
s->buffer_attr.minreq = (uint32_t) -1;
|
||||
s->buffer_attr.prebuf = (uint32_t) -1;
|
||||
s->buffer_attr.fragsize = (uint32_t) -1;
|
||||
|
|
@ -315,7 +315,7 @@ static void request_auto_timing_update(pa_stream *s, pa_bool_t force) {
|
|||
}
|
||||
}
|
||||
|
||||
void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_context *c = userdata;
|
||||
pa_stream *s;
|
||||
uint32_t channel;
|
||||
|
|
@ -382,7 +382,7 @@ static void check_smoother_status(pa_stream *s, pa_bool_t aposteriori, pa_bool_t
|
|||
* if prebuf is non-zero! */
|
||||
}
|
||||
|
||||
void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_context *c = userdata;
|
||||
pa_stream *s;
|
||||
uint32_t channel;
|
||||
|
|
@ -479,7 +479,7 @@ finish:
|
|||
pa_context_unref(c);
|
||||
}
|
||||
|
||||
void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_context *c = userdata;
|
||||
pa_stream *s;
|
||||
uint32_t channel;
|
||||
|
|
@ -563,7 +563,7 @@ finish:
|
|||
pa_context_unref(c);
|
||||
}
|
||||
|
||||
void pa_command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
void pa_command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_stream *s;
|
||||
pa_context *c = userdata;
|
||||
uint32_t bytes, channel;
|
||||
|
|
@ -598,7 +598,7 @@ finish:
|
|||
pa_context_unref(c);
|
||||
}
|
||||
|
||||
void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_stream *s;
|
||||
pa_context *c = userdata;
|
||||
uint32_t channel;
|
||||
|
|
@ -670,7 +670,7 @@ static void invalidate_indexes(pa_stream *s, pa_bool_t r, pa_bool_t w) {
|
|||
request_auto_timing_update(s, TRUE);
|
||||
}
|
||||
|
||||
static void auto_timing_update_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC_UNUSED pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) {
|
||||
static void auto_timing_update_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *tv, void *userdata) {
|
||||
pa_stream *s = userdata;
|
||||
|
||||
pa_assert(s);
|
||||
|
|
@ -694,7 +694,7 @@ static void create_stream_complete(pa_stream *s) {
|
|||
if (s->flags & PA_STREAM_AUTO_TIMING_UPDATE) {
|
||||
struct timeval tv;
|
||||
pa_gettimeofday(&tv);
|
||||
tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */
|
||||
tv.tv_usec += (suseconds_t) LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */
|
||||
pa_assert(!s->auto_timing_update_event);
|
||||
s->auto_timing_update_event = s->mainloop->time_new(s->mainloop, &tv, &auto_timing_update_callback, s);
|
||||
|
||||
|
|
@ -722,7 +722,7 @@ static void automatic_buffer_attr(pa_stream *s, pa_buffer_attr *attr, const pa_s
|
|||
attr->maxlength = 4*1024*1024; /* 4MB is the maximum queue length PulseAudio <= 0.9.9 supported. */
|
||||
|
||||
if (attr->tlength == (uint32_t) -1)
|
||||
attr->tlength = pa_usec_to_bytes(250*PA_USEC_PER_MSEC, ss); /* 250ms of buffering */
|
||||
attr->tlength = (uint32_t) pa_usec_to_bytes(250*PA_USEC_PER_MSEC, ss); /* 250ms of buffering */
|
||||
|
||||
if (attr->minreq == (uint32_t) -1)
|
||||
attr->minreq = (attr->tlength)/5; /* Ask for more data when there are only 200ms left in the playback buffer */
|
||||
|
|
@ -734,7 +734,7 @@ static void automatic_buffer_attr(pa_stream *s, pa_buffer_attr *attr, const pa_s
|
|||
attr->fragsize = attr->tlength; /* Pass data to the app only when the buffer is filled up once */
|
||||
}
|
||||
|
||||
void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_stream *s = userdata;
|
||||
|
||||
pa_assert(pd);
|
||||
|
|
@ -865,6 +865,7 @@ static int create_stream(
|
|||
|
||||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
pa_bool_t volume_set = FALSE;
|
||||
|
||||
pa_assert(s);
|
||||
pa_assert(PA_REFCNT_VALUE(s) >= 1);
|
||||
|
|
@ -930,7 +931,7 @@ static int create_stream(
|
|||
|
||||
t = pa_tagstruct_command(
|
||||
s->context,
|
||||
s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM,
|
||||
(uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM),
|
||||
&tag);
|
||||
|
||||
if (s->context->version < 13)
|
||||
|
|
@ -957,6 +958,8 @@ static int create_stream(
|
|||
PA_TAG_U32, s->syncid,
|
||||
PA_TAG_INVALID);
|
||||
|
||||
volume_set = !!volume;
|
||||
|
||||
if (!volume)
|
||||
volume = pa_cvolume_reset(&cv, s->sample_spec.channels);
|
||||
|
||||
|
|
@ -994,6 +997,15 @@ static int create_stream(
|
|||
pa_tagstruct_putu32(t, s->direct_on_input);
|
||||
}
|
||||
|
||||
if (s->context->version >= 14 &&
|
||||
s->direction == PA_STREAM_PLAYBACK) {
|
||||
|
||||
pa_tagstruct_put(
|
||||
t,
|
||||
PA_TAG_BOOLEAN, volume_set,
|
||||
PA_TAG_INVALID);
|
||||
}
|
||||
|
||||
pa_pstream_send_tagstruct(s->context->pstream, t);
|
||||
pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL);
|
||||
|
||||
|
|
@ -1093,7 +1105,7 @@ int pa_stream_write(
|
|||
free_cb((void*) data);
|
||||
|
||||
if (length < s->requested_bytes)
|
||||
s->requested_bytes -= length;
|
||||
s->requested_bytes -= (uint32_t) length;
|
||||
else
|
||||
s->requested_bytes = 0;
|
||||
|
||||
|
|
@ -1107,10 +1119,10 @@ int pa_stream_write(
|
|||
if (seek == PA_SEEK_ABSOLUTE) {
|
||||
s->write_index_corrections[s->current_write_index_correction].corrupt = FALSE;
|
||||
s->write_index_corrections[s->current_write_index_correction].absolute = TRUE;
|
||||
s->write_index_corrections[s->current_write_index_correction].value = offset + length;
|
||||
s->write_index_corrections[s->current_write_index_correction].value = offset + (int64_t) length;
|
||||
} else if (seek == PA_SEEK_RELATIVE) {
|
||||
if (!s->write_index_corrections[s->current_write_index_correction].corrupt)
|
||||
s->write_index_corrections[s->current_write_index_correction].value += offset + length;
|
||||
s->write_index_corrections[s->current_write_index_correction].value += offset + (int64_t) length;
|
||||
} else
|
||||
s->write_index_corrections[s->current_write_index_correction].corrupt = TRUE;
|
||||
}
|
||||
|
|
@ -1120,10 +1132,10 @@ int pa_stream_write(
|
|||
|
||||
if (seek == PA_SEEK_ABSOLUTE) {
|
||||
s->timing_info.write_index_corrupt = FALSE;
|
||||
s->timing_info.write_index = offset + length;
|
||||
s->timing_info.write_index = offset + (int64_t) length;
|
||||
} else if (seek == PA_SEEK_RELATIVE) {
|
||||
if (!s->timing_info.write_index_corrupt)
|
||||
s->timing_info.write_index += offset + length;
|
||||
s->timing_info.write_index += offset + (int64_t) length;
|
||||
} else
|
||||
s->timing_info.write_index_corrupt = TRUE;
|
||||
}
|
||||
|
|
@ -1173,7 +1185,7 @@ int pa_stream_drop(pa_stream *s) {
|
|||
|
||||
/* Fix the simulated local read index */
|
||||
if (s->timing_info_valid && !s->timing_info.read_index_corrupt)
|
||||
s->timing_info.read_index += s->peek_memchunk.length;
|
||||
s->timing_info.read_index += (int64_t) s->peek_memchunk.length;
|
||||
|
||||
pa_assert(s->peek_data);
|
||||
pa_memblock_release(s->peek_memchunk.memblock);
|
||||
|
|
@ -1257,7 +1269,9 @@ static pa_usec_t calc_time(pa_stream *s, pa_bool_t ignore_transport) {
|
|||
usec -= s->timing_info.sink_usec;
|
||||
}
|
||||
|
||||
} else if (s->direction == PA_STREAM_RECORD) {
|
||||
} else {
|
||||
pa_assert(s->direction == PA_STREAM_RECORD);
|
||||
|
||||
/* The last byte written into the server side queue had
|
||||
* this time value associated */
|
||||
usec = pa_bytes_to_usec(s->timing_info.write_index < 0 ? 0 : (uint64_t) s->timing_info.write_index, &s->sample_spec);
|
||||
|
|
@ -1340,7 +1354,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
|
|||
i->read_index_corrupt = FALSE;
|
||||
|
||||
i->playing = (int) playing;
|
||||
i->since_underrun = playing ? playing_for : underrun_for;
|
||||
i->since_underrun = (int64_t) (playing ? playing_for : underrun_for);
|
||||
|
||||
pa_gettimeofday(&now);
|
||||
|
||||
|
|
@ -1418,7 +1432,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
|
|||
/* Read index correction */
|
||||
|
||||
if (!i->read_index_corrupt)
|
||||
i->read_index -= pa_memblockq_get_length(o->stream->record_memblockq);
|
||||
i->read_index -= (int64_t) pa_memblockq_get_length(o->stream->record_memblockq);
|
||||
}
|
||||
|
||||
/* Update smoother */
|
||||
|
|
@ -1435,7 +1449,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
|
|||
* speakers. Since we follow that timing here, we need
|
||||
* to try to fix this up */
|
||||
|
||||
su = pa_bytes_to_usec(i->since_underrun, &o->stream->sample_spec);
|
||||
su = pa_bytes_to_usec((uint64_t) i->since_underrun, &o->stream->sample_spec);
|
||||
|
||||
if (su < i->sink_usec)
|
||||
x += i->sink_usec - su;
|
||||
|
|
@ -1494,7 +1508,7 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t
|
|||
|
||||
t = pa_tagstruct_command(
|
||||
s->context,
|
||||
s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_GET_PLAYBACK_LATENCY : PA_COMMAND_GET_RECORD_LATENCY,
|
||||
(uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_GET_PLAYBACK_LATENCY : PA_COMMAND_GET_RECORD_LATENCY),
|
||||
&tag);
|
||||
pa_tagstruct_putu32(t, s->channel);
|
||||
pa_tagstruct_put_timeval(t, pa_gettimeofday(&now));
|
||||
|
|
@ -1517,7 +1531,7 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t
|
|||
return o;
|
||||
}
|
||||
|
||||
void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_stream *s = userdata;
|
||||
|
||||
pa_assert(pd);
|
||||
|
|
@ -1557,8 +1571,8 @@ int pa_stream_disconnect(pa_stream *s) {
|
|||
|
||||
t = pa_tagstruct_command(
|
||||
s->context,
|
||||
s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
|
||||
(s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM),
|
||||
(uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
|
||||
(s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)),
|
||||
&tag);
|
||||
pa_tagstruct_putu32(t, s->channel);
|
||||
pa_pstream_send_tagstruct(s->context->pstream, t);
|
||||
|
|
@ -1667,7 +1681,7 @@ void pa_stream_set_started_callback(pa_stream *s, pa_stream_notify_cb_t cb, void
|
|||
s->started_userdata = userdata;
|
||||
}
|
||||
|
||||
void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int success = 1;
|
||||
|
||||
|
|
@ -1715,7 +1729,7 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi
|
|||
|
||||
t = pa_tagstruct_command(
|
||||
s->context,
|
||||
s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CORK_PLAYBACK_STREAM : PA_COMMAND_CORK_RECORD_STREAM,
|
||||
(uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CORK_PLAYBACK_STREAM : PA_COMMAND_CORK_RECORD_STREAM),
|
||||
&tag);
|
||||
pa_tagstruct_putu32(t, s->channel);
|
||||
pa_tagstruct_put_boolean(t, !!b);
|
||||
|
|
@ -1760,7 +1774,7 @@ pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *use
|
|||
PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
|
||||
|
||||
if (!(o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata)))
|
||||
if (!(o = stream_send_simple_command(s, (uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM), cb, userdata)))
|
||||
return NULL;
|
||||
|
||||
if (s->direction == PA_STREAM_PLAYBACK) {
|
||||
|
|
@ -1846,7 +1860,7 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe
|
|||
o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
|
||||
t = pa_tagstruct_command(
|
||||
s->context,
|
||||
s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_NAME : PA_COMMAND_SET_PLAYBACK_STREAM_NAME,
|
||||
(uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_NAME : PA_COMMAND_SET_PLAYBACK_STREAM_NAME),
|
||||
&tag);
|
||||
pa_tagstruct_putu32(t, s->channel);
|
||||
pa_tagstruct_puts(t, name);
|
||||
|
|
@ -1932,7 +1946,7 @@ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) {
|
|||
if (cindex < 0)
|
||||
cindex = 0;
|
||||
|
||||
c = pa_bytes_to_usec(cindex, &s->sample_spec);
|
||||
c = pa_bytes_to_usec((uint64_t) cindex, &s->sample_spec);
|
||||
|
||||
if (s->direction == PA_STREAM_PLAYBACK)
|
||||
*r_usec = time_counter_diff(s, c, t, negative);
|
||||
|
|
@ -1978,7 +1992,7 @@ const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s) {
|
|||
return &s->buffer_attr;
|
||||
}
|
||||
|
||||
static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int success = 1;
|
||||
|
||||
|
|
@ -2046,7 +2060,7 @@ pa_operation* pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr
|
|||
|
||||
t = pa_tagstruct_command(
|
||||
s->context,
|
||||
s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR : PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR,
|
||||
(uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR : PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR),
|
||||
&tag);
|
||||
pa_tagstruct_putu32(t, s->channel);
|
||||
|
||||
|
|
@ -2120,7 +2134,7 @@ int pa_stream_is_corked(pa_stream *s) {
|
|||
return s->corked;
|
||||
}
|
||||
|
||||
static void stream_update_sample_rate_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
static void stream_update_sample_rate_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int success = 1;
|
||||
|
||||
|
|
@ -2177,7 +2191,7 @@ pa_operation *pa_stream_update_sample_rate(pa_stream *s, uint32_t rate, pa_strea
|
|||
|
||||
t = pa_tagstruct_command(
|
||||
s->context,
|
||||
s->direction == PA_STREAM_RECORD ? PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE : PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE,
|
||||
(uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE : PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE),
|
||||
&tag);
|
||||
pa_tagstruct_putu32(t, s->channel);
|
||||
pa_tagstruct_putu32(t, rate);
|
||||
|
|
@ -2205,7 +2219,7 @@ pa_operation *pa_stream_proplist_update(pa_stream *s, pa_update_mode_t mode, pa_
|
|||
|
||||
t = pa_tagstruct_command(
|
||||
s->context,
|
||||
s->direction == PA_STREAM_RECORD ? PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST : PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST,
|
||||
(uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST : PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST),
|
||||
&tag);
|
||||
pa_tagstruct_putu32(t, s->channel);
|
||||
pa_tagstruct_putu32(t, (uint32_t) mode);
|
||||
|
|
@ -2238,7 +2252,7 @@ pa_operation *pa_stream_proplist_remove(pa_stream *s, const char *const keys[],
|
|||
|
||||
t = pa_tagstruct_command(
|
||||
s->context,
|
||||
s->direction == PA_STREAM_RECORD ? PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST : PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST,
|
||||
(uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST : PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST),
|
||||
&tag);
|
||||
pa_tagstruct_putu32(t, s->channel);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#include "subscribe.h"
|
||||
|
||||
void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_context *c = userdata;
|
||||
pa_subscription_event_type_t e;
|
||||
uint32_t idx;
|
||||
|
|
@ -61,7 +61,6 @@ finish:
|
|||
pa_context_unref(c);
|
||||
}
|
||||
|
||||
|
||||
pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata) {
|
||||
pa_operation *o;
|
||||
pa_tagstruct *t;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/mainloop.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/hashmap.h>
|
||||
|
|
@ -94,6 +95,8 @@ static void thread(void *userdata) {
|
|||
pa_threaded_mainloop *pa_threaded_mainloop_new(void) {
|
||||
pa_threaded_mainloop *m;
|
||||
|
||||
pa_init_i18n();
|
||||
|
||||
m = pa_xnew(pa_threaded_mainloop, 1);
|
||||
|
||||
if (!(m->real_mainloop = pa_mainloop_new())) {
|
||||
|
|
|
|||
|
|
@ -90,13 +90,13 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
|
|||
}
|
||||
|
||||
/* Calculate the second difference*/
|
||||
r = ((pa_usec_t) a->tv_sec - b->tv_sec) * PA_USEC_PER_SEC;
|
||||
r = ((pa_usec_t) a->tv_sec - (pa_usec_t) b->tv_sec) * PA_USEC_PER_SEC;
|
||||
|
||||
/* Calculate the microsecond difference */
|
||||
if (a->tv_usec > b->tv_usec)
|
||||
r += ((pa_usec_t) a->tv_usec - b->tv_usec);
|
||||
r += ((pa_usec_t) a->tv_usec - (pa_usec_t) b->tv_usec);
|
||||
else if (a->tv_usec < b->tv_usec)
|
||||
r -= ((pa_usec_t) b->tv_usec - a->tv_usec);
|
||||
r -= ((pa_usec_t) b->tv_usec - (pa_usec_t) a->tv_usec);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -132,7 +132,7 @@ struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
|
|||
pa_assert(tv);
|
||||
|
||||
secs = (unsigned long) (v/PA_USEC_PER_SEC);
|
||||
tv->tv_sec += secs;
|
||||
tv->tv_sec += (time_t) secs;
|
||||
v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
|
||||
|
||||
tv->tv_usec += (suseconds_t) v;
|
||||
|
|
@ -140,7 +140,7 @@ struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
|
|||
/* Normalize */
|
||||
while ((unsigned) tv->tv_usec >= PA_USEC_PER_SEC) {
|
||||
tv->tv_sec++;
|
||||
tv->tv_usec -= PA_USEC_PER_SEC;
|
||||
tv->tv_usec -= (suseconds_t) PA_USEC_PER_SEC;
|
||||
}
|
||||
|
||||
return tv;
|
||||
|
|
@ -151,14 +151,14 @@ struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) {
|
|||
pa_assert(tv);
|
||||
|
||||
secs = (unsigned long) (v/PA_USEC_PER_SEC);
|
||||
tv->tv_sec -= secs;
|
||||
tv->tv_sec -= (time_t) secs;
|
||||
v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
|
||||
|
||||
if (tv->tv_usec >= (suseconds_t) v)
|
||||
tv->tv_usec -= (suseconds_t) v;
|
||||
else {
|
||||
tv->tv_sec --;
|
||||
tv->tv_usec = tv->tv_usec + PA_USEC_PER_SEC - v;
|
||||
tv->tv_usec += (suseconds_t) (PA_USEC_PER_SEC - v);
|
||||
}
|
||||
|
||||
return tv;
|
||||
|
|
@ -167,8 +167,8 @@ struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) {
|
|||
struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
|
||||
pa_assert(tv);
|
||||
|
||||
tv->tv_sec = v / PA_USEC_PER_SEC;
|
||||
tv->tv_usec = v % PA_USEC_PER_SEC;
|
||||
tv->tv_sec = (time_t) (v / PA_USEC_PER_SEC);
|
||||
tv->tv_usec = (suseconds_t) (v % PA_USEC_PER_SEC);
|
||||
|
||||
return tv;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,17 +109,17 @@ static char* utf8_validate(const char *str, char *output) {
|
|||
if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */
|
||||
size = 2;
|
||||
min = 128;
|
||||
val = *p & 0x1e;
|
||||
val = (uint32_t) (*p & 0x1e);
|
||||
goto ONE_REMAINING;
|
||||
} else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/
|
||||
size = 3;
|
||||
min = (1 << 11);
|
||||
val = *p & 0x0f;
|
||||
val = (uint32_t) (*p & 0x0f);
|
||||
goto TWO_REMAINING;
|
||||
} else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */
|
||||
size = 4;
|
||||
min = (1 << 16);
|
||||
val = *p & 0x07;
|
||||
val = (uint32_t) (*p & 0x07);
|
||||
} else {
|
||||
size = 1;
|
||||
goto error;
|
||||
|
|
@ -149,7 +149,7 @@ ONE_REMAINING:
|
|||
goto error;
|
||||
|
||||
if (o) {
|
||||
memcpy(o, last, size);
|
||||
memcpy(o, last, (size_t) size);
|
||||
o += size - 1;
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ char* pa_utf8_filter (const char *str) {
|
|||
char *new_str;
|
||||
|
||||
pa_assert(str);
|
||||
new_str = pa_xnew(char, strlen(str) + 1);
|
||||
new_str = pa_xmalloc(strlen(str) + 1);
|
||||
return utf8_validate(str, new_str);
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +212,7 @@ static char* iconv_simple(const char *str, const char *to, const char *from) {
|
|||
return NULL;
|
||||
|
||||
inlen = len = strlen(str) + 1;
|
||||
new_str = pa_xnew(char, len);
|
||||
new_str = pa_xmalloc(len);
|
||||
|
||||
for (;;) {
|
||||
inbuf = (ICONV_CONST char*) str; /* Brain dead prototype for iconv() */
|
||||
|
|
|
|||
|
|
@ -95,12 +95,15 @@ char *pa_get_user_name(char *s, size_t l) {
|
|||
#elif defined(OS_IS_WIN32) /* HAVE_PWD_H */
|
||||
DWORD size = sizeof(buf);
|
||||
|
||||
if (!GetUserName(buf, &size))
|
||||
if (!GetUserName(buf, &size)) {
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = buf;
|
||||
|
||||
#else /* HAVE_PWD_H */
|
||||
|
||||
return NULL;
|
||||
#endif /* HAVE_PWD_H */
|
||||
}
|
||||
|
|
@ -113,10 +116,8 @@ char *pa_get_host_name(char *s, size_t l) {
|
|||
pa_assert(s);
|
||||
pa_assert(l > 0);
|
||||
|
||||
if (gethostname(s, l) < 0) {
|
||||
pa_log("gethostname(): %s", pa_cstrerror(errno));
|
||||
if (gethostname(s, l) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s[l-1] = 0;
|
||||
return s;
|
||||
|
|
@ -140,20 +141,25 @@ char *pa_get_home_dir(char *s, size_t l) {
|
|||
return pa_strlcpy(s, e, l);
|
||||
|
||||
#ifdef HAVE_PWD_H
|
||||
|
||||
errno = 0;
|
||||
#ifdef HAVE_GETPWUID_R
|
||||
if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
|
||||
pa_log("getpwuid_r() failed");
|
||||
#else
|
||||
/* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
|
||||
* that do not support getpwuid_r. */
|
||||
if ((r = getpwuid(getuid())) == NULL) {
|
||||
pa_log("getpwuid_r() failed");
|
||||
#endif
|
||||
if (!errno)
|
||||
errno = ENOENT;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pa_strlcpy(s, r->pw_dir, l);
|
||||
#else /* HAVE_PWD_H */
|
||||
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -204,6 +210,7 @@ char *pa_get_binary_name(char *s, size_t l) {
|
|||
}
|
||||
#endif
|
||||
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -253,8 +260,8 @@ int pa_msleep(unsigned long t) {
|
|||
#elif defined(HAVE_NANOSLEEP)
|
||||
struct timespec ts;
|
||||
|
||||
ts.tv_sec = t/1000;
|
||||
ts.tv_nsec = (t % 1000) * 1000000;
|
||||
ts.tv_sec = (time_t) (t/1000UL);
|
||||
ts.tv_nsec = (long) ((t % 1000UL) * 1000000UL);
|
||||
|
||||
return nanosleep(&ts, NULL);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) {
|
|||
pa_assert(channels > 0);
|
||||
pa_assert(channels <= PA_CHANNELS_MAX);
|
||||
|
||||
a->channels = channels;
|
||||
a->channels = (uint8_t) channels;
|
||||
|
||||
for (i = 0; i < a->channels; i++)
|
||||
a->values[i] = v;
|
||||
|
|
@ -74,6 +74,18 @@ pa_volume_t pa_cvolume_avg(const pa_cvolume *a) {
|
|||
return (pa_volume_t) sum;
|
||||
}
|
||||
|
||||
pa_volume_t pa_cvolume_max(const pa_cvolume *a) {
|
||||
pa_volume_t m = 0;
|
||||
int i;
|
||||
pa_assert(a);
|
||||
|
||||
for (i = 0; i < a->channels; i++)
|
||||
if (a->values[i] > m)
|
||||
m = a->values[i];
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
|
||||
return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a)* pa_sw_volume_to_linear(b));
|
||||
}
|
||||
|
|
@ -163,7 +175,7 @@ pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const
|
|||
i < b->channels ? b->values[i] : PA_VOLUME_NORM);
|
||||
}
|
||||
|
||||
dest->channels = i;
|
||||
dest->channels = (uint8_t) i;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
|
@ -176,3 +188,88 @@ int pa_cvolume_valid(const pa_cvolume *v) {
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static pa_bool_t on_left(pa_channel_position_t p) {
|
||||
|
||||
return
|
||||
p == PA_CHANNEL_POSITION_FRONT_LEFT ||
|
||||
p == PA_CHANNEL_POSITION_REAR_LEFT ||
|
||||
p == PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER ||
|
||||
p == PA_CHANNEL_POSITION_SIDE_LEFT ||
|
||||
p == PA_CHANNEL_POSITION_TOP_FRONT_LEFT ||
|
||||
p == PA_CHANNEL_POSITION_TOP_REAR_LEFT;
|
||||
}
|
||||
|
||||
static pa_bool_t on_right(pa_channel_position_t p) {
|
||||
|
||||
return
|
||||
p == PA_CHANNEL_POSITION_FRONT_RIGHT ||
|
||||
p == PA_CHANNEL_POSITION_REAR_RIGHT ||
|
||||
p == PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER ||
|
||||
p == PA_CHANNEL_POSITION_SIDE_RIGHT ||
|
||||
p == PA_CHANNEL_POSITION_TOP_FRONT_RIGHT ||
|
||||
p == PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
|
||||
}
|
||||
|
||||
static pa_bool_t on_center(pa_channel_position_t p) {
|
||||
|
||||
return
|
||||
p == PA_CHANNEL_POSITION_FRONT_CENTER ||
|
||||
p == PA_CHANNEL_POSITION_REAR_CENTER ||
|
||||
p == PA_CHANNEL_POSITION_TOP_CENTER ||
|
||||
p == PA_CHANNEL_POSITION_TOP_FRONT_CENTER ||
|
||||
p == PA_CHANNEL_POSITION_TOP_REAR_CENTER;
|
||||
}
|
||||
|
||||
static pa_bool_t on_lfe(pa_channel_position_t p) {
|
||||
return
|
||||
p == PA_CHANNEL_POSITION_LFE;
|
||||
}
|
||||
|
||||
pa_cvolume *pa_cvolume_remap(pa_cvolume *v, pa_channel_map *from, pa_channel_map *to) {
|
||||
int a, b;
|
||||
pa_cvolume result;
|
||||
|
||||
pa_assert(v);
|
||||
pa_assert(from);
|
||||
pa_assert(to);
|
||||
pa_assert(v->channels == from->channels);
|
||||
|
||||
if (pa_channel_map_equal(from, to))
|
||||
return v;
|
||||
|
||||
result.channels = to->channels;
|
||||
|
||||
for (b = 0; b < to->channels; b++) {
|
||||
pa_volume_t k = 0;
|
||||
int n = 0;
|
||||
|
||||
for (a = 0; a < from->channels; a++)
|
||||
if (from->map[a] == to->map[b]) {
|
||||
k += v->values[a];
|
||||
n ++;
|
||||
}
|
||||
|
||||
if (n <= 0) {
|
||||
for (a = 0; a < from->channels; a++)
|
||||
if ((on_left(from->map[a]) && on_left(to->map[b])) ||
|
||||
(on_right(from->map[a]) && on_right(to->map[b])) ||
|
||||
(on_center(from->map[a]) && on_center(to->map[b])) ||
|
||||
(on_lfe(from->map[a]) && on_lfe(to->map[b]))) {
|
||||
|
||||
k += v->values[a];
|
||||
n ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (n <= 0)
|
||||
k = pa_cvolume_avg(v);
|
||||
else
|
||||
k /= n;
|
||||
|
||||
result.values[b] = k;
|
||||
}
|
||||
|
||||
*v = result;
|
||||
return v;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <pulse/cdecl.h>
|
||||
#include <pulse/gccmacro.h>
|
||||
#include <pulse/sample.h>
|
||||
#include <pulse/channelmap.h>
|
||||
|
||||
/** \page volume Volume Control
|
||||
*
|
||||
|
|
@ -133,6 +134,9 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c);
|
|||
/** Return the average volume of all channels */
|
||||
pa_volume_t pa_cvolume_avg(const pa_cvolume *a) PA_GCC_PURE;
|
||||
|
||||
/** Return the maximum volume of all channels. \since 0.9.12 */
|
||||
pa_volume_t pa_cvolume_max(const pa_cvolume *a) PA_GCC_PURE;
|
||||
|
||||
/** Return TRUE when the passed cvolume structure is valid, FALSE otherwise */
|
||||
int pa_cvolume_valid(const pa_cvolume *v) PA_GCC_PURE;
|
||||
|
||||
|
|
@ -170,6 +174,9 @@ double pa_sw_volume_to_linear(pa_volume_t v) PA_GCC_CONST;
|
|||
#define PA_DECIBEL_MININFTY ((double) -200.0)
|
||||
#endif
|
||||
|
||||
/** Remap a volume from one channel mapping to a different channel mapping. \since 0.9.12 */
|
||||
pa_cvolume *pa_cvolume_remap(pa_cvolume *v, pa_channel_map *from, pa_channel_map *to);
|
||||
|
||||
PA_C_DECL_END
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ char *pa_xstrndup(const char *s, size_t l) {
|
|||
return NULL;
|
||||
|
||||
if ((e = memchr(s, 0, l)))
|
||||
return pa_xmemdup(s, e-s+1);
|
||||
return pa_xmemdup(s, (size_t) (e-s+1));
|
||||
|
||||
r = pa_xmalloc(l+1);
|
||||
memcpy(r, s, l);
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ PA_STATIC_FLIST_DECLARE(localq, 0, pa_xfree);
|
|||
|
||||
#define PA_ASYNCQ_CELLS(x) ((pa_atomic_ptr_t*) ((uint8_t*) (x) + PA_ALIGN(sizeof(struct pa_asyncq))))
|
||||
|
||||
static int reduce(pa_asyncq *l, int value) {
|
||||
static unsigned reduce(pa_asyncq *l, unsigned value) {
|
||||
return value & (unsigned) (l->size - 1);
|
||||
}
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ void pa_asyncq_free(pa_asyncq *l, pa_free_cb_t free_cb) {
|
|||
}
|
||||
|
||||
static int push(pa_asyncq*l, void *p, pa_bool_t wait) {
|
||||
int idx;
|
||||
unsigned idx;
|
||||
pa_atomic_ptr_t *cells;
|
||||
|
||||
pa_assert(l);
|
||||
|
|
@ -220,7 +220,7 @@ void pa_asyncq_post(pa_asyncq*l, void *p) {
|
|||
}
|
||||
|
||||
void* pa_asyncq_pop(pa_asyncq*l, pa_bool_t wait) {
|
||||
int idx;
|
||||
unsigned idx;
|
||||
void *ret;
|
||||
pa_atomic_ptr_t *cells;
|
||||
|
||||
|
|
@ -263,7 +263,7 @@ int pa_asyncq_read_fd(pa_asyncq *q) {
|
|||
}
|
||||
|
||||
int pa_asyncq_read_before_poll(pa_asyncq *l) {
|
||||
int idx;
|
||||
unsigned idx;
|
||||
pa_atomic_ptr_t *cells;
|
||||
|
||||
pa_assert(l);
|
||||
|
|
@ -280,8 +280,6 @@ int pa_asyncq_read_before_poll(pa_asyncq *l) {
|
|||
if (pa_fdsem_before_poll(l->write_fdsem) >= 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pa_asyncq_read_after_poll(pa_asyncq *l) {
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ typedef struct pa_atomic {
|
|||
volatile AO_t value;
|
||||
} pa_atomic_t;
|
||||
|
||||
#define PA_ATOMIC_INIT(v) { .value = (v) }
|
||||
#define PA_ATOMIC_INIT(v) { .value = (AO_t) (v) }
|
||||
|
||||
static inline int pa_atomic_load(const pa_atomic_t *a) {
|
||||
return (int) AO_load_full((AO_t*) &a->value);
|
||||
|
|
@ -431,23 +431,23 @@ static inline void pa_atomic_store(pa_atomic_t *a, int i) {
|
|||
}
|
||||
|
||||
static inline int pa_atomic_add(pa_atomic_t *a, int i) {
|
||||
return AO_fetch_and_add_full(&a->value, (AO_t) i);
|
||||
return (int) AO_fetch_and_add_full(&a->value, (AO_t) i);
|
||||
}
|
||||
|
||||
static inline int pa_atomic_sub(pa_atomic_t *a, int i) {
|
||||
return AO_fetch_and_add_full(&a->value, (AO_t) -i);
|
||||
return (int) AO_fetch_and_add_full(&a->value, (AO_t) -i);
|
||||
}
|
||||
|
||||
static inline int pa_atomic_inc(pa_atomic_t *a) {
|
||||
return AO_fetch_and_add1_full(&a->value);
|
||||
return (int) AO_fetch_and_add1_full(&a->value);
|
||||
}
|
||||
|
||||
static inline int pa_atomic_dec(pa_atomic_t *a) {
|
||||
return AO_fetch_and_sub1_full(&a->value);
|
||||
return (int) AO_fetch_and_sub1_full(&a->value);
|
||||
}
|
||||
|
||||
static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) {
|
||||
return AO_compare_and_swap_full(&a->value, old_i, new_i);
|
||||
return AO_compare_and_swap_full(&a->value, (unsigned long) old_i, (unsigned long) new_i);
|
||||
}
|
||||
|
||||
typedef struct pa_atomic_ptr {
|
||||
|
|
|
|||
|
|
@ -1,104 +0,0 @@
|
|||
/***
|
||||
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.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/shared.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/refcnt.h>
|
||||
|
||||
#include "authkey-prop.h"
|
||||
|
||||
struct authkey_data {
|
||||
PA_REFCNT_DECLARE;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
int pa_authkey_prop_get(pa_core *c, const char *name, void *data, size_t len) {
|
||||
struct authkey_data *a;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(name);
|
||||
pa_assert(data);
|
||||
pa_assert(len > 0);
|
||||
|
||||
if (!(a = pa_shared_get(c, name)))
|
||||
return -1;
|
||||
|
||||
pa_assert(a->length == len);
|
||||
memcpy(data, (uint8_t*) a + PA_ALIGN(sizeof(struct authkey_data)), len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pa_authkey_prop_put(pa_core *c, const char *name, const void *data, size_t len) {
|
||||
struct authkey_data *a;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(name);
|
||||
|
||||
if (pa_shared_get(c, name))
|
||||
return -1;
|
||||
|
||||
a = pa_xmalloc(PA_ALIGN(sizeof(struct authkey_data)) + len);
|
||||
PA_REFCNT_INIT(a);
|
||||
a->length = len;
|
||||
memcpy((uint8_t*) a + PA_ALIGN(sizeof(struct authkey_data)), data, len);
|
||||
|
||||
pa_shared_set(c, name, a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pa_authkey_prop_ref(pa_core *c, const char *name) {
|
||||
struct authkey_data *a;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(name);
|
||||
|
||||
a = pa_shared_get(c, name);
|
||||
pa_assert(a);
|
||||
pa_assert(PA_REFCNT_VALUE(a) >= 1);
|
||||
PA_REFCNT_INC(a);
|
||||
}
|
||||
|
||||
void pa_authkey_prop_unref(pa_core *c, const char *name) {
|
||||
struct authkey_data *a;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(name);
|
||||
|
||||
a = pa_shared_get(c, name);
|
||||
pa_assert(a);
|
||||
pa_assert(PA_REFCNT_VALUE(a) >= 1);
|
||||
|
||||
if (PA_REFCNT_DEC(a) <= 0) {
|
||||
pa_shared_remove(c, name);
|
||||
pa_xfree(a);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#ifndef fooauthkeyprophfoo
|
||||
#define fooauthkeyprophfoo
|
||||
|
||||
/***
|
||||
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.
|
||||
***/
|
||||
|
||||
#include <pulsecore/core.h>
|
||||
|
||||
/* The authkey-prop uses a central property to store a previously
|
||||
* loaded cookie in memory. Useful for sharing the same cookie between
|
||||
* several modules. */
|
||||
|
||||
/* Return the data of the specified authorization key property. Doesn't alter the refernce count of the key */
|
||||
int pa_authkey_prop_get(pa_core *c, const char *name, void *data, size_t len);
|
||||
|
||||
/* Store data in the specified authorization key property. The initial reference count is set to 1 */
|
||||
int pa_authkey_prop_put(pa_core *c, const char *name, const void *data, size_t len);
|
||||
|
||||
/* Increase the reference count of the specified authorization key */
|
||||
void pa_authkey_prop_ref(pa_core *c, const char *name);
|
||||
|
||||
/* Decrease the reference count of the specified authorization key */
|
||||
void pa_authkey_prop_unref(pa_core *c, const char *name);
|
||||
|
||||
#endif
|
||||
|
|
@ -158,7 +158,7 @@ void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type_t type) {
|
|||
e->in_action = 0;
|
||||
}
|
||||
|
||||
static void free_func(void *p, PA_GCC_UNUSED void *userdata) {
|
||||
static void free_func(void *p, void *userdata) {
|
||||
pa_autoload_entry *e = p;
|
||||
pa_idxset_remove_by_data(e->core->autoload_idxset, e, NULL);
|
||||
entry_free(e);
|
||||
|
|
|
|||
|
|
@ -188,7 +188,9 @@ static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
|
|||
pa_assert(buf);
|
||||
pa_assert(fail);
|
||||
|
||||
c->mainloop->quit(c->mainloop, 0);
|
||||
if (pa_core_exit(c, FALSE, 0) < 0)
|
||||
pa_strbuf_puts(buf, "Not allowed to terminate daemon.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -316,22 +318,22 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
|
|||
|
||||
pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n",
|
||||
(unsigned) pa_atomic_load(&stat->n_allocated),
|
||||
pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->allocated_size)));
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->allocated_size)));
|
||||
|
||||
pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n",
|
||||
(unsigned) pa_atomic_load(&stat->n_accumulated),
|
||||
pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->accumulated_size)));
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->accumulated_size)));
|
||||
|
||||
pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n",
|
||||
(unsigned) pa_atomic_load(&stat->n_imported),
|
||||
pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->imported_size)));
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->imported_size)));
|
||||
|
||||
pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n",
|
||||
(unsigned) pa_atomic_load(&stat->n_exported),
|
||||
pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->exported_size)));
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->exported_size)));
|
||||
|
||||
pa_strbuf_printf(buf, "Total sample cache size: %s.\n",
|
||||
pa_bytes_snprint(s, sizeof(s), pa_scache_total_size(c)));
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_scache_total_size(c)));
|
||||
|
||||
pa_strbuf_printf(buf, "Default sample spec: %s\n",
|
||||
pa_sample_spec_snprint(s, sizeof(s), &c->default_sample_spec));
|
||||
|
|
@ -415,7 +417,7 @@ static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa
|
|||
return -1;
|
||||
}
|
||||
|
||||
pa_module_unload_request(m);
|
||||
pa_module_unload_request(m, FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1249,8 +1251,8 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
|
|||
nl = 1;
|
||||
}
|
||||
|
||||
pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink)));
|
||||
pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink)));
|
||||
pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink, FALSE)));
|
||||
pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink, FALSE)));
|
||||
pa_strbuf_printf(buf, "suspend-sink %s %s\n", sink->name, pa_yes_no(pa_sink_get_state(sink) == PA_SINK_SUSPENDED));
|
||||
}
|
||||
|
||||
|
|
@ -1263,8 +1265,8 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
|
|||
nl = 1;
|
||||
}
|
||||
|
||||
pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_avg(pa_source_get_volume(source)));
|
||||
pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source)));
|
||||
pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_avg(pa_source_get_volume(source, FALSE)));
|
||||
pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source, FALSE)));
|
||||
pa_strbuf_printf(buf, "suspend-source %s %s\n", source->name, pa_yes_no(pa_source_get_state(source) == PA_SOURCE_SUSPENDED));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -149,10 +149,12 @@ char *pa_sink_list_to_string(pa_core *c) {
|
|||
sink->flags & PA_SINK_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
|
||||
sink->flags & PA_SINK_LATENCY ? "LATENCY " : "",
|
||||
state_table[pa_sink_get_state(sink)],
|
||||
pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink)),
|
||||
pa_yes_no(pa_sink_get_mute(sink)),
|
||||
(double) pa_sink_get_latency(sink) / PA_USEC_PER_MSEC,
|
||||
(double) pa_sink_get_requested_latency(sink) / PA_USEC_PER_MSEC, (double) min_latency / PA_USEC_PER_MSEC, (double) max_latency / PA_USEC_PER_MSEC,
|
||||
pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, FALSE)),
|
||||
pa_yes_no(pa_sink_get_mute(sink, FALSE)),
|
||||
(double) pa_sink_get_latency(sink) / (double) PA_USEC_PER_MSEC,
|
||||
(double) pa_sink_get_requested_latency(sink) / (double) PA_USEC_PER_MSEC,
|
||||
(double) min_latency / PA_USEC_PER_MSEC,
|
||||
(double) max_latency / PA_USEC_PER_MSEC,
|
||||
(unsigned long) pa_sink_get_max_request(sink) / 1024,
|
||||
(unsigned long) pa_sink_get_max_rewind(sink) / 1024,
|
||||
sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
|
||||
|
|
@ -222,10 +224,12 @@ char *pa_source_list_to_string(pa_core *c) {
|
|||
source->flags & PA_SOURCE_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
|
||||
source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
|
||||
state_table[pa_source_get_state(source)],
|
||||
pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source)),
|
||||
pa_yes_no(pa_source_get_mute(source)),
|
||||
pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source, FALSE)),
|
||||
pa_yes_no(pa_source_get_mute(source, FALSE)),
|
||||
(double) pa_source_get_latency(source) / PA_USEC_PER_MSEC,
|
||||
(double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC, (double) min_latency / PA_USEC_PER_MSEC, (double) max_latency / PA_USEC_PER_MSEC,
|
||||
(double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC,
|
||||
(double) min_latency / PA_USEC_PER_MSEC,
|
||||
(double) max_latency / PA_USEC_PER_MSEC,
|
||||
(unsigned long) pa_source_get_max_rewind(source) / 1024,
|
||||
pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec),
|
||||
pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map),
|
||||
|
|
@ -411,7 +415,7 @@ char *pa_scache_list_to_string(pa_core *c) {
|
|||
if (e->memchunk.memblock) {
|
||||
pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec);
|
||||
pa_channel_map_snprint(cm, sizeof(cm), &e->channel_map);
|
||||
l = (double) e->memchunk.length / pa_bytes_per_second(&e->sample_spec);
|
||||
l = (double) e->memchunk.length / (double) pa_bytes_per_second(&e->sample_spec);
|
||||
}
|
||||
|
||||
pa_strbuf_printf(
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) {
|
|||
pa_log_info("Created %u \"%s\"", c->index, pa_strnull(name));
|
||||
pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index);
|
||||
|
||||
pa_core_check_quit(core);
|
||||
pa_core_check_idle(core);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
|
@ -78,7 +78,7 @@ void pa_client_free(pa_client *c) {
|
|||
pa_xfree(c->driver);
|
||||
pa_xfree(c);
|
||||
|
||||
pa_core_check_quit(core);
|
||||
pa_core_check_idle(core);
|
||||
}
|
||||
|
||||
void pa_client_kill(pa_client *c) {
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ finish:
|
|||
return r;
|
||||
}
|
||||
|
||||
int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
int *i = data;
|
||||
int32_t k;
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
int k;
|
||||
pa_bool_t *b = data;
|
||||
|
||||
|
|
@ -185,7 +185,7 @@ int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pa_config_parse_string(const char *filename, PA_GCC_UNUSED unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
|
||||
char **s = data;
|
||||
|
||||
pa_assert(filename);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
|
||||
#define UNLOAD_POLL_TIME 60
|
||||
|
||||
static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) {
|
||||
static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, const struct timeval *tv, void *userdata) {
|
||||
pa_core *c = userdata;
|
||||
struct timeval ntv;
|
||||
|
||||
|
|
@ -282,7 +282,7 @@ int pa_scache_remove_item(pa_core *c, const char *name) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void free_cb(void *p, PA_GCC_UNUSED void *userdata) {
|
||||
static void free_cb(void *p, void *userdata) {
|
||||
pa_scache_entry *e = p;
|
||||
pa_assert(e);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
struct pa_subscription {
|
||||
pa_core *core;
|
||||
int dead;
|
||||
pa_bool_t dead;
|
||||
|
||||
pa_subscription_cb_t callback;
|
||||
void *userdata;
|
||||
|
|
@ -72,7 +72,7 @@ pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, pa_su
|
|||
|
||||
s = pa_xnew(pa_subscription, 1);
|
||||
s->core = c;
|
||||
s->dead = 0;
|
||||
s->dead = FALSE;
|
||||
s->callback = callback;
|
||||
s->userdata = userdata;
|
||||
s->mask = m;
|
||||
|
|
@ -86,7 +86,7 @@ void pa_subscription_free(pa_subscription*s) {
|
|||
pa_assert(s);
|
||||
pa_assert(!s->dead);
|
||||
|
||||
s->dead = 1;
|
||||
s->dead = TRUE;
|
||||
sched_event(s->core);
|
||||
}
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ static void dump_event(const char * prefix, pa_subscription_event*e) {
|
|||
[PA_SUBSCRIPTION_EVENT_REMOVE] = "REMOVE"
|
||||
};
|
||||
|
||||
pa_log("%s event (%s|%s|%u)",
|
||||
pa_log_debug("%s event (%s|%s|%u)",
|
||||
prefix,
|
||||
fac_table[e->type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK],
|
||||
type_table[e->type & PA_SUBSCRIPTION_EVENT_TYPE_MASK],
|
||||
|
|
@ -234,7 +234,7 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i
|
|||
* entry in the queue. */
|
||||
|
||||
free_event(i);
|
||||
pa_log_debug("dropped redundant event.");
|
||||
pa_log_debug("Dropped redundant event due to remove event.");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -242,7 +242,7 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i
|
|||
/* This object has changed. If a "new" or "change" event for
|
||||
* this object is still in the queue we can exit. */
|
||||
|
||||
pa_log_debug("dropped redundant event.");
|
||||
pa_log_debug("Dropped redundant event due to change event.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@
|
|||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <dirent.h>
|
||||
#include <regex.h>
|
||||
#include <langinfo.h>
|
||||
|
||||
#ifdef HAVE_STRTOF_L
|
||||
#include <locale.h>
|
||||
|
|
@ -111,6 +113,8 @@ int pa_set_root(HANDLE handle) {
|
|||
|
||||
strcpy(library_path, PULSE_ROOTENV "=");
|
||||
|
||||
/* FIXME: Needs to set errno */
|
||||
|
||||
if (!GetModuleFileName(handle, library_path + sizeof(PULSE_ROOTENV), MAX_PATH))
|
||||
return 0;
|
||||
|
||||
|
|
@ -168,7 +172,7 @@ void pa_make_fd_cloexec(int fd) {
|
|||
/** Creates a directory securely */
|
||||
int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
|
||||
struct stat st;
|
||||
int r;
|
||||
int r, saved_errno;
|
||||
|
||||
pa_assert(dir);
|
||||
|
||||
|
|
@ -220,7 +224,10 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
saved_errno = errno;
|
||||
rmdir(dir);
|
||||
errno = saved_errno;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -230,6 +237,7 @@ char *pa_parent_dir(const char *fn) {
|
|||
|
||||
if ((slash = (char*) pa_path_get_filename(dir)) == dir) {
|
||||
pa_xfree(dir);
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -337,7 +345,7 @@ ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
|
|||
|
||||
ret += r;
|
||||
data = (uint8_t*) data + r;
|
||||
size -= r;
|
||||
size -= (size_t) r;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -368,7 +376,7 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
|
|||
|
||||
ret += r;
|
||||
data = (const uint8_t*) data + r;
|
||||
size -= r;
|
||||
size -= (size_t) r;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -437,7 +445,7 @@ void pa_check_signal_is_blocked(int sig) {
|
|||
/* The following function is based on an example from the GNU libc
|
||||
* documentation. This function is similar to GNU's asprintf(). */
|
||||
char *pa_sprintf_malloc(const char *format, ...) {
|
||||
int size = 100;
|
||||
size_t size = 100;
|
||||
char *c = NULL;
|
||||
|
||||
pa_assert(format);
|
||||
|
|
@ -454,11 +462,11 @@ char *pa_sprintf_malloc(const char *format, ...) {
|
|||
|
||||
c[size-1] = 0;
|
||||
|
||||
if (r > -1 && r < size)
|
||||
if (r > -1 && (size_t) r < size)
|
||||
return c;
|
||||
|
||||
if (r > -1) /* glibc 2.1 */
|
||||
size = r+1;
|
||||
size = (size_t) r+1;
|
||||
else /* glibc 2.0 */
|
||||
size *= 2;
|
||||
}
|
||||
|
|
@ -467,7 +475,7 @@ char *pa_sprintf_malloc(const char *format, ...) {
|
|||
/* Same as the previous function, but use a va_list instead of an
|
||||
* ellipsis */
|
||||
char *pa_vsprintf_malloc(const char *format, va_list ap) {
|
||||
int size = 100;
|
||||
size_t size = 100;
|
||||
char *c = NULL;
|
||||
|
||||
pa_assert(format);
|
||||
|
|
@ -484,11 +492,11 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) {
|
|||
|
||||
c[size-1] = 0;
|
||||
|
||||
if (r > -1 && r < size)
|
||||
if (r > -1 && (size_t) r < size)
|
||||
return c;
|
||||
|
||||
if (r > -1) /* glibc 2.1 */
|
||||
size = r+1;
|
||||
size = (size_t) r+1;
|
||||
else /* glibc 2.0 */
|
||||
size *= 2;
|
||||
}
|
||||
|
|
@ -546,6 +554,8 @@ int pa_make_realtime(int rtprio) {
|
|||
pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i.", sp.sched_priority);
|
||||
return 0;
|
||||
#else
|
||||
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -653,6 +663,7 @@ int pa_raise_priority(int nice_level) {
|
|||
if (nice_level < 0) {
|
||||
if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
|
||||
pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
|
||||
errno = EPERM;
|
||||
return .-1;
|
||||
} else
|
||||
pa_log_info("Successfully gained high priority class.");
|
||||
|
|
@ -679,15 +690,55 @@ void pa_reset_priority(void) {
|
|||
#endif
|
||||
}
|
||||
|
||||
static int match(const char *expr, const char *v) {
|
||||
int k;
|
||||
regex_t re;
|
||||
int r;
|
||||
|
||||
if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((k = regexec(&re, v, 0, NULL, 0)) == 0)
|
||||
r = 1;
|
||||
else if (k == REG_NOMATCH)
|
||||
r = 0;
|
||||
else
|
||||
r = -1;
|
||||
|
||||
regfree(&re);
|
||||
|
||||
if (r < 0)
|
||||
errno = EINVAL;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Try to parse a boolean string value.*/
|
||||
int pa_parse_boolean(const char *v) {
|
||||
const char *expr;
|
||||
int r;
|
||||
pa_assert(v);
|
||||
|
||||
/* First we check language independant */
|
||||
if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
|
||||
return 1;
|
||||
else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
|
||||
return 0;
|
||||
|
||||
/* And then we check language dependant */
|
||||
if ((expr = nl_langinfo(YESEXPR)))
|
||||
if (expr[0])
|
||||
if ((r = match(expr, v)) > 0)
|
||||
return 1;
|
||||
|
||||
if ((expr = nl_langinfo(NOEXPR)))
|
||||
if (expr[0])
|
||||
if ((r = match(expr, v)) > 0)
|
||||
return 0;
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -875,11 +926,18 @@ static int is_group(gid_t gid, const char *name) {
|
|||
#else
|
||||
n = -1;
|
||||
#endif
|
||||
if (n < 0) n = 512;
|
||||
data = pa_xmalloc(n);
|
||||
if (n < 0)
|
||||
n = 512;
|
||||
|
||||
data = pa_xmalloc((size_t) n);
|
||||
|
||||
errno = 0;
|
||||
if (getgrgid_r(gid, &group, data, (size_t) n, &result) < 0 || !result) {
|
||||
pa_log("getgrgid_r(%u): %s", (unsigned) gid, pa_cstrerror(errno));
|
||||
|
||||
if (!errno)
|
||||
errno = ENOENT;
|
||||
|
||||
if (getgrgid_r(gid, &group, data, n, &result) < 0 || !result) {
|
||||
pa_log("getgrgid_r(%u): %s", (unsigned)gid, pa_cstrerror(errno));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -890,8 +948,14 @@ finish:
|
|||
#else
|
||||
/* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
|
||||
* support getgrgid_r. */
|
||||
|
||||
errno = 0;
|
||||
if ((result = getgrgid(gid)) == NULL) {
|
||||
pa_log("getgrgid(%u): %s", gid, pa_cstrerror(errno));
|
||||
|
||||
if (!errno)
|
||||
errno = ENOENT;
|
||||
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -906,27 +970,32 @@ finish:
|
|||
/* Check the current user is member of the specified group */
|
||||
int pa_own_uid_in_group(const char *name, gid_t *gid) {
|
||||
GETGROUPS_T *gids, tgid;
|
||||
int n = sysconf(_SC_NGROUPS_MAX);
|
||||
int r = -1, i;
|
||||
long n = sysconf(_SC_NGROUPS_MAX);
|
||||
int r = -1, i, k;
|
||||
|
||||
pa_assert(n > 0);
|
||||
|
||||
gids = pa_xmalloc(sizeof(GETGROUPS_T)*n);
|
||||
gids = pa_xmalloc(sizeof(GETGROUPS_T) * (size_t) n);
|
||||
|
||||
if ((n = getgroups(n, gids)) < 0) {
|
||||
if ((n = getgroups((int) n, gids)) < 0) {
|
||||
pa_log("getgroups(): %s", pa_cstrerror(errno));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (is_group(gids[i], name) > 0) {
|
||||
|
||||
if ((k = is_group(gids[i], name)) < 0)
|
||||
goto finish;
|
||||
else if (k > 0) {
|
||||
*gid = gids[i];
|
||||
r = 1;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_group(tgid = getgid(), name) > 0) {
|
||||
if ((k = is_group(tgid = getgid(), name)) < 0)
|
||||
goto finish;
|
||||
else if (k > 0) {
|
||||
*gid = tgid;
|
||||
r = 1;
|
||||
goto finish;
|
||||
|
|
@ -949,18 +1018,25 @@ int pa_uid_in_group(uid_t uid, const char *name) {
|
|||
int r = -1;
|
||||
|
||||
g_n = sysconf(_SC_GETGR_R_SIZE_MAX);
|
||||
g_buf = pa_xmalloc(g_n);
|
||||
g_buf = pa_xmalloc((size_t) g_n);
|
||||
|
||||
p_n = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||
p_buf = pa_xmalloc(p_n);
|
||||
p_buf = pa_xmalloc((size_t) p_n);
|
||||
|
||||
errno = 0;
|
||||
if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) {
|
||||
|
||||
if (!errno)
|
||||
errno = ENOENT;
|
||||
|
||||
if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
for (i = gr->gr_mem; *i; i++) {
|
||||
struct passwd pwbuf, *pw;
|
||||
|
||||
errno = 0;
|
||||
if (getpwnam_r(*i, &pwbuf, p_buf, (size_t) p_n, &pw) != 0 || !pw)
|
||||
continue;
|
||||
|
||||
|
|
@ -985,10 +1061,16 @@ gid_t pa_get_gid_of_group(const char *name) {
|
|||
struct group grbuf, *gr;
|
||||
|
||||
g_n = sysconf(_SC_GETGR_R_SIZE_MAX);
|
||||
g_buf = pa_xmalloc(g_n);
|
||||
g_buf = pa_xmalloc((size_t) g_n);
|
||||
|
||||
errno = 0;
|
||||
if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) {
|
||||
|
||||
if (!errno)
|
||||
errno = ENOENT;
|
||||
|
||||
if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ret = gr->gr_gid;
|
||||
|
||||
|
|
@ -1014,19 +1096,23 @@ int pa_check_in_group(gid_t g) {
|
|||
#else /* HAVE_GRP_H */
|
||||
|
||||
int pa_own_uid_in_group(const char *name, gid_t *gid) {
|
||||
errno = ENOSUP;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
int pa_uid_in_group(uid_t uid, const char *name) {
|
||||
errno = ENOSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
gid_t pa_get_gid_of_group(const char *name) {
|
||||
errno = ENOSUP;
|
||||
return (gid_t) -1;
|
||||
}
|
||||
|
||||
int pa_check_in_group(gid_t g) {
|
||||
errno = ENOSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -1040,7 +1126,7 @@ int pa_lock_fd(int fd, int b) {
|
|||
|
||||
/* Try a R/W lock first */
|
||||
|
||||
flock.l_type = b ? F_WRLCK : F_UNLCK;
|
||||
flock.l_type = (short) (b ? F_WRLCK : F_UNLCK);
|
||||
flock.l_whence = SEEK_SET;
|
||||
flock.l_start = 0;
|
||||
flock.l_len = 0;
|
||||
|
|
@ -1067,6 +1153,8 @@ int pa_lock_fd(int fd, int b) {
|
|||
return 0;
|
||||
|
||||
pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
|
||||
|
||||
/* FIXME: Needs to set errno! */
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
|
|
@ -1133,8 +1221,11 @@ int pa_lock_lockfile(const char *fn) {
|
|||
|
||||
fail:
|
||||
|
||||
if (fd >= 0)
|
||||
if (fd >= 0) {
|
||||
int saved_errno = errno;
|
||||
pa_close(fd);
|
||||
errno = saved_errno;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1164,48 +1255,245 @@ int pa_unlock_lockfile(const char *fn, int fd) {
|
|||
return r;
|
||||
}
|
||||
|
||||
static char *get_dir(mode_t m, const char *env_name) {
|
||||
const char *e;
|
||||
char *d;
|
||||
static char *get_pulse_home(void) {
|
||||
char h[PATH_MAX];
|
||||
struct stat st;
|
||||
|
||||
if ((e = getenv(env_name)))
|
||||
d = pa_xstrdup(e);
|
||||
else {
|
||||
char h[PATH_MAX];
|
||||
struct stat st;
|
||||
|
||||
if (!pa_get_home_dir(h, sizeof(h))) {
|
||||
pa_log_error("Failed to get home directory.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (stat(h, &st) < 0) {
|
||||
pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (st.st_uid != getuid()) {
|
||||
pa_log_error("Home directory %s not ours.", d);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
d = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
|
||||
if (!pa_get_home_dir(h, sizeof(h))) {
|
||||
pa_log_error("Failed to get home directory.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pa_make_secure_dir(d, m, (pid_t) -1, (pid_t) -1) < 0) {
|
||||
if (stat(h, &st) < 0) {
|
||||
pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (st.st_uid != getuid()) {
|
||||
pa_log_error("Home directory %s not ours.", h);
|
||||
errno = EACCES;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
|
||||
}
|
||||
|
||||
char *pa_get_state_dir(void) {
|
||||
char *d;
|
||||
|
||||
/* The state directory shall contain dynamic data that should be
|
||||
* kept across reboots, and is private to this user */
|
||||
|
||||
if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
|
||||
if (!(d = get_pulse_home()))
|
||||
return NULL;
|
||||
|
||||
/* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
|
||||
* dir then this will break. */
|
||||
|
||||
if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
|
||||
pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
|
||||
pa_xfree(d);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
char *pa_get_runtime_dir(void) {
|
||||
return get_dir(pa_in_system_mode() ? 0755 : 0700, "PULSE_RUNTIME_PATH");
|
||||
static char* make_random_dir(mode_t m) {
|
||||
static const char table[] =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
|
||||
char fn[24] = "/tmp/pulse-";
|
||||
|
||||
fn[sizeof(fn)-1] = 0;
|
||||
|
||||
for (;;) {
|
||||
unsigned i;
|
||||
int r;
|
||||
mode_t u;
|
||||
int saved_errno;
|
||||
|
||||
for (i = 11; i < sizeof(fn)-1; i++)
|
||||
fn[i] = table[rand() % (sizeof(table)-1)];
|
||||
|
||||
u = umask((~m) & 0777);
|
||||
r = mkdir(fn, m);
|
||||
saved_errno = errno;
|
||||
umask(u);
|
||||
|
||||
if (r >= 0)
|
||||
return pa_xstrdup(fn);
|
||||
|
||||
errno = saved_errno;
|
||||
|
||||
if (errno != EEXIST) {
|
||||
pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *pa_get_state_dir(void) {
|
||||
return get_dir(0700, "PULSE_STATE_PATH");
|
||||
static int make_random_dir_and_link(mode_t m, const char *k) {
|
||||
char *p;
|
||||
|
||||
if (!(p = make_random_dir(m)))
|
||||
return -1;
|
||||
|
||||
if (symlink(p, k) < 0) {
|
||||
int saved_errno = errno;
|
||||
|
||||
if (errno != EEXIST)
|
||||
pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
|
||||
|
||||
rmdir(p);
|
||||
pa_xfree(p);
|
||||
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *pa_get_runtime_dir(void) {
|
||||
char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
|
||||
struct stat st;
|
||||
|
||||
/* The runtime directory shall contain dynamic data that needs NOT
|
||||
* to be kept accross reboots and is usuallly private to the user,
|
||||
* except in system mode, where it might be accessible by other
|
||||
* users, too. Since we need POSIX locking and UNIX sockets in
|
||||
* this directory, we link it to a random subdir in /tmp, if it
|
||||
* was not explicitly configured. */
|
||||
|
||||
if ((d = getenv("PULSE_RUNTIME_PATH"))) {
|
||||
mode_t m;
|
||||
|
||||
m = pa_in_system_mode() ? 0755U : 0700U;
|
||||
|
||||
if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
|
||||
pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return pa_xstrdup(d);
|
||||
}
|
||||
|
||||
if (!(d = get_pulse_home()))
|
||||
goto fail;
|
||||
|
||||
if (!(mid = pa_machine_id())) {
|
||||
pa_xfree(d);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s:runtime", d, mid);
|
||||
pa_xfree(d);
|
||||
pa_xfree(mid);
|
||||
|
||||
for (;;) {
|
||||
/* OK, first let's check if the "runtime" symlink is already
|
||||
* existant */
|
||||
|
||||
if (!(p = pa_readlink(k))) {
|
||||
|
||||
if (errno != ENOENT) {
|
||||
pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Hmm, so the runtime directory didn't exist yet, so let's
|
||||
* create one in /tmp and symlink that to it */
|
||||
|
||||
if (make_random_dir_and_link(0700, k) < 0) {
|
||||
|
||||
/* Mhmm, maybe another process was quicker than us,
|
||||
* let's check if that was valid */
|
||||
if (errno == EEXIST)
|
||||
continue;
|
||||
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
/* Make sure that this actually makes sense */
|
||||
if (!pa_is_path_absolute(p)) {
|
||||
pa_log_error("Path %s in link %s is not absolute.", p, k);
|
||||
errno = ENOENT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Hmm, so this symlink is still around, make sure nobody fools
|
||||
* us */
|
||||
|
||||
if (lstat(p, &st) < 0) {
|
||||
|
||||
if (errno != ENOENT) {
|
||||
pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (S_ISDIR(st.st_mode) &&
|
||||
(st.st_uid == getuid()) &&
|
||||
((st.st_mode & 0777) == 0700)) {
|
||||
|
||||
pa_xfree(p);
|
||||
return k;
|
||||
}
|
||||
|
||||
pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
|
||||
}
|
||||
|
||||
pa_xfree(p);
|
||||
p = NULL;
|
||||
|
||||
/* Hmm, so the link points to some nonexisting or invalid
|
||||
* dir. Let's replace it by a new link. We first create a
|
||||
* temporary link and then rename that to allow concurrent
|
||||
* execution of this function. */
|
||||
|
||||
t = pa_sprintf_malloc("%s.tmp", k);
|
||||
|
||||
if (make_random_dir_and_link(0700, t) < 0) {
|
||||
|
||||
if (errno != EEXIST) {
|
||||
pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pa_xfree(t);
|
||||
t = NULL;
|
||||
|
||||
/* Hmm, someone lese was quicker then us. Let's give
|
||||
* him some time to finish, and retry. */
|
||||
pa_msleep(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* OK, we succeeded in creating the temporary symlink, so
|
||||
* let's rename it */
|
||||
if (rename(t, k) < 0) {
|
||||
pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pa_xfree(t);
|
||||
return k;
|
||||
}
|
||||
|
||||
fail:
|
||||
pa_xfree(p);
|
||||
pa_xfree(k);
|
||||
pa_xfree(t);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Try to open a configuration file. If "env" is specified, open the
|
||||
|
|
@ -1228,6 +1516,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
|
|||
|
||||
#ifdef OS_IS_WIN32
|
||||
if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
|
||||
/* FIXME: Needs to set errno! */
|
||||
return NULL;
|
||||
fn = buf;
|
||||
#endif
|
||||
|
|
@ -1253,9 +1542,12 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
|
|||
fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
|
||||
else if (pa_get_home_dir(h, sizeof(h)))
|
||||
fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
|
||||
else
|
||||
return NULL;
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
|
||||
/* FIXME: Needs to set errno! */
|
||||
pa_xfree(lfn);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1284,6 +1576,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
|
|||
|
||||
#ifdef OS_IS_WIN32
|
||||
if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
|
||||
/* FIXME: Needs to set errno! */
|
||||
return NULL;
|
||||
global = buf;
|
||||
#endif
|
||||
|
|
@ -1295,9 +1588,9 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
|
|||
|
||||
return f;
|
||||
}
|
||||
} else
|
||||
errno = ENOENT;
|
||||
}
|
||||
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1311,8 +1604,10 @@ char *pa_find_config_file(const char *global, const char *local, const char *env
|
|||
#endif
|
||||
|
||||
if (env && (fn = getenv(env))) {
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
|
||||
/* FIXME: Needs to set errno! */
|
||||
return NULL;
|
||||
fn = buf;
|
||||
#endif
|
||||
|
|
@ -1333,9 +1628,12 @@ char *pa_find_config_file(const char *global, const char *local, const char *env
|
|||
fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
|
||||
else if (pa_get_home_dir(h, sizeof(h)))
|
||||
fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
|
||||
else
|
||||
return NULL;
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
|
||||
/* FIXME: Needs to set errno! */
|
||||
pa_xfree(lfn);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1360,14 +1658,16 @@ char *pa_find_config_file(const char *global, const char *local, const char *env
|
|||
if (global) {
|
||||
#ifdef OS_IS_WIN32
|
||||
if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
|
||||
/* FIXME: Needs to set errno! */
|
||||
return NULL;
|
||||
global = buf;
|
||||
#endif
|
||||
|
||||
if (access(fn, R_OK) == 0)
|
||||
if (access(global, R_OK) == 0)
|
||||
return pa_xstrdup(global);
|
||||
} else
|
||||
errno = ENOENT;
|
||||
}
|
||||
|
||||
errno = ENOENT;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1404,6 +1704,7 @@ static int hexc(char c) {
|
|||
if (c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -1490,7 +1791,7 @@ char *pa_make_path_absolute(const char *p) {
|
|||
/* if fn is null return the PulseAudio run time path in s (~/.pulse)
|
||||
* if fn is non-null and starts with / return fn
|
||||
* otherwise append fn to the run time path and return it */
|
||||
static char *get_path(const char *fn, pa_bool_t rt) {
|
||||
static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
|
||||
char *rtp;
|
||||
|
||||
if (pa_is_path_absolute(fn))
|
||||
|
|
@ -1503,7 +1804,20 @@ static char *get_path(const char *fn, pa_bool_t rt) {
|
|||
|
||||
if (fn) {
|
||||
char *r;
|
||||
r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
|
||||
|
||||
if (prependmid) {
|
||||
char *mid;
|
||||
|
||||
if (!(mid = pa_machine_id())) {
|
||||
pa_xfree(rtp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s:%s", rtp, mid, fn);
|
||||
pa_xfree(mid);
|
||||
} else
|
||||
r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
|
||||
|
||||
pa_xfree(rtp);
|
||||
return r;
|
||||
} else
|
||||
|
|
@ -1511,11 +1825,11 @@ static char *get_path(const char *fn, pa_bool_t rt) {
|
|||
}
|
||||
|
||||
char *pa_runtime_path(const char *fn) {
|
||||
return get_path(fn, 1);
|
||||
return get_path(fn, FALSE, TRUE);
|
||||
}
|
||||
|
||||
char *pa_state_path(const char *fn) {
|
||||
return get_path(fn, 0);
|
||||
char *pa_state_path(const char *fn, pa_bool_t appendmid) {
|
||||
return get_path(fn, appendmid, FALSE);
|
||||
}
|
||||
|
||||
/* Convert the string s to a signed integer in *ret_i */
|
||||
|
|
@ -1529,11 +1843,16 @@ int pa_atoi(const char *s, int32_t *ret_i) {
|
|||
errno = 0;
|
||||
l = strtol(s, &x, 0);
|
||||
|
||||
if (!x || *x || errno != 0)
|
||||
if (!x || *x || errno) {
|
||||
if (!errno)
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((int32_t) l != l)
|
||||
if ((int32_t) l != l) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ret_i = (int32_t) l;
|
||||
|
||||
|
|
@ -1551,11 +1870,16 @@ int pa_atou(const char *s, uint32_t *ret_u) {
|
|||
errno = 0;
|
||||
l = strtoul(s, &x, 0);
|
||||
|
||||
if (!x || *x || errno != 0)
|
||||
if (!x || *x || errno) {
|
||||
if (!errno)
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((uint32_t) l != l)
|
||||
if ((uint32_t) l != l) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ret_u = (uint32_t) l;
|
||||
|
||||
|
|
@ -1573,7 +1897,6 @@ static void c_locale_destroy(void) {
|
|||
int pa_atod(const char *s, double *ret_d) {
|
||||
char *x = NULL;
|
||||
double f;
|
||||
int r = 0;
|
||||
|
||||
pa_assert(s);
|
||||
pa_assert(ret_d);
|
||||
|
|
@ -1599,17 +1922,20 @@ int pa_atod(const char *s, double *ret_d) {
|
|||
f = strtod(s, &x);
|
||||
}
|
||||
|
||||
if (!x || *x || errno != 0)
|
||||
r = -1;
|
||||
else
|
||||
*ret_d = f;
|
||||
if (!x || *x || errno) {
|
||||
if (!errno)
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return r;
|
||||
*ret_d = f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Same as snprintf, but guarantees NUL-termination on every platform */
|
||||
int pa_snprintf(char *str, size_t size, const char *format, ...) {
|
||||
int ret;
|
||||
size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
|
||||
size_t ret;
|
||||
va_list ap;
|
||||
|
||||
pa_assert(str);
|
||||
|
|
@ -1624,7 +1950,7 @@ int pa_snprintf(char *str, size_t size, const char *format, ...) {
|
|||
}
|
||||
|
||||
/* Same as vsnprintf, but guarantees NUL-termination on every platform */
|
||||
int pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
|
||||
size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
|
||||
int ret;
|
||||
|
||||
pa_assert(str);
|
||||
|
|
@ -1636,9 +1962,12 @@ int pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
|
|||
str[size-1] = 0;
|
||||
|
||||
if (ret < 0)
|
||||
ret = strlen(str);
|
||||
return strlen(str);
|
||||
|
||||
return PA_MIN((int) size-1, ret);
|
||||
if ((size_t) ret > size-1)
|
||||
return size-1;
|
||||
|
||||
return (size_t) ret;
|
||||
}
|
||||
|
||||
/* Truncate the specified string, but guarantee that the string
|
||||
|
|
@ -1662,7 +1991,7 @@ char *pa_getcwd(void) {
|
|||
size_t l = 128;
|
||||
|
||||
for (;;) {
|
||||
char *p = pa_xnew(char, l);
|
||||
char *p = pa_xmalloc(l);
|
||||
if (getcwd(p, l))
|
||||
return p;
|
||||
|
||||
|
|
@ -1687,7 +2016,7 @@ void *pa_will_need(const void *p, size_t l) {
|
|||
pa_assert(l > 0);
|
||||
|
||||
a = PA_PAGE_ALIGN_PTR(p);
|
||||
size = (const uint8_t*) p + l - (const uint8_t*) a;
|
||||
size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
|
||||
|
||||
#ifdef HAVE_POSIX_MADVISE
|
||||
if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
|
||||
|
|
@ -1708,10 +2037,11 @@ void *pa_will_need(const void *p, size_t l) {
|
|||
|
||||
if (rlim.rlim_cur < PA_PAGE_SIZE) {
|
||||
pa_log_debug("posix_madvise() failed (or doesn't exist), resource limits don't allow mlock(), can't page in data: %s", pa_cstrerror(r));
|
||||
errno = EPERM;
|
||||
return (void*) p;
|
||||
}
|
||||
|
||||
bs = PA_PAGE_ALIGN(rlim.rlim_cur);
|
||||
bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
|
||||
#else
|
||||
bs = PA_PAGE_SIZE*4;
|
||||
#endif
|
||||
|
|
@ -1763,7 +2093,7 @@ char *pa_readlink(const char *p) {
|
|||
char *c;
|
||||
ssize_t n;
|
||||
|
||||
c = pa_xnew(char, l);
|
||||
c = pa_xmalloc(l);
|
||||
|
||||
if ((n = readlink(p, c, l-1)) < 0) {
|
||||
pa_xfree(c);
|
||||
|
|
@ -1782,8 +2112,8 @@ char *pa_readlink(const char *p) {
|
|||
|
||||
int pa_close_all(int except_fd, ...) {
|
||||
va_list ap;
|
||||
int n = 0, i, r;
|
||||
int *p;
|
||||
unsigned n = 0, i;
|
||||
int r, *p;
|
||||
|
||||
va_start(ap, except_fd);
|
||||
|
||||
|
|
@ -1910,8 +2240,8 @@ int pa_close_allv(const int except_fds[]) {
|
|||
|
||||
int pa_unblock_sigs(int except, ...) {
|
||||
va_list ap;
|
||||
int n = 0, i, r;
|
||||
int *p;
|
||||
unsigned n = 0, i;
|
||||
int r, *p;
|
||||
|
||||
va_start(ap, except);
|
||||
|
||||
|
|
@ -1959,8 +2289,8 @@ int pa_unblock_sigsv(const int except[]) {
|
|||
|
||||
int pa_reset_sigs(int except, ...) {
|
||||
va_list ap;
|
||||
int n = 0, i, r;
|
||||
int *p;
|
||||
unsigned n = 0, i;
|
||||
int *p, r;
|
||||
|
||||
va_start(ap, except);
|
||||
|
||||
|
|
@ -2048,3 +2378,47 @@ pa_bool_t pa_in_system_mode(void) {
|
|||
|
||||
return !!atoi(e);
|
||||
}
|
||||
|
||||
char *pa_machine_id(void) {
|
||||
FILE *f;
|
||||
size_t l;
|
||||
|
||||
if ((f = fopen(PA_MACHINE_ID, "r"))) {
|
||||
char ln[34] = "", *r;
|
||||
|
||||
r = fgets(ln, sizeof(ln)-1, f);
|
||||
fclose(f);
|
||||
|
||||
if (r)
|
||||
return pa_xstrdup(pa_strip_nl(ln));
|
||||
}
|
||||
|
||||
l = 100;
|
||||
|
||||
for (;;) {
|
||||
char *c;
|
||||
|
||||
c = pa_xmalloc(l);
|
||||
|
||||
if (!pa_get_host_name(c, l)) {
|
||||
|
||||
if (errno == EINVAL || errno == ENAMETOOLONG) {
|
||||
pa_xfree(c);
|
||||
l *= 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strlen(c) < l-1)
|
||||
return c;
|
||||
|
||||
/* Hmm, the hostname is as long the space we offered the
|
||||
* function, we cannot know if it fully fit in, so let's play
|
||||
* safe and retry. */
|
||||
|
||||
pa_xfree(c);
|
||||
l *= 2;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,14 +121,14 @@ char* pa_find_config_file(const char *global, const char *local, const char *env
|
|||
char *pa_get_runtime_dir(void);
|
||||
char *pa_get_state_dir(void);
|
||||
char *pa_runtime_path(const char *fn);
|
||||
char *pa_state_path(const char *fn);
|
||||
char *pa_state_path(const char *fn, pa_bool_t prepend_machine_id);
|
||||
|
||||
int pa_atoi(const char *s, int32_t *ret_i);
|
||||
int pa_atou(const char *s, uint32_t *ret_u);
|
||||
int pa_atod(const char *s, double *ret_d);
|
||||
|
||||
int pa_snprintf(char *str, size_t size, const char *format, ...);
|
||||
int pa_vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
||||
size_t pa_snprintf(char *str, size_t size, const char *format, ...);
|
||||
size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
||||
|
||||
char *pa_truncate_utf8(char *c, size_t l);
|
||||
|
||||
|
|
@ -184,4 +184,6 @@ pa_bool_t pa_in_system_mode(void);
|
|||
|
||||
#define pa_streq(a,b) (!strcmp((a),(b)))
|
||||
|
||||
char *pa_machine_id(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue