summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am32
-rw-r--r--src/daemon/caps.c99
-rw-r--r--src/daemon/caps.h3
-rw-r--r--src/daemon/daemon-conf.c2
-rw-r--r--src/daemon/daemon.conf.in2
-rwxr-xr-xsrc/daemon/default.pa.in3
-rw-r--r--src/daemon/main.c204
-rw-r--r--src/modules/alsa/alsa-sink.c1
-rw-r--r--src/modules/alsa/alsa-source.c1
-rw-r--r--src/modules/bluetooth/module-bluetooth-device.c1
-rw-r--r--src/modules/jack/module-jack-sink.c1
-rw-r--r--src/modules/jack/module-jack-source.c1
-rw-r--r--src/modules/module-card-restore.c2
-rw-r--r--src/modules/module-combine.c1
-rw-r--r--src/modules/module-device-restore.c30
-rw-r--r--src/modules/module-esound-sink.c1
-rw-r--r--src/modules/module-intended-roles.c439
-rw-r--r--src/modules/module-null-sink.c1
-rw-r--r--src/modules/module-pipe-sink.c1
-rw-r--r--src/modules/module-pipe-source.c1
-rw-r--r--src/modules/module-rescue-streams.c12
-rw-r--r--src/modules/module-sine-source.c1
-rw-r--r--src/modules/module-stream-restore.c228
-rw-r--r--src/modules/module-tunnel.c1
-rw-r--r--src/modules/oss/module-oss.c1
-rw-r--r--src/modules/raop/module-raop-sink.c1
-rw-r--r--src/pulsecore/core-util.c204
-rw-r--r--src/pulsecore/core-util.h3
-rw-r--r--src/pulsecore/rtkit.c189
-rw-r--r--src/pulsecore/rtkit.h62
-rw-r--r--src/pulsecore/rtpoll.c176
-rw-r--r--src/pulsecore/rtpoll.h3
-rw-r--r--src/pulsecore/rtsig.c131
-rw-r--r--src/pulsecore/rtsig.h39
-rw-r--r--src/tests/rtpoll-test.c6
35 files changed, 1081 insertions, 802 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index b4904803..c580ece8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -119,7 +119,6 @@ EXTRA_DIST = \
modules/module-defs.h.m4 \
daemon/pulseaudio.desktop.in \
map-file \
- daemon/org.pulseaudio.policy.in \
modules/alsa/mixer/profile-sets/default.conf \
modules/alsa/mixer/profile-sets/native-instruments-audio4dj.conf \
modules/alsa/mixer/profile-sets/native-instruments-audio8dj.conf \
@@ -189,16 +188,6 @@ else
pulseaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f))
endif
-if HAVE_POLKIT
-policy_in_files = daemon/org.pulseaudio.policy.in
-policy_DATA = $(policy_in_files:.policy.in=.policy)
-@INTLTOOL_POLICY_RULE@
-
-pulseaudio_SOURCES += daemon/polkit.c daemon/polkit.h
-pulseaudio_CFLAGS += $(POLKIT_CFLAGS)
-pulseaudio_LDADD += $(POLKIT_LIBS)
-endif
-
###################################
# Utility programs #
###################################
@@ -579,6 +568,7 @@ libpulsecommon_@PA_MAJORMINORMICRO@_la_SOURCES = \
pulsecore/core-error.c pulsecore/core-error.h \
pulsecore/core-rtclock.c pulsecore/core-rtclock.h \
pulsecore/core-util.c pulsecore/core-util.h \
+ pulsecore/rtkit.c pulsecore/rtkit.h \
pulsecore/creds.h \
pulsecore/dynarray.c pulsecore/dynarray.h \
pulsecore/endianmacros.h \
@@ -828,7 +818,6 @@ libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES = \
pulsecore/play-memchunk.c pulsecore/play-memchunk.h \
pulsecore/resampler.c pulsecore/resampler.h \
pulsecore/rtpoll.c pulsecore/rtpoll.h \
- pulsecore/rtsig.c pulsecore/rtsig.h \
pulsecore/sample-util.c pulsecore/sample-util.h \
pulsecore/sconv-s16be.c pulsecore/sconv-s16be.h \
pulsecore/sconv-s16le.c pulsecore/sconv-s16le.h \
@@ -982,6 +971,7 @@ modlibexec_LTLIBRARIES += \
module-default-device-restore.la \
module-always-sink.la \
module-rescue-streams.la \
+ module-intended-roles.la \
module-suspend-on-idle.la \
module-http-protocol-tcp.la \
module-sine.la \
@@ -1215,6 +1205,7 @@ SYMDEF_FILES = \
modules/module-default-device-restore-symdef.h \
modules/module-always-sink-symdef.h \
modules/module-rescue-streams-symdef.h \
+ modules/module-intended-roles-symdef.h \
modules/module-suspend-on-idle-symdef.h \
modules/module-hal-detect-symdef.h \
modules/module-udev-detect-symdef.h \
@@ -1547,6 +1538,12 @@ module_rescue_streams_la_LDFLAGS = $(MODULE_LDFLAGS)
module_rescue_streams_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la
module_rescue_streams_la_CFLAGS = $(AM_CFLAGS)
+# Automatically move streams to devices that are intended for their roles
+module_intended_roles_la_SOURCES = modules/module-intended-roles.c
+module_intended_roles_la_LDFLAGS = $(MODULE_LDFLAGS)
+module_intended_roles_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la
+module_intended_roles_la_CFLAGS = $(AM_CFLAGS)
+
# Suspend-on-idle module
module_suspend_on_idle_la_SOURCES = modules/module-suspend-on-idle.c
module_suspend_on_idle_la_LDFLAGS = $(MODULE_LDFLAGS)
@@ -1661,11 +1658,7 @@ module_rygel_media_server_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
# Some minor stuff #
###################################
-suid: pulseaudio .libs/lt-pulseaudio
- chown root $^
- chmod u+s $^
-
-CLEANFILES = esdcompat client.conf default.pa system.pa daemon.conf start-pulseaudio-x11 daemon/pulseaudio.desktop daemon/org.pulseaudio.policy
+CLEANFILES = esdcompat client.conf default.pa system.pa daemon.conf start-pulseaudio-x11 daemon/pulseaudio.desktop
esdcompat: daemon/esdcompat.in Makefile
sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \
@@ -1742,6 +1735,11 @@ update-reserve:
wget -O modules/$$i http://git.0pointer.de/\?p=reserve.git\;a=blob_plain\;f=$$i\;hb=master ; \
done
+update-rtkit:
+ for i in rtkit.c rtkit.h ; do \
+ wget -O pulsecore/$$i http://git.0pointer.de/\?p=rtkit.git\;a=blob_plain\;f=$$i\;hb=master ; \
+ done
+
# Automatically generate linker version script. We use the same one for all public .sos
update-map-file:
( echo "PULSE_0 {" ; \
diff --git a/src/daemon/caps.c b/src/daemon/caps.c
index d2ae8d0e..294be494 100644
--- a/src/daemon/caps.c
+++ b/src/daemon/caps.c
@@ -39,6 +39,7 @@
#ifdef HAVE_SYS_CAPABILITY_H
#include <sys/capability.h>
#endif
+
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif
@@ -51,12 +52,13 @@ int setresgid(gid_t r, gid_t e, gid_t s);
int setresuid(uid_t r, uid_t e, uid_t s);
#endif
-#ifdef HAVE_GETUID
-
/* Drop root rights when called SUID root */
void pa_drop_root(void) {
- uid_t uid = getuid();
+#ifdef HAVE_GETUID
+ uid_t uid;
+
+ uid = getuid();
if (uid == 0 || geteuid() != 0)
return;
@@ -73,90 +75,19 @@ void pa_drop_root(void) {
pa_assert_se(getuid() == uid);
pa_assert_se(geteuid() == uid);
-}
-
-#else
-
-void pa_drop_root(void) {
-}
-
-#endif
-
-#if defined(HAVE_SYS_CAPABILITY_H) && defined(HAVE_SYS_PRCTL_H)
-
-/* Limit permitted capabilities set to CAPSYS_NICE */
-void pa_limit_caps(void) {
- cap_t caps;
- cap_value_t nice_cap = CAP_SYS_NICE;
-
- pa_assert_se(caps = cap_init());
- pa_assert_se(cap_clear(caps) == 0);
- pa_assert_se(cap_set_flag(caps, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET) == 0);
- pa_assert_se(cap_set_flag(caps, CAP_PERMITTED, 1, &nice_cap, CAP_SET) == 0);
-
- if (cap_set_proc(caps) < 0)
- /* Hmm, so we couldn't limit our caps, which probably means we
- * hadn't any in the first place, so let's just make sure of
- * that */
- pa_drop_caps();
- else
- pa_log_info(_("Limited capabilities successfully to CAP_SYS_NICE."));
-
- pa_assert_se(cap_free(caps) == 0);
-
- pa_assert_se(prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == 0);
-}
-
-/* Drop all capabilities, effectively becoming a normal user */
-void pa_drop_caps(void) {
- cap_t caps;
-
-#ifndef __OPTIMIZE__
- /* Valgrind doesn't not know set_caps, so we bypass it here -- but
- * only in development builds.*/
-
- if (pa_in_valgrind() && !pa_have_caps())
- return;
#endif
+#ifdef HAVE_SYS_PRCTL_H
pa_assert_se(prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) == 0);
-
- pa_assert_se(caps = cap_init());
- pa_assert_se(cap_clear(caps) == 0);
- pa_assert_se(cap_set_proc(caps) == 0);
- pa_assert_se(cap_free(caps) == 0);
-
- pa_assert_se(!pa_have_caps());
-}
-
-pa_bool_t pa_have_caps(void) {
- cap_t caps;
- cap_flag_value_t flag = CAP_CLEAR;
-
-#ifdef __OPTIMIZE__
- pa_assert_se(caps = cap_get_proc());
-#else
- if (!(caps = cap_get_proc()))
- return FALSE;
#endif
- pa_assert_se(cap_get_flag(caps, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0);
- pa_assert_se(cap_free(caps) == 0);
-
- return flag == CAP_SET;
-}
-
-#else
-
-/* NOOPs in case capabilities are not available. */
-void pa_limit_caps(void) {
-}
-
-void pa_drop_caps(void) {
- pa_drop_root();
-}
-
-pa_bool_t pa_have_caps(void) {
- return FALSE;
-}
+#ifdef HAVE_SYS_CAPABILITY_H
+ {
+ cap_t caps;
+ pa_assert_se(caps = cap_init());
+ pa_assert_se(cap_clear(caps) == 0);
+ pa_assert_se(cap_set_proc(caps) == 0);
+ pa_assert_se(cap_free(caps) == 0);
+ }
#endif
+}
diff --git a/src/daemon/caps.h b/src/daemon/caps.h
index 94241a9a..5d0ee62e 100644
--- a/src/daemon/caps.h
+++ b/src/daemon/caps.h
@@ -25,8 +25,5 @@
#include <pulsecore/macro.h>
void pa_drop_root(void);
-void pa_drop_caps(void);
-void pa_limit_caps(void);
-pa_bool_t pa_have_caps(void);
#endif
diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index 664e4fde..9010f2f6 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -60,7 +60,7 @@ static const pa_daemon_conf default_conf = {
.fail = TRUE,
.high_priority = TRUE,
.nice_level = -11,
- .realtime_scheduling = FALSE,
+ .realtime_scheduling = TRUE,
.realtime_priority = 5, /* Half of JACK's default rtprio */
.disallow_module_loading = FALSE,
.disallow_exit = FALSE,
diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index d119716d..6931359c 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -33,7 +33,7 @@
; high-priority = yes
; nice-level = -11
-; realtime-scheduling = no
+; realtime-scheduling = yes
; realtime-priority = 5
; exit-idle-time = 20
diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index a35ff8ff..00c000eb 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -100,6 +100,9 @@ load-module module-rescue-streams
### Make sure we always have a sink around, even if it is a null sink.
load-module module-always-sink
+### Honour intended role device property
+load-module module-intended-roles
+
### Automatically suspend sinks/sources that become idle for too long
load-module module-suspend-on-idle
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 399034e9..22759a38 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -85,7 +85,7 @@
#include <pulsecore/pid.h>
#include <pulsecore/namereg.h>
#include <pulsecore/random.h>
-#include <pulsecore/rtsig.h>
+#include <pulsecore/rtclock.h>
#include <pulsecore/macro.h>
#include <pulsecore/mutex.h>
#include <pulsecore/thread.h>
@@ -102,7 +102,6 @@
#include "dumpmodules.h"
#include "caps.h"
#include "ltdl-bind-now.h"
-#include "polkit.h"
#ifdef HAVE_LIBWRAP
/* Only one instance of these variables */
@@ -381,9 +380,7 @@ int main(int argc, char *argv[]) {
pa_mainloop *mainloop = NULL;
char *s;
int r = 0, retval = 1, d = 0;
- pa_bool_t suid_root, real_root;
pa_bool_t valid_pid_file = FALSE;
- gid_t gid = (gid_t) -1;
pa_bool_t ltdl_init = FALSE;
int passed_fd = -1;
const char *e;
@@ -426,30 +423,6 @@ int main(int argc, char *argv[]) {
}
#endif
-#ifdef HAVE_GETUID
- real_root = getuid() == 0;
- suid_root = !real_root && geteuid() == 0;
-#else
- real_root = FALSE;
- suid_root = FALSE;
-#endif
-
- if (!real_root) {
- /* Drop all capabilities except CAP_SYS_NICE */
- pa_limit_caps();
-
- /* Drop privileges, but keep CAP_SYS_NICE */
- pa_drop_root();
-
- /* After dropping root, the effective set is reset, hence,
- * let's raise it again */
- pa_limit_caps();
-
- /* When capabilities are not supported we will not be able to
- * acquire RT sched anymore. But yes, that's the way it is. It
- * is just too risky tun let PA run as root all the time. */
- }
-
if ((e = getenv("PULSE_PASSED_FD"))) {
passed_fd = atoi(e);
@@ -457,15 +430,14 @@ int main(int argc, char *argv[]) {
passed_fd = -1;
}
+ /* We might be autospawned, in which case have no idea in which
+ * context we have been started. Let's cleanup our execution
+ * context as good as possible */
+ pa_drop_root();
pa_close_all(passed_fd, -1);
-
pa_reset_sigs(-1);
pa_unblock_sigs(-1);
- /* At this point, we are a normal user, possibly with CAP_NICE if
- * we were started SUID. If we are started as normal root, than we
- * still are normal root. */
-
setlocale(LC_ALL, "");
pa_init_i18n();
@@ -490,150 +462,6 @@ int main(int argc, char *argv[]) {
pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET);
pa_log_set_show_backtrace(conf->log_backtrace);
- pa_log_debug("Started as real root: %s, suid root: %s", pa_yes_no(real_root), pa_yes_no(suid_root));
-
- if (!real_root && pa_have_caps()) {
-#ifdef HAVE_SYS_RESOURCE_H
- struct rlimit rl;
-#endif
- pa_bool_t allow_high_priority = FALSE, allow_realtime = FALSE;
-
- /* Let's better not enable high prio or RT by default */
-
- 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 '%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 '%s', allowing real-time scheduling."), PA_REALTIME_GROUP);
- allow_realtime = TRUE;
- }
- }
-
-#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."));
- allow_high_priority = TRUE;
- } else
- 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."));
- allow_realtime = TRUE;
- } else
- pa_log_info(_("PolicyKit refuses acquire-real-time privilege."));
- }
-#endif
-
- if (!allow_high_priority && !allow_realtime) {
-
- /* OK, there's no further need to keep CAP_NICE. Hence
- * let's give it up early */
-
- pa_drop_caps();
- }
-
-#ifdef RLIMIT_RTPRIO
- if (getrlimit(RLIMIT_RTPRIO, &rl) >= 0)
- if (rl.rlim_cur > 0) {
- pa_log_info("RLIMIT_RTPRIO is set to %u, allowing real-time scheduling.", (unsigned) rl.rlim_cur);
- allow_realtime = TRUE;
- }
-#endif
-#ifdef RLIMIT_NICE
- if (getrlimit(RLIMIT_NICE, &rl) >= 0)
- if (rl.rlim_cur > 20 ) {
- pa_log_info("RLIMIT_NICE is set to %u, allowing high-priority scheduling.", (unsigned) rl.rlim_cur);
- allow_high_priority = TRUE;
- }
-#endif
-
- if ((conf->high_priority && !allow_high_priority) ||
- (conf->realtime_scheduling && !allow_realtime))
- pa_log_info(_("Called SUID root and real-time and/or high-priority scheduling was requested in the configuration. However, we lack the necessary privileges:\n"
- "We are not in group '%s', PolicyKit refuse to grant us the requested privileges and we have no increase RLIMIT_NICE/RLIMIT_RTPRIO resource limits.\n"
- "For enabling real-time/high-priority scheduling please acquire the appropriate PolicyKit privileges, or become a member of '%s', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user."),
- PA_REALTIME_GROUP, PA_REALTIME_GROUP);
-
-
- if (!allow_realtime)
- conf->realtime_scheduling = FALSE;
-
- if (!allow_high_priority)
- conf->high_priority = FALSE;
- }
-
-#ifdef HAVE_SYS_RESOURCE_H
- /* Reset resource limits. If we are run as root (for system mode)
- * this might end up increasing the limits, which is intended
- * behaviour. For all other cases, i.e. started as normal user, or
- * SUID root at this point we should have no CAP_SYS_RESOURCE and
- * increasing the limits thus should fail. Which is, too, intended
- * behaviour */
-
- set_all_rlimits(conf);
-#endif
-
- if (conf->high_priority && !pa_can_high_priority()) {
- pa_log_info(_("High-priority scheduling enabled in configuration but not allowed by policy."));
- conf->high_priority = FALSE;
- }
-
- if (conf->high_priority && (conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START))
- pa_raise_priority(conf->nice_level);
-
- pa_log_debug("Can realtime: %s, can high-priority: %s", pa_yes_no(pa_can_realtime()), pa_yes_no(pa_can_high_priority()));
-
- if (!real_root && pa_have_caps()) {
- pa_bool_t drop;
-
- drop = (conf->cmd != PA_CMD_DAEMON && conf->cmd != PA_CMD_START) || !conf->realtime_scheduling;
-
-#ifdef RLIMIT_RTPRIO
- if (!drop) {
- struct rlimit rl;
- /* At this point we still have CAP_NICE if we were loaded
- * SUID root. If possible let's acquire RLIMIT_RTPRIO
- * instead and give CAP_NICE up. */
-
- if (getrlimit(RLIMIT_RTPRIO, &rl) >= 0) {
-
- if (rl.rlim_cur >= 9)
- drop = TRUE;
- else {
- rl.rlim_max = rl.rlim_cur = 9;
-
- if (setrlimit(RLIMIT_RTPRIO, &rl) >= 0) {
- pa_log_info(_("Successfully increased RLIMIT_RTPRIO"));
- drop = TRUE;
- } else
- pa_log_warn(_("RLIMIT_RTPRIO failed: %s"), pa_cstrerror(errno));
- }
- }
- }
-#endif
-
- if (drop) {
- pa_log_info(_("Giving up CAP_NICE"));
- pa_drop_caps();
- suid_root = FALSE;
- }
- }
-
- if (conf->realtime_scheduling && !pa_can_realtime()) {
- pa_log_info(_("Real-time scheduling enabled in configuration but not allowed by policy."));
- conf->realtime_scheduling = FALSE;
- }
-
- pa_log_debug("Can realtime: %s, can high-priority: %s", pa_yes_no(pa_can_realtime()), pa_yes_no(pa_can_high_priority()));
-
LTDL_SET_PRELOADED_SYMBOLS();
pa_ltdl_init();
ltdl_init = TRUE;
@@ -718,9 +546,9 @@ int main(int argc, char *argv[]) {
pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START);
}
- if (real_root && !conf->system_instance)
+ if (getuid() == 0 && !conf->system_instance)
pa_log_warn(_("This program is not intended to be run as root (unless --system is specified)."));
- else if (!real_root && conf->system_instance) {
+ else if (getuid() != 0 && conf->system_instance) {
pa_log(_("Root privileges required."));
goto finish;
}
@@ -866,6 +694,13 @@ int main(int argc, char *argv[]) {
pa_assert_se(chdir("/") == 0);
umask(0022);
+#ifdef HAVE_SYS_RESOURCE_H
+ set_all_rlimits(conf);
+#endif
+ pa_rtclock_hrtimer_enable();
+
+ pa_raise_priority(conf->nice_level);
+
if (conf->system_instance)
if (change_user() < 0)
goto finish;
@@ -914,8 +749,8 @@ int main(int argc, char *argv[]) {
pa_xfree(s);
if ((s = pa_session_id())) {
- pa_log_info(_("Session ID is %s."), s);
- pa_xfree(s);
+ pa_log_info(_("Session ID is %s."), s);
+ pa_xfree(s);
}
if (!(s = pa_get_runtime_dir()))
@@ -962,13 +797,6 @@ int main(int argc, char *argv[]) {
else
pa_log_info(_("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!"));
- pa_rtclock_hrtimer_enable();
-
-#ifdef SIGRTMIN
- /* Valgrind uses SIGRTMAX. To easy debugging we don't use it here */
- pa_rtsig_configure(SIGRTMIN, SIGRTMAX-1);
-#endif
-
if (conf->lock_memory) {
#ifdef HAVE_SYS_MMAN_H
if (mlockall(MCL_FUTURE) < 0)
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 9116a69f..c584362d 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1213,7 +1213,6 @@ static void thread_func(void *userdata) {
pa_make_realtime(u->core->realtime_priority);
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
for (;;) {
int ret;
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index ede9306f..a6760e1e 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1095,7 +1095,6 @@ static void thread_func(void *userdata) {
pa_make_realtime(u->core->realtime_priority);
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
for (;;) {
int ret;
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 68ac3acc..e7c6d5e4 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -1266,7 +1266,6 @@ static void thread_func(void *userdata) {
goto fail;
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
for (;;) {
struct pollfd *pollfd;
diff --git a/src/modules/jack/module-jack-sink.c b/src/modules/jack/module-jack-sink.c
index 290038e7..fc976fa7 100644
--- a/src/modules/jack/module-jack-sink.c
+++ b/src/modules/jack/module-jack-sink.c
@@ -225,7 +225,6 @@ static void thread_func(void *userdata) {
pa_make_realtime(u->core->realtime_priority);
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
for (;;) {
int ret;
diff --git a/src/modules/jack/module-jack-source.c b/src/modules/jack/module-jack-source.c
index ef89a98e..a898e0e5 100644
--- a/src/modules/jack/module-jack-source.c
+++ b/src/modules/jack/module-jack-source.c
@@ -196,7 +196,6 @@ static void thread_func(void *userdata) {
pa_make_realtime(u->core->realtime_priority);
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
for (;;) {
int ret;
diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c
index 6b057b4c..7dea94f7 100644
--- a/src/modules/module-card-restore.c
+++ b/src/modules/module-card-restore.c
@@ -195,7 +195,7 @@ static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new
if (!new_data->active_profile) {
pa_log_info("Restoring profile for card %s.", new_data->name);
pa_card_new_data_set_profile(new_data, e->profile);
- new_data->save_profile = FALSE;
+ new_data->save_profile = TRUE;
} else
pa_log_debug("Not restoring profile for card %s, because already set.", new_data->name);
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 757dbda4..d50e59ae 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -278,7 +278,6 @@ static void thread_func(void *userdata) {
pa_make_realtime(u->core->realtime_priority+1);
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
u->thread_info.timestamp = pa_rtclock_now();
u->thread_info.in_null_mode = FALSE;
diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
index 8c15d454..120b762c 100644
--- a/src/modules/module-device-restore.c
+++ b/src/modules/module-device-restore.c
@@ -292,10 +292,10 @@ static pa_hook_result_t sink_new_hook_callback(pa_core *c, pa_sink_new_data *new
char *name;
struct entry *e;
+ pa_assert(c);
pa_assert(new_data);
-
- if (!u->restore_port)
- return PA_HOOK_OK;
+ pa_assert(u);
+ pa_assert(u->restore_port);
name = pa_sprintf_malloc("sink:%s", new_data->name);
@@ -305,7 +305,7 @@ static pa_hook_result_t sink_new_hook_callback(pa_core *c, pa_sink_new_data *new
if (!new_data->active_port) {
pa_log_info("Restoring port for sink %s.", name);
pa_sink_new_data_set_port(new_data, e->port);
- new_data->save_port = FALSE;
+ new_data->save_port = TRUE;
} else
pa_log_debug("Not restoring port for sink %s, because already set.", name);
}
@@ -322,7 +322,10 @@ static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *
char *name;
struct entry *e;
+ pa_assert(c);
pa_assert(new_data);
+ pa_assert(u);
+ pa_assert(u->restore_volume || u->restore_muted);
name = pa_sprintf_malloc("sink:%s", new_data->name);
@@ -339,7 +342,7 @@ static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *
pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
pa_sink_new_data_set_volume(new_data, &v);
- new_data->save_volume = FALSE;
+ new_data->save_volume = TRUE;
} else
pa_log_debug("Not restoring volume for sink %s, because already set.", new_data->name);
}
@@ -349,7 +352,7 @@ static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *
if (!new_data->muted_is_set) {
pa_log_info("Restoring mute state for sink %s.", new_data->name);
pa_sink_new_data_set_muted(new_data, e->muted);
- new_data->save_muted = FALSE;
+ new_data->save_muted = TRUE;
} else
pa_log_debug("Not restoring mute state for sink %s, because already set.", new_data->name);
}
@@ -366,10 +369,10 @@ static pa_hook_result_t source_new_hook_callback(pa_core *c, pa_source_new_data
char *name;
struct entry *e;
+ pa_assert(c);
pa_assert(new_data);
-
- if (!u->restore_port)
- return PA_HOOK_OK;
+ pa_assert(u);
+ pa_assert(u->restore_port);
name = pa_sprintf_malloc("source:%s", new_data->name);
@@ -379,7 +382,7 @@ static pa_hook_result_t source_new_hook_callback(pa_core *c, pa_source_new_data
if (!new_data->active_port) {
pa_log_info("Restoring port for source %s.", name);
pa_source_new_data_set_port(new_data, e->port);
- new_data->save_port = FALSE;
+ new_data->save_port = TRUE;
} else
pa_log_debug("Not restoring port for source %s, because already set.", name);
}
@@ -396,7 +399,10 @@ static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_da
char *name;
struct entry *e;
+ pa_assert(c);
pa_assert(new_data);
+ pa_assert(u);
+ pa_assert(u->restore_volume || u->restore_muted);
name = pa_sprintf_malloc("source:%s", new_data->name);
@@ -413,7 +419,7 @@ static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_da
pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
pa_source_new_data_set_volume(new_data, &v);
- new_data->save_volume = FALSE;
+ new_data->save_volume = TRUE;
} else
pa_log_debug("Not restoring volume for source %s, because already set.", new_data->name);
}
@@ -423,7 +429,7 @@ static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_da
if (!new_data->muted_is_set) {
pa_log_info("Restoring mute state for source %s.", new_data->name);
pa_source_new_data_set_muted(new_data, e->muted);
- new_data->save_muted = FALSE;
+ new_data->save_muted = TRUE;
} else
pa_log_debug("Not restoring mute state for source %s, because already set.", new_data->name);
}
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index b26b465d..d7c678ca 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -201,7 +201,6 @@ static void thread_func(void *userdata) {
pa_log_debug("Thread starting up");
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
pa_smoother_set_time_offset(u->smoother, pa_rtclock_now());
diff --git a/src/modules/module-intended-roles.c b/src/modules/module-intended-roles.c
new file mode 100644
index 00000000..036600e4
--- /dev/null
+++ b/src/modules/module-intended-roles.c
@@ -0,0 +1,439 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2009 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
+ 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 <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <pulse/xmalloc.h>
+#include <pulse/volume.h>
+#include <pulse/timeval.h>
+#include <pulse/util.h>
+
+#include <pulsecore/core-error.h>
+#include <pulsecore/module.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/modargs.h>
+#include <pulsecore/log.h>
+#include <pulsecore/core-subscribe.h>
+#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 <pulsecore/database.h>
+
+#include "module-stream-restore-symdef.h"
+
+PA_MODULE_AUTHOR("Lennart Poettering");
+PA_MODULE_DESCRIPTION("Automatically set device of streams based of intended roles of devices");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(TRUE);
+PA_MODULE_USAGE(
+ "on_hotplug=<When new device becomes available, recheck streams?> "
+ "on_rescue=<When device becomes unavailable, recheck streams?>");
+
+static const char* const valid_modargs[] = {
+ "on_hotplug",
+ "on_rescue",
+ NULL
+};
+
+struct userdata {
+ pa_core *core;
+ pa_module *module;
+ pa_hook_slot
+ *sink_input_new_hook_slot,
+ *source_output_new_hook_slot,
+ *sink_put_hook_slot,
+ *source_put_hook_slot,
+ *sink_unlink_hook_slot,
+ *source_unlink_hook_slot;
+
+ pa_bool_t on_hotplug:1;
+ pa_bool_t on_rescue:1;
+};
+
+static pa_bool_t role_match(pa_proplist *proplist, const char *role) {
+ const char *ir;
+ char *r;
+ const char *state;
+
+ if (!(ir = pa_proplist_gets(proplist, PA_PROP_DEVICE_INTENDED_ROLES)))
+ return FALSE;
+
+ while ((r = pa_split_spaces(ir, &state))) {
+
+ if (pa_streq(role, r)) {
+ pa_xfree(r);
+ return TRUE;
+ }
+
+ pa_xfree(r);
+ }
+
+ return FALSE;
+}
+
+static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
+ const char *role;
+ pa_sink *s, *def;
+ uint32_t idx;
+
+ pa_assert(c);
+ pa_assert(new_data);
+ pa_assert(u);
+
+ if (!new_data->proplist) {
+ pa_log_debug("New stream lacks property data.");
+ return PA_HOOK_OK;
+ }
+
+ if (new_data->sink) {
+ pa_log_debug("Not setting device for stream %s, because already set.", pa_strnull(pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_NAME)));
+ return PA_HOOK_OK;
+ }
+
+ if (!(role = pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_ROLE))) {
+ pa_log_debug("Not setting device for stream %s, because it lacks role.", pa_strnull(pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_NAME)));
+ return PA_HOOK_OK;
+ }
+
+ /* Prefer the default sink over any other sink, just in case... */
+ if ((def = pa_namereg_get_default_sink(c)))
+ if (role_match(def->proplist, role)) {
+ new_data->sink = def;
+ new_data->save_sink = FALSE;
+ return PA_HOOK_OK;
+ }
+
+ PA_IDXSET_FOREACH(s, c->sinks, idx) {
+ if (s == def)
+ continue;
+
+ if (role_match(s->proplist, role)) {
+ new_data->sink = s;
+ new_data->save_sink = FALSE;
+ return PA_HOOK_OK;
+ }
+ }
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
+ const char *role;
+ pa_source *s, *def;
+ uint32_t idx;
+
+ pa_assert(c);
+ pa_assert(new_data);
+ pa_assert(u);
+
+ if (!new_data->proplist) {
+ pa_log_debug("New stream lacks property data.");
+ return PA_HOOK_OK;
+ }
+
+ if (new_data->source) {
+ pa_log_debug("Not setting device for stream %s, because already set.", pa_strnull(pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_NAME)));
+ return PA_HOOK_OK;
+ }
+
+ if (!(role = pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_ROLE))) {
+ pa_log_debug("Not setting device for stream %s, because it lacks role.", pa_strnull(pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_NAME)));
+ return PA_HOOK_OK;
+ }
+
+ /* Prefer the default source over any other source, just in case... */
+ if ((def = pa_namereg_get_default_source(c)))
+ if (role_match(def->proplist, role)) {
+ new_data->source = def;
+ new_data->save_source = FALSE;
+ return PA_HOOK_OK;
+ }
+
+ PA_IDXSET_FOREACH(s, c->sources, idx) {
+ if (s == def)
+ continue;
+
+ if (role_match(s->proplist, role)) {
+ new_data->source = s;
+ new_data->save_source = FALSE;
+ return PA_HOOK_OK;
+ }
+ }
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
+ pa_sink_input *si;
+ uint32_t idx;
+
+ pa_assert(c);
+ pa_assert(sink);
+ pa_assert(u);
+ pa_assert(u->on_hotplug);
+
+ PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
+ const char *role;
+
+ if (si->sink == sink)
+ continue;
+
+ if (si->save_sink)
+ continue;
+
+ if (!(role = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_ROLE)))
+ continue;
+
+ if (role_match(si->sink->proplist, role))
+ continue;
+
+ if (!role_match(sink->proplist, role))
+ continue;
+
+ pa_sink_input_move_to(si, sink, FALSE);
+ }
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
+ pa_source_output *so;
+ uint32_t idx;
+
+ pa_assert(c);
+ pa_assert(source);
+ pa_assert(u);
+ pa_assert(u->on_hotplug);
+
+ PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
+ const char *role;
+
+ if (so->source == source)
+ continue;
+
+ if (so->save_source)
+ continue;
+
+ if (so->direct_on_input)
+ continue;
+
+ if (!(role = pa_proplist_gets(so->proplist, PA_PROP_MEDIA_ROLE)))
+ continue;
+
+ if (role_match(so->source->proplist, role))
+ continue;
+
+ if (!role_match(source->proplist, role))
+ continue;
+
+ pa_source_output_move_to(so, source, FALSE);
+ }
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
+ pa_sink_input *si;
+ uint32_t idx;
+ pa_sink *def;
+
+ pa_assert(c);
+ pa_assert(sink);
+ pa_assert(u);
+ pa_assert(u->on_rescue);
+
+ /* There's no point in doing anything if the core is shut down anyway */
+ if (c->state == PA_CORE_SHUTDOWN)
+ return PA_HOOK_OK;
+
+ /* If there not default sink, then there is no sink at all */
+ if (!(def = pa_namereg_get_default_sink(c)))
+ return PA_HOOK_OK;
+
+ PA_IDXSET_FOREACH(si, sink->inputs, idx) {
+ const char *role;
+ uint32_t jdx;
+ pa_sink *d;
+
+ if (!(role = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_ROLE)))
+ continue;
+
+ /* Would the default sink fit? If so, let's use it */
+ if (def != sink && role_match(def->proplist, role)) {
+ pa_sink_input_move_to(si, def, FALSE);
+ continue;
+ }
+
+ /* Try to find some other fitting sink */
+ PA_IDXSET_FOREACH(d, c->sinks, jdx) {
+ if (d == def || d == sink)
+ continue;
+
+ if (role_match(d->proplist, role)) {
+ pa_sink_input_move_to(si, d, FALSE);
+ break;
+ }
+ }
+ }
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
+ pa_source_output *so;
+ uint32_t idx;
+ pa_source *def;
+
+ pa_assert(c);
+ pa_assert(source);
+ pa_assert(u);
+ pa_assert(u->on_rescue);
+
+ /* There's no point in doing anything if the core is shut down anyway */
+ if (c->state == PA_CORE_SHUTDOWN)
+ return PA_HOOK_OK;
+
+ /* If there not default source, then there is no source at all */
+ if (!(def = pa_namereg_get_default_source(c)))
+ return PA_HOOK_OK;
+
+ PA_IDXSET_FOREACH(so, source->outputs, idx) {
+ const char *role;
+ uint32_t jdx;
+ pa_source *d;
+
+ if (so->direct_on_input)
+ continue;
+
+ if (!(role = pa_proplist_gets(so->proplist, PA_PROP_MEDIA_ROLE)))
+ continue;
+
+ /* Would the default source fit? If so, let's use it */
+ if (def != source && role_match(def->proplist, role) && !source->monitor_of == !def->monitor_of) {
+ pa_source_output_move_to(so, def, FALSE);
+ continue;
+ }
+
+ /* Try to find some other fitting source */
+ PA_IDXSET_FOREACH(d, c->sources, jdx) {
+ if (d == def || d == source)
+ continue;
+
+ if (role_match(d->proplist, role) && !source->monitor_of == !d->monitor_of) {
+ pa_source_output_move_to(so, d, FALSE);
+ break;
+ }
+ }
+ }
+
+ return PA_HOOK_OK;
+}
+
+int pa__init(pa_module*m) {
+ pa_modargs *ma = NULL;
+ struct userdata *u;
+ pa_bool_t on_hotplug = TRUE, on_rescue = TRUE;
+
+ pa_assert(m);
+
+ if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+ pa_log("Failed to parse module arguments");
+ goto fail;
+ }
+
+ if (pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 ||
+ pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
+ pa_log("on_hotplug= and on_rescue= expect boolean arguments");
+ goto fail;
+ }
+
+ m->userdata = u = pa_xnew0(struct userdata, 1);
+ u->core = m->core;
+ u->module = m;
+ u->on_hotplug = on_hotplug;
+ u->on_rescue = on_rescue;
+
+ /* A little bit later than module-stream-restore */
+ u->sink_input_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY+10, (pa_hook_cb_t) sink_input_new_hook_callback, u);
+ u->source_output_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY+10, (pa_hook_cb_t) source_output_new_hook_callback, u);
+
+ if (on_hotplug) {
+ /* A little bit later than module-stream-restore */
+ u->sink_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE+10, (pa_hook_cb_t) sink_put_hook_callback, u);
+ u->source_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE+10, (pa_hook_cb_t) source_put_hook_callback, u);
+ }
+
+ if (on_rescue) {
+ /* A little bit later than module-stream-restore, a little bit earlier than module-rescue-streams, ... */
+ u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+10, (pa_hook_cb_t) sink_unlink_hook_callback, NULL);
+ u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+10, (pa_hook_cb_t) source_unlink_hook_callback, NULL);
+ }
+
+ pa_modargs_free(ma);
+ return 0;
+
+fail:
+ pa__done(m);
+
+ if (ma)
+ pa_modargs_free(ma);
+
+ return -1;
+}
+
+void pa__done(pa_module*m) {
+ struct userdata* u;
+
+ pa_assert(m);
+
+ if (!(u = m->userdata))
+ return;
+
+ if (u->sink_input_new_hook_slot)
+ pa_hook_slot_free(u->sink_input_new_hook_slot);
+ if (u->source_output_new_hook_slot)
+ pa_hook_slot_free(u->source_output_new_hook_slot);
+
+ if (u->sink_put_hook_slot)
+ pa_hook_slot_free(u->sink_put_hook_slot);
+ if (u->source_put_hook_slot)
+ pa_hook_slot_free(u->source_put_hook_slot);
+
+ if (u->sink_unlink_hook_slot)
+ pa_hook_slot_free(u->sink_unlink_hook_slot);
+ if (u->source_unlink_hook_slot)
+ pa_hook_slot_free(u->source_unlink_hook_slot);
+
+ pa_xfree(u);
+}
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 2669776d..36c50b05 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -209,7 +209,6 @@ static void thread_func(void *userdata) {
pa_log_debug("Thread starting up");
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
u->timestamp = pa_rtclock_now();
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 5b0f6414..8a7dc846 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -170,7 +170,6 @@ static void thread_func(void *userdata) {
pa_log_debug("Thread starting up");
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
for (;;) {
struct pollfd *pollfd;
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 61c9fc0e..e5609fb5 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -129,7 +129,6 @@ static void thread_func(void *userdata) {
pa_log_debug("Thread starting up");
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
for (;;) {
int ret;
diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c
index c22711ae..e933cc2e 100644
--- a/src/modules/module-rescue-streams.c
+++ b/src/modules/module-rescue-streams.c
@@ -65,14 +65,14 @@ static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* user
return PA_HOOK_OK;
}
- if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SINK)) || target == sink) {
+ if (!(target = pa_namereg_get_default_sink(c)) || target == sink) {
PA_IDXSET_FOREACH(target, c->sinks, idx)
if (target != sink)
break;
if (!target) {
- pa_log_info("No evacuation sink found.");
+ pa_log_debug("No evacuation sink found.");
return PA_HOOK_OK;
}
}
@@ -108,7 +108,7 @@ static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void
return PA_HOOK_OK;
}
- if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SOURCE)) || target == source) {
+ if (!(target = pa_namereg_get_default_source(c)) || target == source) {
PA_IDXSET_FOREACH(target, c->sources, idx)
if (target != source && !target->monitor_of == !source->monitor_of)
@@ -146,8 +146,10 @@ int pa__init(pa_module*m) {
}
m->userdata = u = pa_xnew(struct userdata, 1);
- u->sink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_hook_callback, NULL);
- u->source_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) source_hook_callback, NULL);
+
+ /* A little bit later than module-stream-restore, module-intended-roles... */
+ u->sink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+20, (pa_hook_cb_t) sink_hook_callback, NULL);
+ u->source_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+20, (pa_hook_cb_t) source_hook_callback, NULL);
pa_modargs_free(ma);
return 0;
diff --git a/src/modules/module-sine-source.c b/src/modules/module-sine-source.c
index 33be66f5..9826e5f4 100644
--- a/src/modules/module-sine-source.c
+++ b/src/modules/module-sine-source.c
@@ -167,7 +167,6 @@ static void thread_func(void *userdata) {
pa_log_debug("Thread starting up");
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
u->timestamp = pa_rtclock_now();
diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
index 99c69f66..7ae93c7d 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -60,7 +60,9 @@ PA_MODULE_LOAD_ONCE(TRUE);
PA_MODULE_USAGE(
"restore_device=<Save/restore sinks/sources?> "
"restore_volume=<Save/restore volumes?> "
- "restore_muted=<Save/restore muted states?>");
+ "restore_muted=<Save/restore muted states?> "
+ "on_hotplug=<When new device becomes available, recheck streams?> "
+ "on_rescue=<When device becomes unavailable, recheck streams?>");
#define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
#define IDENTIFICATION_PROPERTY "module-stream-restore.id"
@@ -69,6 +71,8 @@ static const char* const valid_modargs[] = {
"restore_device",
"restore_volume",
"restore_muted",
+ "on_hotplug",
+ "on_rescue",
NULL
};
@@ -80,6 +84,10 @@ struct userdata {
*sink_input_new_hook_slot,
*sink_input_fixate_hook_slot,
*source_output_new_hook_slot,
+ *sink_put_hook_slot,
+ *source_put_hook_slot,
+ *sink_unlink_hook_slot,
+ *source_unlink_hook_slot,
*connection_unlink_hook_slot;
pa_time_event *save_time_event;
pa_database* database;
@@ -87,6 +95,8 @@ struct userdata {
pa_bool_t restore_device:1;
pa_bool_t restore_volume:1;
pa_bool_t restore_muted:1;
+ pa_bool_t on_hotplug:1;
+ pa_bool_t on_rescue:1;
pa_native_protocol *protocol;
pa_idxset *subscribed;
@@ -350,10 +360,10 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n
char *name;
struct entry *e;
+ pa_assert(c);
pa_assert(new_data);
-
- if (!u->restore_device)
- return PA_HOOK_OK;
+ pa_assert(u);
+ pa_assert(u->restore_device);
if (!(name = get_name(new_data->proplist, "sink-input")))
return PA_HOOK_OK;
@@ -367,9 +377,9 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n
if (!new_data->sink) {
pa_log_info("Restoring device for stream %s.", name);
new_data->sink = s;
- new_data->save_sink = FALSE;
+ new_data->save_sink = TRUE;
} else
- pa_log_info("Not restoring device for stream %s, because already set.", name);
+ pa_log_debug("Not restoring device for stream %s, because already set.", name);
}
}
@@ -385,10 +395,10 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu
char *name;
struct entry *e;
+ pa_assert(c);
pa_assert(new_data);
-
- if (!u->restore_volume && !u->restore_muted)
- return PA_HOOK_OK;
+ pa_assert(u);
+ pa_assert(u->restore_volume || u->restore_muted);
if (!(name = get_name(new_data->proplist, "sink-input")))
return PA_HOOK_OK;
@@ -407,7 +417,7 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu
pa_sink_input_new_data_set_volume(new_data, &v);
new_data->volume_is_absolute = FALSE;
- new_data->save_volume = FALSE;
+ new_data->save_volume = TRUE;
} else
pa_log_debug("Not restoring volume for sink input %s, because already set.", name);
}
@@ -417,7 +427,7 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu
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);
- new_data->save_muted = FALSE;
+ new_data->save_muted = TRUE;
} else
pa_log_debug("Not restoring mute state for sink input %s, because already set.", name);
}
@@ -434,10 +444,10 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou
char *name;
struct entry *e;
+ pa_assert(c);
pa_assert(new_data);
-
- if (!u->restore_device)
- return PA_HOOK_OK;
+ pa_assert(u);
+ pa_assert(u->restore_device);
if (new_data->direct_on_input)
return PA_HOOK_OK;
@@ -453,9 +463,9 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou
if (!new_data->source) {
pa_log_info("Restoring device for stream %s.", name);
new_data->source = s;
- new_data->save_source = FALSE;
+ new_data->save_source = TRUE;
} else
- pa_log_info("Not restoring device for stream %s, because already set", name);
+ pa_log_debug("Not restoring device for stream %s, because already set", name);
}
}
@@ -467,6 +477,155 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou
return PA_HOOK_OK;
}
+static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
+ pa_sink_input *si;
+ uint32_t idx;
+
+ pa_assert(c);
+ pa_assert(sink);
+ pa_assert(u);
+ pa_assert(u->on_hotplug && u->restore_device);
+
+ PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
+ char *name;
+ struct entry *e;
+
+ if (si->sink == sink)
+ continue;
+
+ if (si->save_sink)
+ continue;
+
+ if (!(name = get_name(si->proplist, "sink-input")))
+ continue;
+
+ if ((e = read_entry(u, name))) {
+ if (e->device_valid && pa_streq(e->device, sink->name))
+ pa_sink_input_move_to(si, sink, TRUE);
+
+ pa_xfree(e);
+ }
+
+ pa_xfree(name);
+ }
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
+ pa_source_output *so;
+ uint32_t idx;
+
+ pa_assert(c);
+ pa_assert(source);
+ pa_assert(u);
+ pa_assert(u->on_hotplug && u->restore_device);
+
+ PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
+ char *name;
+ struct entry *e;
+
+ if (so->source == source)
+ continue;
+
+ if (so->save_source)
+ continue;
+
+ if (so->direct_on_input)
+ continue;
+
+ if (!(name = get_name(so->proplist, "source-input")))
+ continue;
+
+ if ((e = read_entry(u, name))) {
+ if (e->device_valid && pa_streq(e->device, source->name))
+ pa_source_output_move_to(so, source, TRUE);
+
+ pa_xfree(e);
+ }
+
+ pa_xfree(name);
+ }
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
+ pa_sink_input *si;
+ uint32_t idx;
+
+ pa_assert(c);
+ pa_assert(sink);
+ pa_assert(u);
+ pa_assert(u->on_rescue && u->restore_device);
+
+ /* There's no point in doing anything if the core is shut down anyway */
+ if (c->state == PA_CORE_SHUTDOWN)
+ return PA_HOOK_OK;
+
+ PA_IDXSET_FOREACH(si, sink->inputs, idx) {
+ char *name;
+ struct entry *e;
+
+ if (!(name = get_name(si->proplist, "sink-input")))
+ continue;
+
+ if ((e = read_entry(u, name))) {
+
+ if (e->device_valid) {
+ pa_sink *d;
+
+ if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) && d != sink)
+ pa_sink_input_move_to(si, d, TRUE);
+ }
+
+ pa_xfree(e);
+ }
+
+ pa_xfree(name);
+ }
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
+ pa_source_output *so;
+ uint32_t idx;
+
+ pa_assert(c);
+ pa_assert(source);
+ pa_assert(u);
+ pa_assert(u->on_rescue && u->restore_device);
+
+ /* There's no point in doing anything if the core is shut down anyway */
+ if (c->state == PA_CORE_SHUTDOWN)
+ return PA_HOOK_OK;
+
+ PA_IDXSET_FOREACH(so, source->outputs, idx) {
+ char *name;
+ struct entry *e;
+
+ if (!(name = get_name(so->proplist, "source-output")))
+ continue;
+
+ if ((e = read_entry(u, name))) {
+
+ if (e->device_valid) {
+ pa_source *d;
+
+ if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) && d != source)
+ pa_source_output_move_to(so, d, TRUE);
+ }
+
+ pa_xfree(e);
+ }
+
+ pa_xfree(name);
+ }
+
+ return PA_HOOK_OK;
+}
+
#define EXT_VERSION 1
static void apply_entry(struct userdata *u, const char *name, struct entry *e) {
@@ -772,7 +931,7 @@ int pa__init(pa_module*m) {
pa_sink_input *si;
pa_source_output *so;
uint32_t idx;
- pa_bool_t restore_device = TRUE, restore_volume = TRUE, restore_muted = TRUE;
+ pa_bool_t restore_device = TRUE, restore_volume = TRUE, restore_muted = TRUE, on_hotplug = TRUE, on_rescue = TRUE;
pa_assert(m);
@@ -783,8 +942,10 @@ int pa__init(pa_module*m) {
if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 ||
pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 ||
- pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0) {
- pa_log("restore_device=, restore_volume= and restore_muted= expect boolean arguments");
+ pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
+ pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 ||
+ pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
+ pa_log("restore_device=, restore_volume=, restore_muted=, on_hotplug= and on_rescue= expect boolean arguments");
goto fail;
}
@@ -797,6 +958,8 @@ int pa__init(pa_module*m) {
u->restore_device = restore_device;
u->restore_volume = restore_volume;
u->restore_muted = restore_muted;
+ u->on_hotplug = on_hotplug;
+ u->on_rescue = on_rescue;
u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
u->protocol = pa_native_protocol_get(m->core);
@@ -807,10 +970,23 @@ int pa__init(pa_module*m) {
u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
if (restore_device) {
+ /* A little bit earlier than module-intended-roles ... */
u->sink_input_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_new_hook_callback, u);
u->source_output_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_new_hook_callback, u);
}
+ if (restore_device && on_hotplug) {
+ /* A little bit earlier than module-intended-roles ... */
+ u->sink_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE, (pa_hook_cb_t) sink_put_hook_callback, u);
+ u->source_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE, (pa_hook_cb_t) source_put_hook_callback, u);
+ }
+
+ if (restore_device && on_rescue) {
+ /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */
+ u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_unlink_hook_callback, NULL);
+ u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) source_unlink_hook_callback, NULL);
+ }
+
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);
@@ -826,10 +1002,10 @@ int pa__init(pa_module*m) {
pa_log_info("Sucessfully opened database file '%s'.", fname);
pa_xfree(fname);
- for (si = pa_idxset_first(m->core->sink_inputs, &idx); si; si = pa_idxset_next(m->core->sink_inputs, &idx))
+ PA_IDXSET_FOREACH(si, m->core->sink_inputs, idx)
subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, si->index, u);
- for (so = pa_idxset_first(m->core->source_outputs, &idx); so; so = pa_idxset_next(m->core->source_outputs, &idx))
+ PA_IDXSET_FOREACH(so, m->core->source_outputs, idx)
subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, so->index, u);
pa_modargs_free(ma);
@@ -862,6 +1038,16 @@ 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->sink_put_hook_slot)
+ pa_hook_slot_free(u->sink_put_hook_slot);
+ if (u->source_put_hook_slot)
+ pa_hook_slot_free(u->source_put_hook_slot);
+
+ if (u->sink_unlink_hook_slot)
+ pa_hook_slot_free(u->sink_unlink_hook_slot);
+ if (u->source_unlink_hook_slot)
+ pa_hook_slot_free(u->source_unlink_hook_slot);
+
if (u->connection_unlink_hook_slot)
pa_hook_slot_free(u->connection_unlink_hook_slot);
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index ce37bf47..d1153829 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -684,7 +684,6 @@ static void thread_func(void *userdata) {
pa_log_debug("Thread starting up");
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
for (;;) {
int ret;
diff --git a/src/modules/oss/module-oss.c b/src/modules/oss/module-oss.c
index b1afcfd6..c44b882b 100644
--- a/src/modules/oss/module-oss.c
+++ b/src/modules/oss/module-oss.c
@@ -889,7 +889,6 @@ static void thread_func(void *userdata) {
pa_make_realtime(u->core->realtime_priority);
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
for (;;) {
int ret;
diff --git a/src/modules/raop/module-raop-sink.c b/src/modules/raop/module-raop-sink.c
index c226b0c3..9699132d 100644
--- a/src/modules/raop/module-raop-sink.c
+++ b/src/modules/raop/module-raop-sink.c
@@ -324,7 +324,6 @@ static void thread_func(void *userdata) {
pa_log_debug("Thread starting up");
pa_thread_mq_install(&u->thread_mq);
- pa_rtpoll_install(u->rtpoll);
pa_smoother_set_time_offset(u->smoother, pa_rtclock_now());
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index a71ba0b0..4550344f 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -50,6 +50,10 @@
#ifdef HAVE_SCHED_H
#include <sched.h>
+
+#if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
+#define SCHED_RESET_ON_FORK 0x40000000
+#endif
#endif
#ifdef HAVE_SYS_RESOURCE_H
@@ -92,6 +96,10 @@
#include <xlocale.h>
#endif
+#ifdef HAVE_DBUS
+#include "rtkit.h"
+#endif
+
#include <pulse/xmalloc.h>
#include <pulse/util.h>
#include <pulse/utf8.h>
@@ -552,127 +560,121 @@ char *pa_strlcpy(char *b, const char *s, size_t l) {
return b;
}
-/* Make the current thread a realtime thread, and acquire the highest
- * rtprio we can get that is less or equal the specified parameter. If
- * the thread is already realtime, don't do anything. */
-int pa_make_realtime(int rtprio) {
-
-#ifdef _POSIX_PRIORITY_SCHEDULING
+static int set_scheduler(int rtprio) {
struct sched_param sp;
- int r, policy;
+ int r;
+#ifdef HAVE_DBUS
+ DBusError error;
+ DBusConnection *bus;
- memset(&sp, 0, sizeof(sp));
- policy = 0;
+ dbus_error_init(&error);
+#endif
- if ((r = pthread_getschedparam(pthread_self(), &policy, &sp)) != 0) {
- pa_log("pthread_getschedgetparam(): %s", pa_cstrerror(r));
- return -1;
+ pa_zero(sp);
+ sp.sched_priority = rtprio;
+
+#ifdef SCHED_RESET_ON_FORK
+ if ((r = pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp)) == 0) {
+ pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
+ return 0;
}
+#endif
- if (policy == SCHED_FIFO && sp.sched_priority >= rtprio) {
- pa_log_info("Thread already being scheduled with SCHED_FIFO with priority %i.", sp.sched_priority);
+ if ((r = pthread_setschedparam(pthread_self(), SCHED_RR, &sp)) == 0) {
+ pa_log_debug("SCHED_RR worked.");
return 0;
}
- sp.sched_priority = rtprio;
- if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) != 0) {
+#ifdef HAVE_DBUS
+ /* Try to talk to RealtimeKit */
- while (sp.sched_priority > 1) {
- sp.sched_priority --;
+ if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
+ pa_log("Failed to connect to system bus: %s\n", error.message);
+ dbus_error_free(&error);
+ errno = -EIO;
+ return -1;
+ }
- if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) == 0) {
- pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i, which is lower than the requested %i.", sp.sched_priority, rtprio);
- return 0;
- }
- }
+ r = rtkit_make_realtime(bus, 0, rtprio);
+ dbus_connection_unref(bus);
- pa_log_warn("pthread_setschedparam(): %s", pa_cstrerror(r));
- return -1;
+ if (r >= 0) {
+ pa_log_debug("RealtimeKit worked.");
+ return 0;
}
- pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i.", sp.sched_priority);
- return 0;
+ errno = -r;
#else
+ errno = r;
+#endif
- errno = ENOTSUP;
return -1;
-#endif
}
-/* This is merely used for giving the user a hint. This is not correct
- * for anything security related */
-pa_bool_t pa_can_realtime(void) {
-
- if (geteuid() == 0)
- return TRUE;
+/* Make the current thread a realtime thread, and acquire the highest
+ * rtprio we can get that is less or equal the specified parameter. If
+ * the thread is already realtime, don't do anything. */
+int pa_make_realtime(int rtprio) {
-#if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
- {
- struct rlimit rl;
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ int p;
- if (getrlimit(RLIMIT_RTPRIO, &rl) >= 0)
- if (rl.rlim_cur > 0 || rl.rlim_cur == RLIM_INFINITY)
- return TRUE;
+ if (set_scheduler(rtprio) >= 0) {
+ pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio);
+ return 0;
}
-#endif
-#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
- {
- cap_t cap;
-
- if ((cap = cap_get_proc())) {
- cap_flag_value_t flag = CAP_CLEAR;
+ for (p = rtprio-1; p >= 1; p--)
+ if (set_scheduler(p)) {
+ pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p, rtprio);
+ return 0;
+ }
- if (cap_get_flag(cap, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0)
- if (flag == CAP_SET) {
- cap_free(cap);
- return TRUE;
- }
+ pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno));
+ return -1;
+#else
- cap_free(cap);
- }
- }
+ errno = ENOTSUP;
+ return -1;
#endif
-
- return FALSE;
}
-/* This is merely used for giving the user a hint. This is not correct
- * for anything security related */
-pa_bool_t pa_can_high_priority(void) {
-
- if (geteuid() == 0)
- return TRUE;
+static int set_nice(int nice_level) {
+#ifdef HAVE_DBUS
+ DBusError error;
+ DBusConnection *bus;
+ int r;
-#if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
- {
- struct rlimit rl;
+ dbus_error_init(&error);
+#endif
- if (getrlimit(RLIMIT_NICE, &rl) >= 0)
- if (rl.rlim_cur >= 21 || rl.rlim_cur == RLIM_INFINITY)
- return TRUE;
+ if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) {
+ pa_log_debug("setpriority() worked.");
+ return 0;
}
-#endif
-#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
- {
- cap_t cap;
+#ifdef HAVE_DBUS
+ /* Try to talk to RealtimeKit */
- if ((cap = cap_get_proc())) {
- cap_flag_value_t flag = CAP_CLEAR;
+ if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
+ pa_log("Failed to connect to system bus: %s\n", error.message);
+ dbus_error_free(&error);
+ errno = -EIO;
+ return -1;
+ }
- if (cap_get_flag(cap, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0)
- if (flag == CAP_SET) {
- cap_free(cap);
- return TRUE;
- }
+ r = rtkit_make_high_priority(bus, 0, nice_level);
+ dbus_connection_unref(bus);
- cap_free(cap);
- }
+ if (r >= 0) {
+ pa_log_debug("RealtimeKit worked.");
+ return 0;
}
+
+ errno = -r;
#endif
- return FALSE;
+ return -1;
}
/* Raise the priority of the current process as much as possible that
@@ -680,22 +682,21 @@ pa_bool_t pa_can_high_priority(void) {
int pa_raise_priority(int nice_level) {
#ifdef HAVE_SYS_RESOURCE_H
- if (setpriority(PRIO_PROCESS, 0, nice_level) < 0) {
- int n;
+ int n;
- for (n = nice_level+1; n < 0; n++) {
+ if (set_nice(nice_level) >= 0) {
+ pa_log_info("Successfully gained nice level %i.", nice_level);
+ return 0;
+ }
- if (setpriority(PRIO_PROCESS, 0, n) == 0) {
- pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level);
- return 0;
- }
+ for (n = nice_level+1; n < 0; n++)
+ if (set_nice(n) > 0) {
+ pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level);
+ return 0;
}
- pa_log_warn("setpriority(): %s", pa_cstrerror(errno));
- return -1;
- }
-
- pa_log_info("Successfully gained nice level %i.", nice_level);
+ pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno));
+ return -1;
#endif
#ifdef OS_IS_WIN32
@@ -703,9 +704,10 @@ int pa_raise_priority(int nice_level) {
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.");
+ return -1;
+ }
+
+ pa_log_info("Successfully gained high priority class.");
}
#endif
@@ -720,8 +722,8 @@ void pa_reset_priority(void) {
setpriority(PRIO_PROCESS, 0, 0);
- memset(&sp, 0, sizeof(sp));
- pa_assert_se(pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp) == 0);
+ pa_zero(sp);
+ pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp);
#endif
#ifdef OS_IS_WIN32
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index b841edbb..96a0480a 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -80,9 +80,6 @@ int pa_make_realtime(int rtprio);
int pa_raise_priority(int nice_level);
void pa_reset_priority(void);
-pa_bool_t pa_can_realtime(void);
-pa_bool_t pa_can_high_priority(void);
-
int pa_parse_boolean(const char *s) PA_GCC_PURE;
static inline const char *pa_yes_no(pa_bool_t b) {
diff --git a/src/pulsecore/rtkit.c b/src/pulsecore/rtkit.c
new file mode 100644
index 00000000..aecc4e32
--- /dev/null
+++ b/src/pulsecore/rtkit.c
@@ -0,0 +1,189 @@
+/*-*- Mode: C; c-basic-offset: 8 -*-*/
+
+/***
+ Copyright 2009 Lennart Poettering
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+***/
+
+#include <errno.h>
+
+#include "rtkit.h"
+
+#ifdef __linux__
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+
+static pid_t _gettid(void) {
+ return (pid_t) syscall(SYS_gettid);
+}
+
+static int translate_error(const char *name) {
+ if (strcmp(name, DBUS_ERROR_NO_MEMORY) == 0)
+ return -ENOMEM;
+ if (strcmp(name, DBUS_ERROR_SERVICE_UNKNOWN) == 0 ||
+ strcmp(name, DBUS_ERROR_NAME_HAS_NO_OWNER) == 0)
+ return -ENOENT;
+ if (strcmp(name, DBUS_ERROR_ACCESS_DENIED) == 0 ||
+ strcmp(name, DBUS_ERROR_AUTH_FAILED) == 0)
+ return -EACCES;
+
+ return -EIO;
+}
+
+int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) {
+ DBusMessage *m = NULL, *r = NULL;
+ dbus_uint64_t u64;
+ dbus_uint32_t u32;
+ DBusError error;
+ int ret;
+
+ dbus_error_init(&error);
+
+ if (thread == 0)
+ thread = _gettid();
+
+ if (!(m = dbus_message_new_method_call(
+ RTKIT_SERVICE_NAME,
+ RTKIT_OBJECT_PATH,
+ "org.freedesktop.RealtimeKit1",
+ "MakeThreadRealtime"))) {
+ ret = -ENOMEM;
+ goto finish;
+ }
+
+ u64 = (dbus_uint64_t) thread;
+ u32 = (dbus_uint32_t) priority;
+
+ if (!dbus_message_append_args(
+ m,
+ DBUS_TYPE_UINT64, &u64,
+ DBUS_TYPE_UINT32, &u32,
+ DBUS_TYPE_INVALID)) {
+ ret = -ENOMEM;
+ goto finish;
+ }
+
+ if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) {
+ ret = translate_error(error.name);
+ goto finish;
+ }
+
+
+ if (dbus_set_error_from_message(&error, r)) {
+ ret = translate_error(error.name);
+ goto finish;
+ }
+
+ ret = 0;
+
+finish:
+
+ if (m)
+ dbus_message_unref(m);
+
+ if (r)
+ dbus_message_unref(r);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
+
+int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) {
+ DBusMessage *m = NULL, *r = NULL;
+ dbus_uint64_t u64;
+ dbus_int32_t s32;
+ DBusError error;
+ int ret;
+
+ dbus_error_init(&error);
+
+ if (thread == 0)
+ thread = _gettid();
+
+ if (!(m = dbus_message_new_method_call(
+ RTKIT_SERVICE_NAME,
+ RTKIT_OBJECT_PATH,
+ "org.freedesktop.RealtimeKit1",
+ "MakeThreadHighPriority"))) {
+ ret = -ENOMEM;
+ goto finish;
+ }
+
+ u64 = (dbus_uint64_t) thread;
+ s32 = (dbus_int32_t) nice_level;
+
+ if (!dbus_message_append_args(
+ m,
+ DBUS_TYPE_UINT64, &u64,
+ DBUS_TYPE_INT32, &s32,
+ DBUS_TYPE_INVALID)) {
+ ret = -ENOMEM;
+ goto finish;
+ }
+
+
+
+ if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) {
+ ret = translate_error(error.name);
+ goto finish;
+ }
+
+
+ if (dbus_set_error_from_message(&error, r)) {
+ ret = translate_error(error.name);
+ goto finish;
+ }
+
+ ret = 0;
+
+finish:
+
+ if (m)
+ dbus_message_unref(m);
+
+ if (r)
+ dbus_message_unref(r);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
+
+#else
+
+int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) {
+ return -ENOTSUP;
+}
+
+int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) {
+ return -ENOTSUP;
+}
+
+#endif
diff --git a/src/pulsecore/rtkit.h b/src/pulsecore/rtkit.h
new file mode 100644
index 00000000..2081b4e9
--- /dev/null
+++ b/src/pulsecore/rtkit.h
@@ -0,0 +1,62 @@
+/*-*- Mode: C; c-basic-offset: 8 -*-*/
+
+#ifndef foortkithfoo
+#define foortkithfoo
+
+/***
+ Copyright 2009 Lennart Poettering
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+***/
+
+#include <sys/types.h>
+#include <dbus/dbus.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This is the reference implementation for a client for
+ * RealtimeKit. You don't have to use this, but if do, just copy these
+ * sources into your repository */
+
+#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1"
+#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1"
+
+/* This is mostly equivalent to sched_setparam(thread, SCHED_RR, {
+ * .sched_priority = priority }). 'thread' needs to be a kernel thread
+ * id as returned by gettid(), not a pthread_t! If 'thread' is 0 the
+ * current thread is used. The returned value is a negative errno
+ * style error code, or 0 on success. */
+int rtkit_make_realtime(DBusConnection *system_bus, pid_t thread, int priority);
+
+/* This is mostly equivalent to setpriority(PRIO_PROCESS, thread,
+ * nice_level). 'thread' needs to be a kernel thread id as returned by
+ * gettid(), not a pthread_t! If 'thread' is 0 the current thread is
+ * used. The returned value is a negative errno style error code, or 0
+ * on success.*/
+int rtkit_make_high_priority(DBusConnection *system_bus, pid_t thread, int nice_level);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index 9401debd..5cbec321 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -30,10 +30,6 @@
#include <string.h>
#include <errno.h>
-#ifdef __linux__
-#include <sys/utsname.h>
-#endif
-
#ifdef HAVE_POLL_H
#include <poll.h>
#else
@@ -47,7 +43,6 @@
#include <pulsecore/core-rtclock.h>
#include <pulsecore/macro.h>
#include <pulsecore/llist.h>
-#include <pulsecore/rtsig.h>
#include <pulsecore/flist.h>
#include <pulsecore/core-util.h>
#include <pulsecore/winsock.h>
@@ -66,20 +61,9 @@ struct pa_rtpoll {
pa_bool_t scan_for_dead:1;
pa_bool_t running:1;
- pa_bool_t installed:1;
pa_bool_t rebuild_needed:1;
pa_bool_t quit:1;
-#ifdef HAVE_PPOLL
- pa_bool_t timer_armed:1;
-#ifdef __linux__
- pa_bool_t dont_use_ppoll:1;
-#endif
- int rtsig;
- sigset_t sigset_unblocked;
- timer_t timer;
-#endif
-
#ifdef DEBUG_TIMING
pa_usec_t timestamp;
pa_usec_t slept, awake;
@@ -107,52 +91,20 @@ struct pa_rtpoll_item {
PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
-static void signal_handler_noop(int s) { /* write(2, "signal\n", 7); */ }
-
pa_rtpoll *pa_rtpoll_new(void) {
pa_rtpoll *p;
p = pa_xnew(pa_rtpoll, 1);
-#ifdef HAVE_PPOLL
-
-#ifdef __linux__
- /* ppoll is broken on Linux < 2.6.16 */
- p->dont_use_ppoll = FALSE;
-
- {
- struct utsname u;
- unsigned major, minor, micro;
-
- pa_assert_se(uname(&u) == 0);
-
- if (sscanf(u.release, "%u.%u.%u", &major, &minor, &micro) != 3 ||
- (major < 2) ||
- (major == 2 && minor < 6) ||
- (major == 2 && minor == 6 && micro < 16))
-
- p->dont_use_ppoll = TRUE;
- }
-
-#endif
-
- p->rtsig = -1;
- sigemptyset(&p->sigset_unblocked);
- p->timer = (timer_t) -1;
- p->timer_armed = FALSE;
-
-#endif
-
p->n_pollfd_alloc = 32;
p->pollfd = pa_xnew(struct pollfd, p->n_pollfd_alloc);
p->pollfd2 = pa_xnew(struct pollfd, p->n_pollfd_alloc);
p->n_pollfd_used = 0;
- memset(&p->next_elapse, 0, sizeof(p->next_elapse));
+ pa_zero(p->next_elapse);
p->timer_enabled = FALSE;
p->running = FALSE;
- p->installed = FALSE;
p->scan_for_dead = FALSE;
p->rebuild_needed = FALSE;
p->quit = FALSE;
@@ -167,46 +119,6 @@ pa_rtpoll *pa_rtpoll_new(void) {
return p;
}
-void pa_rtpoll_install(pa_rtpoll *p) {
- pa_assert(p);
- pa_assert(!p->installed);
-
- p->installed = TRUE;
-
-#ifdef HAVE_PPOLL
-# ifdef __linux__
- if (p->dont_use_ppoll)
- return;
-# endif
-
- if ((p->rtsig = pa_rtsig_get_for_thread()) < 0) {
- pa_log_warn("Failed to reserve POSIX realtime signal.");
- return;
- }
-
- pa_log_debug("Acquired POSIX realtime signal %s", pa_sig2str(p->rtsig));
-
- {
- sigset_t ss;
- struct sigaction sa;
-
- pa_assert_se(sigemptyset(&ss) == 0);
- pa_assert_se(sigaddset(&ss, p->rtsig) == 0);
- pa_assert_se(pthread_sigmask(SIG_BLOCK, &ss, &p->sigset_unblocked) == 0);
- pa_assert_se(sigdelset(&p->sigset_unblocked, p->rtsig) == 0);
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = signal_handler_noop;
- pa_assert_se(sigemptyset(&sa.sa_mask) == 0);
-
- pa_assert_se(sigaction(p->rtsig, &sa, NULL) == 0);
-
- /* We never reset the signal handler. Why should we? */
- }
-
-#endif
-}
-
static void rtpoll_rebuild(pa_rtpoll *p) {
struct pollfd *e, *t;
@@ -250,7 +162,6 @@ static void rtpoll_rebuild(pa_rtpoll *p) {
if (ra)
p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
-
}
static void rtpoll_item_destroy(pa_rtpoll_item *i) {
@@ -279,11 +190,6 @@ void pa_rtpoll_free(pa_rtpoll *p) {
pa_xfree(p->pollfd);
pa_xfree(p->pollfd2);
-#ifdef HAVE_PPOLL
- if (p->timer != (timer_t) -1)
- timer_delete(p->timer);
-#endif
-
pa_xfree(p);
}
@@ -321,7 +227,6 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
pa_assert(p);
pa_assert(!p->running);
- pa_assert(p->installed);
p->running = TRUE;
@@ -402,22 +307,15 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
/* OK, now let's sleep */
#ifdef HAVE_PPOLL
-
-#ifdef __linux__
- if (!p->dont_use_ppoll)
-#endif
{
struct timespec ts;
ts.tv_sec = timeout.tv_sec;
ts.tv_nsec = timeout.tv_usec * 1000;
- r = ppoll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || p->timer_enabled) ? &ts : NULL, p->rtsig < 0 ? NULL : &p->sigset_unblocked);
+ r = ppoll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || p->timer_enabled) ? &ts : NULL, NULL);
}
-#ifdef __linux__
- else
-#endif
-
-#endif
+#else
r = poll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || p->timer_enabled) ? (int) ((timeout.tv_sec*1000) + (timeout.tv_usec / 1000)) : -1);
+#endif
#ifdef DEBUG_TIMING
{
@@ -472,73 +370,11 @@ finish:
return r < 0 ? r : !p->quit;
}
-static void update_timer(pa_rtpoll *p) {
- pa_assert(p);
-
-#ifdef HAVE_PPOLL
-
-#ifdef __linux__
- if (p->dont_use_ppoll)
- return;
-#endif
-
- if (p->timer == (timer_t) -1) {
- struct sigevent se;
-
- memset(&se, 0, sizeof(se));
- se.sigev_notify = SIGEV_SIGNAL;
- se.sigev_signo = p->rtsig;
-
- if (timer_create(CLOCK_MONOTONIC, &se, &p->timer) < 0)
- if (timer_create(CLOCK_REALTIME, &se, &p->timer) < 0) {
- pa_log_warn("Failed to allocate POSIX timer: %s", pa_cstrerror(errno));
- p->timer = (timer_t) -1;
- }
- }
-
- if (p->timer != (timer_t) -1) {
- struct itimerspec its;
- struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
- sigset_t ss;
-
- if (p->timer_armed) {
- /* First disarm timer */
- memset(&its, 0, sizeof(its));
- pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
-
- /* Remove a signal that might be waiting in the signal q */
- pa_assert_se(sigemptyset(&ss) == 0);
- pa_assert_se(sigaddset(&ss, p->rtsig) == 0);
- sigtimedwait(&ss, NULL, &ts);
- }
-
- /* And install the new timer */
- if (p->timer_enabled) {
- memset(&its, 0, sizeof(its));
-
- its.it_value.tv_sec = p->next_elapse.tv_sec;
- its.it_value.tv_nsec = p->next_elapse.tv_usec*1000;
-
- /* Make sure that 0,0 is not understood as
- * "disarming" */
- if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0)
- its.it_value.tv_nsec = 1;
- pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
- }
-
- p->timer_armed = p->timer_enabled;
- }
-
-#endif
-}
-
void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, pa_usec_t usec) {
pa_assert(p);
pa_timeval_store(&p->next_elapse, usec);
p->timer_enabled = TRUE;
-
- update_timer(p);
}
void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
@@ -550,8 +386,6 @@ void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
pa_rtclock_get(&p->next_elapse);
pa_timeval_add(&p->next_elapse, usec);
p->timer_enabled = TRUE;
-
- update_timer(p);
}
void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) {
@@ -559,8 +393,6 @@ void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) {
memset(&p->next_elapse, 0, sizeof(p->next_elapse));
p->timer_enabled = FALSE;
-
- update_timer(p);
}
pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds) {
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
index 08776ef0..d2d69cad 100644
--- a/src/pulsecore/rtpoll.h
+++ b/src/pulsecore/rtpoll.h
@@ -62,9 +62,6 @@ typedef enum pa_rtpoll_priority {
pa_rtpoll *pa_rtpoll_new(void);
void pa_rtpoll_free(pa_rtpoll *p);
-/* Install the rtpoll in the current thread */
-void pa_rtpoll_install(pa_rtpoll *p);
-
/* Sleep on the rtpoll until the time event, or any of the fd events
* is triggered. If "wait" is 0 we don't sleep but only update the
* struct pollfd. Returns negative on error, positive if the loop
diff --git a/src/pulsecore/rtsig.c b/src/pulsecore/rtsig.c
deleted file mode 100644
index 4cd6aa8f..00000000
--- a/src/pulsecore/rtsig.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/***
- This file is part of PulseAudio.
-
- Copyright 2004-2006 Lennart Poettering
- Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.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 <signal.h>
-
-#include <pulsecore/macro.h>
-#include <pulsecore/flist.h>
-#include <pulsecore/once.h>
-#include <pulsecore/thread.h>
-#include <pulsecore/core-util.h>
-
-#include "rtsig.h"
-
-#ifdef SIGRTMIN
-
-static void _free_rtsig(void *p) {
- pa_rtsig_put(PA_PTR_TO_INT(p));
-}
-
-PA_STATIC_FLIST_DECLARE(rtsig_flist, pa_make_power_of_two((unsigned) (SIGRTMAX-SIGRTMIN+1)), NULL);
-PA_STATIC_TLS_DECLARE(rtsig_tls, _free_rtsig);
-
-static pa_atomic_t rtsig_current = PA_ATOMIC_INIT(-1);
-
-static int rtsig_start = -1, rtsig_end = -1;
-
-int pa_rtsig_get(void) {
- void *p;
- int sig;
-
- if ((p = pa_flist_pop(PA_STATIC_FLIST_GET(rtsig_flist))))
- return PA_PTR_TO_INT(p);
-
- sig = pa_atomic_dec(&rtsig_current);
-
- pa_assert(sig <= SIGRTMAX);
- pa_assert(sig <= rtsig_end);
-
- if (sig < rtsig_start) {
- pa_atomic_inc(&rtsig_current);
- return -1;
- }
-
- return sig;
-}
-
-int pa_rtsig_get_for_thread(void) {
- int sig;
- void *p;
-
- if ((p = PA_STATIC_TLS_GET(rtsig_tls)))
- return PA_PTR_TO_INT(p);
-
- if ((sig = pa_rtsig_get()) < 0)
- return -1;
-
- PA_STATIC_TLS_SET(rtsig_tls, PA_INT_TO_PTR(sig));
- return sig;
-}
-
-void pa_rtsig_put(int sig) {
- pa_assert(sig >= rtsig_start);
- pa_assert(sig <= rtsig_end);
-
- pa_assert_se(pa_flist_push(PA_STATIC_FLIST_GET(rtsig_flist), PA_INT_TO_PTR(sig)) >= 0);
-}
-
-void pa_rtsig_configure(int start, int end) {
- int s;
- sigset_t ss;
-
- pa_assert(pa_atomic_load(&rtsig_current) == -1);
-
- pa_assert(SIGRTMIN <= start);
- pa_assert(start <= end);
- pa_assert(end <= SIGRTMAX);
-
- rtsig_start = start;
- rtsig_end = end;
-
- sigemptyset(&ss);
-
- for (s = rtsig_start; s <= rtsig_end; s++)
- pa_assert_se(sigaddset(&ss, s) == 0);
-
- pa_assert(pthread_sigmask(SIG_BLOCK, &ss, NULL) == 0);
-
- /* We allocate starting from the end */
- pa_atomic_store(&rtsig_current, rtsig_end);
-}
-
-#else /* SIGRTMIN */
-
-int pa_rtsig_get(void) {
- return -1;
-}
-
-int pa_rtsig_get_for_thread(void) {
- return -1;
-}
-
-void pa_rtsig_put(int sig) {
-}
-
-void pa_rtsig_configure(int start, int end) {
-}
-
-#endif /* SIGRTMIN */
diff --git a/src/pulsecore/rtsig.h b/src/pulsecore/rtsig.h
deleted file mode 100644
index e414122d..00000000
--- a/src/pulsecore/rtsig.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef foopulsertsighfoo
-#define foopulsertsighfoo
-
-/***
- 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.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.
-***/
-
-/* Return the next unused POSIX Realtime signals */
-int pa_rtsig_get(void);
-
-/* If not called before in the current thread, return the next unused
- * rtsig, and install it in a TLS region and give it up automatically
- * when the thread shuts down */
-int pa_rtsig_get_for_thread(void);
-
-/* Give an rtsig back. */
-void pa_rtsig_put(int sig);
-
-/* Block all RT signals */
-void pa_rtsig_configure(int start, int end);
-
-#endif
diff --git a/src/tests/rtpoll-test.c b/src/tests/rtpoll-test.c
index 4ac96446..1706cdfa 100644
--- a/src/tests/rtpoll-test.c
+++ b/src/tests/rtpoll-test.c
@@ -26,7 +26,6 @@
#include <pulsecore/log.h>
#include <pulsecore/rtpoll.h>
-#include <pulsecore/rtsig.h>
static int before(pa_rtpoll_item *i) {
pa_log("before");
@@ -47,10 +46,6 @@ int main(int argc, char *argv[]) {
pa_rtpoll_item *i, *w;
struct pollfd *pollfd;
-#ifdef SIGRTMIN
- pa_rtsig_configure(SIGRTMIN+10, SIGRTMAX);
-#endif
-
p = pa_rtpoll_new();
i = pa_rtpoll_item_new(p, PA_RTPOLL_EARLY, 1);
@@ -64,7 +59,6 @@ int main(int argc, char *argv[]) {
w = pa_rtpoll_item_new(p, PA_RTPOLL_NORMAL, 0);
pa_rtpoll_item_set_before_callback(w, worker);
- pa_rtpoll_install(p);
pa_rtpoll_set_timer_relative(p, 10000000); /* 10 s */
pa_rtpoll_run(p, 1);