summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am48
-rw-r--r--src/daemon/daemon-conf.c2
-rw-r--r--src/daemon/daemon.conf.in4
-rw-r--r--src/daemon/main.c33
-rw-r--r--src/daemon/org.pulseaudio.policy.in50
-rw-r--r--src/daemon/polkit.c172
-rw-r--r--src/daemon/polkit.h27
-rw-r--r--src/modules/alsa/alsa-mixer.c43
-rw-r--r--src/modules/alsa/alsa-mixer.h2
-rw-r--r--src/modules/alsa/alsa-sink.c86
-rw-r--r--src/modules/alsa/alsa-source.c81
-rw-r--r--src/modules/alsa/alsa-util.c255
-rw-r--r--src/modules/alsa/alsa-util.h10
-rw-r--r--src/modules/alsa/mixer/paths/analog-input.conf.common8
-rw-r--r--src/modules/alsa/mixer/paths/analog-output-headphones.conf2
-rw-r--r--src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf2
-rw-r--r--src/modules/alsa/mixer/paths/analog-output-mono.conf2
-rw-r--r--src/modules/alsa/module-alsa-card.c2
-rw-r--r--src/modules/bluetooth/module-bluetooth-device.c9
-rw-r--r--src/modules/gconf/module-gconf.c2
-rw-r--r--src/modules/hal-util.c2
-rw-r--r--src/modules/module-always-sink.c6
-rw-r--r--src/modules/module-cli.c28
-rw-r--r--src/modules/module-hal-detect.c4
-rw-r--r--src/modules/module-ladspa-sink.c25
-rw-r--r--src/modules/module-null-sink.c5
-rw-r--r--src/modules/module-position-event-sounds.c58
-rw-r--r--src/modules/module-remap-sink.c24
-rw-r--r--src/modules/module-stream-restore.c2
-rw-r--r--src/modules/module-tunnel.c69
-rw-r--r--src/modules/module-udev-detect.c47
-rw-r--r--src/modules/raop/base64.c1
-rw-r--r--src/modules/raop/module-raop-discover.c4
-rw-r--r--src/modules/reserve-wrap.c10
-rw-r--r--src/modules/rtp/rtsp_client.c22
-rw-r--r--src/modules/x11/module-x11-publish.c2
-rw-r--r--src/pulse/context.c5
-rw-r--r--src/pulse/context.h7
-rw-r--r--src/pulse/def.h17
-rw-r--r--src/pulse/error.c4
-rw-r--r--src/pulse/gccmacro.h2
-rw-r--r--src/pulse/introspect.c2
-rw-r--r--src/pulse/introspect.h12
-rw-r--r--src/pulse/mainloop.c179
-rw-r--r--src/pulse/proplist.h23
-rw-r--r--src/pulse/pulseaudio.h16
-rw-r--r--src/pulse/sample.h7
-rw-r--r--src/pulse/scache.c14
-rw-r--r--src/pulse/scache.h4
-rw-r--r--src/pulse/stream.h2
-rw-r--r--src/pulse/timeval.c67
-rw-r--r--src/pulse/timeval.h7
-rw-r--r--src/pulse/utf8.c9
-rw-r--r--src/pulse/volume.c60
-rw-r--r--src/pulse/volume.h9
-rw-r--r--src/pulsecore/cli-command.c56
-rw-r--r--src/pulsecore/conf-parser.c2
-rw-r--r--src/pulsecore/core-rtclock.c22
-rw-r--r--src/pulsecore/core-rtclock.h1
-rw-r--r--src/pulsecore/core-scache.c4
-rw-r--r--src/pulsecore/core-util.c90
-rw-r--r--src/pulsecore/core-util.h4
-rw-r--r--src/pulsecore/cpu-x86.c2
-rw-r--r--src/pulsecore/flist.c22
-rw-r--r--src/pulsecore/macro.h12
-rw-r--r--src/pulsecore/memblock.c29
-rw-r--r--src/pulsecore/memtrap.c9
-rw-r--r--src/pulsecore/namereg.c13
-rw-r--r--src/pulsecore/pid.c4
-rw-r--r--src/pulsecore/protocol-esound.c4
-rw-r--r--src/pulsecore/protocol-native.c40
-rw-r--r--src/pulsecore/protocol-simple.c2
-rw-r--r--src/pulsecore/ratelimit.h18
-rw-r--r--src/pulsecore/remap_mmx.c42
-rw-r--r--src/pulsecore/remap_sse.c75
-rw-r--r--src/pulsecore/sample-util.c10
-rw-r--r--src/pulsecore/sample-util.h2
-rw-r--r--src/pulsecore/sconv_sse.c16
-rw-r--r--src/pulsecore/sink-input.c84
-rw-r--r--src/pulsecore/sink-input.h7
-rw-r--r--src/pulsecore/sink.c106
-rw-r--r--src/pulsecore/socket-client.c64
-rw-r--r--src/pulsecore/socket-client.h2
-rw-r--r--src/pulsecore/source-output.c8
-rw-r--r--src/pulsecore/source.c13
-rw-r--r--src/pulsecore/start-child.c5
-rw-r--r--src/pulsecore/svolume_mmx.c31
-rw-r--r--src/pulsecore/svolume_sse.c19
-rw-r--r--src/pulsecore/vector.h3
-rw-r--r--src/tests/stripnul.c2
-rw-r--r--src/utils/pacat.c23
-rw-r--r--src/utils/pactl.c268
-rw-r--r--src/utils/padsp.c12
93 files changed, 1616 insertions, 1105 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 623cef57..69711ac1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -178,8 +178,8 @@ pulseaudio_SOURCES = \
daemon/main.c \
daemon/server-lookup.c daemon/server-lookup.h
-pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSPEEX_CFLAGS) $(LIBSNDFILE_CFLAGS) $(CAP_CFLAGS) $(LIBOIL_CFLAGS) $(DBUS_CFLAGS)
-pulseaudio_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSPEEX_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS) $(DBUS_LIBS)
+pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSPEEX_CFLAGS) $(LIBSNDFILE_CFLAGS) $(CAP_CFLAGS) $(DBUS_CFLAGS)
+pulseaudio_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSPEEX_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(DBUS_LIBS)
# This is needed because automake doesn't properly expand the foreach below
pulseaudio_DEPENDENCIES = libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la $(PREOPEN_LIBS)
@@ -497,18 +497,18 @@ sig2str_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
resampler_test_SOURCES = tests/resampler-test.c
resampler_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
-resampler_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
-resampler_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+resampler_test_CFLAGS = $(AM_CFLAGS)
+resampler_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
mix_test_SOURCES = tests/mix-test.c
mix_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
-mix_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
-mix_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+mix_test_CFLAGS = $(AM_CFLAGS)
+mix_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
remix_test_SOURCES = tests/remix-test.c
remix_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
-remix_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
-remix_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+remix_test_CFLAGS = $(AM_CFLAGS)
+remix_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
smoother_test_SOURCES = tests/smoother-test.c
smoother_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
@@ -517,38 +517,38 @@ smoother_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
envelope_test_SOURCES = tests/envelope-test.c
envelope_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
-envelope_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
-envelope_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+envelope_test_CFLAGS = $(AM_CFLAGS)
+envelope_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
proplist_test_SOURCES = tests/proplist-test.c
proplist_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
-proplist_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
-proplist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+proplist_test_CFLAGS = $(AM_CFLAGS)
+proplist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
rtstutter_SOURCES = tests/rtstutter.c
rtstutter_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
-rtstutter_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
-rtstutter_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+rtstutter_CFLAGS = $(AM_CFLAGS)
+rtstutter_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
stripnul_SOURCES = tests/stripnul.c
stripnul_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
-stripnul_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
-stripnul_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+stripnul_CFLAGS = $(AM_CFLAGS)
+stripnul_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
lock_autospawn_test_SOURCES = tests/lock-autospawn-test.c
lock_autospawn_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
-lock_autospawn_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
-lock_autospawn_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+lock_autospawn_test_CFLAGS = $(AM_CFLAGS)
+lock_autospawn_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
prioq_test_SOURCES = tests/prioq-test.c
prioq_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
-prioq_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
-prioq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+prioq_test_CFLAGS = $(AM_CFLAGS)
+prioq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
sigbus_test_SOURCES = tests/sigbus-test.c
sigbus_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
-sigbus_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
-sigbus_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+sigbus_test_CFLAGS = $(AM_CFLAGS)
+sigbus_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
gtk_test_SOURCES = tests/gtk-test.c
gtk_test_LDADD = $(AM_LDADD) libpulse.la libpulse-mainloop-glib.la
@@ -859,9 +859,9 @@ libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES = \
pulsecore/time-smoother.c pulsecore/time-smoother.h \
pulsecore/database.h
-libpulsecore_@PA_MAJORMINORMICRO@_la_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSPEEX_CFLAGS) $(WINSOCK_CFLAGS) $(LIBOIL_CFLAGS)
+libpulsecore_@PA_MAJORMINORMICRO@_la_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSPEEX_CFLAGS) $(WINSOCK_CFLAGS)
libpulsecore_@PA_MAJORMINORMICRO@_la_LDFLAGS = -avoid-version
-libpulsecore_@PA_MAJORMINORMICRO@_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSPEEX_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LTLIBICONV) libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la libpulsecore-foreign.la
+libpulsecore_@PA_MAJORMINORMICRO@_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSPEEX_LIBS) $(WINSOCK_LIBS) $(LTLIBICONV) libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la libpulsecore-foreign.la
if HAVE_X11
libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES += pulsecore/x11wrap.c pulsecore/x11wrap.h
diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index 3428f807..571faae4 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -86,7 +86,7 @@ static const pa_daemon_conf default_conf = {
#ifdef HAVE_DBUS
.local_server_type = PA_SERVER_TYPE_UNSET, /* The actual default is _USER, but we have to detect when the user doesn't specify this option. */
#endif
- .no_cpu_limit = FALSE,
+ .no_cpu_limit = TRUE,
.disable_shm = FALSE,
.lock_memory = FALSE,
.default_n_fragments = 4,
diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index a11fd06c..7c1a7b8c 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -29,7 +29,7 @@
; enable-shm = yes
; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
; lock-memory = no
-; cpu-limit = yes
+; cpu-limit = no
; high-priority = yes
; nice-level = -11
@@ -71,7 +71,7 @@
; rlimit-msgqueue = -1
; rlimit-nice = 31
; rlimit-rtprio = 9
-; rlimit-rtttime = 1000000
+; rlimit-rttime = 1000000
; default-sample-format = s16le
; default-sample-rate = 44100
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 409823b1..9e5647a8 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -260,9 +260,14 @@ static int change_user(void) {
pa_set_env("HOME", PA_SYSTEM_RUNTIME_PATH);
/* Relevant for pa_runtime_path() */
- pa_set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH);
- pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_CONFIG_PATH);
- pa_set_env("PULSE_STATE_PATH", PA_SYSTEM_STATE_PATH);
+ if (!getenv("PULSE_RUNTIME_PATH"))
+ pa_set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH);
+
+ if (!getenv("PULSE_CONFIG_PATH"))
+ pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_CONFIG_PATH);
+
+ if (!getenv("PULSE_STATE_PATH"))
+ pa_set_env("PULSE_STATE_PATH", PA_SYSTEM_STATE_PATH);
pa_log_info(_("Successfully dropped root privileges."));
@@ -413,23 +418,28 @@ int main(int argc, char *argv[]) {
if (!getenv("LD_BIND_NOW")) {
char *rp;
+ char *canonical_rp;
/* We have to execute ourselves, because the libc caches the
* value of $LD_BIND_NOW on initialization. */
pa_set_env("LD_BIND_NOW", "1");
+ canonical_rp = pa_realpath(PA_BINARY);
+
if ((rp = pa_readlink("/proc/self/exe"))) {
- if (pa_streq(rp, PA_BINARY))
+ if (pa_streq(rp, canonical_rp))
pa_assert_se(execv(rp, argv) == 0);
else
- pa_log_warn("/proc/self/exe does not point to " PA_BINARY ", cannot self execute. Are you playing games?");
+ pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp);
pa_xfree(rp);
} else
pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?");
+
+ pa_xfree(canonical_rp);
}
#endif
@@ -731,7 +741,7 @@ int main(int argc, char *argv[]) {
#endif
}
- pa_set_env("PULSE_INTERNAL", "1");
+ pa_set_env_and_record("PULSE_INTERNAL", "1");
pa_assert_se(chdir("/") == 0);
umask(0022);
@@ -746,7 +756,7 @@ int main(int argc, char *argv[]) {
if (change_user() < 0)
goto finish;
- pa_set_env("PULSE_SYSTEM", conf->system_instance ? "1" : "0");
+ pa_set_env_and_record("PULSE_SYSTEM", conf->system_instance ? "1" : "0");
pa_log_info(_("This is PulseAudio %s"), PACKAGE_VERSION);
pa_log_debug(_("Compilation host: %s"), CANONICAL_HOST);
@@ -853,8 +863,10 @@ int main(int argc, char *argv[]) {
pa_memtrap_install();
- pa_cpu_init_x86();
- pa_cpu_init_arm();
+ if (!getenv("PULSE_NO_SIMD")) {
+ pa_cpu_init_x86();
+ pa_cpu_init_arm();
+ }
pa_assert_se(mainloop = pa_mainloop_new());
@@ -1021,6 +1033,9 @@ finish:
if (valid_pid_file)
pa_pid_file_remove();
+ /* This has no real purpose except making things valgrind-clean */
+ pa_unset_env_recorded();
+
#ifdef OS_IS_WIN32
WSACleanup();
#endif
diff --git a/src/daemon/org.pulseaudio.policy.in b/src/daemon/org.pulseaudio.policy.in
deleted file mode 100644
index 1d0b6a7d..00000000
--- a/src/daemon/org.pulseaudio.policy.in
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><!--*-nxml-*-->
-<!DOCTYPE policyconfig PUBLIC
- "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
-
-<!--
-This file is part of PulseAudio.
-
-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.
--->
-
-<policyconfig>
- <vendor>The PulseAudio Project</vendor>
- <vendor_url>http://pulseaudio.org/</vendor_url>
- <icon_name>audio-card</icon_name>
-
- <action id="org.pulseaudio.acquire-real-time">
- <_description>Real-time scheduling for the PulseAudio daemon</_description>
- <_message>System policy prevents PulseAudio from acquiring real-time scheduling.</_message>
- <defaults>
- <allow_any>no</allow_any>
- <allow_inactive>no</allow_inactive>
- <allow_active>no</allow_active>
- </defaults>
- </action>
-
- <action id="org.pulseaudio.acquire-high-priority">
- <_description>High-priority scheduling (negative Unix nice level) for the PulseAudio daemon</_description>
- <_message>System policy prevents PulseAudio from acquiring high-priority scheduling.</_message>
- <defaults>
- <allow_any>no</allow_any>
- <allow_inactive>no</allow_inactive>
- <allow_active>no</allow_active>
- </defaults>
- </action>
-
-</policyconfig>
diff --git a/src/daemon/polkit.c b/src/daemon/polkit.c
deleted file mode 100644
index 9799e094..00000000
--- a/src/daemon/polkit.c
+++ /dev/null
@@ -1,172 +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
- 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 <stdlib.h>
-#include <inttypes.h>
-
-#include <dbus/dbus.h>
-#include <polkit-dbus/polkit-dbus.h>
-
-#include <pulse/i18n.h>
-
-#include <pulsecore/log.h>
-#include <pulsecore/macro.h>
-
-#include "polkit.h"
-
-int pa_polkit_check(const char *action_id) {
- int ret = -1;
- DBusError dbus_error;
- DBusConnection *bus = NULL;
- PolKitCaller *caller = NULL;
- PolKitAction *action = NULL;
- PolKitContext *context = NULL;
- PolKitError *polkit_error = NULL;
- PolKitSession *session = NULL;
- PolKitResult polkit_result;
-
- 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);
- goto finish;
- }
-
- /* There seems to be a bug in some versions of D-Bus that causes
- * dbus_shutdown() to call exit() when a connection without this
- * flag disabled was created during runtime.*/
- 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);
- goto finish;
- }
-
- /* This function is called when PulseAudio is called SUID root. We
- * want to authenticate the real user that called us and not the
- * effective user we gained through being SUID root. Hence we
- * overwrite the UID caller data here explicitly, just for
- * paranoia. In fact PolicyKit should fill in the UID here anyway
- * -- 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."));
- goto finish;
- }
-
- if (!(polkit_caller_get_ck_session(caller, &session))) {
- pa_log_error(_("Failed to get CK session."));
- goto finish;
- }
-
- /* We need to overwrite the UID in both the caller and the session
- * object */
-
- if (!(polkit_session_set_uid(session, getuid()))) {
- pa_log_error(_("Cannot set UID on session object."));
- goto finish;
- }
-
- if (!(action = polkit_action_new())) {
- pa_log_error(_("Cannot allocate PolKitAction."));
- goto finish;
- }
-
- if (!polkit_action_set_action_id(action, action_id)) {
- pa_log_error(_("Cannot set action_id"));
- goto finish;
- }
-
- if (!(context = polkit_context_new())) {
- 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));
- goto finish;
- }
-
- for (;;) {
-
- 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));
- goto finish;
- }
-
- if (polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
- polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
- polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS ||
- polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT ||
- polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH ||
- polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION ||
- polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS ||
- polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT
- ) {
-
- if (polkit_auth_obtain(action_id, 0, getpid(), &dbus_error)) {
- polkit_result = POLKIT_RESULT_YES;
- break;
- }
-
- if (dbus_error_is_set(&dbus_error)) {
- pa_log_error(_("Cannot obtain auth: %s"), dbus_error.message);
- goto finish;
- }
- }
-
- break;
- }
-
- 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));
-
- ret = polkit_result == POLKIT_RESULT_YES;
-
-finish:
-
- if (caller)
- polkit_caller_unref(caller);
-
- if (action)
- polkit_action_unref(action);
-
- if (context)
- polkit_context_unref(context);
-
- if (bus)
- dbus_connection_unref(bus);
-
- dbus_error_free(&dbus_error);
-
- if (polkit_error)
- polkit_error_free(polkit_error);
-
- return ret;
-}
diff --git a/src/daemon/polkit.h b/src/daemon/polkit.h
deleted file mode 100644
index 018f6ef1..00000000
--- a/src/daemon/polkit.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef foopolkithfoo
-#define foopolkithfoo
-
-/***
- This file is part of PulseAudio.
-
- Copyright 2007 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.
-***/
-
-int pa_polkit_check(const char *action);
-
-#endif
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 61c92cd0..f3ce681f 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -479,7 +479,6 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
snd_mixer_elem_t *me;
snd_mixer_selem_channel_id_t c;
pa_channel_position_mask_t mask = 0;
- pa_volume_t max_channel_volume = PA_VOLUME_MUTED;
unsigned k;
pa_assert(m);
@@ -546,9 +545,6 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
f = from_alsa_volume(value, e->min_volume, e->max_volume);
}
- if (f > max_channel_volume)
- max_channel_volume = f;
-
for (k = 0; k < cm->channels; k++)
if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k]))
if (v->values[k] < f)
@@ -559,7 +555,7 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
for (k = 0; k < cm->channels; k++)
if (!(mask & PA_CHANNEL_POSITION_MASK(cm->map[k])))
- v->values[k] = max_channel_volume;
+ v->values[k] = PA_VOLUME_NORM;
return 0;
}
@@ -681,7 +677,6 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
snd_mixer_elem_t *me;
snd_mixer_selem_channel_id_t c;
pa_channel_position_mask_t mask = 0;
- pa_volume_t max_channel_volume = PA_VOLUME_MUTED;
unsigned k;
pa_assert(m);
@@ -771,9 +766,6 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
f = from_alsa_volume(value, e->min_volume, e->max_volume);
}
- if (f > max_channel_volume)
- max_channel_volume = f;
-
for (k = 0; k < cm->channels; k++)
if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k]))
if (rv.values[k] < f)
@@ -784,7 +776,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
for (k = 0; k < cm->channels; k++)
if (!(mask & PA_CHANNEL_POSITION_MASK(cm->map[k])))
- rv.values[k] = max_channel_volume;
+ rv.values[k] = PA_VOLUME_NORM;
*v = rv;
return 0;
@@ -1716,11 +1708,11 @@ static int option_verify(pa_alsa_option *o) {
{ "input-radio", N_("Radio") },
{ "input-video", N_("Video") },
{ "input-agc-on", N_("Automatic Gain Control") },
- { "input-agc-off", "" },
+ { "input-agc-off", N_("No Automatic Gain Control") },
{ "input-boost-on", N_("Boost") },
- { "input-boost-off", "" },
+ { "input-boost-off", N_("No Boost") },
{ "output-amplifier-on", N_("Amplifier") },
- { "output-amplifier-off", "" }
+ { "output-amplifier-off", N_("No Amplifier") }
};
pa_assert(o);
@@ -2889,7 +2881,7 @@ static void profile_set_add_auto_pair(
else
name = pa_sprintf_malloc("input:%s", n->name);
- if ((p = pa_hashmap_get(ps->profiles, name))) {
+ if (pa_hashmap_get(ps->profiles, name)) {
pa_xfree(name);
return;
}
@@ -3145,7 +3137,13 @@ fail:
return NULL;
}
-void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss) {
+void pa_alsa_profile_set_probe(
+ pa_alsa_profile_set *ps,
+ const char *dev_id,
+ const pa_sample_spec *ss,
+ unsigned default_n_fragments,
+ unsigned default_fragment_size_msec) {
+
void *state;
pa_alsa_profile *p, *last = NULL;
pa_alsa_mapping *m;
@@ -3160,6 +3158,7 @@ void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, cons
PA_HASHMAP_FOREACH(p, ps->profiles, state) {
pa_sample_spec try_ss;
pa_channel_map try_map;
+ snd_pcm_uframes_t try_period_size, try_buffer_size;
uint32_t idx;
/* Is this already marked that it is supported? (i.e. from the config file) */
@@ -3213,13 +3212,18 @@ void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, cons
try_ss = *ss;
try_ss.channels = try_map.channels;
+ try_period_size =
+ pa_usec_to_bytes(default_fragment_size_msec * PA_USEC_PER_MSEC, &try_ss) /
+ pa_frame_size(&try_ss);
+ try_buffer_size = default_n_fragments * try_period_size;
+
if (!(m ->output_pcm = pa_alsa_open_by_template(
m->device_strings,
dev_id,
NULL,
&try_ss, &try_map,
SND_PCM_STREAM_PLAYBACK,
- NULL, NULL, 0, NULL, NULL,
+ &try_period_size, &try_buffer_size, 0, NULL, NULL,
TRUE))) {
p->supported = FALSE;
break;
@@ -3237,13 +3241,18 @@ void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, cons
try_ss = *ss;
try_ss.channels = try_map.channels;
+ try_period_size =
+ pa_usec_to_bytes(default_fragment_size_msec*PA_USEC_PER_MSEC, &try_ss) /
+ pa_frame_size(&try_ss);
+ try_buffer_size = default_n_fragments * try_period_size;
+
if (!(m ->input_pcm = pa_alsa_open_by_template(
m->device_strings,
dev_id,
NULL,
&try_ss, &try_map,
SND_PCM_STREAM_CAPTURE,
- NULL, NULL, 0, NULL, NULL,
+ &try_period_size, &try_buffer_size, 0, NULL, NULL,
TRUE))) {
p->supported = FALSE;
break;
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index 76788183..a0d4fcbe 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -269,7 +269,7 @@ void pa_alsa_mapping_dump(pa_alsa_mapping *m);
void pa_alsa_profile_dump(pa_alsa_profile *p);
pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus);
-void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss);
+void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss, unsigned default_n_fragments, unsigned default_fragment_size_msec);
void pa_alsa_profile_set_free(pa_alsa_profile_set *s);
void pa_alsa_profile_set_dump(pa_alsa_profile_set *s);
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 07d53880..22e88b4a 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -69,9 +69,12 @@
#define TSCHED_WATERMARK_INC_STEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms -- On underrun, increase watermark by this */
#define TSCHED_WATERMARK_DEC_STEP_USEC (5*PA_USEC_PER_MSEC) /* 5ms -- When everything's great, decrease watermark by this */
#define TSCHED_WATERMARK_VERIFY_AFTER_USEC (20*PA_USEC_PER_SEC) /* 20s -- How long after a drop out recheck if things are good now */
-#define TSCHED_WATERMARK_INC_THRESHOLD_USEC (1*PA_USEC_PER_MSEC) /* 3ms -- If the buffer level ever below this theshold, increase the watermark */
+#define TSCHED_WATERMARK_INC_THRESHOLD_USEC (0*PA_USEC_PER_MSEC) /* 0ms -- If the buffer level ever below this theshold, increase the watermark */
#define TSCHED_WATERMARK_DEC_THRESHOLD_USEC (100*PA_USEC_PER_MSEC) /* 100ms -- If the buffer level didn't drop below this theshold in the verification time, decrease the watermark */
+/* Note that TSCHED_WATERMARK_INC_THRESHOLD_USEC == 0 means tht we
+ * will increase the watermark only if we hit a real underrun. */
+
#define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms -- Sleep at least 10ms on each iteration */
#define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC) /* 4ms -- Wakeup at least this long before the buffer runs empty*/
@@ -113,7 +116,6 @@ struct userdata {
pa_usec_t watermark_dec_not_before;
- unsigned nfragments;
pa_memchunk memchunk;
char *device_name; /* name of the PCM device */
@@ -410,6 +412,7 @@ static int try_recover(struct userdata *u, const char *call, int err) {
static size_t check_left_to_play(struct userdata *u, size_t n_bytes, pa_bool_t on_timeout) {
size_t left_to_play;
+ pa_bool_t underrun = FALSE;
/* We use <= instead of < for this check here because an underrun
* only happens after the last sample was processed, not already when
@@ -422,6 +425,7 @@ static size_t check_left_to_play(struct userdata *u, size_t n_bytes, pa_bool_t o
/* We got a dropout. What a mess! */
left_to_play = 0;
+ underrun = TRUE;
#ifdef DEBUG_TIMING
PA_DEBUG_TRAP;
@@ -443,7 +447,7 @@ static size_t check_left_to_play(struct userdata *u, size_t n_bytes, pa_bool_t o
pa_bool_t reset_not_before = TRUE;
if (!u->first && !u->after_rewind) {
- if (left_to_play < u->watermark_inc_threshold)
+ if (underrun || left_to_play < u->watermark_inc_threshold)
increase_watermark(u);
else if (left_to_play > u->watermark_dec_threshold) {
reset_not_before = FALSE;
@@ -651,6 +655,7 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle
snd_pcm_sframes_t n;
size_t n_bytes;
int r;
+ pa_bool_t after_avail = TRUE;
if (PA_UNLIKELY((n = pa_alsa_safe_avail(u->pcm_handle, u->hwbuf_size, &u->sink->sample_spec)) < 0)) {
@@ -705,7 +710,6 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle
for (;;) {
snd_pcm_sframes_t frames;
void *p;
- pa_bool_t after_avail = TRUE;
/* pa_log_debug("%lu frames to write", (unsigned long) frames); */
@@ -938,8 +942,7 @@ static int unsuspend(struct userdata *u) {
pa_sample_spec ss;
int err;
pa_bool_t b, d;
- unsigned nfrags;
- snd_pcm_uframes_t period_size;
+ snd_pcm_uframes_t period_size, buffer_size;
pa_assert(u);
pa_assert(!u->pcm_handle);
@@ -947,7 +950,7 @@ static int unsuspend(struct userdata *u) {
pa_log_info("Trying resume...");
if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK,
- /*SND_PCM_NONBLOCK|*/
+ SND_PCM_NONBLOCK|
SND_PCM_NO_AUTO_RESAMPLE|
SND_PCM_NO_AUTO_CHANNELS|
SND_PCM_NO_AUTO_FORMAT)) < 0) {
@@ -956,12 +959,12 @@ static int unsuspend(struct userdata *u) {
}
ss = u->sink->sample_spec;
- nfrags = u->nfragments;
period_size = u->fragment_size / u->frame_size;
+ buffer_size = u->hwbuf_size / u->frame_size;
b = u->use_mmap;
d = u->use_tsched;
- if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, u->hwbuf_size / u->frame_size, &b, &d, TRUE)) < 0) {
+ if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &period_size, &buffer_size, 0, &b, &d, TRUE)) < 0) {
pa_log("Failed to set hardware parameters: %s", pa_alsa_strerror(err));
goto fail;
}
@@ -976,10 +979,11 @@ static int unsuspend(struct userdata *u) {
goto fail;
}
- if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
- pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
- (unsigned long) u->nfragments, (unsigned long) u->fragment_size,
- (unsigned long) nfrags, period_size * u->frame_size);
+ if (period_size*u->frame_size != u->fragment_size ||
+ buffer_size*u->frame_size != u->hwbuf_size) {
+ pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu/%lu, New %lu/%lu)",
+ (unsigned long) u->hwbuf_size, (unsigned long) u->fragment_size,
+ (unsigned long) (buffer_size*u->fragment_size), (unsigned long) (period_size*u->frame_size));
goto fail;
}
@@ -1007,7 +1011,7 @@ fail:
u->pcm_handle = NULL;
}
- return -1;
+ return -PA_ERR_IO;
}
/* Called from IO context */
@@ -1031,28 +1035,33 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
- case PA_SINK_SUSPENDED:
+ case PA_SINK_SUSPENDED: {
+ int r;
+
pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
- if (suspend(u) < 0)
- return -1;
+ if ((r = suspend(u)) < 0)
+ return r;
break;
+ }
case PA_SINK_IDLE:
- case PA_SINK_RUNNING:
+ case PA_SINK_RUNNING: {
+ int r;
if (u->sink->thread_info.state == PA_SINK_INIT) {
if (build_pollfd(u) < 0)
- return -1;
+ return -PA_ERR_IO;
}
if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
- if (unsuspend(u) < 0)
- return -1;
+ if ((r = unsuspend(u)) < 0)
+ return r;
}
break;
+ }
case PA_SINK_UNLINKED:
case PA_SINK_INIT:
@@ -1080,7 +1089,7 @@ static int sink_set_state_cb(pa_sink *s, pa_sink_state_t new_state) {
reserve_done(u);
else if (old_state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(new_state))
if (reserve_init(u, u->device_name) < 0)
- return -1;
+ return -PA_ERR_BUSY;
return 0;
}
@@ -1633,8 +1642,8 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
const char *dev_id = NULL;
pa_sample_spec ss, requested_ss;
pa_channel_map map;
- uint32_t nfrags, hwbuf_size, frag_size, tsched_size, tsched_watermark;
- snd_pcm_uframes_t period_frames, tsched_frames;
+ uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
+ snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
size_t frame_size;
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE;
pa_sink_new_data data;
@@ -1668,8 +1677,10 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
goto fail;
}
- hwbuf_size = frag_size * nfrags;
+ buffer_size = nfrags * frag_size;
+
period_frames = frag_size/frame_size;
+ buffer_frames = buffer_size/frame_size;
tsched_frames = tsched_size/frame_size;
if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
@@ -1736,7 +1747,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
&u->device_name,
&ss, &map,
SND_PCM_STREAM_PLAYBACK,
- &nfrags, &period_frames, tsched_frames,
+ &period_frames, &buffer_frames, tsched_frames,
&b, &d, mapping)))
goto fail;
@@ -1751,7 +1762,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
&u->device_name,
&ss, &map,
SND_PCM_STREAM_PLAYBACK,
- &nfrags, &period_frames, tsched_frames,
+ &period_frames, &buffer_frames, tsched_frames,
&b, &d, profile_set, &mapping)))
goto fail;
@@ -1763,7 +1774,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
&u->device_name,
&ss, &map,
SND_PCM_STREAM_PLAYBACK,
- &nfrags, &period_frames, tsched_frames,
+ &period_frames, &buffer_frames, tsched_frames,
&b, &d, FALSE)))
goto fail;
}
@@ -1789,11 +1800,6 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
u->use_tsched = use_tsched = FALSE;
}
- if (use_tsched && !pa_alsa_pcm_is_hw(u->pcm_handle)) {
- pa_log_info("Device is not a hardware device, disabling timer-based scheduling.");
- u->use_tsched = use_tsched = FALSE;
- }
-
if (u->use_mmap)
pa_log_info("Successfully enabled mmap() mode.");
@@ -1815,7 +1821,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
- pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
+ pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (buffer_frames * frame_size));
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
@@ -1856,13 +1862,15 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
pa_sink_set_rtpoll(u->sink, u->rtpoll);
u->frame_size = frame_size;
- u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size);
- u->nfragments = nfrags;
- u->hwbuf_size = u->fragment_size * nfrags;
+ u->fragment_size = frag_size = (size_t) (period_frames * frame_size);
+ u->hwbuf_size = buffer_size = (size_t) (buffer_frames * frame_size);
pa_cvolume_mute(&u->hardware_volume, u->sink->sample_spec.channels);
- pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
- nfrags, (long unsigned) u->fragment_size,
+ pa_log_info("Using %0.1f fragments of size %lu bytes (%0.2fms), buffer size is %lu bytes (%0.2fms)",
+ (double) u->hwbuf_size / (double) u->fragment_size,
+ (long unsigned) u->fragment_size,
+ (double) pa_bytes_to_usec(u->fragment_size, &ss) / PA_USEC_PER_MSEC,
+ (long unsigned) u->hwbuf_size,
(double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
pa_sink_set_max_request(u->sink, u->hwbuf_size);
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 165b2e3b..fa3ac0aa 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -66,7 +66,7 @@
#define TSCHED_WATERMARK_INC_STEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */
#define TSCHED_WATERMARK_DEC_STEP_USEC (5*PA_USEC_PER_MSEC) /* 5ms */
#define TSCHED_WATERMARK_VERIFY_AFTER_USEC (20*PA_USEC_PER_SEC) /* 20s */
-#define TSCHED_WATERMARK_INC_THRESHOLD_USEC (1*PA_USEC_PER_MSEC) /* 3ms */
+#define TSCHED_WATERMARK_INC_THRESHOLD_USEC (0*PA_USEC_PER_MSEC) /* 0ms */
#define TSCHED_WATERMARK_DEC_THRESHOLD_USEC (100*PA_USEC_PER_MSEC) /* 100ms */
#define TSCHED_WATERMARK_STEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */
@@ -111,8 +111,6 @@ struct userdata {
pa_usec_t watermark_dec_not_before;
- unsigned nfragments;
-
char *device_name;
char *control_device;
@@ -406,6 +404,7 @@ static int try_recover(struct userdata *u, const char *call, int err) {
static size_t check_left_to_record(struct userdata *u, size_t n_bytes, pa_bool_t on_timeout) {
size_t left_to_record;
size_t rec_space = u->hwbuf_size - u->hwbuf_unused;
+ pa_bool_t overrun = FALSE;
/* We use <= instead of < for this check here because an overrun
* only happens after the last sample was processed, not already when
@@ -418,6 +417,7 @@ static size_t check_left_to_record(struct userdata *u, size_t n_bytes, pa_bool_t
/* We got a dropout. What a mess! */
left_to_record = 0;
+ overrun = TRUE;
#ifdef DEBUG_TIMING
PA_DEBUG_TRAP;
@@ -434,7 +434,7 @@ static size_t check_left_to_record(struct userdata *u, size_t n_bytes, pa_bool_t
if (u->use_tsched) {
pa_bool_t reset_not_before = TRUE;
- if (left_to_record < u->watermark_inc_threshold)
+ if (overrun || left_to_record < u->watermark_inc_threshold)
increase_watermark(u);
else if (left_to_record > u->watermark_dec_threshold) {
reset_not_before = FALSE;
@@ -889,8 +889,7 @@ static int unsuspend(struct userdata *u) {
pa_sample_spec ss;
int err;
pa_bool_t b, d;
- unsigned nfrags;
- snd_pcm_uframes_t period_size;
+ snd_pcm_uframes_t period_size, buffer_size;
pa_assert(u);
pa_assert(!u->pcm_handle);
@@ -898,7 +897,7 @@ static int unsuspend(struct userdata *u) {
pa_log_info("Trying resume...");
if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE,
- /*SND_PCM_NONBLOCK|*/
+ SND_PCM_NONBLOCK|
SND_PCM_NO_AUTO_RESAMPLE|
SND_PCM_NO_AUTO_CHANNELS|
SND_PCM_NO_AUTO_FORMAT)) < 0) {
@@ -907,12 +906,12 @@ static int unsuspend(struct userdata *u) {
}
ss = u->source->sample_spec;
- nfrags = u->nfragments;
period_size = u->fragment_size / u->frame_size;
+ buffer_size = u->hwbuf_size / u->frame_size;
b = u->use_mmap;
d = u->use_tsched;
- if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, u->hwbuf_size / u->frame_size, &b, &d, TRUE)) < 0) {
+ if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &period_size, &buffer_size, 0, &b, &d, TRUE)) < 0) {
pa_log("Failed to set hardware parameters: %s", pa_alsa_strerror(err));
goto fail;
}
@@ -927,10 +926,11 @@ static int unsuspend(struct userdata *u) {
goto fail;
}
- if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
- pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
- (unsigned long) u->nfragments, (unsigned long) u->fragment_size,
- (unsigned long) nfrags, period_size * u->frame_size);
+ if (period_size*u->frame_size != u->fragment_size ||
+ buffer_size*u->frame_size != u->hwbuf_size) {
+ pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu/%lu, New %lu/%lu)",
+ (unsigned long) u->hwbuf_size, (unsigned long) u->fragment_size,
+ (unsigned long) (buffer_size*u->fragment_size), (unsigned long) (period_size*u->frame_size));
goto fail;
}
@@ -959,7 +959,7 @@ fail:
u->pcm_handle = NULL;
}
- return -1;
+ return -PA_ERR_IO;
}
static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
@@ -982,30 +982,34 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
- case PA_SOURCE_SUSPENDED:
+ case PA_SOURCE_SUSPENDED: {
+ int r;
pa_assert(PA_SOURCE_IS_OPENED(u->source->thread_info.state));
- if (suspend(u) < 0)
- return -1;
+ if ((r = suspend(u)) < 0)
+ return r;
break;
+ }
case PA_SOURCE_IDLE:
- case PA_SOURCE_RUNNING:
+ case PA_SOURCE_RUNNING: {
+ int r;
if (u->source->thread_info.state == PA_SOURCE_INIT) {
if (build_pollfd(u) < 0)
- return -1;
+ return -PA_ERR_IO;
snd_pcm_start(u->pcm_handle);
}
if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
- if (unsuspend(u) < 0)
- return -1;
+ if ((r = unsuspend(u)) < 0)
+ return r;
}
break;
+ }
case PA_SOURCE_UNLINKED:
case PA_SOURCE_INIT:
@@ -1033,7 +1037,7 @@ static int source_set_state_cb(pa_source *s, pa_source_state_t new_state) {
reserve_done(u);
else if (old_state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(new_state))
if (reserve_init(u, u->device_name) < 0)
- return -1;
+ return -PA_ERR_BUSY;
return 0;
}
@@ -1481,8 +1485,8 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
const char *dev_id = NULL;
pa_sample_spec ss, requested_ss;
pa_channel_map map;
- uint32_t nfrags, hwbuf_size, frag_size, tsched_size, tsched_watermark;
- snd_pcm_uframes_t period_frames, tsched_frames;
+ uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
+ snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
size_t frame_size;
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE;
pa_source_new_data data;
@@ -1516,8 +1520,10 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
goto fail;
}
- hwbuf_size = frag_size * nfrags;
+ buffer_size = nfrags * frag_size;
+
period_frames = frag_size/frame_size;
+ buffer_frames = buffer_size/frame_size;
tsched_frames = tsched_size/frame_size;
if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
@@ -1583,7 +1589,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
&u->device_name,
&ss, &map,
SND_PCM_STREAM_CAPTURE,
- &nfrags, &period_frames, tsched_frames,
+ &period_frames, &buffer_frames, tsched_frames,
&b, &d, mapping)))
goto fail;
@@ -1597,7 +1603,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
&u->device_name,
&ss, &map,
SND_PCM_STREAM_CAPTURE,
- &nfrags, &period_frames, tsched_frames,
+ &period_frames, &buffer_frames, tsched_frames,
&b, &d, profile_set, &mapping)))
goto fail;
@@ -1608,7 +1614,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
&u->device_name,
&ss, &map,
SND_PCM_STREAM_CAPTURE,
- &nfrags, &period_frames, tsched_frames,
+ &period_frames, &buffer_frames, tsched_frames,
&b, &d, FALSE)))
goto fail;
}
@@ -1634,11 +1640,6 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
u->use_tsched = use_tsched = FALSE;
}
- if (use_tsched && !pa_alsa_pcm_is_hw(u->pcm_handle)) {
- pa_log_info("Device is not a hardware device, disabling timer-based scheduling.");
- u->use_tsched = use_tsched = FALSE;
- }
-
if (u->use_mmap)
pa_log_info("Successfully enabled mmap() mode.");
@@ -1660,7 +1661,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
- pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
+ pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (buffer_frames * frame_size));
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
@@ -1701,13 +1702,15 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
pa_source_set_rtpoll(u->source, u->rtpoll);
u->frame_size = frame_size;
- u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size);
- u->nfragments = nfrags;
- u->hwbuf_size = u->fragment_size * nfrags;
+ u->fragment_size = frag_size = (size_t) (period_frames * frame_size);
+ u->hwbuf_size = buffer_size = (size_t) (buffer_frames * frame_size);
pa_cvolume_mute(&u->hardware_volume, u->source->sample_spec.channels);
- pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
- nfrags, (long unsigned) u->fragment_size,
+ pa_log_info("Using %0.1f fragments of size %lu bytes (%0.2fms), buffer size is %lu bytes (%0.2fms)",
+ (double) u->hwbuf_size / (double) u->fragment_size,
+ (long unsigned) u->fragment_size,
+ (double) pa_bytes_to_usec(u->fragment_size, &ss) / PA_USEC_PER_MSEC,
+ (long unsigned) u->hwbuf_size,
(double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
if (u->use_tsched) {
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index a47a8958..43a8e829 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -93,6 +93,7 @@ static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_s
int ret;
pa_assert(pcm_handle);
+ pa_assert(hwparams);
pa_assert(f);
if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
@@ -148,33 +149,71 @@ try_auto:
return -1;
}
+static int set_period_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
+ snd_pcm_uframes_t s;
+ int d, ret;
+
+ pa_assert(pcm_handle);
+ pa_assert(hwparams);
+
+ s = size;
+ d = 0;
+ if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
+ s = size;
+ d = -1;
+ if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
+ s = size;
+ d = 1;
+ if ((ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d)) < 0) {
+ pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret));
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int set_buffer_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
+ int ret;
+
+ pa_assert(pcm_handle);
+ pa_assert(hwparams);
+
+ if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &size)) < 0) {
+ pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
+ return ret;
+ }
+
+ return 0;
+}
+
/* Set the hardware parameters of the given ALSA device. Returns the
- * selected fragment settings in *period and *period_size */
+ * selected fragment settings in *buffer_size and *period_size. If tsched mode can be enabled */
int pa_alsa_set_hw_params(
snd_pcm_t *pcm_handle,
pa_sample_spec *ss,
- uint32_t *periods,
snd_pcm_uframes_t *period_size,
+ snd_pcm_uframes_t *buffer_size,
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap,
pa_bool_t *use_tsched,
pa_bool_t require_exact_channel_number) {
int ret = -1;
+ snd_pcm_hw_params_t *hwparams, *hwparams_copy;
+ int dir;
snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
- unsigned int _periods = periods ? *periods : 0;
- unsigned int r = ss->rate;
- unsigned int c = ss->channels;
- pa_sample_format_t f = ss->format;
- snd_pcm_hw_params_t *hwparams;
+ snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
pa_bool_t _use_mmap = use_mmap && *use_mmap;
pa_bool_t _use_tsched = use_tsched && *use_tsched;
- int dir;
+ pa_sample_spec _ss = *ss;
pa_assert(pcm_handle);
pa_assert(ss);
snd_pcm_hw_params_alloca(&hwparams);
+ snd_pcm_hw_params_alloca(&hwparams_copy);
if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
@@ -208,114 +247,143 @@ int pa_alsa_set_hw_params(
if (!_use_mmap)
_use_tsched = FALSE;
- if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
+ if (!pa_alsa_pcm_is_hw(pcm_handle))
+ _use_tsched = FALSE;
+
+ if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0)
goto finish;
- if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0) {
+ if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) {
pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
goto finish;
}
if (require_exact_channel_number) {
- if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, c)) < 0) {
- pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", c, pa_alsa_strerror(ret));
+ if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {
+ pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
goto finish;
}
} else {
+ unsigned int c = _ss.channels;
+
if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
- pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", c, pa_alsa_strerror(ret));
+ pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
goto finish;
}
- }
- if ((ret = snd_pcm_hw_params_set_periods_integer(pcm_handle, hwparams)) < 0) {
- pa_log_debug("snd_pcm_hw_params_set_periods_integer() failed: %s", pa_alsa_strerror(ret));
- goto finish;
+ _ss.channels = c;
}
- if (_period_size > 0 && tsched_size > 0 && _periods > 0) {
- snd_pcm_uframes_t buffer_size;
- unsigned int p;
+ if (_use_tsched && tsched_size > 0) {
+ _buffer_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * _ss.rate) / ss->rate);
+ _period_size = _buffer_size;
+ } else {
+ _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * _ss.rate) / ss->rate);
+ _buffer_size = (snd_pcm_uframes_t) (((uint64_t) _buffer_size * _ss.rate) / ss->rate);
+ }
- /* Adjust the buffer sizes, if we didn't get the rate we were asking for */
- _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * r) / ss->rate);
- tsched_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * r) / ss->rate);
+ if (_buffer_size > 0 || _period_size > 0) {
+ snd_pcm_uframes_t max_frames = 0;
- if (_use_tsched) {
- buffer_size = 0;
+ if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
+ pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
+ else
+ pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames * PA_MSEC_PER_SEC / _ss.rate));
- if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &buffer_size)) < 0)
- pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
- else
- pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size * 1000 / r);
+ /* Some ALSA drivers really don't like if we set the buffer
+ * size first and the number of periods second. (which would
+ * make a lot more sense to me) So, try a few combinations
+ * before we give up. */
+
+ if (_buffer_size > 0 && _period_size > 0) {
+ snd_pcm_hw_params_copy(hwparams_copy, hwparams);
+
+ /* First try: set buffer size first, followed by period size */
+ if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
+ set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
+ snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
+ pa_log_debug("Set buffer size first, period size second.");
+ goto success;
+ }
- _period_size = tsched_size;
- _periods = 1;
+ /* Second try: set period size first, followed by buffer size */
+ if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
+ set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
+ snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
+ pa_log_debug("Set period size first, buffer size second.");
+ goto success;
+ }
}
- /* Some ALSA drivers really don't like if we set the buffer
- * size first and the number of periods second. (which would
- * make a lot more sense to me) So, follow this rule and
- * adjust the periods first and the buffer size second */
-
- /* First we pass 0 as direction to get exactly what we
- * asked for. That this is necessary is presumably a bug
- * in ALSA. All in all this is mostly a hint to ALSA, so
- * we don't care if this fails. */
-
- p = _periods;
- dir = 0;
- if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir) < 0) {
- p = _periods;
- dir = 1;
- if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir) < 0) {
- p = _periods;
- dir = -1;
- if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir)) < 0)
- pa_log_info("snd_pcm_hw_params_set_periods_near() failed: %s", pa_alsa_strerror(ret));
+ if (_buffer_size > 0) {
+ snd_pcm_hw_params_copy(hwparams_copy, hwparams);
+
+ /* Third try: set only buffer size */
+ if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
+ snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
+ pa_log_debug("Set only buffer size second.");
+ goto success;
}
}
- /* Now set the buffer size */
- buffer_size = _periods * _period_size;
- if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0)
- pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
+ if (_period_size > 0) {
+ snd_pcm_hw_params_copy(hwparams_copy, hwparams);
+
+ /* Fourth try: set only period size */
+ if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
+ snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
+ pa_log_debug("Set only period size second.");
+ goto success;
+ }
+ }
}
- if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0)
+ pa_log_debug("Set neither period nor buffer size.");
+
+ /* Last chance, set nothing */
+ if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
+ pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret));
goto finish;
+ }
+
+success:
- if (ss->rate != r)
- pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r);
+ if (ss->rate != _ss.rate)
+ pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, _ss.rate);
- if (ss->channels != c)
- pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c);
+ if (ss->channels != _ss.channels)
+ pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, _ss.channels);
- if (ss->format != f)
- pa_log_info("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f));
+ if (ss->format != _ss.format)
+ pa_log_info("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(_ss.format));
if ((ret = snd_pcm_prepare(pcm_handle)) < 0) {
pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret));
goto finish;
}
+ if ((ret = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
+ pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret));
+ goto finish;
+ }
+
if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
- (ret = snd_pcm_hw_params_get_periods(hwparams, &_periods, &dir)) < 0) {
- pa_log_info("snd_pcm_hw_params_get_period{s|_size}() failed: %s", pa_alsa_strerror(ret));
+ (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
+ pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret));
goto finish;
}
/* 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 = (uint8_t) c;
- ss->format = f;
+ if (_ss.rate < ss->rate*.95 || _ss.rate > ss->rate*1.05)
+ ss->rate = _ss.rate;
+ ss->channels = _ss.channels;
+ ss->format = _ss.format;
- pa_assert(_periods > 0);
pa_assert(_period_size > 0);
+ pa_assert(_buffer_size > 0);
- if (periods)
- *periods = _periods;
+ if (buffer_size)
+ *buffer_size = _buffer_size;
if (period_size)
*period_size = _period_size;
@@ -393,8 +461,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
pa_sample_spec *ss,
pa_channel_map* map,
int mode,
- uint32_t *nfrags,
snd_pcm_uframes_t *period_size,
+ snd_pcm_uframes_t *buffer_size,
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap,
pa_bool_t *use_tsched,
@@ -410,8 +478,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
pa_assert(dev);
pa_assert(ss);
pa_assert(map);
- pa_assert(nfrags);
- pa_assert(period_size);
pa_assert(ps);
/* First we try to find a device string with a superset of the
@@ -433,8 +499,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
ss,
map,
mode,
- nfrags,
period_size,
+ buffer_size,
tsched_size,
use_mmap,
use_tsched,
@@ -460,8 +526,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
ss,
map,
mode,
- nfrags,
period_size,
+ buffer_size,
tsched_size,
use_mmap,
use_tsched,
@@ -478,7 +544,18 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
/* OK, we didn't find any good device, so let's try the raw hw: stuff */
d = pa_sprintf_malloc("hw:%s", dev_id);
pa_log_debug("Trying %s as last resort...", d);
- pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, tsched_size, use_mmap, use_tsched, FALSE);
+ pcm_handle = pa_alsa_open_by_device_string(
+ d,
+ dev,
+ ss,
+ map,
+ mode,
+ period_size,
+ buffer_size,
+ tsched_size,
+ use_mmap,
+ use_tsched,
+ FALSE);
pa_xfree(d);
if (pcm_handle && mapping)
@@ -493,8 +570,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
pa_sample_spec *ss,
pa_channel_map* map,
int mode,
- uint32_t *nfrags,
snd_pcm_uframes_t *period_size,
+ snd_pcm_uframes_t *buffer_size,
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap,
pa_bool_t *use_tsched,
@@ -508,8 +585,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
pa_assert(dev);
pa_assert(ss);
pa_assert(map);
- pa_assert(nfrags);
- pa_assert(period_size);
pa_assert(m);
try_ss.channels = m->channel_map.channels;
@@ -524,8 +599,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
&try_ss,
&try_map,
mode,
- nfrags,
period_size,
+ buffer_size,
tsched_size,
use_mmap,
use_tsched,
@@ -547,8 +622,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
pa_sample_spec *ss,
pa_channel_map* map,
int mode,
- uint32_t *nfrags,
snd_pcm_uframes_t *period_size,
+ snd_pcm_uframes_t *buffer_size,
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap,
pa_bool_t *use_tsched,
@@ -579,7 +654,15 @@ snd_pcm_t *pa_alsa_open_by_device_string(
pa_log_debug("Managed to open %s", d);
- if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, require_exact_channel_number)) < 0) {
+ if ((err = pa_alsa_set_hw_params(
+ pcm_handle,
+ ss,
+ period_size,
+ buffer_size,
+ tsched_size,
+ use_mmap,
+ use_tsched,
+ require_exact_channel_number)) < 0) {
if (!reformat) {
reformat = TRUE;
@@ -632,8 +715,8 @@ snd_pcm_t *pa_alsa_open_by_template(
pa_sample_spec *ss,
pa_channel_map* map,
int mode,
- uint32_t *nfrags,
snd_pcm_uframes_t *period_size,
+ snd_pcm_uframes_t *buffer_size,
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap,
pa_bool_t *use_tsched,
@@ -653,8 +736,8 @@ snd_pcm_t *pa_alsa_open_by_template(
ss,
map,
mode,
- nfrags,
period_size,
+ buffer_size,
tsched_size,
use_mmap,
use_tsched,
@@ -900,7 +983,7 @@ void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
snd_ctl_card_info_alloca(&info);
if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
- pa_log_warn("Error opening low-level control device '%s'", name);
+ pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
return;
}
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index 830a922e..265cd28c 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -42,8 +42,8 @@
int pa_alsa_set_hw_params(
snd_pcm_t *pcm_handle,
pa_sample_spec *ss, /* modified at return */
- uint32_t *periods, /* modified at return */
snd_pcm_uframes_t *period_size, /* modified at return */
+ snd_pcm_uframes_t *buffer_size, /* modified at return */
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap, /* modified at return */
pa_bool_t *use_tsched, /* modified at return */
@@ -60,8 +60,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
pa_sample_spec *ss, /* modified at return */
pa_channel_map* map, /* modified at return */
int mode,
- uint32_t *nfrags, /* modified at return */
snd_pcm_uframes_t *period_size, /* modified at return */
+ snd_pcm_uframes_t *buffer_size, /* modified at return */
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap, /* modified at return */
pa_bool_t *use_tsched, /* modified at return */
@@ -75,8 +75,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
pa_sample_spec *ss, /* modified at return */
pa_channel_map* map, /* modified at return */
int mode,
- uint32_t *nfrags, /* modified at return */
snd_pcm_uframes_t *period_size, /* modified at return */
+ snd_pcm_uframes_t *buffer_size, /* modified at return */
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap, /* modified at return */
pa_bool_t *use_tsched, /* modified at return */
@@ -89,8 +89,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
pa_sample_spec *ss, /* modified at return */
pa_channel_map* map, /* modified at return */
int mode,
- uint32_t *nfrags, /* modified at return */
snd_pcm_uframes_t *period_size, /* modified at return */
+ snd_pcm_uframes_t *buffer_size, /* modified at return */
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap, /* modified at return */
pa_bool_t *use_tsched, /* modified at return */
@@ -104,8 +104,8 @@ snd_pcm_t *pa_alsa_open_by_template(
pa_sample_spec *ss, /* modified at return */
pa_channel_map* map, /* modified at return */
int mode,
- uint32_t *nfrags, /* modified at return */
snd_pcm_uframes_t *period_size, /* modified at return */
+ snd_pcm_uframes_t *buffer_size, /* modified at return */
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap, /* modified at return */
pa_bool_t *use_tsched, /* modified at return */
diff --git a/src/modules/alsa/mixer/paths/analog-input.conf.common b/src/modules/alsa/mixer/paths/analog-input.conf.common
index 6728a6ae..87af38b3 100644
--- a/src/modules/alsa/mixer/paths/analog-input.conf.common
+++ b/src/modules/alsa/mixer/paths/analog-input.conf.common
@@ -78,6 +78,10 @@ priority = 19
name = input-microphone
priority = 19
+[Option Input Source:Internal Mic]
+name = input-microphone
+priority = 19
+
[Option Input Source:Line]
name = input-linein
priority = 18
@@ -90,6 +94,10 @@ priority = 18
name = input-linein
priority = 18
+[Option Input Source:Docking-Station]
+name = input-docking
+priority = 17
+
;;; ' Capture Source'
[Element Capture Source]
diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones.conf b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
index 691cb3f2..61d2e297 100644
--- a/src/modules/alsa/mixer/paths/analog-output-headphones.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
@@ -56,7 +56,7 @@ volume = off
switch = off
volume = off
-[Element Sourround]
+[Element Surround]
switch = off
volume = off
diff --git a/src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf b/src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf
index 3457d4a2..911361d7 100644
--- a/src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf
@@ -62,7 +62,7 @@ volume = off
switch = off
volume = off
-[Element Sourround]
+[Element Surround]
switch = off
volume = off
diff --git a/src/modules/alsa/mixer/paths/analog-output-mono.conf b/src/modules/alsa/mixer/paths/analog-output-mono.conf
index dc270cfe..2fbc60b7 100644
--- a/src/modules/alsa/mixer/paths/analog-output-mono.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-mono.conf
@@ -59,7 +59,7 @@ volume = off
switch = off
volume = off
-[Element Sourround]
+[Element Surround]
switch = off
volume = off
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index 55f6a6e2..6bea33d7 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -329,7 +329,7 @@ int pa__init(pa_module *m) {
if (!u->profile_set)
goto fail;
- pa_alsa_profile_set_probe(u->profile_set, u->device_id, &m->core->default_sample_spec);
+ pa_alsa_profile_set_probe(u->profile_set, u->device_id, &m->core->default_sample_spec, m->core->default_n_fragments, m->core->default_fragment_size_msec);
pa_card_new_data_init(&data);
data.driver = __FILE__;
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index b8a88042..4592fca1 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -221,9 +221,7 @@ static int service_recv(struct userdata *u, bt_audio_msg_header_t *msg, size_t r
pa_assert(u);
pa_assert(u->service_fd >= 0);
pa_assert(msg);
-
- if (room <= 0)
- room = BT_SUGGESTED_BUFFER_SIZE;
+ pa_assert(room >= sizeof(*msg));
pa_log_debug("Trying to receive message from audio service...");
@@ -236,6 +234,11 @@ static int service_recv(struct userdata *u, bt_audio_msg_header_t *msg, size_t r
return -1;
}
+ if (msg->length > room) {
+ pa_log_error("Not enough room.");
+ return -1;
+ }
+
/* Secondly, read the payload */
if (msg->length > sizeof(*msg)) {
diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c
index 85523b39..5f31d688 100644
--- a/src/modules/gconf/module-gconf.c
+++ b/src/modules/gconf/module-gconf.c
@@ -342,7 +342,7 @@ int pa__init(pa_module*m) {
if ((u->fd = pa_start_child_for_read(
#if defined(__linux__) && !defined(__OPTIMIZE__)
- pa_run_from_build_tree() ? PA_BUILDDIR "/.libs/gconf-helper" :
+ pa_run_from_build_tree() ? PA_BUILDDIR "/gconf-helper" :
#endif
PA_GCONF_HELPER, NULL, &u->pid)) < 0)
goto fail;
diff --git a/src/modules/hal-util.c b/src/modules/hal-util.c
index e2a2d8d7..2d59f51d 100644
--- a/src/modules/hal-util.c
+++ b/src/modules/hal-util.c
@@ -65,7 +65,7 @@ int pa_hal_get_info(pa_core *core, pa_proplist *p, int card) {
goto finish;
}
- if (!(udis = libhal_find_device_by_capability(hal, "sound", &n, &error)) < 0) {
+ if (!(udis = libhal_find_device_by_capability(hal, "sound", &n, &error))) {
pa_log_error("Couldn't find devices: %s: %s", error.name, error.message);
goto finish;
}
diff --git a/src/modules/module-always-sink.c b/src/modules/module-always-sink.c
index aee1c650..3d7de9c6 100644
--- a/src/modules/module-always-sink.c
+++ b/src/modules/module-always-sink.c
@@ -24,6 +24,7 @@
#endif
#include <pulse/xmalloc.h>
+#include <pulse/i18n.h>
#include <pulsecore/core.h>
#include <pulsecore/sink-input.h>
@@ -35,7 +36,7 @@
#include "module-always-sink-symdef.h"
PA_MODULE_AUTHOR("Colin Guthrie");
-PA_MODULE_DESCRIPTION("Always keeps at least one sink loaded even if it's a null one");
+PA_MODULE_DESCRIPTION(_("Always keeps at least one sink loaded even if it's a null one"));
PA_MODULE_VERSION(PACKAGE_VERSION);
PA_MODULE_LOAD_ONCE(TRUE);
PA_MODULE_USAGE(
@@ -78,7 +79,8 @@ static void load_null_sink_if_needed(pa_core *c, pa_sink *sink, struct userdata*
u->ignore = TRUE;
- t = pa_sprintf_malloc("sink_name=%s", u->sink_name);
+ t = pa_sprintf_malloc("sink_name=%s sink_properties='device.description=\"%s\"'", u->sink_name,
+ _("Dummy Output"));
m = pa_module_load(c, "module-null-sink", t);
u->null_module = m ? m->index : PA_INVALID_INDEX;
pa_xfree(t);
diff --git a/src/modules/module-cli.c b/src/modules/module-cli.c
index fd9452b4..6bd0f4fc 100644
--- a/src/modules/module-cli.c
+++ b/src/modules/module-cli.c
@@ -25,6 +25,8 @@
#include <stdio.h>
#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
#include <pulsecore/module.h>
#include <pulsecore/iochannel.h>
@@ -33,6 +35,8 @@
#include <pulsecore/log.h>
#include <pulsecore/modargs.h>
#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/core-error.h>
#include "module-cli-symdef.h"
@@ -69,6 +73,7 @@ int pa__init(pa_module*m) {
pa_iochannel *io;
pa_modargs *ma;
pa_bool_t exit_on_eof = FALSE;
+ int fd;
pa_assert(m);
@@ -88,15 +93,28 @@ int pa__init(pa_module*m) {
}
if (pa_stdio_acquire() < 0) {
- pa_log("STDIN/STDUSE already in use.");
+ pa_log("STDIN/STDOUT already in use.");
goto fail;
}
- io = pa_iochannel_new(m->core->mainloop, STDIN_FILENO, STDOUT_FILENO);
- pa_iochannel_set_noclose(io, 1);
+ /* We try to open the controlling tty anew here. This has the
+ * benefit of giving us a new fd that doesn't share the O_NDELAY
+ * flag with fds 0, 1, or 2. Since pa_iochannel_xxx needs O_NDELAY
+ * on its fd using those fds directly could set O_NDELAY which
+ * fprintf() doesn't really like, resulting in truncated output
+ * of log messages, particularly because if stdout and stderr are
+ * dup'ed they share the same O_NDELAY, too. */
+
+ if ((fd = open("/dev/tty", O_RDWR|O_CLOEXEC|O_NONBLOCK)) >= 0) {
+ io = pa_iochannel_new(m->core->mainloop, fd, fd);
+ pa_log_debug("Managed to open /dev/tty.");
+ } else {
+ io = pa_iochannel_new(m->core->mainloop, STDIN_FILENO, STDOUT_FILENO);
+ pa_iochannel_set_noclose(io, TRUE);
+ pa_log_debug("Failed to open /dev/tty, using stdin/stdout fds instead.");
+ }
m->userdata = pa_cli_new(m->core, io, m);
-
pa_cli_set_eof_callback(m->userdata, exit_on_eof ? eof_and_exit_cb : eof_and_unload_cb, m);
pa_modargs_free(ma);
@@ -114,7 +132,7 @@ fail:
void pa__done(pa_module*m) {
pa_assert(m);
- if (m->core->running_as_daemon == 0) {
+ if (m->userdata) {
pa_cli_free(m->userdata);
pa_stdio_release();
}
diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index 6034d0ee..18519131 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -435,9 +435,7 @@ static int hal_device_add_all(struct userdata *u) {
int i;
for (i = 0; i < n; i++) {
- struct device *d;
-
- if ((d = hal_device_add(u, udis[i]))) {
+ if (hal_device_add(u, udis[i])) {
count++;
pa_log_debug("Loaded device %s", udis[i]);
} else
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 933fb182..994c778f 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -82,6 +82,8 @@ struct userdata {
LADSPA_Data control_out;
pa_memblockq *memblockq;
+
+ pa_bool_t auto_desc;
};
static const char* const valid_modargs[] = {
@@ -423,6 +425,19 @@ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
} else
pa_sink_set_asyncmsgq(u->sink, NULL);
+
+ if (u->auto_desc && dest) {
+ const char *z;
+ pa_proplist *pl;
+
+ pl = pa_proplist_new();
+ z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
+ pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s",
+ pa_proplist_gets(u->sink->proplist, "device.ladspa.name"), z ? z : dest->name);
+
+ pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl);
+ pa_proplist_free(pl);
+ }
}
/* Called from main context */
@@ -451,7 +466,6 @@ int pa__init(pa_module*m) {
pa_channel_map map;
pa_modargs *ma;
char *t;
- const char *z;
pa_sink *master;
pa_sink_input_new_data sink_input_data;
pa_sink_new_data sink_data;
@@ -765,8 +779,6 @@ int pa__init(pa_module*m) {
sink_data.name = pa_sprintf_malloc("%s.ladspa", master->name);
pa_sink_new_data_set_sample_spec(&sink_data, &ss);
pa_sink_new_data_set_channel_map(&sink_data, &map);
- z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
- pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s", d->Name, z ? z : master->name);
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
pa_proplist_sets(sink_data.proplist, "device.ladspa.module", plugin);
@@ -782,6 +794,13 @@ int pa__init(pa_module*m) {
goto fail;
}
+ if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
+ const char *z;
+
+ z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
+ pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s", d->Name, z ? z : master->name);
+ }
+
u->sink = pa_sink_new(m->core, &sink_data,
PA_SINK_HW_MUTE_CTRL|PA_SINK_HW_VOLUME_CTRL|PA_SINK_DECIBEL_VOLUME|
(master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 36c50b05..74a2ebb1 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -35,6 +35,7 @@
#include <pulse/rtclock.h>
#include <pulse/timeval.h>
#include <pulse/xmalloc.h>
+#include <pulse/i18n.h>
#include <pulsecore/macro.h>
#include <pulsecore/sink.h>
@@ -51,7 +52,7 @@
#include "module-null-sink-symdef.h"
PA_MODULE_AUTHOR("Lennart Poettering");
-PA_MODULE_DESCRIPTION("Clocked NULL sink");
+PA_MODULE_DESCRIPTION(_("Clocked NULL sink"));
PA_MODULE_VERSION(PACKAGE_VERSION);
PA_MODULE_LOAD_ONCE(FALSE);
PA_MODULE_USAGE(
@@ -287,7 +288,7 @@ int pa__init(pa_module*m) {
pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
pa_sink_new_data_set_sample_spec(&data, &ss);
pa_sink_new_data_set_channel_map(&data, &map);
- pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "Null Output"));
+ pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", _("Null Output")));
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract");
if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
diff --git a/src/modules/module-position-event-sounds.c b/src/modules/module-position-event-sounds.c
index e191ec33..7221b14f 100644
--- a/src/modules/module-position-event-sounds.c
+++ b/src/modules/module-position-event-sounds.c
@@ -57,35 +57,69 @@ struct userdata {
pa_hook_slot *sink_input_fixate_hook_slot;
};
+static int parse_pos(const char *pos, double *f) {
+
+ if (pa_atod(pos, f) < 0) {
+ pa_log_warn("Failed to parse hpos/vpos property '%s'.", pos);
+ return -1;
+ }
+
+ if (*f < 0.0 || *f > 1.0) {
+ pa_log_debug("Property hpos/vpos out of range %0.2f", *f);
+
+ *f = PA_CLAMP(*f, 0.0, 1.0);
+ }
+
+ return 0;
+}
+
static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *core, pa_sink_input_new_data *data, struct userdata *u) {
- const char *hpos;
+ const char *hpos, *vpos, *role;
double f;
char t[PA_CVOLUME_SNPRINT_MAX];
pa_cvolume v;
pa_assert(data);
- if (!(hpos = pa_proplist_gets(data->proplist, PA_PROP_EVENT_MOUSE_HPOS)))
+ if (!(role = pa_proplist_gets(data->proplist, PA_PROP_MEDIA_ROLE)))
return PA_HOOK_OK;
- if (pa_atod(hpos, &f) < 0) {
- pa_log_warn("Failed to parse "PA_PROP_EVENT_MOUSE_HPOS" property '%s'.", hpos);
+ if (!pa_streq(role, "event"))
return PA_HOOK_OK;
- }
- if (f < 0.0 || f > 1.0) {
- pa_log_warn("Property "PA_PROP_EVENT_MOUSE_HPOS" out of range %0.2f", f);
+ if (!(hpos = pa_proplist_gets(data->proplist, PA_PROP_EVENT_MOUSE_HPOS)))
+ hpos = pa_proplist_gets(data->proplist, PA_PROP_WINDOW_HPOS);
+
+ if (!(vpos = pa_proplist_gets(data->proplist, PA_PROP_EVENT_MOUSE_VPOS)))
+ vpos = pa_proplist_gets(data->proplist, PA_PROP_WINDOW_VPOS);
+
+ if (!hpos && !vpos)
return PA_HOOK_OK;
+
+ pa_cvolume_reset(&v, data->sink->sample_spec.channels);
+
+ if (hpos) {
+ if (parse_pos(hpos, &f) < 0)
+ return PA_HOOK_OK;
+
+ if (pa_channel_map_can_balance(&data->sink->channel_map)) {
+ pa_log_debug("Positioning event sound '%s' horizontally at %0.2f.", pa_strnull(pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID)), f);
+ pa_cvolume_set_balance(&v, &data->sink->channel_map, f*2.0-1.0);
+ }
}
- pa_log_debug("Positioning event sound '%s' at %0.2f.", pa_strnull(pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID)), f);
+ if (vpos) {
+ if (parse_pos(vpos, &f) < 0)
+ return PA_HOOK_OK;
- pa_cvolume_reset(&v, data->sample_spec.channels);
- pa_cvolume_set_balance(&v, &data->channel_map, f*2.0-1.0);
+ if (pa_channel_map_can_fade(&data->sink->channel_map)) {
+ pa_log_debug("Positioning event sound '%s' vertically at %0.2f.", pa_strnull(pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID)), f);
+ pa_cvolume_set_fade(&v, &data->sink->channel_map, f*2.0-1.0);
+ }
+ }
pa_log_debug("Final volume factor %s.", pa_cvolume_snprint(t, sizeof(t), &v));
-
- pa_sink_input_new_data_apply_volume_factor(data, &v);
+ pa_sink_input_new_data_apply_volume_factor_sink(data, &v);
return PA_HOOK_OK;
}
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 6cfd0d15..43748bd0 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -58,6 +58,8 @@ struct userdata {
pa_sink *sink;
pa_sink_input *sink_input;
+
+ pa_bool_t auto_desc;
};
static const char* const valid_modargs[] = {
@@ -307,6 +309,18 @@ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
} else
pa_sink_set_asyncmsgq(u->sink, NULL);
+
+ if (u->auto_desc && dest) {
+ const char *k;
+ pa_proplist *pl;
+
+ pl = pa_proplist_new();
+ k = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
+ pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : dest->name);
+
+ pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl);
+ pa_proplist_free(pl);
+ }
}
int pa__init(pa_module*m) {
@@ -314,7 +328,6 @@ int pa__init(pa_module*m) {
pa_sample_spec ss;
pa_channel_map sink_map, stream_map;
pa_modargs *ma;
- const char *k;
pa_sink *master;
pa_sink_input_new_data sink_input_data;
pa_sink_new_data sink_data;
@@ -370,8 +383,6 @@ int pa__init(pa_module*m) {
sink_data.name = pa_sprintf_malloc("%s.remapped", master->name);
pa_sink_new_data_set_sample_spec(&sink_data, &ss);
pa_sink_new_data_set_channel_map(&sink_data, &sink_map);
- k = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
- pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : master->name);
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
@@ -381,6 +392,13 @@ int pa__init(pa_module*m) {
goto fail;
}
+ if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
+ const char *k;
+
+ k = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
+ pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : master->name);
+ }
+
u->sink = pa_sink_new(m->core, &sink_data, master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY));
pa_sink_new_data_done(&sink_data);
diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
index 5a6c8a3d..1e2dc4df 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1476,7 +1476,7 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
if (!so->source)
continue;
- /* It might happen that a stream and a sink are set up at the
+ /* It might happen that a stream and a source are set up at the
same time, in which case we want to make sure we don't
interfere with that */
if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(so)))
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index 5ccb81d0..c97de3a1 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -332,7 +332,7 @@ static void command_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
static void command_stream_buffer_attr_changed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
struct userdata *u = userdata;
- uint32_t channel, maxlength, tlength, fragsize, prebuf, minreq;
+ uint32_t channel, maxlength, tlength = 0, fragsize, prebuf, minreq;
pa_usec_t usec;
pa_assert(pd);
@@ -1069,6 +1069,33 @@ static void sink_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_t
}
}
+ if (u->version >= 16) {
+ uint32_t n_ports;
+ const char *s;
+
+ if (pa_tagstruct_getu32(t, &n_ports)) {
+ pa_log("Parse failure");
+ goto fail;
+ }
+
+ for (uint32_t j = 0; j < n_ports; j++) {
+ uint32_t priority;
+
+ if (pa_tagstruct_gets(t, &s) < 0 || /* name */
+ pa_tagstruct_gets(t, &s) < 0 || /* description */
+ pa_tagstruct_getu32(t, &priority) < 0) {
+
+ pa_log("Parse failure");
+ goto fail;
+ }
+ }
+
+ if (pa_tagstruct_gets(t, &s) < 0) { /* active port */
+ pa_log("Parse failure");
+ goto fail;
+ }
+ }
+
if (!pa_tagstruct_eof(t)) {
pa_log("Packet too long");
goto fail;
@@ -1097,7 +1124,7 @@ static void sink_input_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag
uint32_t idx, owner_module, client, sink;
pa_usec_t buffer_usec, sink_usec;
const char *name, *driver, *resample_method;
- pa_bool_t mute;
+ pa_bool_t mute = FALSE;
pa_sample_spec sample_spec;
pa_channel_map channel_map;
pa_cvolume volume;
@@ -1245,6 +1272,33 @@ static void source_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
}
}
+ if (u->version >= 16) {
+ uint32_t n_ports;
+ const char *s;
+
+ if (pa_tagstruct_getu32(t, &n_ports)) {
+ pa_log("Parse failure");
+ goto fail;
+ }
+
+ for (uint32_t j = 0; j < n_ports; j++) {
+ uint32_t priority;
+
+ if (pa_tagstruct_gets(t, &s) < 0 || /* name */
+ pa_tagstruct_gets(t, &s) < 0 || /* description */
+ pa_tagstruct_getu32(t, &priority) < 0) {
+
+ pa_log("Parse failure");
+ goto fail;
+ }
+ }
+
+ if (pa_tagstruct_gets(t, &s) < 0) { /* active port */
+ pa_log("Parse failure");
+ goto fail;
+ }
+ }
+
if (!pa_tagstruct_eof(t)) {
pa_log("Packet too long");
goto fail;
@@ -1345,12 +1399,11 @@ static void command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32
/* Called from main context */
static void start_subscribe(struct userdata *u) {
pa_tagstruct *t;
- uint32_t tag;
pa_assert(u);
t = pa_tagstruct_new(NULL, 0);
pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, tag = u->ctag++);
+ pa_tagstruct_putu32(t, u->ctag++);
pa_tagstruct_putu32(t, PA_SUBSCRIPTION_MASK_SERVER|
#ifdef TUNNEL_SINK
PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SINK
@@ -1526,7 +1579,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
reply = pa_tagstruct_new(NULL, 0);
pa_tagstruct_putu32(reply, PA_COMMAND_SET_CLIENT_NAME);
- pa_tagstruct_putu32(reply, tag = u->ctag++);
+ pa_tagstruct_putu32(reply, u->ctag++);
if (u->version >= 13) {
pa_proplist *pl;
@@ -1753,7 +1806,6 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata
static void sink_set_volume(pa_sink *sink) {
struct userdata *u;
pa_tagstruct *t;
- uint32_t tag;
pa_assert(sink);
u = sink->userdata;
@@ -1761,7 +1813,7 @@ static void sink_set_volume(pa_sink *sink) {
t = pa_tagstruct_new(NULL, 0);
pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME);
- pa_tagstruct_putu32(t, tag = u->ctag++);
+ pa_tagstruct_putu32(t, u->ctag++);
pa_tagstruct_putu32(t, u->device_index);
pa_tagstruct_put_cvolume(t, &sink->real_volume);
pa_pstream_send_tagstruct(u->pstream, t);
@@ -1771,7 +1823,6 @@ static void sink_set_volume(pa_sink *sink) {
static void sink_set_mute(pa_sink *sink) {
struct userdata *u;
pa_tagstruct *t;
- uint32_t tag;
pa_assert(sink);
u = sink->userdata;
@@ -1782,7 +1833,7 @@ static void sink_set_mute(pa_sink *sink) {
t = pa_tagstruct_new(NULL, 0);
pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_MUTE);
- pa_tagstruct_putu32(t, tag = u->ctag++);
+ pa_tagstruct_putu32(t, u->ctag++);
pa_tagstruct_putu32(t, u->device_index);
pa_tagstruct_put_boolean(t, !!sink->muted);
pa_pstream_send_tagstruct(u->pstream, t);
diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
index b41b9c0f..1b1e9c1a 100644
--- a/src/modules/module-udev-detect.c
+++ b/src/modules/module-udev-detect.c
@@ -29,10 +29,13 @@
#include <sys/inotify.h>
#include <libudev.h>
+#include <pulse/timeval.h>
+
#include <pulsecore/modargs.h>
#include <pulsecore/core-error.h>
#include <pulsecore/core-util.h>
#include <pulsecore/namereg.h>
+#include <pulsecore/ratelimit.h>
#include "module-udev-detect-symdef.h"
@@ -50,6 +53,7 @@ struct device {
char *card_name;
char *args;
uint32_t module;
+ pa_ratelimit ratelimit;
};
struct userdata {
@@ -110,6 +114,9 @@ static pa_bool_t is_card_busy(const char *id) {
pa_assert(id);
+ /* This simply uses /proc/asound/card.../pcm.../sub.../status to
+ * check whether there is still a process using this audio device. */
+
card_path = pa_sprintf_malloc("/proc/asound/card%s", id);
if (!(card_dir = opendir(card_path))) {
@@ -234,14 +241,41 @@ static void verify_access(struct userdata *u, struct device *d) {
pa_log_debug("%s is busy: %s", d->path, pa_yes_no(busy));
if (!busy) {
- pa_log_debug("Loading module-alsa-card with arguments '%s'", d->args);
- m = pa_module_load(u->core, "module-alsa-card", d->args);
- if (m) {
- d->module = m->index;
- pa_log_info("Card %s (%s) module loaded.", d->path, d->card_name);
+ /* So, why do we rate limit here? It's certainly ugly,
+ * but there seems to be no other way. Problem is
+ * this: if we are unable to configure/probe an audio
+ * device after opening it we will close it again and
+ * the module initialization will fail. This will then
+ * cause an inotify event on the device node which
+ * will be forwarded to us. We then try to reopen the
+ * audio device again, practically entering a busy
+ * loop.
+ *
+ * A clean fix would be if we would be able to ignore
+ * our own inotify close events. However, inotify
+ * lacks such functionality. Also, during probing of
+ * the device we cannot really distuingish between
+ * other processes causing EBUSY or ourselves, which
+ * means we have no way to figure out if the probing
+ * during opening was canceled by a "try again"
+ * failure or a "fatal" failure. */
+
+ if (pa_ratelimit_test(&d->ratelimit)) {
+ pa_log_debug("Loading module-alsa-card with arguments '%s'", d->args);
+ m = pa_module_load(u->core, "module-alsa-card", d->args);
+
+ if (m) {
+ d->module = m->index;
+ pa_log_info("Card %s (%s) module loaded.", d->path, d->card_name);
+ } else
+ pa_log_info("Card %s (%s) failed to load module.", d->path, d->card_name);
} else
- pa_log_info("Card %s (%s) failed to load module.", d->path, d->card_name);
+ pa_log_warn("Tried to configure %s (%s) more often than %u times in %llus",
+ d->path,
+ d->card_name,
+ d->ratelimit.burst,
+ (long long unsigned) (d->ratelimit.interval / PA_USEC_PER_SEC));
}
}
@@ -277,6 +311,7 @@ static void card_changed(struct userdata *u, struct udev_device *dev) {
d = pa_xnew0(struct device, 1);
d->path = pa_xstrdup(path);
d->module = PA_INVALID_INDEX;
+ PA_INIT_RATELIMIT(d->ratelimit, 10*PA_USEC_PER_SEC, 5);
if (!(t = udev_device_get_property_value(dev, "PULSE_NAME")))
if (!(t = udev_device_get_property_value(dev, "ID_ID")))
diff --git a/src/modules/raop/base64.c b/src/modules/raop/base64.c
index e1cbed02..5b061034 100644
--- a/src/modules/raop/base64.c
+++ b/src/modules/raop/base64.c
@@ -57,7 +57,6 @@ int pa_base64_encode(const void *data, int size, char **str)
p = s = pa_xnew(char, size * 4 / 3 + 4);
q = (const unsigned char *) data;
- i = 0;
for (i = 0; i < size;) {
c = q[i++];
c *= 256;
diff --git a/src/modules/raop/module-raop-discover.c b/src/modules/raop/module-raop-discover.c
index eaeb77fc..adba8e4f 100644
--- a/src/modules/raop/module-raop-discover.c
+++ b/src/modules/raop/module-raop-discover.c
@@ -265,7 +265,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, TRUE);
+ pa_module_unload_request_by_index(u->core, t2->module_index, TRUE);
pa_hashmap_remove(u->tunnels, t2);
tunnel_free(t2);
}
@@ -386,7 +386,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, TRUE);
+ pa_module_unload_request_by_index(u->core, t->module_index, TRUE);
tunnel_free(t);
}
diff --git a/src/modules/reserve-wrap.c b/src/modules/reserve-wrap.c
index 6086fc99..4be19c73 100644
--- a/src/modules/reserve-wrap.c
+++ b/src/modules/reserve-wrap.c
@@ -137,7 +137,7 @@ pa_reserve_wrapper* pa_reserve_wrapper_get(pa_core *c, const char *device_name)
#ifdef HAVE_DBUS
if (!(r->connection = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
- pa_log_warn("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
+ pa_log_debug("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
/* We don't treat this as error here because we want allow PA
* to run even when no session bus is available. */
@@ -154,10 +154,10 @@ pa_reserve_wrapper* pa_reserve_wrapper_get(pa_core *c, const char *device_name)
NULL)) < 0) {
if (k == -EBUSY) {
- pa_log_error("Device '%s' already locked.", device_name);
+ pa_log_debug("Device '%s' already locked.", device_name);
goto fail;
} else {
- pa_log_warn("Failed to acquire reservation lock on device '%s': %s", device_name, pa_cstrerror(-k));
+ pa_log_debug("Failed to acquire reservation lock on device '%s': %s", device_name, pa_cstrerror(-k));
return r;
}
}
@@ -280,7 +280,7 @@ pa_reserve_monitor_wrapper* pa_reserve_monitor_wrapper_get(pa_core *c, const cha
#ifdef HAVE_DBUS
if (!(w->connection = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
- pa_log_warn("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
+ pa_log_debug("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
/* We don't treat this as error here because we want allow PA
* to run even when no session bus is available. */
@@ -294,7 +294,7 @@ pa_reserve_monitor_wrapper* pa_reserve_monitor_wrapper_get(pa_core *c, const cha
change_cb,
NULL)) < 0) {
- pa_log_warn("Failed to create watch on device '%s': %s", device_name, pa_cstrerror(-k));
+ pa_log_debug("Failed to create watch on device '%s': %s", device_name, pa_cstrerror(-k));
goto fail;
}
diff --git a/src/modules/rtp/rtsp_client.c b/src/modules/rtp/rtsp_client.c
index ba657f74..59618064 100644
--- a/src/modules/rtp/rtsp_client.c
+++ b/src/modules/rtp/rtsp_client.c
@@ -60,7 +60,6 @@ struct pa_rtsp_client {
uint16_t port;
pa_socket_client *sc;
- pa_iochannel *io;
pa_ioline *ioline;
pa_rtsp_cb_t callback;
@@ -111,10 +110,8 @@ void pa_rtsp_client_free(pa_rtsp_client* c) {
if (c->sc)
pa_socket_client_unref(c->sc);
- if (c->ioline)
- pa_ioline_close(c->ioline);
- else if (c->io)
- pa_iochannel_free(c->io);
+
+ pa_rtsp_disconnect(c);
pa_xfree(c->hostname);
pa_xfree(c->url);
@@ -187,7 +184,6 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) {
if (!s) {
/* Keep the ioline/iochannel open as they will be freed automatically */
c->ioline = NULL;
- c->io = NULL;
c->callback(c, STATE_DISCONNECTED, NULL, c->userdata);
return;
}
@@ -303,8 +299,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata
pa_log("Connection failed: %s", pa_cstrerror(errno));
return;
}
- pa_assert(!c->io);
- c->io = io;
+ pa_assert(!c->ioline);
c->ioline = pa_ioline_new(io);
pa_ioline_set_callback(c->ioline, line_callback, c);
@@ -360,9 +355,6 @@ void pa_rtsp_disconnect(pa_rtsp_client *c) {
if (c->ioline)
pa_ioline_close(c->ioline);
- else if (c->io)
- pa_iochannel_free(c->io);
- c->io = NULL;
c->ioline = NULL;
}
@@ -408,13 +400,11 @@ static int rtsp_exec(pa_rtsp_client* c, const char* cmd,
pa_headerlist* headers) {
pa_strbuf* buf;
char* hdrs;
- ssize_t l;
pa_assert(c);
pa_assert(c->url);
-
- if (!cmd)
- return -1;
+ pa_assert(cmd);
+ pa_assert(c->ioline);
pa_log_debug("Sending command: %s", cmd);
@@ -453,7 +443,7 @@ static int rtsp_exec(pa_rtsp_client* c, const char* cmd,
hdrs = pa_strbuf_tostring_free(buf);
/*pa_log_debug("Submitting request:");
pa_log_debug(hdrs);*/
- l = pa_iochannel_write(c->io, hdrs, strlen(hdrs));
+ pa_ioline_puts(c->ioline, hdrs);
pa_xfree(hdrs);
return 0;
diff --git a/src/modules/x11/module-x11-publish.c b/src/modules/x11/module-x11-publish.c
index 2c7fdc12..7ee1b6da 100644
--- a/src/modules/x11/module-x11-publish.c
+++ b/src/modules/x11/module-x11-publish.c
@@ -90,7 +90,7 @@ static void publish_servers(struct userdata *u, pa_strlist *l) {
l = pa_strlist_reverse(l);
s = pa_strlist_tostring(l);
- l = pa_strlist_reverse(l);
+ pa_strlist_reverse(l);
pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SERVER", s);
pa_xfree(s);
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 894ab2e0..23ae30ce 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -1045,7 +1045,10 @@ pa_context_state_t pa_context_get_state(pa_context *c) {
}
int pa_context_errno(pa_context *c) {
- pa_assert(c);
+
+ if (!c)
+ return PA_ERR_INVALID;
+
pa_assert(PA_REFCNT_VALUE(c) >= 1);
return c->error;
diff --git a/src/pulse/context.h b/src/pulse/context.h
index cd129313..ecff58df 100644
--- a/src/pulse/context.h
+++ b/src/pulse/context.h
@@ -147,12 +147,6 @@
* server. A pa_context object wraps a connection to a PulseAudio
* server using its native protocol. */
-/** \example pacat.c
- * A playback and recording tool using the asynchronous API */
-
-/** \example paplay.c
- * A sound file playback tool using the asynchronous API, based on libsndfile */
-
PA_C_DECL_BEGIN
/** An opaque connection context to a daemon */
@@ -267,7 +261,6 @@ pa_time_event* pa_context_rttime_new(pa_context *c, pa_usec_t usec, pa_time_even
for mainloop->time_restart). \since 0.9.16 */
void pa_context_rttime_restart(pa_context *c, pa_time_event *e, pa_usec_t usec);
-
PA_C_DECL_END
#endif
diff --git a/src/pulse/def.h b/src/pulse/def.h
index 08399ca8..5d0a0b4b 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -95,13 +95,14 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) {
typedef enum pa_operation_state {
PA_OPERATION_RUNNING, /**< The operation is still running */
PA_OPERATION_DONE, /**< The operation has been completed */
- PA_OPERATION_CANCELED /**< The operation has been canceled */
+ PA_OPERATION_CANCELLED /**< The operation has been cancelled. Before 0.9.18 this was called PA_OPERATION_CANCELED. That name is still available for compatibility. */
} pa_operation_state_t;
/** \cond fulldocs */
#define PA_OPERATION_RUNNING PA_OPERATION_RUNNING
#define PA_OPERATION_DONE PA_OPERATION_DONE
-#define PA_OPERATION_CANCELED PA_OPERATION_CANCELED
+#define PA_OPERATION_CANCELED PA_OPERATION_CANCELLED
+#define PA_OPERATION_CANCELLED PA_OPERATION_CANCELLED
/** \endcond */
/** An invalid index */
@@ -109,6 +110,8 @@ typedef enum pa_operation_state {
/** Some special flags for contexts. */
typedef enum pa_context_flags {
+ PA_CONTEXT_NOFLAGS = 0x0000U,
+ /**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */
PA_CONTEXT_NOAUTOSPAWN = 0x0001U,
/**< Disabled autospawning of the PulseAudio daemon if required */
PA_CONTEXT_NOFAIL = 0x0002U
@@ -139,6 +142,9 @@ typedef enum pa_stream_direction {
/** Some special flags for stream connections. */
typedef enum pa_stream_flags {
+ PA_STREAM_NOFLAGS = 0x0000U,
+ /**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */
+
PA_STREAM_START_CORKED = 0x0001U,
/**< Create the stream corked, requiring an explicit
* pa_stream_cork() call to uncork it. */
@@ -394,6 +400,7 @@ enum {
PA_ERR_NOTIMPLEMENTED, /**< Missing implementation. \since 0.9.15 */
PA_ERR_FORKED, /**< The caller forked without calling execve() and tried to reuse the context. \since 0.9.15 */
PA_ERR_IO, /**< An IO error happened. \since 0.9.16 */
+ PA_ERR_BUSY, /**< Device or resource busy. \since 0.9.17 */
PA_ERR_MAX /**< Not really an error but the first invalid error code */
};
@@ -686,6 +693,9 @@ typedef enum pa_seek_mode {
/** Special sink flags. */
typedef enum pa_sink_flags {
+ PA_SINK_NOFLAGS = 0x0000U,
+ /**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */
+
PA_SINK_HW_VOLUME_CTRL = 0x0001U,
/**< Supports hardware volume control */
@@ -773,6 +783,9 @@ static inline int PA_SINK_IS_OPENED(pa_sink_state_t x) {
/** Special source flags. */
typedef enum pa_source_flags {
+ PA_SOURCE_NOFLAGS = 0x0000U,
+ /**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */
+
PA_SOURCE_HW_VOLUME_CTRL = 0x0001U,
/**< Supports hardware volume control */
diff --git a/src/pulse/error.c b/src/pulse/error.c
index 93a13fc6..e8276990 100644
--- a/src/pulse/error.c
+++ b/src/pulse/error.c
@@ -64,7 +64,9 @@ const char*pa_strerror(int error) {
[PA_ERR_NOEXTENSION] = N_("No such extension"),
[PA_ERR_OBSOLETE] = N_("Obsolete functionality"),
[PA_ERR_NOTIMPLEMENTED] = N_("Missing implementation"),
- [PA_ERR_FORKED] = N_("Client forked")
+ [PA_ERR_FORKED] = N_("Client forked"),
+ [PA_ERR_IO] = N_("Input/Output error"),
+ [PA_ERR_BUSY] = N_("Device or resource busy")
};
pa_init_i18n();
diff --git a/src/pulse/gccmacro.h b/src/pulse/gccmacro.h
index e85ecb66..57e80509 100644
--- a/src/pulse/gccmacro.h
+++ b/src/pulse/gccmacro.h
@@ -118,7 +118,7 @@
#endif
#ifndef PA_GCC_WEAKREF
-#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ > 1)) || (__GNUC__ > 4))
+#if defined(__GNUC__) && defined(__ELF__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ > 1)) || (__GNUC__ > 4))
/** Macro for usgae of GCC's weakref attribute */
#define PA_GCC_WEAKREF(x) __attribute__((weakref(#x)));
#endif
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 27a587cb..100413ee 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -834,6 +834,8 @@ pa_operation* pa_context_get_card_info_by_name(pa_context *c, const char*name, p
}
pa_operation* pa_context_get_card_info_list(pa_context *c, pa_card_info_cb_t cb, void *userdata) {
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
+
return pa_context_send_simple_command(c, PA_COMMAND_GET_CARD_INFO_LIST, context_get_card_info_callback, (pa_operation_cb_t) cb, userdata);
}
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index ee982100..68cfc874 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -331,6 +331,12 @@ pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, i
/** Set the mute switch of a source device specified by its name */
pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata);
+/** Suspend/Resume a source. \since 0.9.7 */
+pa_operation* pa_context_suspend_source_by_name(pa_context *c, const char *source_name, int suspend, pa_context_success_cb_t cb, void* userdata);
+
+/** Suspend/Resume a source. If idx is PA_INVALID_INDEX all sources will be suspended. \since 0.9.7 */
+pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata);
+
/** Change the profile of a source. \since 0.9.16 */
pa_operation* pa_context_set_source_port_by_index(pa_context *c, uint32_t idx, const char*port, pa_context_success_cb_t cb, void *userdata);
@@ -557,12 +563,6 @@ pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx,
/** Move the specified source output to a different source. \since 0.9.5 */
pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx, uint32_t source_idx, pa_context_success_cb_t cb, void* userdata);
-/** Suspend/Resume a source. \since 0.9.7 */
-pa_operation* pa_context_suspend_source_by_name(pa_context *c, const char *source_name, int suspend, pa_context_success_cb_t cb, void* userdata);
-
-/** Suspend/Resume a source. If idx is PA_INVALID_INDEX all sources will be suspended. \since 0.9.7 */
-pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata);
-
/** Kill a source output. */
pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c
index 93a4742d..090ac8c2 100644
--- a/src/pulse/mainloop.c
+++ b/src/pulse/mainloop.c
@@ -78,6 +78,7 @@ struct pa_time_event {
pa_bool_t dead:1;
pa_bool_t enabled:1;
+ pa_bool_t use_rtclock:1;
pa_usec_t time;
pa_time_event_cb_t callback;
@@ -112,7 +113,7 @@ struct pa_mainloop {
struct pollfd *pollfds;
unsigned max_pollfds, n_pollfds;
- int prepared_timeout;
+ pa_usec_t prepared_timeout;
pa_time_event *cached_next_time_event;
pa_mainloop_api api;
@@ -172,17 +173,14 @@ static pa_io_event* mainloop_io_new(
m = a->userdata;
pa_assert(a == &m->api);
- e = pa_xnew(pa_io_event, 1);
+ e = pa_xnew0(pa_io_event, 1);
e->mainloop = m;
- e->dead = FALSE;
e->fd = fd;
e->events = events;
- e->pollfd = NULL;
e->callback = callback;
e->userdata = userdata;
- e->destroy_callback = NULL;
#ifdef OS_IS_WIN32
{
@@ -265,16 +263,14 @@ static pa_defer_event* mainloop_defer_new(
m = a->userdata;
pa_assert(a == &m->api);
- e = pa_xnew(pa_defer_event, 1);
+ e = pa_xnew0(pa_defer_event, 1);
e->mainloop = m;
- e->dead = FALSE;
e->enabled = TRUE;
m->n_enabled_defer_events++;
e->callback = callback;
e->userdata = userdata;
- e->destroy_callback = NULL;
PA_LLIST_PREPEND(pa_defer_event, m->defer_events, e);
@@ -320,18 +316,20 @@ static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy
}
/* Time events */
-static pa_usec_t timeval_load(const struct timeval *tv) {
- pa_bool_t is_rtclock;
+static pa_usec_t make_rt(const struct timeval *tv, pa_bool_t *use_rtclock) {
struct timeval ttv;
- if (!tv)
+ if (!tv) {
+ *use_rtclock = FALSE;
return PA_USEC_INVALID;
+ }
ttv = *tv;
- is_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK);
- ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK;
+ *use_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK);
- if (!is_rtclock)
+ if (*use_rtclock)
+ ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK;
+ else
pa_rtclock_from_wallclock(&ttv);
return pa_timeval_load(&ttv);
@@ -346,22 +344,23 @@ static pa_time_event* mainloop_time_new(
pa_mainloop *m;
pa_time_event *e;
pa_usec_t t;
+ pa_bool_t use_rtclock = FALSE;
pa_assert(a);
pa_assert(a->userdata);
pa_assert(callback);
- t = timeval_load(tv);
+ t = make_rt(tv, &use_rtclock);
m = a->userdata;
pa_assert(a == &m->api);
- e = pa_xnew(pa_time_event, 1);
+ e = pa_xnew0(pa_time_event, 1);
e->mainloop = m;
- e->dead = FALSE;
if ((e->enabled = (t != PA_USEC_INVALID))) {
e->time = t;
+ e->use_rtclock= use_rtclock;
m->n_enabled_time_events++;
@@ -375,7 +374,6 @@ static pa_time_event* mainloop_time_new(
e->callback = callback;
e->userdata = userdata;
- e->destroy_callback = NULL;
PA_LLIST_PREPEND(pa_time_event, m->time_events, e);
@@ -388,11 +386,12 @@ static pa_time_event* mainloop_time_new(
static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
pa_bool_t valid;
pa_usec_t t;
+ pa_bool_t use_rtclock = FALSE;
pa_assert(e);
pa_assert(!e->dead);
- t = timeval_load(tv);
+ t = make_rt(tv, &use_rtclock);
valid = (t != PA_USEC_INVALID);
if (e->enabled && !valid) {
@@ -403,6 +402,7 @@ static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
if ((e->enabled = valid)) {
e->time = t;
+ e->use_rtclock = use_rtclock;
pa_mainloop_wakeup(e->mainloop);
}
@@ -480,9 +480,8 @@ pa_mainloop *pa_mainloop_new(void) {
pa_init_i18n();
- m = pa_xnew(pa_mainloop, 1);
+ m = pa_xnew0(pa_mainloop, 1);
- m->wakeup_pipe_type = 0;
if (pipe(m->wakeup_pipe) < 0) {
pa_log_error("ERROR: cannot create wakeup pipe");
pa_xfree(m);
@@ -493,43 +492,23 @@ 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 = FALSE;
-
- PA_LLIST_HEAD_INIT(pa_io_event, m->io_events);
- PA_LLIST_HEAD_INIT(pa_time_event, m->time_events);
- PA_LLIST_HEAD_INIT(pa_defer_event, m->defer_events);
-
- m->n_enabled_defer_events = m->n_enabled_time_events = m->n_io_events = 0;
- m->io_events_please_scan = m->time_events_please_scan = m->defer_events_please_scan = 0;
-
- m->cached_next_time_event = NULL;
- m->prepared_timeout = 0;
- m->pollfds = NULL;
- m->max_pollfds = m->n_pollfds = 0;
m->rebuild_pollfds = TRUE;
- m->quit = FALSE;
- m->retval = 0;
-
m->api = vtable;
m->api.userdata = m;
m->state = STATE_PASSIVE;
- m->poll_func = NULL;
- m->poll_func_userdata = NULL;
m->poll_func_ret = -1;
return m;
}
static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) {
- pa_io_event *e;
+ pa_io_event *e, *n;
- e = m->io_events;
- while (e) {
- pa_io_event *n = e->next;
+ PA_LLIST_FOREACH_SAFE(e, n, m->io_events) {
if (!force && m->io_events_please_scan <= 0)
break;
@@ -549,19 +528,15 @@ static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) {
m->rebuild_pollfds = TRUE;
}
-
- e = n;
}
pa_assert(m->io_events_please_scan == 0);
}
static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) {
- pa_time_event *e;
+ pa_time_event *e, *n;
- e = m->time_events;
- while (e) {
- pa_time_event *n = e->next;
+ PA_LLIST_FOREACH_SAFE(e, n, m->time_events) {
if (!force && m->time_events_please_scan <= 0)
break;
@@ -585,19 +560,15 @@ static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) {
pa_xfree(e);
}
-
- e = n;
}
pa_assert(m->time_events_please_scan == 0);
}
static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) {
- pa_defer_event *e;
+ pa_defer_event *e, *n;
- e = m->defer_events;
- while (e) {
- pa_defer_event *n = e->next;
+ PA_LLIST_FOREACH_SAFE(e, n, m->defer_events) {
if (!force && m->defer_events_please_scan <= 0)
break;
@@ -621,8 +592,6 @@ static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) {
pa_xfree(e);
}
-
- e = n;
}
pa_assert(m->defer_events_please_scan == 0);
@@ -679,7 +648,7 @@ static void rebuild_pollfds(pa_mainloop *m) {
m->n_pollfds++;
}
- for (e = m->io_events; e; e = e->next) {
+ PA_LLIST_FOREACH(e, m->io_events) {
if (e->dead) {
e->pollfd = NULL;
continue;
@@ -697,36 +666,46 @@ static void rebuild_pollfds(pa_mainloop *m) {
m->rebuild_pollfds = FALSE;
}
-static int dispatch_pollfds(pa_mainloop *m) {
+static unsigned dispatch_pollfds(pa_mainloop *m) {
pa_io_event *e;
- int r = 0, k;
+ unsigned r = 0, k;
pa_assert(m->poll_func_ret > 0);
- for (e = m->io_events, k = m->poll_func_ret; e && !m->quit && k > 0; e = e->next) {
+ k = m->poll_func_ret;
+
+ PA_LLIST_FOREACH(e, m->io_events) {
+
+ if (k <= 0 || m->quit)
+ break;
+
if (e->dead || !e->pollfd || !e->pollfd->revents)
continue;
pa_assert(e->pollfd->fd == e->fd);
pa_assert(e->callback);
+
e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata);
e->pollfd->revents = 0;
r++;
-
k--;
}
return r;
}
-static int dispatch_defer(pa_mainloop *m) {
+static unsigned dispatch_defer(pa_mainloop *m) {
pa_defer_event *e;
- int r = 0;
+ unsigned r = 0;
if (m->n_enabled_defer_events <= 0)
return 0;
- for (e = m->defer_events; e && !m->quit; e = e->next) {
+ PA_LLIST_FOREACH(e, m->defer_events) {
+
+ if (m->quit)
+ break;
+
if (e->dead || !e->enabled)
continue;
@@ -745,7 +724,7 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) {
if (m->cached_next_time_event)
return m->cached_next_time_event;
- for (t = m->time_events; t; t = t->next) {
+ PA_LLIST_FOREACH(t, m->time_events) {
if (t->dead || !t->enabled)
continue;
@@ -763,12 +742,12 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) {
return n;
}
-static int calc_next_timeout(pa_mainloop *m) {
+static pa_usec_t calc_next_timeout(pa_mainloop *m) {
pa_time_event *t;
pa_usec_t clock_now;
- if (!m->n_enabled_time_events)
- return -1;
+ if (m->n_enabled_time_events <= 0)
+ return PA_USEC_INVALID;
pa_assert_se(t = find_next_time_event(m));
@@ -780,13 +759,13 @@ static int calc_next_timeout(pa_mainloop *m) {
if (t->time <= clock_now)
return 0;
- return (int) ((t->time - clock_now) / 1000); /* in milliseconds */
+ return t->time - clock_now;
}
-static int dispatch_timeout(pa_mainloop *m) {
+static unsigned dispatch_timeout(pa_mainloop *m) {
pa_time_event *e;
pa_usec_t now;
- int r = 0;
+ unsigned r = 0;
pa_assert(m);
if (m->n_enabled_time_events <= 0)
@@ -794,7 +773,10 @@ static int dispatch_timeout(pa_mainloop *m) {
now = pa_rtclock_now();
- for (e = m->time_events; e && !m->quit; e = e->next) {
+ PA_LLIST_FOREACH(e, m->time_events) {
+
+ if (m->quit)
+ break;
if (e->dead || !e->enabled)
continue;
@@ -806,7 +788,7 @@ static int dispatch_timeout(pa_mainloop *m) {
/* Disable time event */
mainloop_time_restart(e, NULL);
- e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, TRUE), e->userdata);
+ e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, e->use_rtclock), e->userdata);
r++;
}
@@ -834,7 +816,8 @@ static void clear_wakeup(pa_mainloop *m) {
return;
if (m->wakeup_requested) {
- while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c));
+ while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c))
+ ;
m->wakeup_requested = 0;
}
}
@@ -850,12 +833,17 @@ int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
goto quit;
if (m->n_enabled_defer_events <= 0) {
+
if (m->rebuild_pollfds)
rebuild_pollfds(m);
m->prepared_timeout = calc_next_timeout(m);
- if (timeout >= 0 && (timeout < m->prepared_timeout || m->prepared_timeout < 0))
- m->prepared_timeout = timeout;
+ if (timeout >= 0) {
+ uint64_t u = (uint64_t) timeout * PA_USEC_PER_MSEC;
+
+ if (u < m->prepared_timeout || m->prepared_timeout == PA_USEC_INVALID)
+ m->prepared_timeout = timeout;
+ }
}
m->state = STATE_PREPARED;
@@ -866,6 +854,13 @@ quit:
return -2;
}
+static int usec_to_timeout(pa_usec_t u) {
+ if (u == PA_USEC_INVALID)
+ return -1;
+
+ return (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC;
+}
+
int pa_mainloop_poll(pa_mainloop *m) {
pa_assert(m);
pa_assert(m->state == STATE_PREPARED);
@@ -881,9 +876,24 @@ int pa_mainloop_poll(pa_mainloop *m) {
pa_assert(!m->rebuild_pollfds);
if (m->poll_func)
- m->poll_func_ret = m->poll_func(m->pollfds, m->n_pollfds, m->prepared_timeout, m->poll_func_userdata);
- else
- m->poll_func_ret = poll(m->pollfds, m->n_pollfds, m->prepared_timeout);
+ m->poll_func_ret = m->poll_func(
+ m->pollfds, m->n_pollfds,
+ usec_to_timeout(m->prepared_timeout),
+ m->poll_func_userdata);
+ else {
+#ifdef HAVE_PPOLL
+ struct timespec ts;
+
+ m->poll_func_ret = ppoll(
+ m->pollfds, m->n_pollfds,
+ m->prepared_timeout == PA_USEC_INVALID ? NULL : pa_timespec_store(&ts, m->prepared_timeout),
+ NULL);
+#else
+ m->poll_func_ret = poll(
+ m->pollfds, m->n_pollfds,
+ usec_to_timeout(m->prepared_timeout));
+#endif
+ }
if (m->poll_func_ret < 0) {
if (errno == EINTR)
@@ -902,7 +912,7 @@ quit:
}
int pa_mainloop_dispatch(pa_mainloop *m) {
- int dispatched = 0;
+ unsigned dispatched = 0;
pa_assert(m);
pa_assert(m->state == STATE_POLLED);
@@ -928,7 +938,7 @@ int pa_mainloop_dispatch(pa_mainloop *m) {
m->state = STATE_PASSIVE;
- return dispatched;
+ return (int) dispatched;
quit:
m->state = STATE_QUIT;
@@ -937,6 +947,7 @@ quit:
int pa_mainloop_get_retval(pa_mainloop *m) {
pa_assert(m);
+
return m->retval;
}
@@ -965,7 +976,8 @@ quit:
int pa_mainloop_run(pa_mainloop *m, int *retval) {
int r;
- while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0);
+ while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0)
+ ;
if (r == -2)
return 1;
@@ -985,6 +997,7 @@ void pa_mainloop_quit(pa_mainloop *m, int retval) {
pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) {
pa_assert(m);
+
return &m->api;
}
diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h
index 9effc861..aae05346 100644
--- a/src/pulse/proplist.h
+++ b/src/pulse/proplist.h
@@ -97,6 +97,27 @@ PA_C_DECL_BEGIN
/** For streams that belong to a window on the screen: an XDG icon name for the window. e.g. "totem" */
#define PA_PROP_WINDOW_ICON_NAME "window.icon_name"
+/** For streams that belong to a window on the screen: absolute horizontal window position on the screen, integer formatted as text string. e.g. "865". \since 0.9.17 */
+#define PA_PROP_WINDOW_X "window.x"
+
+/** For streams that belong to a window on the screen: absolute vertical window position on the screen, integer formatted as text string. e.g. "343". \since 0.9.17 */
+#define PA_PROP_WINDOW_Y "window.y"
+
+/** For streams that belong to a window on the screen: window width on the screen, integer formatted as text string. e.g. "365". \since 0.9.17 */
+#define PA_PROP_WINDOW_WIDTH "window.width"
+
+/** For streams that belong to a window on the screen: window height on the screen, integer formatted as text string. e.g. "643". \since 0.9.17 */
+#define PA_PROP_WINDOW_HEIGHT "window.height"
+
+/** For streams that belong to a window on the screen: relative position of the window center on the screen, float formatted as text string, ranging from 0.0 (left side of the screen) to 1.0 (right side of the screen). e.g. "0.65". \since 0.9.17 */
+#define PA_PROP_WINDOW_HPOS "window.hpos"
+
+/** For streams that belong to a window on the screen: relative position of the window center on the screen, float formatted as text string, ranging from 0.0 (top of the screen) to 1.0 (bottom of the screen). e.g. "0.43". \since 0.9.17 */
+#define PA_PROP_WINDOW_VPOS "window.vpos"
+
+/** For streams that belong to a window on the screen: if the windowing system supports multiple desktops, a comma seperated list of indexes of the desktops this window is visible on. If this property is an empty string, it is visible on all desktops (i.e. 'sticky'). The first desktop is 0. e.g. "0,2,3" \since 0.9.18 */
+#define PA_PROP_WINDOW_DESKTOP "window.desktop"
+
/** For streams that belong to an X11 window on the screen: the X11 display string. e.g. ":0.0" */
#define PA_PROP_WINDOW_X11_DISPLAY "window.x11.display"
@@ -197,7 +218,7 @@ PA_C_DECL_BEGIN
/** For filter devices: master device id if applicable. */
#define PA_PROP_DEVICE_MASTER_DEVICE "device.master_device"
-/** For devices: buffer size in bytes, integer formatted as string.. */
+/** For devices: buffer size in bytes, integer formatted as string. */
#define PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE "device.buffering.buffer_size"
/** For devices: fragment size in bytes, integer formatted as string. */
diff --git a/src/pulse/pulseaudio.h b/src/pulse/pulseaudio.h
index aa369e69..793ba9b1 100644
--- a/src/pulse/pulseaudio.h
+++ b/src/pulse/pulseaudio.h
@@ -44,15 +44,17 @@
#include <pulse/util.h>
#include <pulse/timeval.h>
#include <pulse/proplist.h>
+#include <pulse/rtclock.h>
/** \file
- * Include all libpulse header files at once. The following
- * files are included: \ref mainloop-api.h, \ref sample.h, \ref def.h,
- * \ref context.h, \ref stream.h, \ref introspect.h, \ref subscribe.h,
- * \ref scache.h, \ref version.h, \ref error.h, \ref channelmap.h,
- * \ref operation.h,\ref volume.h, \ref xmalloc.h, \ref utf8.h, \ref
- * thread-mainloop.h, \ref mainloop.h, \ref util.h, \ref proplist.h, \ref timeval.h and
- * \ref mainloop-signal.h at once */
+ * Include all libpulse header files at once. The following files are
+ * included: \ref mainloop-api.h, \ref sample.h, \ref def.h, \ref
+ * context.h, \ref stream.h, \ref introspect.h, \ref subscribe.h, \ref
+ * scache.h, \ref version.h, \ref error.h, \ref channelmap.h, \ref
+ * operation.h,\ref volume.h, \ref xmalloc.h, \ref utf8.h, \ref
+ * thread-mainloop.h, \ref mainloop.h, \ref util.h, \ref proplist.h,
+ * \ref timeval.h, \ref rtclock.h and \ref mainloop-signal.h at
+ * once */
/** \mainpage
*
diff --git a/src/pulse/sample.h b/src/pulse/sample.h
index 53d7dea3..7a4a55a0 100644
--- a/src/pulse/sample.h
+++ b/src/pulse/sample.h
@@ -302,6 +302,13 @@ pa_sample_format_t pa_parse_sample_format(const char *format) PA_GCC_PURE;
/** Pretty print a sample type specification to a string */
char* pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec);
+/** Maximum required string length for pa_bytes_snprint(). Please note
+ * that this value can change with any release without warning and
+ * without being considered API or ABI breakage. You should not use
+ * this definition anywhere where it might become part of an
+ * ABI. \since 0.9.16 */
+#define PA_BYTES_SNPRINT_MAX 11
+
/** Pretty print a byte size value. (i.e. "2.5 MiB") */
char* pa_bytes_snprint(char *s, size_t l, unsigned v);
diff --git a/src/pulse/scache.c b/src/pulse/scache.c
index 77f60d72..27da6887 100644
--- a/src/pulse/scache.c
+++ b/src/pulse/scache.c
@@ -187,7 +187,7 @@ pa_operation *pa_context_play_sample(pa_context *c, const char *name, const char
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
pa_tagstruct_puts(t, dev);
- if (volume == (pa_volume_t) -1 && c->version < 15)
+ if (volume == PA_VOLUME_INVALID && c->version < 15)
volume = PA_VOLUME_NORM;
pa_tagstruct_putu32(t, volume);
@@ -216,7 +216,6 @@ pa_operation *pa_context_play_sample_with_proplist(pa_context *c, const char *na
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
PA_CHECK_VALIDITY_RETURN_NULL(c, !dev || *dev, PA_ERR_INVALID);
- PA_CHECK_VALIDITY_RETURN_NULL(c, p, PA_ERR_INVALID);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
@@ -228,12 +227,19 @@ pa_operation *pa_context_play_sample_with_proplist(pa_context *c, const char *na
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
pa_tagstruct_puts(t, dev);
- if (volume == (pa_volume_t) -1 && c->version < 15)
+ if (volume == PA_VOLUME_INVALID && c->version < 15)
volume = PA_VOLUME_NORM;
pa_tagstruct_putu32(t, volume);
pa_tagstruct_puts(t, name);
- pa_tagstruct_put_proplist(t, p);
+
+ if (p)
+ pa_tagstruct_put_proplist(t, p);
+ else {
+ p = pa_proplist_new();
+ pa_tagstruct_put_proplist(t, p);
+ pa_proplist_free(p);
+ }
pa_pstream_send_tagstruct(c->pstream, t);
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, play_sample_with_proplist_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
diff --git a/src/pulse/scache.h b/src/pulse/scache.h
index cd579d2e..31cf7b01 100644
--- a/src/pulse/scache.h
+++ b/src/pulse/scache.h
@@ -101,7 +101,7 @@ pa_operation* pa_context_play_sample(
pa_context *c /**< Context */,
const char *name /**< Name of the sample to play */,
const char *dev /**< Sink to play this sample on */,
- pa_volume_t volume /**< Volume to play this sample with. Starting with 0.9.15 you may pass here (pa_volume_t) -1 which will leave the decision about the volume to the server side which is a good idea. */ ,
+ pa_volume_t volume /**< Volume to play this sample with. Starting with 0.9.15 you may pass here PA_VOLUME_INVALID which will leave the decision about the volume to the server side which is a good idea. */ ,
pa_context_success_cb_t cb /**< Call this function after successfully starting playback, or NULL */,
void *userdata /**< Userdata to pass to the callback */);
@@ -113,7 +113,7 @@ pa_operation* pa_context_play_sample_with_proplist(
pa_context *c /**< Context */,
const char *name /**< Name of the sample to play */,
const char *dev /**< Sink to play this sample on */,
- pa_volume_t volume /**< Volume to play this sample with. Starting with 0.9.15 you may pass here (pa_volume_t) -1 which will leave the decision about the volume to the server side which is a good idea. */ ,
+ pa_volume_t volume /**< Volume to play this sample with. Starting with 0.9.15 you may pass here PA_VOLUME_INVALID which will leave the decision about the volume to the server side which is a good idea. */ ,
pa_proplist *proplist /**< Property list for this sound. The property list of the cached entry will be merged into this property list */,
pa_context_play_sample_cb_t cb /**< Call this function after successfully starting playback, or NULL */,
void *userdata /**< Userdata to pass to the callback */);
diff --git a/src/pulse/stream.h b/src/pulse/stream.h
index 8a08421f..21dd0a85 100644
--- a/src/pulse/stream.h
+++ b/src/pulse/stream.h
@@ -319,7 +319,7 @@ typedef struct pa_stream pa_stream;
typedef void (*pa_stream_success_cb_t) (pa_stream*s, int success, void *userdata);
/** A generic request callback */
-typedef void (*pa_stream_request_cb_t)(pa_stream *p, size_t bytes, void *userdata);
+typedef void (*pa_stream_request_cb_t)(pa_stream *p, size_t nbytes, void *userdata);
/** A generic notification callback */
typedef void (*pa_stream_notify_cb_t)(pa_stream *p, void *userdata);
diff --git a/src/pulse/timeval.c b/src/pulse/timeval.c
index 376cf13c..cde4417c 100644
--- a/src/pulse/timeval.c
+++ b/src/pulse/timeval.c
@@ -33,6 +33,7 @@
#include <pulsecore/winsock.h>
#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
#include "timeval.h"
@@ -54,9 +55,9 @@ struct timeval *pa_gettimeofday(struct timeval *tv) {
#define EPOCHFILETIME (116444736000000000LL)
#endif
- FILETIME ft;
- LARGE_INTEGER li;
- __int64 t;
+ FILETIME ft;
+ LARGE_INTEGER li;
+ int64_t t;
pa_assert(tv);
@@ -82,7 +83,7 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
pa_assert(b);
/* Check which whan is the earlier time and swap the two arguments if required. */
- if (pa_timeval_cmp(a, b) < 0) {
+ if (PA_UNLIKELY(pa_timeval_cmp(a, b) < 0)) {
const struct timeval *c;
c = a;
a = b;
@@ -94,9 +95,9 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
/* Calculate the microsecond difference */
if (a->tv_usec > b->tv_usec)
- r += ((pa_usec_t) a->tv_usec - (pa_usec_t) 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 - (pa_usec_t) a->tv_usec);
+ r -= (pa_usec_t) b->tv_usec - (pa_usec_t) a->tv_usec;
return r;
}
@@ -128,45 +129,77 @@ pa_usec_t pa_timeval_age(const struct timeval *tv) {
}
struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
- unsigned long secs;
+ time_t secs;
pa_assert(tv);
- secs = (unsigned long) (v/PA_USEC_PER_SEC);
- tv->tv_sec += (time_t) secs;
- v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
+ secs = (time_t) (v/PA_USEC_PER_SEC);
+ if (PA_UNLIKELY(tv->tv_sec > PA_INT_TYPE_MAX(time_t) - secs))
+ goto overflow;
+
+ tv->tv_sec += secs;
+ v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
tv->tv_usec += (suseconds_t) v;
/* Normalize */
- while ((unsigned) tv->tv_usec >= PA_USEC_PER_SEC) {
+ while ((pa_usec_t) tv->tv_usec >= PA_USEC_PER_SEC) {
+
+ if (PA_UNLIKELY(tv->tv_sec >= PA_INT_TYPE_MAX(time_t)))
+ goto overflow;
+
tv->tv_sec++;
tv->tv_usec -= (suseconds_t) PA_USEC_PER_SEC;
}
return tv;
+
+overflow:
+ tv->tv_sec = PA_INT_TYPE_MAX(time_t);
+ tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
+ return tv;
}
struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) {
- unsigned long secs;
+ time_t secs;
pa_assert(tv);
- secs = (unsigned long) (v/PA_USEC_PER_SEC);
- tv->tv_sec -= (time_t) secs;
- v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
+ secs = (time_t) (v/PA_USEC_PER_SEC);
+
+ if (PA_UNLIKELY(tv->tv_sec < secs))
+ goto underflow;
+
+ tv->tv_sec -= secs;
+ v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
if (tv->tv_usec >= (suseconds_t) v)
tv->tv_usec -= (suseconds_t) v;
else {
+
+ if (PA_UNLIKELY(tv->tv_sec <= 0))
+ goto underflow;
+
tv->tv_sec --;
tv->tv_usec += (suseconds_t) (PA_USEC_PER_SEC - v);
}
return tv;
+
+underflow:
+ tv->tv_sec = 0;
+ tv->tv_usec = 0;
+ return tv;
}
struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
pa_assert(tv);
+ if (PA_UNLIKELY(v == PA_USEC_INVALID)) {
+ tv->tv_sec = PA_INT_TYPE_MAX(time_t);
+ tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
+
+ return tv;
+ }
+
tv->tv_sec = (time_t) (v / PA_USEC_PER_SEC);
tv->tv_usec = (suseconds_t) (v % PA_USEC_PER_SEC);
@@ -174,7 +207,9 @@ struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
}
pa_usec_t pa_timeval_load(const struct timeval *tv) {
- pa_assert(tv);
+
+ if (PA_UNLIKELY(!tv))
+ return PA_USEC_INVALID;
return
(pa_usec_t) tv->tv_sec * PA_USEC_PER_SEC +
diff --git a/src/pulse/timeval.h b/src/pulse/timeval.h
index 48c6cdb3..3cea5d3b 100644
--- a/src/pulse/timeval.h
+++ b/src/pulse/timeval.h
@@ -51,12 +51,15 @@ PA_C_DECL_BEGIN
/** The number of nanoseconds in a microsecond */
#define PA_NSEC_PER_USEC ((unsigned long long) 1000ULL)
-/** Invalid time in usec */
+/** Invalid time in usec. \since 0.9.15 */
#define PA_USEC_INVALID ((pa_usec_t) -1)
+/** Biggest time in usec. \since 0.9.18 */
+#define PA_USEC_MAX ((pa_usec_t) -2)
+
struct timeval;
-/** Return the current timestamp, just like UNIX gettimeofday() */
+/** Return the current wallclock timestamp, just like UNIX gettimeofday(). */
struct timeval *pa_gettimeofday(struct timeval *tv);
/** Calculate the difference between the two specified timeval
diff --git a/src/pulse/utf8.c b/src/pulse/utf8.c
index 6b58bde3..fe7bcd26 100644
--- a/src/pulse/utf8.c
+++ b/src/pulse/utf8.c
@@ -120,10 +120,8 @@ static char* utf8_validate(const char *str, char *output) {
size = 4;
min = (1 << 16);
val = (uint32_t) (*p & 0x07);
- } else {
- size = 1;
+ } else
goto error;
- }
p++;
if (!is_continuation_char(*p))
@@ -150,12 +148,9 @@ ONE_REMAINING:
if (o) {
memcpy(o, last, (size_t) size);
- o += size - 1;
+ o += size;
}
- if (o)
- o++;
-
continue;
error:
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 234c3f72..2d2bba25 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -64,7 +64,7 @@ pa_cvolume* pa_cvolume_init(pa_cvolume *a) {
a->channels = 0;
for (c = 0; c < PA_CHANNELS_MAX; c++)
- a->values[c] = (pa_volume_t) -1;
+ a->values[c] = PA_VOLUME_INVALID;
return a;
}
@@ -155,7 +155,7 @@ pa_volume_t pa_cvolume_min(const pa_cvolume *a) {
pa_volume_t pa_cvolume_max_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
pa_volume_t m = PA_VOLUME_MUTED;
- unsigned c, n;
+ unsigned c;
pa_assert(a);
@@ -164,7 +164,7 @@ pa_volume_t pa_cvolume_max_mask(const pa_cvolume *a, const pa_channel_map *cm, p
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
- for (c = n = 0; c < a->channels; c++) {
+ for (c = 0; c < a->channels; c++) {
if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
continue;
@@ -178,7 +178,7 @@ pa_volume_t pa_cvolume_max_mask(const pa_cvolume *a, const pa_channel_map *cm, p
pa_volume_t pa_cvolume_min_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
pa_volume_t m = PA_VOLUME_MAX;
- unsigned c, n;
+ unsigned c;
pa_assert(a);
@@ -187,7 +187,7 @@ pa_volume_t pa_cvolume_min_mask(const pa_cvolume *a, const pa_channel_map *cm, p
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
- for (c = n = 0; c < a->channels; c++) {
+ for (c = 0; c < a->channels; c++) {
if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
continue;
@@ -201,6 +201,9 @@ pa_volume_t pa_cvolume_min_mask(const pa_cvolume *a, const pa_channel_map *cm, p
pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
+ pa_return_val_if_fail(a != PA_VOLUME_INVALID, PA_VOLUME_INVALID);
+ pa_return_val_if_fail(b != PA_VOLUME_INVALID, PA_VOLUME_INVALID);
+
/* cbrt((a/PA_VOLUME_NORM)^3*(b/PA_VOLUME_NORM)^3)*PA_VOLUME_NORM = a*b/PA_VOLUME_NORM */
return (pa_volume_t) (((uint64_t) a * (uint64_t) b + (uint64_t) PA_VOLUME_NORM / 2ULL) / (uint64_t) PA_VOLUME_NORM);
@@ -208,6 +211,9 @@ pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) {
+ pa_return_val_if_fail(a != PA_VOLUME_INVALID, PA_VOLUME_INVALID);
+ pa_return_val_if_fail(b != PA_VOLUME_INVALID, PA_VOLUME_INVALID);
+
if (b <= PA_VOLUME_MUTED)
return 0;
@@ -232,6 +238,8 @@ pa_volume_t pa_sw_volume_from_dB(double dB) {
double pa_sw_volume_to_dB(pa_volume_t v) {
+ pa_return_val_if_fail(v != PA_VOLUME_INVALID, PA_DECIBEL_MININFTY);
+
if (v <= PA_VOLUME_MUTED)
return PA_DECIBEL_MININFTY;
@@ -259,6 +267,8 @@ pa_volume_t pa_sw_volume_from_linear(double v) {
double pa_sw_volume_to_linear(pa_volume_t v) {
double f;
+ pa_return_val_if_fail(v != PA_VOLUME_INVALID, 0.0);
+
if (v <= PA_VOLUME_MUTED)
return 0.0;
@@ -307,7 +317,7 @@ char *pa_volume_snprint(char *s, size_t l, pa_volume_t v) {
pa_init_i18n();
- if (v == (pa_volume_t) -1) {
+ if (v == PA_VOLUME_INVALID) {
pa_snprintf(s, l, _("(invalid)"));
return s;
}
@@ -357,7 +367,7 @@ char *pa_sw_volume_snprint_dB(char *s, size_t l, pa_volume_t v) {
pa_init_i18n();
- if (v == (pa_volume_t) -1) {
+ if (v == PA_VOLUME_INVALID) {
pa_snprintf(s, l, _("(invalid)"));
return s;
}
@@ -374,6 +384,7 @@ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) {
pa_assert(a);
pa_return_val_if_fail(pa_cvolume_valid(a), 0);
+ pa_return_val_if_fail(v != PA_VOLUME_INVALID, 0);
for (c = 0; c < a->channels; c++)
if (a->values[c] != v)
@@ -407,6 +418,7 @@ pa_cvolume *pa_sw_cvolume_multiply_scalar(pa_cvolume *dest, const pa_cvolume *a,
pa_assert(a);
pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
+ pa_return_val_if_fail(b != PA_VOLUME_INVALID, NULL);
for (i = 0; i < a->channels; i++)
dest->values[i] = pa_sw_volume_multiply(a->values[i], b);
@@ -441,6 +453,7 @@ pa_cvolume *pa_sw_cvolume_divide_scalar(pa_cvolume *dest, const pa_cvolume *a, p
pa_assert(a);
pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
+ pa_return_val_if_fail(b != PA_VOLUME_INVALID, NULL);
for (i = 0; i < a->channels; i++)
dest->values[i] = pa_sw_volume_divide(a->values[i], b);
@@ -459,7 +472,7 @@ int pa_cvolume_valid(const pa_cvolume *v) {
return 0;
for (c = 0; c < v->channels; c++)
- if (v->values[c] == (pa_volume_t) -1)
+ if (v->values[c] == PA_VOLUME_INVALID)
return 0;
return 1;
@@ -497,8 +510,6 @@ pa_cvolume *pa_cvolume_remap(pa_cvolume *v, const pa_channel_map *from, const pa
pa_assert(from);
pa_assert(to);
- pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
- pa_return_val_if_fail(pa_channel_map_valid(from), NULL);
pa_return_val_if_fail(pa_channel_map_valid(to), NULL);
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, from), NULL);
@@ -600,8 +611,6 @@ float pa_cvolume_get_balance(const pa_cvolume *v, const pa_channel_map *map) {
pa_assert(v);
pa_assert(map);
- pa_return_val_if_fail(pa_cvolume_valid(v), 0.0f);
- pa_return_val_if_fail(pa_channel_map_valid(map), 0.0f);
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
if (!pa_channel_map_can_balance(map))
@@ -633,12 +642,10 @@ pa_cvolume* pa_cvolume_set_balance(pa_cvolume *v, const pa_channel_map *map, flo
pa_assert(map);
pa_assert(v);
- pa_assert(new_balance >= -1.0f);
- pa_assert(new_balance <= 1.0f);
- pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
- pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
+ pa_return_val_if_fail(new_balance >= -1.0f, NULL);
+ pa_return_val_if_fail(new_balance <= 1.0f, NULL);
if (!pa_channel_map_can_balance(map))
return v;
@@ -679,7 +686,7 @@ pa_cvolume* pa_cvolume_scale(pa_cvolume *v, pa_volume_t max) {
pa_assert(v);
pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
- pa_return_val_if_fail(max != (pa_volume_t) -1, NULL);
+ pa_return_val_if_fail(max != PA_VOLUME_INVALID, NULL);
t = pa_cvolume_max(v);
@@ -698,8 +705,12 @@ pa_cvolume* pa_cvolume_scale_mask(pa_cvolume *v, pa_volume_t max, pa_channel_map
pa_assert(v);
- pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
- pa_return_val_if_fail(max != (pa_volume_t) -1, NULL);
+ pa_return_val_if_fail(max != PA_VOLUME_INVALID, NULL);
+
+ if (!cm)
+ return pa_cvolume_scale(v, max);
+
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, cm), NULL);
t = pa_cvolume_max_mask(v, cm, mask);
@@ -750,8 +761,6 @@ float pa_cvolume_get_fade(const pa_cvolume *v, const pa_channel_map *map) {
pa_assert(v);
pa_assert(map);
- pa_return_val_if_fail(pa_cvolume_valid(v), 0.0f);
- pa_return_val_if_fail(pa_channel_map_valid(map), 0.0f);
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
if (!pa_channel_map_can_fade(map))
@@ -774,12 +783,10 @@ pa_cvolume* pa_cvolume_set_fade(pa_cvolume *v, const pa_channel_map *map, float
pa_assert(map);
pa_assert(v);
- pa_assert(new_fade >= -1.0f);
- pa_assert(new_fade <= 1.0f);
- pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
- pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
+ pa_return_val_if_fail(new_fade >= -1.0f, NULL);
+ pa_return_val_if_fail(new_fade <= 1.0f, NULL);
if (!pa_channel_map_can_fade(map))
return v;
@@ -827,6 +834,7 @@ pa_cvolume* pa_cvolume_set_position(
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), NULL);
pa_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, NULL);
+ pa_return_val_if_fail(v != PA_VOLUME_INVALID, NULL);
for (c = 0; c < map->channels; c++)
if (map->map[c] == t) {
@@ -883,6 +891,7 @@ pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc) {
pa_assert(v);
pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
+ pa_return_val_if_fail(inc != PA_VOLUME_INVALID, NULL);
m = pa_cvolume_max(v);
@@ -900,6 +909,7 @@ pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec) {
pa_assert(v);
pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
+ pa_return_val_if_fail(dec != PA_VOLUME_INVALID, NULL);
m = pa_cvolume_max(v);
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index 543b0af1..c964020a 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -106,11 +106,14 @@ typedef uint32_t pa_volume_t;
/** Normal volume (100%, 0 dB) */
#define PA_VOLUME_NORM ((pa_volume_t) 0x10000U)
-/** Muted volume (0%, -inf dB) */
+/** Muted (minimal valid) volume (0%, -inf dB) */
#define PA_VOLUME_MUTED ((pa_volume_t) 0U)
-/** Maximum volume we can store. \since 0.9.15 */
-#define PA_VOLUME_MAX ((pa_volume_t) UINT32_MAX)
+/** Maximum valid volume we can store. \since 0.9.15 */
+#define PA_VOLUME_MAX ((pa_volume_t) UINT32_MAX-1)
+
+/** Special 'invalid' volume. \since 0.9.16 */
+#define PA_VOLUME_INVALID ((pa_volume_t) UINT32_MAX)
/** A structure encapsulating a per-channel volume */
typedef struct pa_cvolume {
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 6ec74647..b57919a4 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -328,7 +328,7 @@ static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf
static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
- char s[256];
+ char bytes[PA_BYTES_SNPRINT_MAX];
const pa_mempool_stat *stat;
unsigned k;
pa_sink *def_sink;
@@ -352,22 +352,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), (unsigned) pa_atomic_load(&stat->allocated_size)));
+ pa_bytes_snprint(bytes, sizeof(bytes), (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), (unsigned) pa_atomic_load(&stat->accumulated_size)));
+ pa_bytes_snprint(bytes, sizeof(bytes), (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), (unsigned) pa_atomic_load(&stat->imported_size)));
+ pa_bytes_snprint(bytes, sizeof(bytes), (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), (unsigned) pa_atomic_load(&stat->exported_size)));
+ pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&stat->exported_size)));
pa_strbuf_printf(buf, "Total sample cache size: %s.\n",
- pa_bytes_snprint(s, sizeof(s), (unsigned) pa_scache_total_size(c)));
+ pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_scache_total_size(c)));
pa_strbuf_printf(buf, "Default sample spec: %s\n",
pa_sample_spec_snprint(ss, sizeof(ss), &c->default_sample_spec));
@@ -529,7 +529,7 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
return -1;
}
- pa_cvolume_set(&cvolume, sink->sample_spec.channels, volume);
+ pa_cvolume_set(&cvolume, 1, volume);
pa_sink_set_volume(sink, &cvolume, TRUE, TRUE);
return 0;
}
@@ -571,7 +571,7 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb
return -1;
}
- pa_cvolume_set(&cvolume, si->sample_spec.channels, volume);
+ pa_cvolume_set(&cvolume, 1, volume);
pa_sink_input_set_volume(si, &cvolume, TRUE, TRUE);
return 0;
}
@@ -607,7 +607,7 @@ static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *
return -1;
}
- pa_cvolume_set(&cvolume, source->sample_spec.channels, volume);
+ pa_cvolume_set(&cvolume, 1, volume);
pa_source_set_volume(source, &cvolume, TRUE);
return 0;
}
@@ -1549,7 +1549,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
pa_sink *sink;
pa_source *source;
pa_card *card;
- int nl;
+ pa_bool_t nl;
uint32_t idx;
char txt[256];
time_t now;
@@ -1567,7 +1567,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
#endif
- for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) {
+ PA_IDXSET_FOREACH(m, c->modules, idx) {
pa_strbuf_printf(buf, "load-module %s", m->name);
@@ -1577,58 +1577,58 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
pa_strbuf_puts(buf, "\n");
}
- nl = 0;
-
- for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) {
+ nl = FALSE;
+ PA_IDXSET_FOREACH(sink, c->sinks, idx) {
if (!nl) {
pa_strbuf_puts(buf, "\n");
- nl = 1;
+ nl = TRUE;
}
- 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-volume %s 0x%03x\n", sink->name, pa_cvolume_max(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));
}
- for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) {
+ nl = FALSE;
+ PA_IDXSET_FOREACH(source, c->sources, idx) {
if (!nl) {
pa_strbuf_puts(buf, "\n");
- nl = 1;
+ nl = TRUE;
}
- 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-volume %s 0x%03x\n", source->name, pa_cvolume_max(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));
}
- for (card = pa_idxset_first(c->cards, &idx); card; card = pa_idxset_next(c->cards, &idx)) {
+ nl = FALSE;
+ PA_IDXSET_FOREACH(card, c->cards, idx) {
if (!nl) {
pa_strbuf_puts(buf, "\n");
- nl = 1;
+ nl = TRUE;
}
if (card->active_profile)
pa_strbuf_printf(buf, "set-card-profile %s %s\n", card->name, card->active_profile->name);
}
- nl = 0;
-
+ nl = FALSE;
if ((sink = pa_namereg_get_default_sink(c))) {
if (!nl) {
pa_strbuf_puts(buf, "\n");
- nl = 1;
+ nl = TRUE;
}
+
pa_strbuf_printf(buf, "set-default-sink %s\n", sink->name);
}
if ((source = pa_namereg_get_default_source(c))) {
- if (!nl) {
+ if (!nl)
pa_strbuf_puts(buf, "\n");
- nl = 1;
- }
+
pa_strbuf_printf(buf, "set-default-source %s\n", source->name);
}
@@ -1813,8 +1813,6 @@ int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_b
ret = pa_cli_command_execute_file_stream(c, f, buf, fail);
- ret = 0;
-
fail:
if (f)
fclose(f);
diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c
index b4ab23cc..dd4a99ee 100644
--- a/src/pulsecore/conf-parser.c
+++ b/src/pulsecore/conf-parser.c
@@ -113,7 +113,7 @@ static int parse_line(const char *filename, unsigned line, char **section, const
return 0;
if (pa_startswith(b, ".include ")) {
- char *path, *fn;
+ char *path = NULL, *fn;
int r;
fn = strip(b+9);
diff --git a/src/pulsecore/core-rtclock.c b/src/pulsecore/core-rtclock.c
index 3b3e3a64..1420470a 100644
--- a/src/pulsecore/core-rtclock.c
+++ b/src/pulsecore/core-rtclock.c
@@ -132,6 +132,8 @@ struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) {
pa_assert(tv);
+ /* pa_timeval_sub() saturates on underflow! */
+
if (pa_timeval_cmp(&wc_now, tv) < 0)
pa_timeval_add(&rt_now, pa_timeval_diff(tv, &wc_now));
else
@@ -144,13 +146,29 @@ struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) {
}
pa_usec_t pa_timespec_load(const struct timespec *ts) {
- pa_assert(ts);
+
+ if (PA_UNLIKELY(!ts))
+ return PA_USEC_INVALID;
return
(pa_usec_t) ts->tv_sec * PA_USEC_PER_SEC +
(pa_usec_t) ts->tv_nsec / PA_NSEC_PER_USEC;
}
+struct timespec* pa_timespec_store(struct timespec *ts, pa_usec_t v) {
+ pa_assert(ts);
+
+ if (PA_UNLIKELY(v == PA_USEC_INVALID)) {
+ ts->tv_sec = PA_INT_TYPE_MAX(time_t);
+ ts->tv_nsec = (long) (PA_NSEC_PER_SEC-1);
+ return NULL;
+ }
+
+ ts->tv_sec = (time_t) (v / PA_USEC_PER_SEC);
+ ts->tv_nsec = (long) ((v % PA_USEC_PER_SEC) * PA_NSEC_PER_USEC);
+
+ return ts;
+}
static struct timeval* wallclock_from_rtclock(struct timeval *tv) {
@@ -162,6 +180,8 @@ static struct timeval* wallclock_from_rtclock(struct timeval *tv) {
pa_assert(tv);
+ /* pa_timeval_sub() saturates on underflow! */
+
if (pa_timeval_cmp(&rt_now, tv) < 0)
pa_timeval_add(&wc_now, pa_timeval_diff(tv, &rt_now));
else
diff --git a/src/pulsecore/core-rtclock.h b/src/pulsecore/core-rtclock.h
index 9f5ae2dd..3b393ed5 100644
--- a/src/pulsecore/core-rtclock.h
+++ b/src/pulsecore/core-rtclock.h
@@ -44,6 +44,7 @@ void pa_rtclock_hrtimer_enable(void);
struct timeval* pa_rtclock_from_wallclock(struct timeval *tv);
pa_usec_t pa_timespec_load(const struct timespec *ts);
+struct timespec* pa_timespec_store(struct timespec *ts, pa_usec_t v);
struct timeval* pa_timeval_rtstore(struct timeval *tv, pa_usec_t v, pa_bool_t rtclock);
diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c
index fde12ecf..1fb81d0d 100644
--- a/src/pulsecore/core-scache.c
+++ b/src/pulsecore/core-scache.c
@@ -335,12 +335,12 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t
pass_volume = TRUE;
- if (e->volume_is_set && volume != (pa_volume_t) -1) {
+ if (e->volume_is_set && volume != PA_VOLUME_INVALID) {
pa_cvolume_set(&r, e->sample_spec.channels, volume);
pa_sw_cvolume_multiply(&r, &r, &e->volume);
} else if (e->volume_is_set)
r = e->volume;
- else if (volume != (pa_volume_t) -1)
+ else if (volume != PA_VOLUME_INVALID)
pa_cvolume_set(&r, e->sample_spec.channels, volume);
else
pass_volume = FALSE;
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index d576d01d..27e09cbc 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -116,6 +116,7 @@
#include <pulsecore/thread.h>
#include <pulsecore/strbuf.h>
#include <pulsecore/usergroup.h>
+#include <pulsecore/strlist.h>
#include "core-util.h"
@@ -124,6 +125,8 @@
#define MSG_NOSIGNAL 0
#endif
+static pa_strlist *recorded_env = NULL;
+
#ifdef OS_IS_WIN32
#define PULSE_ROOTENV "PULSE_ROOT"
@@ -588,13 +591,13 @@ static int set_scheduler(int rtprio) {
sp.sched_priority = rtprio;
#ifdef SCHED_RESET_ON_FORK
- if ((r = pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp)) == 0) {
+ if (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 ((r = pthread_setschedparam(pthread_self(), SCHED_RR, &sp)) == 0) {
+ if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == 0) {
pa_log_debug("SCHED_RR worked.");
return 0;
}
@@ -609,6 +612,11 @@ static int set_scheduler(int rtprio) {
return -1;
}
+ /* We need to disable exit on disconnect because otherwise
+ * dbus_shutdown will kill us. See
+ * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
+ dbus_connection_set_exit_on_disconnect(bus, FALSE);
+
r = rtkit_make_realtime(bus, 0, rtprio);
dbus_connection_unref(bus);
@@ -677,6 +685,11 @@ static int set_nice(int nice_level) {
return -1;
}
+ /* We need to disable exit on disconnect because otherwise
+ * dbus_shutdown will kill us. See
+ * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
+ dbus_connection_set_exit_on_disconnect(bus, FALSE);
+
r = rtkit_make_high_priority(bus, 0, nice_level);
dbus_connection_unref(bus);
@@ -773,7 +786,6 @@ int pa_match(const char *expr, const char *v) {
/* 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 */
@@ -785,12 +797,12 @@ int pa_parse_boolean(const char *v) {
/* And then we check language dependant */
if ((expr = nl_langinfo(YESEXPR)))
if (expr[0])
- if ((r = pa_match(expr, v)) > 0)
+ if (pa_match(expr, v) > 0)
return 1;
if ((expr = nl_langinfo(NOEXPR)))
if (expr[0])
- if ((r = pa_match(expr, v)) > 0)
+ if (pa_match(expr, v) > 0)
return 0;
errno = EINVAL;
@@ -1182,7 +1194,7 @@ char* pa_strip_nl(char *s) {
/* Create a temporary lock file and lock it. */
int pa_lock_lockfile(const char *fn) {
- int fd = -1;
+ int fd;
pa_assert(fn);
for (;;) {
@@ -1225,8 +1237,6 @@ int pa_lock_lockfile(const char *fn) {
fd = -1;
goto fail;
}
-
- fd = -1;
}
return fd;
@@ -1368,19 +1378,10 @@ static char* make_random_dir(mode_t m) {
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
- const char *tmpdir;
char *fn;
size_t pathlen;
- if (!(tmpdir = getenv("TMPDIR")))
- if (!(tmpdir = getenv("TMP")))
- if (!(tmpdir = getenv("TEMP")))
- tmpdir = getenv("TEMPDIR");
-
- if (!tmpdir || !pa_is_path_absolute(tmpdir))
- tmpdir = "/tmp";
-
- fn = pa_sprintf_malloc("%s/pulse-XXXXXXXXXXXX", tmpdir);
+ fn = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse-XXXXXXXXXXXX", pa_get_temp_dir());
pathlen = strlen(fn);
for (;;) {
@@ -2394,7 +2395,7 @@ int pa_reset_sigs(int except, ...) {
p[i++] = except;
while ((sig = va_arg(ap, int)) >= 0)
- sig = p[i++];
+ p[i++] = sig;
}
p[i] = -1;
@@ -2451,9 +2452,38 @@ void pa_set_env(const char *key, const char *value) {
pa_assert(key);
pa_assert(value);
+ /* This is not thread-safe */
+
putenv(pa_sprintf_malloc("%s=%s", key, value));
}
+void pa_set_env_and_record(const char *key, const char *value) {
+ pa_assert(key);
+ pa_assert(value);
+
+ /* This is not thread-safe */
+
+ pa_set_env(key, value);
+ recorded_env = pa_strlist_prepend(recorded_env, key);
+}
+
+void pa_unset_env_recorded(void) {
+
+ /* This is not thread-safe */
+
+ for (;;) {
+ char *s;
+
+ recorded_env = pa_strlist_pop(recorded_env, &s);
+
+ if (!s)
+ break;
+
+ unsetenv(s);
+ pa_xfree(s);
+ }
+}
+
pa_bool_t pa_in_system_mode(void) {
const char *e;
@@ -2837,3 +2867,25 @@ pa_bool_t pa_run_from_build_tree(void) {
}
#endif
+
+const char *pa_get_temp_dir(void) {
+ const char *t;
+
+ if ((t = getenv("TMPDIR")) &&
+ pa_is_path_absolute(t))
+ return t;
+
+ if ((t = getenv("TMP")) &&
+ pa_is_path_absolute(t))
+ return t;
+
+ if ((t = getenv("TEMP")) &&
+ pa_is_path_absolute(t))
+ return t;
+
+ if ((t = getenv("TEMPDIR")) &&
+ pa_is_path_absolute(t))
+ return t;
+
+ return "/tmp";
+}
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index 8c13b535..9986b14a 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -195,6 +195,8 @@ int pa_reset_sigs(int except, ...);
int pa_reset_sigsv(const int except[]);
void pa_set_env(const char *key, const char *value);
+void pa_set_env_and_record(const char *key, const char *value);
+void pa_unset_env_recorded(void);
pa_bool_t pa_in_system_mode(void);
@@ -254,4 +256,6 @@ void pa_reset_personality(void);
pa_bool_t pa_run_from_build_tree(void);
#endif
+const char *pa_get_temp_dir(void);
+
#endif
diff --git a/src/pulsecore/cpu-x86.c b/src/pulsecore/cpu-x86.c
index 1ba9f1a4..f194a608 100644
--- a/src/pulsecore/cpu-x86.c
+++ b/src/pulsecore/cpu-x86.c
@@ -115,7 +115,7 @@ void pa_cpu_init_x86 (void) {
pa_remap_func_init_mmx (flags);
}
- if (flags & PA_CPU_X86_SSE) {
+ if (flags & (PA_CPU_X86_SSE | PA_CPU_X86_SSE2)) {
pa_volume_func_init_sse (flags);
pa_remap_func_init_sse (flags);
pa_convert_func_init_sse (flags);
diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c
index 6fb944f9..7e5ee244 100644
--- a/src/pulsecore/flist.c
+++ b/src/pulsecore/flist.c
@@ -130,15 +130,22 @@ void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb) {
}
int pa_flist_push(pa_flist*l, void *p) {
- unsigned idx, n, len;
+ unsigned idx, n;
pa_atomic_ptr_t*cells;
+#ifdef PROFILE
+ unsigned len;
+#endif
pa_assert(l);
pa_assert(p);
cells = PA_FLIST_CELLS(l);
- n = len = l->size + N_EXTRA_SCAN - (unsigned) pa_atomic_load(&l->length);
+ n = l->size + N_EXTRA_SCAN - (unsigned) pa_atomic_load(&l->length);
+
+#ifdef PROFILE
+ len = n;
+#endif
_Y;
idx = reduce(l, (unsigned) pa_atomic_load(&l->write_idx));
@@ -171,14 +178,21 @@ int pa_flist_push(pa_flist*l, void *p) {
}
void* pa_flist_pop(pa_flist*l) {
- unsigned idx, len, n;
+ unsigned idx, n;
pa_atomic_ptr_t *cells;
+#ifdef PROFILE
+ unsigned len;
+#endif
pa_assert(l);
cells = PA_FLIST_CELLS(l);
- n = len = (unsigned) pa_atomic_load(&l->length) + N_EXTRA_SCAN;
+ n = (unsigned) pa_atomic_load(&l->length) + N_EXTRA_SCAN;
+
+#ifdef PROFILE
+ len = n;
+#endif
_Y;
idx = reduce(l, (unsigned) pa_atomic_load(&l->read_idx));
diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index bffcc264..9a5a2670 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -304,6 +304,18 @@ typedef int pa_bool_t;
#define pa_memzero(x,l) (memset((x), 0, (l)))
#define pa_zero(x) (pa_memzero(&(x), sizeof(x)))
+#define PA_INT_TYPE_SIGNED(type) (!!((type) 0 > (type) -1))
+
+#define PA_INT_TYPE_MAX(type) \
+ ((type) (PA_INT_TYPE_SIGNED(type) \
+ ? ~(~(type) 0 << (8*sizeof(type)-1)) \
+ : (type) -1))
+
+#define PA_INT_TYPE_MIN(type) \
+ ((type) (PA_INT_TYPE_SIGNED(type) \
+ ? (~(type) 0 << (8*sizeof(type)-1)) \
+ : (type) 0))
+
/* We include this at the very last place */
#include <pulsecore/log.h>
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 441b397b..f38b17c6 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -303,10 +303,17 @@ static struct mempool_slot* mempool_slot_by_ptr(pa_mempool *p, void *ptr) {
pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
pa_memblock *b = NULL;
struct mempool_slot *slot;
+ static int mempool_disable = 0;
pa_assert(p);
pa_assert(length);
+ if (mempool_disable == 0)
+ mempool_disable = getenv("PULSE_MEMPOOL_DISABLE") ? 1 : -1;
+
+ if (mempool_disable > 0)
+ return NULL;
+
/* If -1 is passed as length we choose the size for the caller: we
* take the largest size that fits in one of our slots. */
@@ -361,6 +368,7 @@ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, pa_boo
if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks))))
b = pa_xnew(pa_memblock, 1);
+
PA_REFCNT_INIT(b);
b->pool = p;
b->type = PA_MEMBLOCK_FIXED;
@@ -387,6 +395,7 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, pa_free
if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks))))
b = pa_xnew(pa_memblock, 1);
+
PA_REFCNT_INIT(b);
b->pool = p;
b->type = PA_MEMBLOCK_USER;
@@ -499,13 +508,19 @@ static void memblock_free(pa_memblock *b) {
/* Fall through */
case PA_MEMBLOCK_FIXED:
- case PA_MEMBLOCK_APPENDED :
if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0)
pa_xfree(b);
break;
- case PA_MEMBLOCK_IMPORTED : {
+ case PA_MEMBLOCK_APPENDED:
+
+ /* We could attached it unused_memblocks, but that would
+ * probably waste some considerable memory */
+ pa_xfree(b);
+ break;
+
+ case PA_MEMBLOCK_IMPORTED: {
pa_memimport_segment *segment;
pa_memimport *import;
@@ -539,8 +554,7 @@ static void memblock_free(pa_memblock *b) {
struct mempool_slot *slot;
pa_bool_t call_free;
- slot = mempool_slot_by_ptr(b->pool, pa_atomic_ptr_load(&b->data));
- pa_assert(slot);
+ pa_assert_se(slot = mempool_slot_by_ptr(b->pool, pa_atomic_ptr_load(&b->data)));
call_free = b->type == PA_MEMBLOCK_POOL_EXTERNAL;
@@ -694,7 +708,7 @@ static void memblock_replace_import(pa_memblock *b) {
pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size) {
pa_mempool *p;
- char t1[64], t2[64];
+ char t1[PA_BYTES_SNPRINT_MAX], t2[PA_BYTES_SNPRINT_MAX];
p = pa_xnew(pa_mempool, 1);
@@ -891,7 +905,7 @@ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) {
if (pa_hashmap_size(i->segments) >= PA_MEMIMPORT_SEGMENTS_MAX)
return NULL;
- seg = pa_xnew(pa_memimport_segment, 1);
+ seg = pa_xnew0(pa_memimport_segment, 1);
if (pa_shm_attach_ro(&seg->memory, shm_id) < 0) {
pa_xfree(seg);
@@ -899,10 +913,9 @@ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) {
}
seg->import = i;
- seg->n_blocks = 0;
seg->trap = pa_memtrap_add(seg->memory.ptr, seg->memory.size);
- pa_hashmap_put(i->segments, PA_UINT32_TO_PTR(shm_id), seg);
+ pa_hashmap_put(i->segments, PA_UINT32_TO_PTR(seg->memory.id), seg);
return seg;
}
diff --git a/src/pulsecore/memtrap.c b/src/pulsecore/memtrap.c
index c647e507..4fc18210 100644
--- a/src/pulsecore/memtrap.c
+++ b/src/pulsecore/memtrap.c
@@ -107,7 +107,10 @@ static void memtrap_link(pa_memtrap *m, unsigned j) {
pa_assert(m);
m->prev[j] = NULL;
- m->next[j] = memtraps[j];
+
+ if ((m->next[j] = memtraps[j]))
+ m->next[j]->prev[j] = m;
+
memtraps[j] = m;
}
@@ -200,13 +203,13 @@ pa_memtrap *pa_memtrap_update(pa_memtrap *m, const void *start, size_t size) {
goto unlock;
memtrap_unlink(m, j);
- j = pa_aupdate_write_swap(aupdate);
+ pa_aupdate_write_swap(aupdate);
m->start = (void*) start;
m->size = size;
pa_atomic_store(&m->bad, 0);
- j = pa_aupdate_write_swap(aupdate);
+ pa_assert_se(pa_aupdate_write_swap(aupdate) == j);
memtrap_link(m, j);
unlock:
diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c
index 37755777..d9821876 100644
--- a/src/pulsecore/namereg.c
+++ b/src/pulsecore/namereg.c
@@ -98,7 +98,7 @@ char* pa_namereg_make_valid_name(const char *name) {
if (*name == 0)
return NULL;
- n = pa_xmalloc(strlen(name)+1);
+ n = pa_xnew(char, strlen(name)+1);
for (a = name, b = n; *a && (a-name < PA_NAME_MAX); a++, b++)
*b = (char) (is_valid_char(*a) ? *a : '_');
@@ -170,6 +170,17 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t
pa_assert_se(pa_hashmap_put(c->namereg, e->name, e) >= 0);
+ /* If a sink or source is registered and there was none registered
+ * before we inform the clients which then can ask for the default
+ * sink/source which is then assigned. We don't adjust the default
+ * sink/source here right away to give the module the chance to
+ * register more sinks/sources before we choose a new default
+ * sink/source. */
+
+ if ((!c->default_sink && type == PA_NAMEREG_SINK) ||
+ (!c->default_source && type == PA_NAMEREG_SOURCE))
+ pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SERVER|PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
+
return e->name;
}
diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c
index 00878462..996946c2 100644
--- a/src/pulsecore/pid.c
+++ b/src/pulsecore/pid.c
@@ -81,7 +81,7 @@ static pid_t read_pid(const char *fn, int fd) {
}
static int open_pid_file(const char *fn, int mode) {
- int fd = -1;
+ int fd;
pa_assert(fn);
@@ -123,8 +123,6 @@ static int open_pid_file(const char *fn, int mode) {
fd = -1;
goto fail;
}
-
- fd = -1;
}
return fd;
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 480af6d5..2326eb3a 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -771,7 +771,6 @@ static int esd_proto_stream_pan(connection *c, esd_proto_t request, const void *
memcpy(&rvolume, data, sizeof(uint32_t));
rvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume);
- data = (const char*)data + sizeof(uint32_t);
if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx)) && conn->sink_input) {
pa_cvolume volume;
@@ -809,7 +808,6 @@ static int esd_proto_sample_pan(connection *c, esd_proto_t request, const void *
memcpy(&rvolume, data, sizeof(uint32_t));
rvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume);
- data = (const char*)data + sizeof(uint32_t);
volume.values[0] = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
@@ -1123,7 +1121,7 @@ static int do_read(connection *c) {
ssize_t r;
size_t l;
void *p;
- size_t space;
+ size_t space = 0;
pa_assert(c->input_memblockq);
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index a5e952a3..d06dd4eb 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -628,7 +628,6 @@ static record_stream* record_stream_new(
record_stream *s;
pa_source_output *source_output = NULL;
- size_t base;
pa_source_output_new_data data;
pa_assert(c);
@@ -682,7 +681,7 @@ static record_stream* record_stream_new(
0,
s->buffer_attr.maxlength,
0,
- base = pa_frame_size(&source_output->sample_spec),
+ pa_frame_size(&source_output->sample_spec),
1,
0,
0,
@@ -827,24 +826,26 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
break;
- case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH: {
- pa_tagstruct *t;
+ case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH:
s->buffer_attr.tlength = (uint32_t) offset;
- t = pa_tagstruct_new(NULL, 0);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED);
- pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
- pa_tagstruct_putu32(t, s->index);
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- pa_tagstruct_put_usec(t, s->configured_sink_latency);
- pa_pstream_send_tagstruct(s->connection->pstream, t);
+ if (s->connection->version >= 15) {
+ pa_tagstruct *t;
+
+ t = pa_tagstruct_new(NULL, 0);
+ pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED);
+ pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
+ pa_tagstruct_putu32(t, s->index);
+ pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
+ pa_tagstruct_putu32(t, s->buffer_attr.tlength);
+ pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
+ pa_tagstruct_putu32(t, s->buffer_attr.minreq);
+ pa_tagstruct_put_usec(t, s->configured_sink_latency);
+ pa_pstream_send_tagstruct(s->connection->pstream, t);
+ }
break;
- }
}
return 0;
@@ -2274,6 +2275,8 @@ static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
ret = pa_core_exit(c->protocol->core, FALSE, 0);
CHECK_VALIDITY(c->pstream, ret >= 0, tag, PA_ERR_ACCESS);
+ pa_log_debug("Client %s asks us to terminate.", pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)));
+
pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
}
@@ -3390,12 +3393,18 @@ static void command_set_volume(
client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
if (sink) {
+ CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &sink->sample_spec), tag, PA_ERR_INVALID);
+
pa_log_debug("Client %s changes volume of sink %s.", client_name, sink->name);
pa_sink_set_volume(sink, &volume, TRUE, TRUE);
} else if (source) {
+ CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &source->sample_spec), tag, PA_ERR_INVALID);
+
pa_log_debug("Client %s changes volume of source %s.", client_name, source->name);
pa_source_set_volume(source, &volume, TRUE);
} else if (si) {
+ CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &si->sample_spec), tag, PA_ERR_INVALID);
+
pa_log_debug("Client %s changes volume of sink input %s.",
client_name,
pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
@@ -3441,7 +3450,6 @@ static void command_set_mute(
switch (command) {
case PA_COMMAND_SET_SINK_MUTE:
-
if (idx != PA_INVALID_INDEX)
sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
else
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index d66db4b7..a9f73896 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -154,7 +154,7 @@ static int do_read(connection *c) {
ssize_t r;
size_t l;
void *p;
- size_t space;
+ size_t space = 0;
connection_assert_ref(c);
diff --git a/src/pulsecore/ratelimit.h b/src/pulsecore/ratelimit.h
index ec3b5a38..9857a291 100644
--- a/src/pulsecore/ratelimit.h
+++ b/src/pulsecore/ratelimit.h
@@ -26,21 +26,31 @@
#include <pulsecore/macro.h>
typedef struct pa_ratelimit {
- const pa_usec_t interval;
- const unsigned burst;
+ pa_usec_t interval;
+ unsigned burst;
unsigned n_printed, n_missed;
pa_usec_t begin;
} pa_ratelimit;
#define PA_DEFINE_RATELIMIT(_name, _interval, _burst) \
pa_ratelimit _name = { \
- .interval = _interval, \
- .burst = _burst, \
+ .interval = (_interval), \
+ .burst = (_burst), \
.n_printed = 0, \
.n_missed = 0, \
.begin = 0 \
}
+#define PA_INIT_RATELIMIT(v, _interval, _burst) \
+ do { \
+ pa_ratelimit *r = &(v); \
+ r->interval = (_interval); \
+ r->burst = (_burst); \
+ r->n_printed = 0; \
+ r->n_missed = 0; \
+ r->begin = 0; \
+ } while (FALSE);
+
pa_bool_t pa_ratelimit_test(pa_ratelimit *r);
#endif
diff --git a/src/pulsecore/remap_mmx.c b/src/pulsecore/remap_mmx.c
index b5fe82ee..d358a58b 100644
--- a/src/pulsecore/remap_mmx.c
+++ b/src/pulsecore/remap_mmx.c
@@ -65,16 +65,24 @@
" add $32, %1 \n\t" \
" add $64, %0 \n\t"
-#define HANDLE_SINGLE(s) \
+#define HANDLE_SINGLE_dq() \
" movd (%1), %%mm0 \n\t" \
- " punpckl"#s" %%mm0, %%mm0 \n\t" \
+ " punpckldq %%mm0, %%mm0 \n\t" \
" movq %%mm0, (%0) \n\t" \
" add $4, %1 \n\t" \
" add $8, %0 \n\t"
-#define MONO_TO_STEREO(s) \
- " mov %3, %2 \n\t" \
- " sar $3, %2 \n\t" \
+#define HANDLE_SINGLE_wd() \
+ " movw (%1), %w3 \n\t" \
+ " movd %3, %%mm0 \n\t" \
+ " punpcklwd %%mm0, %%mm0 \n\t" \
+ " movd %%mm0, (%0) \n\t" \
+ " add $2, %1 \n\t" \
+ " add $4, %0 \n\t"
+
+#define MONO_TO_STEREO(s,shift,mask) \
+ " mov %4, %2 \n\t" \
+ " sar $"#shift", %2 \n\t" \
" cmp $0, %2 \n\t" \
" je 2f \n\t" \
"1: \n\t" \
@@ -84,11 +92,11 @@
" dec %2 \n\t" \
" jne 1b \n\t" \
"2: \n\t" \
- " mov %3, %2 \n\t" \
- " and $7, %2 \n\t" \
+ " mov %4, %2 \n\t" \
+ " and $"#mask", %2 \n\t" \
" je 4f \n\t" \
"3: \n\t" \
- HANDLE_SINGLE(s) \
+ HANDLE_SINGLE_##s() \
" dec %2 \n\t" \
" jne 3b \n\t" \
"4: \n\t" \
@@ -96,14 +104,14 @@
#if defined (__i386__) || defined (__amd64__)
static void remap_mono_to_stereo_mmx (pa_remap_t *m, void *dst, const void *src, unsigned n) {
- pa_reg_x86 temp;
+ pa_reg_x86 temp, temp2;
switch (*m->format) {
case PA_SAMPLE_FLOAT32NE:
{
__asm__ __volatile__ (
- MONO_TO_STEREO(dq) /* do doubles to quads */
- : "+r" (dst), "+r" (src), "=&r" (temp)
+ MONO_TO_STEREO(dq,3,7) /* do doubles to quads */
+ : "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
: "r" ((pa_reg_x86)n)
: "cc"
);
@@ -112,8 +120,8 @@ static void remap_mono_to_stereo_mmx (pa_remap_t *m, void *dst, const void *src,
case PA_SAMPLE_S16NE:
{
__asm__ __volatile__ (
- MONO_TO_STEREO(wd) /* do words to doubles */
- : "+r" (dst), "+r" (src), "=&r" (temp)
+ MONO_TO_STEREO(wd,4,15) /* do words to doubles */
+ : "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
: "r" ((pa_reg_x86)n)
: "cc"
);
@@ -142,8 +150,12 @@ static void init_remap_mmx (pa_remap_t *m) {
void pa_remap_func_init_mmx (pa_cpu_x86_flag_t flags) {
#if defined (__i386__) || defined (__amd64__)
- pa_log_info("Initialising MMX optimized remappers.");
- pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_mmx);
+ if (flags & PA_CPU_X86_MMX) {
+ pa_log_info("Initialising MMX optimized remappers.");
+
+ pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_mmx);
+ }
+
#endif /* defined (__i386__) || defined (__amd64__) */
}
diff --git a/src/pulsecore/remap_sse.c b/src/pulsecore/remap_sse.c
index 97f2476e..0ccf3161 100644
--- a/src/pulsecore/remap_sse.c
+++ b/src/pulsecore/remap_sse.c
@@ -65,43 +65,52 @@
" add $64, %1 \n\t" \
" add $128, %0 \n\t"
-#define HANDLE_SINGLE(s) \
+#define HANDLE_SINGLE_dq() \
" movd (%1), %%xmm0 \n\t" \
- " punpckl"#s" %%xmm0, %%xmm0 \n\t" \
+ " punpckldq %%xmm0, %%xmm0 \n\t" \
" movq %%xmm0, (%0) \n\t" \
" add $4, %1 \n\t" \
" add $8, %0 \n\t"
-#define MONO_TO_STEREO(s) \
- " mov %3, %2 \n\t" \
- " sar $4, %2 \n\t" \
- " cmp $0, %2 \n\t" \
- " je 2f \n\t" \
- "1: \n\t" \
- LOAD_SAMPLES \
- UNPACK_SAMPLES(s) \
- STORE_SAMPLES \
- " dec %2 \n\t" \
- " jne 1b \n\t" \
- "2: \n\t" \
- " mov %3, %2 \n\t" \
- " and $15, %2 \n\t" \
- " je 4f \n\t" \
- "3: \n\t" \
- HANDLE_SINGLE(s) \
- " dec %2 \n\t" \
- " jne 3b \n\t" \
+#define HANDLE_SINGLE_wd() \
+ " movw (%1), %w3 \n\t" \
+ " movd %3, %%xmm0 \n\t" \
+ " punpcklwd %%xmm0, %%xmm0 \n\t" \
+ " movd %%xmm0, (%0) \n\t" \
+ " add $2, %1 \n\t" \
+ " add $4, %0 \n\t"
+
+#define MONO_TO_STEREO(s,shift,mask) \
+ " mov %4, %2 \n\t" \
+ " sar $"#shift", %2 \n\t" \
+ " cmp $0, %2 \n\t" \
+ " je 2f \n\t" \
+ "1: \n\t" \
+ LOAD_SAMPLES \
+ UNPACK_SAMPLES(s) \
+ STORE_SAMPLES \
+ " dec %2 \n\t" \
+ " jne 1b \n\t" \
+ "2: \n\t" \
+ " mov %4, %2 \n\t" \
+ " and $"#mask", %2 \n\t" \
+ " je 4f \n\t" \
+ "3: \n\t" \
+ HANDLE_SINGLE_##s() \
+ " dec %2 \n\t" \
+ " jne 3b \n\t" \
"4: \n\t"
-static void remap_mono_to_stereo_sse (pa_remap_t *m, void *dst, const void *src, unsigned n) {
- pa_reg_x86 temp;
+#if defined (__i386__) || defined (__amd64__)
+static void remap_mono_to_stereo_sse2 (pa_remap_t *m, void *dst, const void *src, unsigned n) {
+ pa_reg_x86 temp, temp2;
switch (*m->format) {
case PA_SAMPLE_FLOAT32NE:
{
__asm__ __volatile__ (
- MONO_TO_STEREO(dq) /* do doubles to quads */
- : "+r" (dst), "+r" (src), "=&r" (temp)
+ MONO_TO_STEREO(dq, 4, 15) /* do doubles to quads */
+ : "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
: "r" ((pa_reg_x86)n)
: "cc"
);
@@ -110,8 +119,8 @@ static void remap_mono_to_stereo_sse (pa_remap_t *m, void *dst, const void *src,
case PA_SAMPLE_S16NE:
{
__asm__ __volatile__ (
- MONO_TO_STEREO(wd) /* do words to doubles */
- : "+r" (dst), "+r" (src), "=&r" (temp)
+ MONO_TO_STEREO(wd, 5, 31) /* do words to doubles */
+ : "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
: "r" ((pa_reg_x86)n)
: "cc"
);
@@ -123,7 +132,7 @@ static void remap_mono_to_stereo_sse (pa_remap_t *m, void *dst, const void *src,
}
/* set the function that will execute the remapping based on the matrices */
-static void init_remap_sse (pa_remap_t *m) {
+static void init_remap_sse2 (pa_remap_t *m) {
unsigned n_oc, n_ic;
n_oc = m->o_ss->channels;
@@ -132,15 +141,19 @@ static void init_remap_sse (pa_remap_t *m) {
/* find some common channel remappings, fall back to full matrix operation. */
if (n_ic == 1 && n_oc == 2 &&
m->map_table_f[0][0] >= 1.0 && m->map_table_f[1][0] >= 1.0) {
- m->do_remap = (pa_do_remap_func_t) remap_mono_to_stereo_sse;
+ m->do_remap = (pa_do_remap_func_t) remap_mono_to_stereo_sse2;
pa_log_info("Using SSE mono to stereo remapping");
}
}
+#endif /* defined (__i386__) || defined (__amd64__) */
void pa_remap_func_init_sse (pa_cpu_x86_flag_t flags) {
#if defined (__i386__) || defined (__amd64__)
- pa_log_info("Initialising SSE optimized remappers.");
- pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_sse);
+ if (flags & PA_CPU_X86_SSE2) {
+ pa_log_info("Initialising SSE2 optimized remappers.");
+ pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_sse2);
+ }
+
#endif /* defined (__i386__) || defined (__amd64__) */
}
diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 5fae1928..a26dc876 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -1056,3 +1056,13 @@ void pa_memchunk_sine(pa_memchunk *c, pa_mempool *pool, unsigned rate, unsigned
calc_sine(p, c->length, freq * l / rate);
pa_memblock_release(c->memblock);
}
+
+size_t pa_convert_size(size_t size, const pa_sample_spec *from, const pa_sample_spec *to) {
+ pa_usec_t usec;
+
+ pa_assert(from);
+ pa_assert(to);
+
+ usec = pa_bytes_to_usec_round_up(size, from);
+ return pa_usec_to_bytes_round_up(usec, to);
+}
diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h
index 34df5cf3..d0235d60 100644
--- a/src/pulsecore/sample-util.h
+++ b/src/pulsecore/sample-util.h
@@ -91,6 +91,8 @@ typedef void (*pa_do_volume_func_t) (void *samples, void *volumes, unsigned chan
pa_do_volume_func_t pa_get_volume_func(pa_sample_format_t f);
void pa_set_volume_func(pa_sample_format_t f, pa_do_volume_func_t func);
+size_t pa_convert_size(size_t size, const pa_sample_spec *from, const pa_sample_spec *to);
+
#define PA_CHANNEL_POSITION_MASK_LEFT \
(PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT) \
| PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_LEFT) \
diff --git a/src/pulsecore/sconv_sse.c b/src/pulsecore/sconv_sse.c
index ef78fc26..3737af2a 100644
--- a/src/pulsecore/sconv_sse.c
+++ b/src/pulsecore/sconv_sse.c
@@ -83,7 +83,7 @@ static void pa_sconv_s16le_from_f32ne_sse(unsigned n, const float *a, int16_t *b
"2: \n\t"
" mov %4, %1 \n\t" /* prepare for leftovers */
- " and $15, %1 \n\t"
+ " and $7, %1 \n\t"
" je 4f \n\t"
"3: \n\t"
@@ -142,7 +142,7 @@ static void pa_sconv_s16le_from_f32ne_sse2(unsigned n, const float *a, int16_t *
"2: \n\t"
" mov %4, %1 \n\t" /* prepare for leftovers */
- " and $15, %1 \n\t"
+ " and $7, %1 \n\t"
" je 4f \n\t"
"3: \n\t"
@@ -218,16 +218,18 @@ static void run_test (void) {
void pa_convert_func_init_sse (pa_cpu_x86_flag_t flags) {
#if defined (__i386__) || defined (__amd64__)
- pa_log_info("Initialising SSE optimized conversions.");
#ifdef RUN_TEST
run_test ();
#endif
- if (flags & PA_CPU_X86_SSE2)
- pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse2);
- else
- pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse);
+ if (flags & PA_CPU_X86_SSE2) {
+ pa_log_info("Initialising SSE2 optimized conversions.");
+ pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse2);
+ } else {
+ pa_log_info("Initialising SSE optimized conversions.");
+ pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse);
+ }
#endif /* defined (__i386__) || defined (__amd64__) */
}
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index d3e7a45c..1af2823f 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -92,6 +92,18 @@ void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, co
}
}
+void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data *data, const pa_cvolume *volume_factor) {
+ pa_assert(data);
+ pa_assert(volume_factor);
+
+ if (data->volume_factor_sink_is_set)
+ pa_sw_cvolume_multiply(&data->volume_factor_sink, &data->volume_factor_sink, volume_factor);
+ else {
+ data->volume_factor_sink_is_set = TRUE;
+ data->volume_factor_sink = *volume_factor;
+ }
+}
+
void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) {
pa_assert(data);
@@ -141,6 +153,7 @@ int pa_sink_input_new(
char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
pa_channel_map original_cm;
int r;
+ char *pt;
pa_assert(_i);
pa_assert(core);
@@ -176,7 +189,6 @@ int pa_sink_input_new(
pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
}
- pa_return_val_if_fail(pa_channel_map_valid(&data->channel_map), -PA_ERR_INVALID);
pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID);
if (!data->volume_is_set) {
@@ -185,15 +197,18 @@ int pa_sink_input_new(
data->save_volume = FALSE;
}
- pa_return_val_if_fail(pa_cvolume_valid(&data->volume), -PA_ERR_INVALID);
pa_return_val_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec), -PA_ERR_INVALID);
if (!data->volume_factor_is_set)
pa_cvolume_reset(&data->volume_factor, data->sample_spec.channels);
- pa_return_val_if_fail(pa_cvolume_valid(&data->volume_factor), -PA_ERR_INVALID);
pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor, &data->sample_spec), -PA_ERR_INVALID);
+ if (!data->volume_factor_sink_is_set)
+ pa_cvolume_reset(&data->volume_factor_sink, data->sink->sample_spec.channels);
+
+ pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor_sink, &data->sink->sample_spec), -PA_ERR_INVALID);
+
if (!data->muted_is_set)
data->muted = FALSE;
@@ -283,6 +298,7 @@ int pa_sink_input_new(
i->volume = data->volume;
i->volume_factor = data->volume_factor;
+ i->volume_factor_sink = data->volume_factor_sink;
i->real_ratio = i->reference_ratio = data->volume;
pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels);
pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
@@ -338,12 +354,15 @@ int pa_sink_input_new(
if (i->client)
pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0);
- pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s",
+ pt = pa_proplist_to_string_sep(i->proplist, "\n ");
+ pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s\n %s",
i->index,
pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)),
i->sink->name,
pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec),
- pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map));
+ pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
+ pt);
+ pa_xfree(pt);
/* Don't forget to call pa_sink_input_put! */
@@ -576,7 +595,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {
/* Called from thread context */
void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) {
- pa_bool_t do_volume_adj_here;
+ pa_bool_t do_volume_adj_here, need_volume_factor_sink;
pa_bool_t volume_is_norm;
size_t block_size_max_sink, block_size_max_sink_input;
size_t ilength;
@@ -624,6 +643,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p
do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
volume_is_norm = pa_cvolume_is_norm(&i->thread_info.soft_volume) && !i->thread_info.muted;
+ need_volume_factor_sink = !pa_cvolume_is_norm(&i->volume_factor_sink);
while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {
pa_memchunk tchunk;
@@ -655,6 +675,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p
while (tchunk.length > 0) {
pa_memchunk wchunk;
+ pa_bool_t nvfs = need_volume_factor_sink;
wchunk = tchunk;
pa_memblock_ref(wchunk.memblock);
@@ -666,18 +687,41 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p
if (do_volume_adj_here && !volume_is_norm) {
pa_memchunk_make_writable(&wchunk, 0);
- if (i->thread_info.muted)
+ if (i->thread_info.muted) {
pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec);
- else
+ nvfs = FALSE;
+
+ } else if (!i->thread_info.resampler && nvfs) {
+ pa_cvolume v;
+
+ /* If we don't need a resampler we can merge the
+ * post and the pre volume adjustment into one */
+
+ pa_sw_cvolume_multiply(&v, &i->thread_info.soft_volume, &i->volume_factor_sink);
+ pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &v);
+ nvfs = FALSE;
+
+ } else
pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &i->thread_info.soft_volume);
}
- if (!i->thread_info.resampler)
+ if (!i->thread_info.resampler) {
+
+ if (nvfs) {
+ pa_memchunk_make_writable(&wchunk, 0);
+ pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink);
+ }
+
pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk);
- else {
+ } else {
pa_memchunk rchunk;
pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk);
+ if (nvfs) {
+ pa_memchunk_make_writable(&rchunk, 0);
+ pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink);
+ }
+
/* pa_log_debug("pushing %lu", (unsigned long) rchunk.length); */
if (rchunk.memblock) {
@@ -941,12 +985,22 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
pa_assert(volume);
pa_assert(pa_cvolume_valid(volume));
- pa_assert(pa_cvolume_compatible(volume, &i->sample_spec));
+ pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec));
if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !absolute) {
v = i->sink->reference_volume;
pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map);
- volume = pa_sw_cvolume_multiply(&v, &v, volume);
+
+ if (pa_cvolume_compatible(volume, &i->sample_spec))
+ volume = pa_sw_cvolume_multiply(&v, &v, volume);
+ else
+ volume = pa_sw_cvolume_multiply_scalar(&v, &v, pa_cvolume_max(volume));
+ } else {
+
+ if (!pa_cvolume_compatible(volume, &i->sample_spec)) {
+ v = i->volume;
+ volume = pa_cvolume_scale(&v, pa_cvolume_max(volume));
+ }
}
if (pa_cvolume_equal(volume, &i->volume)) {
@@ -1142,7 +1196,6 @@ pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
/* Called from main context */
int pa_sink_input_start_move(pa_sink_input *i) {
pa_source_output *o, *p = NULL;
- pa_sink *origin;
int r;
pa_sink_input_assert_ref(i);
@@ -1156,8 +1209,6 @@ int pa_sink_input_start_move(pa_sink_input *i) {
if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0)
return r;
- origin = i->sink;
-
/* Kill directly connected outputs */
while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
pa_assert(o != p);
@@ -1179,6 +1230,7 @@ int pa_sink_input_start_move(pa_sink_input *i) {
pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
pa_sink_update_status(i->sink);
+ pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);
i->sink = NULL;
pa_sink_input_unref(i);
@@ -1233,6 +1285,8 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
i->save_sink = save;
pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
+ pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map);
+
if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
i->sink->n_corked++;
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 59eabe36..415a801f 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -100,6 +100,8 @@ struct pa_sink_input {
pa_cvolume volume_factor; /* An internally used volume factor that can be used by modules to apply effects and suchlike without having that visible to the outside */
pa_cvolume soft_volume; /* The internal software volume we apply to all PCM data while it passes through. Usually calculated as real_ratio * volume_factor */
+ pa_cvolume volume_factor_sink; /* A second volume factor in format of the sink this stream is connected to */
+
pa_bool_t muted:1;
/* if TRUE then the source we are connected to and/or the volume
@@ -273,13 +275,13 @@ typedef struct pa_sink_input_new_data {
pa_sample_spec sample_spec;
pa_channel_map channel_map;
- pa_cvolume volume, volume_factor;
+ pa_cvolume volume, volume_factor, volume_factor_sink;
pa_bool_t muted:1;
pa_bool_t sample_spec_is_set:1;
pa_bool_t channel_map_is_set:1;
- pa_bool_t volume_is_set:1, volume_factor_is_set:1;
+ pa_bool_t volume_is_set:1, volume_factor_is_set:1, volume_factor_sink_is_set:1;
pa_bool_t muted_is_set:1;
pa_bool_t volume_is_absolute:1;
@@ -292,6 +294,7 @@ void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const
void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map);
void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume);
void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, const pa_cvolume *volume_factor);
+void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data *data, const pa_cvolume *volume_factor);
void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute);
void pa_sink_input_new_data_done(pa_sink_input_new_data *data);
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 48c50b0b..bda92fcc 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -778,7 +778,7 @@ static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, uns
/* Called from IO thread context */
static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *result) {
pa_sink_input *i;
- void *state = NULL;
+ void *state;
unsigned p = 0;
unsigned n_unreffed = 0;
@@ -790,7 +790,7 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *
/* We optimize for the case where the order of the inputs has not changed */
- while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
+ PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
unsigned j;
pa_mix_info* m = NULL;
@@ -884,8 +884,6 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
pa_assert(pa_frame_aligned(length, &s->sample_spec));
pa_assert(result);
- pa_sink_ref(s);
-
pa_assert(!s->thread_info.rewind_requested);
pa_assert(s->thread_info.rewind_nbytes == 0);
@@ -896,6 +894,8 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
return;
}
+ pa_sink_ref(s);
+
if (length <= 0)
length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
@@ -973,8 +973,6 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
pa_assert(target->length > 0);
pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
- pa_sink_ref(s);
-
pa_assert(!s->thread_info.rewind_requested);
pa_assert(s->thread_info.rewind_nbytes == 0);
@@ -983,6 +981,8 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
return;
}
+ pa_sink_ref(s);
+
length = target->length;
block_size_max = pa_mempool_block_size_max(s->core->mempool);
if (length > block_size_max)
@@ -1057,11 +1057,16 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
pa_assert(target->length > 0);
pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
- pa_sink_ref(s);
-
pa_assert(!s->thread_info.rewind_requested);
pa_assert(s->thread_info.rewind_nbytes == 0);
+ if (s->thread_info.state == PA_SINK_SUSPENDED) {
+ pa_silence_memchunk(target, &s->sample_spec);
+ return;
+ }
+
+ pa_sink_ref(s);
+
l = target->length;
d = 0;
while (l > 0) {
@@ -1080,10 +1085,6 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
/* Called from IO thread context */
void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
- pa_mix_info info[MAX_MIX_CHANNELS];
- size_t length1st = length;
- unsigned n;
-
pa_sink_assert_ref(s);
pa_sink_assert_io_context(s);
pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
@@ -1091,81 +1092,24 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
pa_assert(pa_frame_aligned(length, &s->sample_spec));
pa_assert(result);
- pa_sink_ref(s);
-
pa_assert(!s->thread_info.rewind_requested);
pa_assert(s->thread_info.rewind_nbytes == 0);
- pa_assert(length > 0);
-
- n = fill_mix_info(s, &length1st, info, MAX_MIX_CHANNELS);
-
- if (n == 0) {
- pa_silence_memchunk_get(&s->core->silence_cache,
- s->core->mempool,
- result,
- &s->sample_spec,
- length1st);
- } else if (n == 1) {
- pa_cvolume volume;
-
- *result = info[0].chunk;
- pa_memblock_ref(result->memblock);
-
- if (result->length > length)
- result->length = length;
-
- pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
-
- if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) {
- if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) {
- pa_memblock_unref(result->memblock);
- pa_silence_memchunk_get(&s->core->silence_cache,
- s->core->mempool,
- result,
- &s->sample_spec,
- result->length);
- } else {
- pa_memchunk_make_writable(result, length);
- pa_volume_memchunk(result, &s->sample_spec, &volume);
- }
- }
- } else {
- void *ptr;
-
- result->index = 0;
- result->memblock = pa_memblock_new(s->core->mempool, length);
-
- ptr = pa_memblock_acquire(result->memblock);
-
- result->length = pa_mix(info, n,
- (uint8_t*) ptr + result->index, length1st,
- &s->sample_spec,
- &s->thread_info.soft_volume,
- s->thread_info.soft_muted);
-
- pa_memblock_release(result->memblock);
- }
+ pa_sink_ref(s);
- inputs_drop(s, info, n, result);
+ pa_sink_render(s, length, result);
if (result->length < length) {
pa_memchunk chunk;
- size_t l, d;
+
pa_memchunk_make_writable(result, length);
- l = length - result->length;
- d = result->index + result->length;
- while (l > 0) {
- chunk = *result;
- chunk.index = d;
- chunk.length = l;
+ chunk.memblock = result->memblock;
+ chunk.index = result->index + result->length;
+ chunk.length = length - result->length;
- pa_sink_render_into(s, &chunk);
+ pa_sink_render_into_full(s, &chunk);
- d += chunk.length;
- l -= chunk.length;
- }
result->length = length;
}
@@ -1408,8 +1352,11 @@ void pa_sink_set_volume(
pa_assert_ctl_context();
pa_assert(PA_SINK_IS_LINKED(s->state));
pa_assert(!volume || pa_cvolume_valid(volume));
- pa_assert(!volume || pa_cvolume_compatible(volume, &s->sample_spec));
pa_assert(volume || (s->flags & PA_SINK_FLAT_VOLUME));
+ pa_assert(!volume || volume->channels == 1 || pa_cvolume_compatible(volume, &s->sample_spec));
+
+ /* As a special exception we accept mono volumes on all sinks --
+ * even on those with more complex channel maps */
/* If volume is NULL we synchronize the sink's real and reference
* volumes with the stream volumes. If it is not NULL we update
@@ -1419,7 +1366,10 @@ void pa_sink_set_volume(
if (volume) {
- s->reference_volume = *volume;
+ if (pa_cvolume_compatible(volume, &s->sample_spec))
+ s->reference_volume = *volume;
+ else
+ pa_cvolume_scale(&s->reference_volume, pa_cvolume_max(volume));
if (s->flags & PA_SINK_FLAT_VOLUME) {
/* OK, propagate this volume change back to the inputs */
diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c
index 24535157..b9d69505 100644
--- a/src/pulsecore/socket-client.c
+++ b/src/pulsecore/socket-client.c
@@ -73,14 +73,18 @@
struct pa_socket_client {
PA_REFCNT_DECLARE;
- pa_mainloop_api *mainloop;
int fd;
+
+ pa_mainloop_api *mainloop;
pa_io_event *io_event;
pa_time_event *timeout_event;
pa_defer_event *defer_event;
+
pa_socket_client_cb_t callback;
void *userdata;
+
pa_bool_t local;
+
#ifdef HAVE_LIBASYNCNS
asyncns_t *asyncns;
asyncns_query_t * asyncns_query;
@@ -92,22 +96,10 @@ static pa_socket_client* socket_client_new(pa_mainloop_api *m) {
pa_socket_client *c;
pa_assert(m);
- c = pa_xnew(pa_socket_client, 1);
+ c = pa_xnew0(pa_socket_client, 1);
PA_REFCNT_INIT(c);
c->mainloop = m;
c->fd = -1;
- c->io_event = NULL;
- c->timeout_event = NULL;
- c->defer_event = NULL;
- c->callback = NULL;
- c->userdata = NULL;
- c->local = FALSE;
-
-#ifdef HAVE_LIBASYNCNS
- c->asyncns = NULL;
- c->asyncns_io_event = NULL;
- c->asyncns_query = NULL;
-#endif
return c;
}
@@ -163,7 +155,6 @@ static void do_call(pa_socket_client *c) {
}
io = pa_iochannel_new(c->mainloop, c->fd, c->fd);
- pa_assert(io);
finish:
if (!io && c->fd >= 0)
@@ -172,7 +163,6 @@ finish:
free_events(c);
- pa_assert(c->callback);
c->callback(c, io, c->userdata);
pa_socket_client_unref(c);
@@ -202,8 +192,6 @@ static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event
}
static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t len) {
- int r;
-
pa_assert(c);
pa_assert(PA_REFCNT_VALUE(c) >= 1);
pa_assert(sa);
@@ -211,7 +199,7 @@ static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t
pa_make_fd_nonblock(c->fd);
- if ((r = connect(c->fd, sa, len)) < 0) {
+ if (connect(c->fd, sa, len) < 0) {
#ifdef OS_IS_WIN32
if (WSAGetLastError() != EWOULDBLOCK) {
pa_log_debug("connect(): %d", WSAGetLastError());
@@ -222,9 +210,9 @@ static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t
return -1;
}
- pa_assert_se(c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c));
+ c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c);
} else
- pa_assert_se(c->defer_event = c->mainloop->defer_new(c->mainloop, connect_defer_cb, c));
+ c->defer_event = c->mainloop->defer_new(c->mainloop, connect_defer_cb, c);
return 0;
}
@@ -235,7 +223,7 @@ pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address
pa_assert(m);
pa_assert(port > 0);
- memset(&sa, 0, sizeof(sa));
+ pa_zero(sa);
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
sa.sin_addr.s_addr = htonl(address);
@@ -243,28 +231,24 @@ pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address
return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
}
-#ifdef HAVE_SYS_UN_H
pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
+#ifdef HAVE_SYS_UN_H
struct sockaddr_un sa;
pa_assert(m);
pa_assert(filename);
- memset(&sa, 0, sizeof(sa));
+ pa_zero(sa);
sa.sun_family = AF_UNIX;
pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
-}
-
#else /* HAVE_SYS_UN_H */
-pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
return NULL;
-}
-
#endif /* HAVE_SYS_UN_H */
+}
static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size_t salen) {
pa_assert(c);
@@ -302,7 +286,7 @@ pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct
pa_assert(sa);
pa_assert(salen > 0);
- pa_assert_se(c = socket_client_new(m));
+ c = socket_client_new(m);
if (sockaddr_prepare(c, sa, salen) < 0)
goto fail;
@@ -359,22 +343,25 @@ void pa_socket_client_set_callback(pa_socket_client *c, pa_socket_client_cb_t on
c->userdata = userdata;
}
-#ifdef HAVE_IPV6
pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) {
+#ifdef HAVE_IPV6
struct sockaddr_in6 sa;
pa_assert(m);
pa_assert(address);
pa_assert(port > 0);
- memset(&sa, 0, sizeof(sa));
+ pa_zero(sa);
sa.sin6_family = AF_INET6;
sa.sin6_port = htons(port);
memcpy(&sa.sin6_addr, address, sizeof(sa.sin6_addr));
return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
-}
+
+#else
+ return NULL;
#endif
+}
#ifdef HAVE_LIBASYNCNS
@@ -468,14 +455,13 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_
case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */
case PA_PARSED_ADDRESS_TCP6: /* Fallthrough */
- case PA_PARSED_ADDRESS_TCP_AUTO:{
-
+ case PA_PARSED_ADDRESS_TCP_AUTO: {
struct addrinfo hints;
char port[12];
pa_snprintf(port, sizeof(port), "%u", (unsigned) a.port);
- memset(&hints, 0, sizeof(hints));
+ pa_zero(hints);
if (a.type == PA_PARSED_ADDRESS_TCP4)
hints.ai_family = PF_INET;
#ifdef HAVE_IPV6
@@ -494,11 +480,10 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_
if (!(asyncns = asyncns_new(1)))
goto finish;
- pa_assert_se(c = socket_client_new(m));
+ c = socket_client_new(m);
c->asyncns = asyncns;
c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c);
- c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints);
- pa_assert(c->asyncns_query);
+ pa_assert_se(c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints));
start_timeout(c, use_rtclock);
}
#elif defined(HAVE_GETADDRINFO)
@@ -541,6 +526,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_
if (!host)
goto finish;
+ pa_zero(sa);
s.sin_family = AF_INET;
memcpy(&s.sin_addr, host->h_addr, sizeof(struct in_addr));
s.sin_port = htons(a.port);
diff --git a/src/pulsecore/socket-client.h b/src/pulsecore/socket-client.h
index b896afa9..138f658c 100644
--- a/src/pulsecore/socket-client.h
+++ b/src/pulsecore/socket-client.h
@@ -35,9 +35,7 @@ typedef struct pa_socket_client pa_socket_client;
typedef void (*pa_socket_client_cb_t)(pa_socket_client *c, pa_iochannel*io, void *userdata);
pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port);
-#ifdef HAVE_IPV6
pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port);
-#endif
pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename);
pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen);
pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_rtclock, const char *a, uint16_t default_port);
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 1509807b..57ccc067 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -107,6 +107,7 @@ int pa_source_output_new(
pa_resampler *resampler = NULL;
char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
int r;
+ char *pt;
pa_assert(_o);
pa_assert(core);
@@ -247,12 +248,15 @@ int pa_source_output_new(
if (o->direct_on_input)
pa_assert_se(pa_idxset_put(o->direct_on_input->direct_outputs, o, NULL) == 0);
- pa_log_info("Created output %u \"%s\" on %s with sample spec %s and channel map %s",
+ pt = pa_proplist_to_string_sep(o->proplist, "\n ");
+ pa_log_info("Created output %u \"%s\" on %s with sample spec %s and channel map %s\n %s",
o->index,
pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_MEDIA_NAME)),
o->source->name,
pa_sample_spec_snprint(st, sizeof(st), &o->sample_spec),
- pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map));
+ pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map),
+ pt);
+ pa_xfree(pt);
/* Don't forget to call pa_source_output_put! */
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 1c77e0b9..415c54bc 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -760,15 +760,22 @@ void pa_source_set_volume(
pa_bool_t save) {
pa_bool_t real_changed;
+ pa_cvolume old_volume;
pa_source_assert_ref(s);
pa_assert_ctl_context();
pa_assert(PA_SOURCE_IS_LINKED(s->state));
pa_assert(pa_cvolume_valid(volume));
- pa_assert(pa_cvolume_compatible(volume, &s->sample_spec));
+ pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &s->sample_spec));
- real_changed = !pa_cvolume_equal(volume, &s->volume);
- s->volume = *volume;
+ old_volume = s->volume;
+
+ if (pa_cvolume_compatible(volume, &s->sample_spec))
+ s->volume = *volume;
+ else
+ pa_cvolume_scale(&s->volume, pa_cvolume_max(volume));
+
+ real_changed = !pa_cvolume_equal(&old_volume, &s->volume);
s->save_volume = (!real_changed && s->save_volume) || save;
if (s->set_volume) {
diff --git a/src/pulsecore/start-child.c b/src/pulsecore/start-child.c
index b3bce131..4a70aea1 100644
--- a/src/pulsecore/start-child.c
+++ b/src/pulsecore/start-child.c
@@ -86,6 +86,11 @@ int pa_start_child_for_read(const char *name, const char *argv1, pid_t *pid) {
pa_reset_sigs(-1);
pa_unblock_sigs(-1);
pa_reset_priority();
+ pa_unset_env_recorded();
+
+ /* Make sure our children are not influenced by the
+ * LD_BIND_NOW we set for ourselves. */
+ unsetenv("LD_BIND_NOW");
#ifdef PR_SET_PDEATHSIG
/* On Linux we can use PR_SET_PDEATHSIG to have the helper
diff --git a/src/pulsecore/svolume_mmx.c b/src/pulsecore/svolume_mmx.c
index 8510b0c4..1768eb50 100644
--- a/src/pulsecore/svolume_mmx.c
+++ b/src/pulsecore/svolume_mmx.c
@@ -57,14 +57,12 @@
" punpcklwd %%mm4, "#s" \n\t" /* .. | 0 | p0 | */ \
" pcmpgtw "#v", %%mm4 \n\t" /* .. | 0 | s(vl) | */ \
" pand "#s", %%mm4 \n\t" /* .. | 0 | (p0) | (vl >> 15) & p */ \
- " movq %%mm6, %%mm5 \n\t" /* .. | ffff | 0 | */ \
- " pand "#v", %%mm5 \n\t" /* .. | vh | 0 | */ \
- " por %%mm5, %%mm4 \n\t" /* .. | vh | (p0) | */ \
- " pmulhw "#s", "#v" \n\t" /* .. | 0 | vl*p0 | */ \
- " paddw %%mm4, "#v" \n\t" /* .. | vh | vl*p0 | vh + sign correct */ \
- " pslld $16, "#s" \n\t" /* .. | p0 | 0 | */ \
- " por %%mm7, "#s" \n\t" /* .. | p0 | 1 | */ \
- " pmaddwd "#s", "#v" \n\t" /* .. | p0 * v0 | */ \
+ " movq "#s", %%mm5 \n\t" \
+ " pmulhw "#v", "#s" \n\t" /* .. | 0 | vl*p0 | */ \
+ " paddw %%mm4, "#s" \n\t" /* .. | 0 | vl*p0 | + sign correct */ \
+ " psrld $16, "#v" \n\t" /* .. | 0 | vh | */ \
+ " pmaddwd %%mm5, "#v" \n\t" /* .. | p0 * vh | */ \
+ " paddd "#s", "#v" \n\t" /* .. | p0 * v0 | */ \
" packssdw "#v", "#v" \n\t" /* .. | p1*v1 | p0*v0 | */
/* approximately advances %3 = (%3 + a) % b. This function requires that
@@ -105,10 +103,6 @@ pa_volume_s16ne_mmx (int16_t *samples, int32_t *volumes, unsigned channels, unsi
__asm__ __volatile__ (
" xor %3, %3 \n\t"
" sar $1, %2 \n\t" /* length /= sizeof (int16_t) */
- " pcmpeqw %%mm6, %%mm6 \n\t" /* .. | ffff | ffff | */
- " pcmpeqw %%mm7, %%mm7 \n\t" /* .. | ffff | ffff | */
- " pslld $16, %%mm6 \n\t" /* .. | ffff | 0 | */
- " psrld $31, %%mm7 \n\t" /* .. | 0 | 1 | */
" test $1, %2 \n\t" /* check for odd samples */
" je 2f \n\t"
@@ -158,7 +152,7 @@ pa_volume_s16ne_mmx (int16_t *samples, int32_t *volumes, unsigned channels, unsi
" emms \n\t"
: "+r" (samples), "+r" (volumes), "+r" (length), "=D" ((pa_reg_x86)channel), "=&r" (temp)
- : "r" ((pa_reg_x86)channels)
+ : "X" ((pa_reg_x86)channels)
: "cc"
);
}
@@ -234,7 +228,7 @@ pa_volume_s16re_mmx (int16_t *samples, int32_t *volumes, unsigned channels, unsi
" emms \n\t"
: "+r" (samples), "+r" (volumes), "+r" (length), "=D" ((pa_reg_x86)channel), "=&r" (temp)
- : "r" ((pa_reg_x86)channels)
+ : "X" ((pa_reg_x86)channels)
: "cc"
);
}
@@ -301,13 +295,16 @@ static void run_test (void) {
void pa_volume_func_init_mmx (pa_cpu_x86_flag_t flags) {
#if defined (__i386__) || defined (__amd64__)
- pa_log_info("Initialising MMX optimized functions.");
#ifdef RUN_TEST
run_test ();
#endif
- pa_set_volume_func (PA_SAMPLE_S16NE, (pa_do_volume_func_t) pa_volume_s16ne_mmx);
- pa_set_volume_func (PA_SAMPLE_S16RE, (pa_do_volume_func_t) pa_volume_s16re_mmx);
+ if (flags & PA_CPU_X86_MMX) {
+ pa_log_info("Initialising MMX optimized functions.");
+
+ pa_set_volume_func (PA_SAMPLE_S16NE, (pa_do_volume_func_t) pa_volume_s16ne_mmx);
+ pa_set_volume_func (PA_SAMPLE_S16RE, (pa_do_volume_func_t) pa_volume_s16re_mmx);
+ }
#endif /* defined (__i386__) || defined (__amd64__) */
}
diff --git a/src/pulsecore/svolume_sse.c b/src/pulsecore/svolume_sse.c
index 54af4a57..ab9394fb 100644
--- a/src/pulsecore/svolume_sse.c
+++ b/src/pulsecore/svolume_sse.c
@@ -45,7 +45,7 @@
" movdqa "#s", %%xmm5 \n\t" \
" pmulhuw "#v", "#s" \n\t" /* .. | 0 | vl*p0 | */ \
" psubd %%xmm4, "#s" \n\t" /* .. | 0 | vl*p0 | + sign correct */ \
- " psrld $16, "#v" \n\t" /* .. | p0 | 0 | */ \
+ " psrld $16, "#v" \n\t" /* .. | 0 | vh | */ \
" pmaddwd %%xmm5, "#v" \n\t" /* .. | p0 * vh | */ \
" paddd "#s", "#v" \n\t" /* .. | p0 * v0 | */ \
" packssdw "#v", "#v" \n\t" /* .. | p1*v1 | p0*v0 | */
@@ -75,7 +75,7 @@
" por %%xmm5, "#s2" \n\t"
static void
-pa_volume_s16ne_sse (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
+pa_volume_s16ne_sse2 (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
{
pa_reg_x86 channel, temp;
@@ -149,13 +149,13 @@ pa_volume_s16ne_sse (int16_t *samples, int32_t *volumes, unsigned channels, unsi
"8: \n\t"
: "+r" (samples), "+r" (volumes), "+r" (length), "=D" (channel), "=&r" (temp)
- : "r" ((pa_reg_x86)channels)
+ : "X" ((pa_reg_x86)channels)
: "cc"
);
}
static void
-pa_volume_s16re_sse (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
+pa_volume_s16re_sse2 (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
{
pa_reg_x86 channel, temp;
@@ -237,7 +237,7 @@ pa_volume_s16re_sse (int16_t *samples, int32_t *volumes, unsigned channels, unsi
"8: \n\t"
: "+r" (samples), "+r" (volumes), "+r" (length), "=D" (channel), "=&r" (temp)
- : "r" ((pa_reg_x86)channels)
+ : "X" ((pa_reg_x86)channels)
: "cc"
);
}
@@ -302,13 +302,16 @@ static void run_test (void) {
void pa_volume_func_init_sse (pa_cpu_x86_flag_t flags) {
#if defined (__i386__) || defined (__amd64__)
- pa_log_info("Initialising SSE optimized functions.");
#ifdef RUN_TEST
run_test ();
#endif
- pa_set_volume_func (PA_SAMPLE_S16NE, (pa_do_volume_func_t) pa_volume_s16ne_sse);
- pa_set_volume_func (PA_SAMPLE_S16RE, (pa_do_volume_func_t) pa_volume_s16re_sse);
+ if (flags & PA_CPU_X86_SSE2) {
+ pa_log_info("Initialising SSE2 optimized functions.");
+
+ pa_set_volume_func (PA_SAMPLE_S16NE, (pa_do_volume_func_t) pa_volume_s16ne_sse2);
+ pa_set_volume_func (PA_SAMPLE_S16RE, (pa_do_volume_func_t) pa_volume_s16re_sse2);
+ }
#endif /* defined (__i386__) || defined (__amd64__) */
}
diff --git a/src/pulsecore/vector.h b/src/pulsecore/vector.h
index 924e3cb8..9de3b8cd 100644
--- a/src/pulsecore/vector.h
+++ b/src/pulsecore/vector.h
@@ -23,7 +23,8 @@
#include <inttypes.h>
/* First, define HAVE_VECTOR if we have the gcc vector extensions at all */
-#if defined(__SSE2__) || defined(__ALTIVEC__)
+#if defined(__SSE2__)
+ /* || defined(__ALTIVEC__)*/
#define HAVE_VECTOR
diff --git a/src/tests/stripnul.c b/src/tests/stripnul.c
index 1d8c4938..d677ad20 100644
--- a/src/tests/stripnul.c
+++ b/src/tests/stripnul.c
@@ -31,7 +31,7 @@
int main(int argc, char *argv[]) {
FILE *i, *o;
size_t granularity;
- pa_bool_t found;
+ pa_bool_t found = FALSE;
uint8_t *zero;
pa_assert_se(argc >= 2);
diff --git a/src/utils/pacat.c b/src/utils/pacat.c
index 9264a062..5f29ba39 100644
--- a/src/utils/pacat.c
+++ b/src/utils/pacat.c
@@ -406,7 +406,6 @@ static void context_state_callback(pa_context *c, void *userdata) {
break;
case PA_CONTEXT_READY: {
- int r;
pa_buffer_attr buffer_attr;
pa_assert(c);
@@ -431,25 +430,29 @@ static void context_state_callback(pa_context *c, void *userdata) {
pa_stream_set_event_callback(stream, stream_event_callback, NULL);
pa_stream_set_buffer_attr_callback(stream, stream_buffer_attr_callback, NULL);
+ pa_zero(buffer_attr);
+ buffer_attr.maxlength = (uint32_t) -1;
+ buffer_attr.prebuf = (uint32_t) -1;
+
if (latency > 0) {
- memset(&buffer_attr, 0, sizeof(buffer_attr));
- buffer_attr.tlength = (uint32_t) latency;
+ buffer_attr.fragsize = buffer_attr.tlength = (uint32_t) latency;
buffer_attr.minreq = (uint32_t) process_time;
- buffer_attr.maxlength = (uint32_t) -1;
- buffer_attr.prebuf = (uint32_t) -1;
- buffer_attr.fragsize = (uint32_t) latency;
flags |= PA_STREAM_ADJUST_LATENCY;
+ } else {
+ buffer_attr.tlength = (uint32_t) -1;
+ buffer_attr.minreq = (uint32_t) -1;
+ buffer_attr.fragsize = (uint32_t) -1;
}
if (mode == PLAYBACK) {
pa_cvolume cv;
- if ((r = pa_stream_connect_playback(stream, device, latency > 0 ? &buffer_attr : NULL, flags, volume_is_set ? pa_cvolume_set(&cv, sample_spec.channels, volume) : NULL, NULL)) < 0) {
+ if (pa_stream_connect_playback(stream, device, latency > 0 ? &buffer_attr : NULL, flags, volume_is_set ? pa_cvolume_set(&cv, sample_spec.channels, volume) : NULL, NULL) < 0) {
pa_log(_("pa_stream_connect_playback() failed: %s"), pa_strerror(pa_context_errno(c)));
goto fail;
}
} else {
- if ((r = pa_stream_connect_record(stream, device, latency > 0 ? &buffer_attr : NULL, flags)) < 0) {
+ if (pa_stream_connect_record(stream, device, latency > 0 ? &buffer_attr : NULL, flags) < 0) {
pa_log(_("pa_stream_connect_record() failed: %s"), pa_strerror(pa_context_errno(c)));
goto fail;
}
@@ -574,9 +577,10 @@ static void stream_update_timing_callback(pa_stream *s, int success, void *userd
return;
}
- pa_log(_("Time: %0.3f sec; Latency: %0.0f usec. \r"),
+ fprintf(stderr, _("Time: %0.3f sec; Latency: %0.0f usec."),
(float) usec / 1000000,
(float) l * (negative?-1.0f:1.0f));
+ fprintf(stderr, " \r");
}
/* Someone requested that the latency is shown */
@@ -768,7 +772,6 @@ int main(int argc, char *argv[]) {
case ARG_STREAM_NAME: {
char *t;
- t = pa_locale_to_utf8(optarg);
if (!(t = pa_locale_to_utf8(optarg)) ||
pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, t) < 0) {
diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index c8c3a437..141ab5b1 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -50,7 +50,6 @@ static pa_context *context = NULL;
static pa_mainloop_api *mainloop_api = NULL;
static char
- *device = NULL,
*sample_name = NULL,
*sink_name = NULL,
*source_name = NULL,
@@ -66,6 +65,8 @@ static uint32_t
static uint32_t module_index;
static pa_bool_t suspend;
+static pa_bool_t mute;
+static pa_volume_t volume;
static pa_proplist *proplist = NULL;
@@ -74,7 +75,6 @@ static pa_stream *sample_stream = NULL;
static pa_sample_spec sample_spec;
static pa_channel_map channel_map;
static size_t sample_length = 0;
-
static int actions = 1;
static pa_bool_t nl = FALSE;
@@ -95,7 +95,13 @@ static enum {
SUSPEND_SOURCE,
SET_CARD_PROFILE,
SET_SINK_PORT,
- SET_SOURCE_PORT
+ SET_SOURCE_PORT,
+ SET_SINK_VOLUME,
+ SET_SOURCE_VOLUME,
+ SET_SINK_INPUT_VOLUME,
+ SET_SINK_MUTE,
+ SET_SOURCE_MUTE,
+ SET_SINK_INPUT_MUTE
} action = NONE;
static void quit(int ret) {
@@ -109,6 +115,7 @@ static void context_drain_complete(pa_context *c, void *userdata) {
static void drain(void) {
pa_operation *o;
+
if (!(o = pa_context_drain(context, context_drain_complete, NULL)))
pa_context_disconnect(context);
else
@@ -123,9 +130,9 @@ static void complete_action(void) {
}
static void stat_callback(pa_context *c, const pa_stat_info *i, void *userdata) {
- char s[128];
+ char s[PA_BYTES_SNPRINT_MAX];
if (!i) {
- pa_log(_("Failed to get statistics: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get statistics: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
@@ -146,7 +153,7 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
if (!i) {
- pa_log(_("Failed to get server information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get server information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
@@ -195,7 +202,7 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get sink information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get sink information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
@@ -287,7 +294,7 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get source information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get source information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
@@ -365,7 +372,7 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get module information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get module information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
@@ -402,7 +409,7 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get client information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get client information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
@@ -437,7 +444,7 @@ static void get_card_info_callback(pa_context *c, const pa_card_info *i, int is_
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get card information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get card information: %s"), pa_strerror(pa_context_errno(c)));
complete_action();
return;
}
@@ -486,7 +493,7 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get sink input information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get sink input information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
@@ -544,7 +551,7 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get source output information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get source output information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
@@ -591,11 +598,11 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu
}
static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int is_last, void *userdata) {
- char t[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+ char t[PA_BYTES_SNPRINT_MAX], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get sample information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get sample information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
@@ -643,7 +650,7 @@ static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int
static void simple_callback(pa_context *c, int success, void *userdata) {
if (!success) {
- pa_log(_("Failure: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failure: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
@@ -653,7 +660,7 @@ static void simple_callback(pa_context *c, int success, void *userdata) {
static void index_callback(pa_context *c, uint32_t idx, void *userdata) {
if (idx == PA_INVALID_INDEX) {
- pa_log(_("Failure: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failure: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
@@ -677,7 +684,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) {
case PA_STREAM_FAILED:
default:
- pa_log(_("Failed to upload sample: %s\n"), pa_strerror(pa_context_errno(pa_stream_get_context(s))));
+ pa_log(_("Failed to upload sample: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s))));
quit(1);
}
}
@@ -694,7 +701,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) {
if ((sf_readf_float(sndfile, d, l)) != l) {
pa_xfree(d);
- pa_log(_("Premature end of file\n"));
+ pa_log(_("Premature end of file"));
quit(1);
return;
}
@@ -726,7 +733,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
break;
case PLAY_SAMPLE:
- pa_operation_unref(pa_context_play_sample(c, sample_name, device, PA_VOLUME_NORM, simple_callback, NULL));
+ pa_operation_unref(pa_context_play_sample(c, sample_name, sink_name, PA_VOLUME_NORM, simple_callback, NULL));
break;
case REMOVE_SAMPLE:
@@ -800,6 +807,42 @@ static void context_state_callback(pa_context *c, void *userdata) {
pa_operation_unref(pa_context_set_source_port_by_name(c, source_name, port_name, simple_callback, NULL));
break;
+ case SET_SINK_MUTE:
+ pa_operation_unref(pa_context_set_sink_mute_by_name(c, sink_name, mute, simple_callback, NULL));
+ break;
+
+ case SET_SOURCE_MUTE:
+ pa_operation_unref(pa_context_set_source_mute_by_name(c, source_name, mute, simple_callback, NULL));
+ break;
+
+ case SET_SINK_INPUT_MUTE:
+ pa_operation_unref(pa_context_set_sink_input_mute(c, sink_input_idx, mute, simple_callback, NULL));
+ break;
+
+ case SET_SINK_VOLUME: {
+ pa_cvolume v;
+
+ pa_cvolume_set(&v, 1, volume);
+ pa_operation_unref(pa_context_set_sink_volume_by_name(c, sink_name, &v, simple_callback, NULL));
+ break;
+ }
+
+ case SET_SOURCE_VOLUME: {
+ pa_cvolume v;
+
+ pa_cvolume_set(&v, 1, volume);
+ pa_operation_unref(pa_context_set_source_volume_by_name(c, source_name, &v, simple_callback, NULL));
+ break;
+ }
+
+ case SET_SINK_INPUT_VOLUME: {
+ pa_cvolume v;
+
+ pa_cvolume_set(&v, 1, volume);
+ pa_operation_unref(pa_context_set_sink_input_volume(c, sink_input_idx, &v, simple_callback, NULL));
+ break;
+ }
+
default:
pa_assert_not_reached();
}
@@ -811,13 +854,13 @@ static void context_state_callback(pa_context *c, void *userdata) {
case PA_CONTEXT_FAILED:
default:
- pa_log(_("Connection failure: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Connection failure: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
}
}
static void exit_signal_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) {
- pa_log(_("Got SIGINT, exiting.\n"));
+ pa_log(_("Got SIGINT, exiting."));
quit(0);
}
@@ -829,20 +872,30 @@ static void help(const char *argv0) {
"%s [options] upload-sample FILENAME [NAME]\n"
"%s [options] play-sample NAME [SINK]\n"
"%s [options] remove-sample NAME\n"
- "%s [options] move-sink-input ID SINK\n"
- "%s [options] move-source-output ID SOURCE\n"
+ "%s [options] move-sink-input SINKINPUT SINK\n"
+ "%s [options] move-source-output SOURCEOUTPUT SOURCE\n"
"%s [options] load-module NAME [ARGS ...]\n"
- "%s [options] unload-module ID\n"
- "%s [options] suspend-sink [SINK] 1|0\n"
- "%s [options] suspend-source [SOURCE] 1|0\n"
- "%s [options] set-card-profile [CARD] [PROFILE] \n"
- "%s [options] set-sink-port [SINK] [PORT] \n"
- "%s [options] set-source-port [SOURCE] [PORT] \n\n"
+ "%s [options] unload-module MODULE\n"
+ "%s [options] suspend-sink SINK 1|0\n"
+ "%s [options] suspend-source SOURCE 1|0\n"
+ "%s [options] set-card-profile CARD PROFILE\n"
+ "%s [options] set-sink-port SINK PORT\n"
+ "%s [options] set-source-port SOURCE PORT\n"
+ "%s [options] set-sink-volume SINK VOLUME\n"
+ "%s [options] set-source-volume SOURCE VOLUME\n"
+ "%s [options] set-sink-input-volume SINKINPUT VOLUME\n"
+ "%s [options] set-sink-mute SINK 1|0\n"
+ "%s [options] set-source-mute SOURCE 1|0\n"
+ "%s [options] set-sink-input-mute SINKINPUT 1|0\n\n"
" -h, --help Show this help\n"
" --version Show version\n\n"
" -s, --server=SERVER The name of the server to connect to\n"
" -n, --client-name=NAME How to call this client on the server\n"),
- argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0);
+ argv0, argv0, argv0, argv0, argv0,
+ argv0, argv0, argv0, argv0, argv0,
+ argv0, argv0, argv0, argv0, argv0,
+ argv0, argv0, argv0, argv0, argv0,
+ argv0);
}
enum {
@@ -897,7 +950,7 @@ int main(int argc, char *argv[]) {
if (!(t = pa_locale_to_utf8(optarg)) ||
pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t) < 0) {
- pa_log(_("Invalid client name '%s'\n"), t ? t : optarg);
+ pa_log(_("Invalid client name '%s'"), t ? t : optarg);
pa_xfree(t);
goto quit;
}
@@ -923,7 +976,7 @@ int main(int argc, char *argv[]) {
action = UPLOAD_SAMPLE;
if (optind+1 >= argc) {
- pa_log(_("Please specify a sample file to load\n"));
+ pa_log(_("Please specify a sample file to load"));
goto quit;
}
@@ -936,19 +989,19 @@ int main(int argc, char *argv[]) {
pa_zero(sfi);
if (!(sndfile = sf_open(argv[optind+1], SFM_READ, &sfi))) {
- pa_log(_("Failed to open sound file.\n"));
+ pa_log(_("Failed to open sound file."));
goto quit;
}
if (pa_sndfile_read_sample_spec(sndfile, &sample_spec) < 0) {
- pa_log(_("Failed to determine sample specification from file.\n"));
+ pa_log(_("Failed to determine sample specification from file."));
goto quit;
}
sample_spec.format = PA_SAMPLE_FLOAT32;
if (pa_sndfile_read_channel_map(sndfile, &channel_map) < 0) {
if (sample_spec.channels > 2)
- pa_log(_("Warning: Failed to determine sample specification from file.\n"));
+ pa_log(_("Warning: Failed to determine sample specification from file."));
pa_channel_map_init_extend(&channel_map, sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
}
@@ -958,19 +1011,19 @@ int main(int argc, char *argv[]) {
} else if (pa_streq(argv[optind], "play-sample")) {
action = PLAY_SAMPLE;
if (argc != optind+2 && argc != optind+3) {
- pa_log(_("You have to specify a sample name to play\n"));
+ pa_log(_("You have to specify a sample name to play"));
goto quit;
}
sample_name = pa_xstrdup(argv[optind+1]);
if (optind+2 < argc)
- device = pa_xstrdup(argv[optind+2]);
+ sink_name = pa_xstrdup(argv[optind+2]);
} else if (pa_streq(argv[optind], "remove-sample")) {
action = REMOVE_SAMPLE;
if (argc != optind+2) {
- pa_log(_("You have to specify a sample name to remove\n"));
+ pa_log(_("You have to specify a sample name to remove"));
goto quit;
}
@@ -979,7 +1032,7 @@ int main(int argc, char *argv[]) {
} else if (pa_streq(argv[optind], "move-sink-input")) {
action = MOVE_SINK_INPUT;
if (argc != optind+3) {
- pa_log(_("You have to specify a sink input index and a sink\n"));
+ pa_log(_("You have to specify a sink input index and a sink"));
goto quit;
}
@@ -989,7 +1042,7 @@ int main(int argc, char *argv[]) {
} else if (pa_streq(argv[optind], "move-source-output")) {
action = MOVE_SOURCE_OUTPUT;
if (argc != optind+3) {
- pa_log(_("You have to specify a source output index and a source\n"));
+ pa_log(_("You have to specify a source output index and a source"));
goto quit;
}
@@ -1004,7 +1057,7 @@ int main(int argc, char *argv[]) {
action = LOAD_MODULE;
if (argc <= optind+1) {
- pa_log(_("You have to specify a module name and arguments.\n"));
+ pa_log(_("You have to specify a module name and arguments."));
goto quit;
}
@@ -1024,7 +1077,7 @@ int main(int argc, char *argv[]) {
action = UNLOAD_MODULE;
if (argc != optind+2) {
- pa_log(_("You have to specify a module index\n"));
+ pa_log(_("You have to specify a module index"));
goto quit;
}
@@ -1034,7 +1087,7 @@ int main(int argc, char *argv[]) {
action = SUSPEND_SINK;
if (argc > optind+3 || optind+1 >= argc) {
- pa_log(_("You may not specify more than one sink. You have to specify a boolean value.\n"));
+ pa_log(_("You may not specify more than one sink. You have to specify a boolean value."));
goto quit;
}
@@ -1047,7 +1100,7 @@ int main(int argc, char *argv[]) {
action = SUSPEND_SOURCE;
if (argc > optind+3 || optind+1 >= argc) {
- pa_log(_("You may not specify more than one source. You have to specify a boolean value.\n"));
+ pa_log(_("You may not specify more than one source. You have to specify a boolean value."));
goto quit;
}
@@ -1059,7 +1112,7 @@ int main(int argc, char *argv[]) {
action = SET_CARD_PROFILE;
if (argc != optind+3) {
- pa_log(_("You have to specify a card name/index and a profile name\n"));
+ pa_log(_("You have to specify a card name/index and a profile name"));
goto quit;
}
@@ -1070,7 +1123,7 @@ int main(int argc, char *argv[]) {
action = SET_SINK_PORT;
if (argc != optind+3) {
- pa_log(_("You have to specify a sink name/index and a port name\n"));
+ pa_log(_("You have to specify a sink name/index and a port name"));
goto quit;
}
@@ -1081,13 +1134,123 @@ int main(int argc, char *argv[]) {
action = SET_SOURCE_PORT;
if (argc != optind+3) {
- pa_log(_("You have to specify a source name/index and a port name\n"));
+ pa_log(_("You have to specify a source name/index and a port name"));
goto quit;
}
source_name = pa_xstrdup(argv[optind+1]);
port_name = pa_xstrdup(argv[optind+2]);
+ } else if (pa_streq(argv[optind], "set-sink-volume")) {
+ uint32_t v;
+ action = SET_SINK_VOLUME;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a sink name/index and a volume"));
+ goto quit;
+ }
+
+ if (pa_atou(argv[optind+2], &v) < 0) {
+ pa_log(_("Invalid volume specification"));
+ goto quit;
+ }
+
+ sink_name = pa_xstrdup(argv[optind+1]);
+ volume = (pa_volume_t) v;
+
+ } else if (pa_streq(argv[optind], "set-source-volume")) {
+ uint32_t v;
+ action = SET_SOURCE_VOLUME;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a source name/index and a volume"));
+ goto quit;
+ }
+
+ if (pa_atou(argv[optind+2], &v) < 0) {
+ pa_log(_("Invalid volume specification"));
+ goto quit;
+ }
+
+ source_name = pa_xstrdup(argv[optind+1]);
+ volume = (pa_volume_t) v;
+
+ } else if (pa_streq(argv[optind], "set-sink-input-volume")) {
+ uint32_t v;
+ action = SET_SINK_INPUT_VOLUME;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a sink input index and a volume"));
+ goto quit;
+ }
+
+ if (pa_atou(argv[optind+1], &sink_input_idx) < 0) {
+ pa_log(_("Invalid sink input index"));
+ goto quit;
+ }
+
+ if (pa_atou(argv[optind+2], &v) < 0) {
+ pa_log(_("Invalid volume specification"));
+ goto quit;
+ }
+
+ volume = (pa_volume_t) v;
+
+ } else if (pa_streq(argv[optind], "set-sink-mute")) {
+ int b;
+ action = SET_SINK_MUTE;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a sink name/index and a mute boolean"));
+ goto quit;
+ }
+
+ if ((b = pa_parse_boolean(argv[optind+2])) < 0) {
+ pa_log(_("Invalid volume specification"));
+ goto quit;
+ }
+
+ sink_name = pa_xstrdup(argv[optind+1]);
+ mute = b;
+
+ } else if (pa_streq(argv[optind], "set-source-mute")) {
+ int b;
+ action = SET_SOURCE_MUTE;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a source name/index and a mute boolean"));
+ goto quit;
+ }
+
+ if ((b = pa_parse_boolean(argv[optind+2])) < 0) {
+ pa_log(_("Invalid volume specification"));
+ goto quit;
+ }
+
+ source_name = pa_xstrdup(argv[optind+1]);
+ mute = b;
+
+ } else if (pa_streq(argv[optind], "set-sink-input-mute")) {
+ int b;
+ action = SET_SINK_INPUT_MUTE;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a sink input index and a mute boolean"));
+ goto quit;
+ }
+
+ if (pa_atou(argv[optind+1], &sink_input_idx) < 0) {
+ pa_log(_("Invalid sink input index specification"));
+ goto quit;
+ }
+
+ if ((b = pa_parse_boolean(argv[optind+2])) < 0) {
+ pa_log(_("Invalid volume specification"));
+ goto quit;
+ }
+
+ mute = b;
+
} else if (pa_streq(argv[optind], "help")) {
help(bn);
ret = 0;
@@ -1096,12 +1259,12 @@ int main(int argc, char *argv[]) {
}
if (action == NONE) {
- pa_log(_("No valid command specified.\n"));
+ pa_log(_("No valid command specified."));
goto quit;
}
if (!(m = pa_mainloop_new())) {
- pa_log(_("pa_mainloop_new() failed.\n"));
+ pa_log(_("pa_mainloop_new() failed."));
goto quit;
}
@@ -1113,7 +1276,7 @@ int main(int argc, char *argv[]) {
pa_disable_sigpipe();
if (!(context = pa_context_new_with_proplist(mainloop_api, NULL, proplist))) {
- pa_log(_("pa_context_new() failed.\n"));
+ pa_log(_("pa_context_new() failed."));
goto quit;
}
@@ -1124,7 +1287,7 @@ int main(int argc, char *argv[]) {
}
if (pa_mainloop_run(m, &ret) < 0) {
- pa_log(_("pa_mainloop_run() failed.\n"));
+ pa_log(_("pa_mainloop_run() failed."));
goto quit;
}
@@ -1141,7 +1304,6 @@ quit:
}
pa_xfree(server);
- pa_xfree(device);
pa_xfree(sample_name);
pa_xfree(sink_name);
pa_xfree(source_name);
diff --git a/src/utils/padsp.c b/src/utils/padsp.c
index 882522c4..2ed0a039 100644
--- a/src/utils/padsp.c
+++ b/src/utils/padsp.c
@@ -1394,11 +1394,13 @@ static int sndstat_open(int flags, int *_errno) {
"Mixers:\n"
"0: PulseAudio Virtual OSS\n";
- char fn[] = "/tmp/padsp-sndstat-XXXXXX";
+ char *fn;
mode_t u;
int fd = -1;
int e;
+ fn = pa_sprintf_malloc("%s" PA_PATH_SEP "padsp-sndstat-XXXXXX", pa_get_temp_dir());
+
debug(DEBUG_LEVEL_NORMAL, __FILE__": sndstat_open()\n");
if (flags != O_RDONLY
@@ -1423,6 +1425,7 @@ static int sndstat_open(int flags, int *_errno) {
}
unlink(fn);
+ pa_xfree(fn);
if (write(fd, sndstat, sizeof(sndstat) -1) != sizeof(sndstat)-1) {
*_errno = errno;
@@ -1439,6 +1442,7 @@ static int sndstat_open(int flags, int *_errno) {
return fd;
fail:
+ pa_xfree(fn);
if (fd >= 0)
close(fd);
return -1;
@@ -1821,7 +1825,7 @@ fail:
pa_threaded_mainloop_unlock(i->mainloop);
- return 0;
+ return r;
}
static int dsp_trigger(fd_info *i) {
@@ -1864,7 +1868,7 @@ fail:
pa_threaded_mainloop_unlock(i->mainloop);
- return 0;
+ return r;
}
static int dsp_cork(fd_info *i, pa_stream *s, int b) {
@@ -1902,7 +1906,7 @@ fail:
pa_threaded_mainloop_unlock(i->mainloop);
- return 0;
+ return r;
}
static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) {