]> code.delx.au - pulseaudio/commitdiff
Merge remote branch 'tanuk/master'
authorColin Guthrie <cguthrie@mandriva.org>
Mon, 30 Nov 2009 14:55:57 +0000 (14:55 +0000)
committerColin Guthrie <cguthrie@mandriva.org>
Mon, 30 Nov 2009 14:55:57 +0000 (14:55 +0000)
102 files changed:
PROTOCOL
configure.ac
man/Makefile.am
src/.gitignore
src/Makefile.am
src/daemon/.gitignore
src/daemon/cpulimit.c
src/daemon/daemon-conf.c
src/daemon/main.c
src/map-file
src/modules/alsa/alsa-mixer.c
src/modules/alsa/alsa-sink.c
src/modules/alsa/alsa-source.c
src/modules/alsa/alsa-util.c
src/modules/alsa/alsa-util.h
src/modules/alsa/mixer/paths/analog-input.conf.common
src/modules/alsa/mixer/paths/analog-output-headphones-2.conf [new file with mode: 0644]
src/modules/alsa/mixer/paths/analog-output-headphones.conf
src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf
src/modules/alsa/mixer/paths/analog-output-mono.conf
src/modules/alsa/mixer/paths/analog-output-speaker.conf [new file with mode: 0644]
src/modules/alsa/mixer/paths/analog-output.conf
src/modules/alsa/mixer/paths/analog-output.conf.common
src/modules/alsa/mixer/profile-sets/default.conf
src/modules/bluetooth/bluetooth-util.c
src/modules/dbus/iface-card.c
src/modules/dbus/iface-client.c
src/modules/dbus/iface-core.c
src/modules/dbus/iface-device.c
src/modules/dbus/iface-module.c
src/modules/dbus/iface-sample.c
src/modules/dbus/iface-stream.c
src/modules/dbus/module-dbus-protocol.c
src/modules/jack/module-jack-sink.c
src/modules/jack/module-jack-source.c
src/modules/module-cli.c
src/modules/module-default-device-restore.c
src/modules/module-detect.c
src/modules/module-device-manager.c
src/modules/module-equalizer-sink.c [changed mode: 0755->0644]
src/modules/module-lirc.c
src/modules/module-match.c
src/modules/module-mmkbd-evdev.c
src/modules/module-pipe-sink.c
src/modules/module-pipe-source.c
src/modules/module-rygel-media-server.c
src/modules/module-solaris.c
src/modules/module-stream-restore.c
src/modules/module-udev-detect.c
src/modules/oss/oss-util.c
src/modules/rtp/module-rtp-recv.c
src/modules/rtp/module-rtp-send.c
src/pulse/client-conf.c
src/pulse/context.c
src/pulse/context.h
src/pulse/def.h
src/pulse/ext-device-manager.h
src/pulse/mainloop-signal.c
src/pulse/mainloop.c
src/pulse/stream.c
src/pulse/stream.h
src/pulse/util.c
src/pulse/volume.c
src/pulse/volume.h
src/pulsecore/atomic.h
src/pulsecore/authkey.c
src/pulsecore/cli-command.c
src/pulsecore/conf-parser.c
src/pulsecore/core-rtclock.c
src/pulsecore/core-util.c
src/pulsecore/core-util.h
src/pulsecore/cpu-arm.c
src/pulsecore/database-simple.c
src/pulsecore/database-tdb.c
src/pulsecore/envelope.c
src/pulsecore/envelope.h
src/pulsecore/fdsem.c
src/pulsecore/lock-autospawn.c
src/pulsecore/memblock.c
src/pulsecore/pid.c
src/pulsecore/protocol-dbus.c
src/pulsecore/protocol-native.c
src/pulsecore/random.c
src/pulsecore/sample-util.c
src/pulsecore/semaphore-osx.c [new file with mode: 0644]
src/pulsecore/sink-input.c
src/pulsecore/sink-input.h
src/pulsecore/sink.c
src/pulsecore/socket-client.c
src/pulsecore/socket-server.c
src/pulsecore/socket-util.c
src/pulsecore/sound-file-stream.c
src/pulsecore/sound-file.c
src/pulsecore/svolume_mmx.c
src/pulsecore/svolume_sse.c
src/pulsecore/time-smoother.c
src/pulsecore/x11prop.c
src/utils/pacat.c
src/utils/pacmd.c
src/utils/pactl.c
src/utils/pasuspender.c
src/utils/qpaeq [new file with mode: 0755]

index 92cc28323584f882e6b08bb0063d3396e59c1fba..883b8bb651898af319518d556261a14f9c04a0ca 100644 (file)
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -188,3 +188,9 @@ new messages:
 
   PA_COMMAND_SET_SINK_PORT
   PA_COMMAND_SET_SOURCE_PORT
+
+## v17, implemented by >= 0.9.20
+
+new flag at end of CREATE_PLAYBACK_STREAM:
+
+    bool relative_volume
index 77ec8846b841c2ed26cc54cfda1033c1f8bf9bc2..dfbd9bc0acc74ea68eb2d35742c31081a06d7ce9 100644 (file)
@@ -40,7 +40,7 @@ AC_SUBST(PA_MAJORMINORMICRO, pa_major.pa_minor.pa_micro)
 AC_SUBST(PACKAGE_URL, [http://pulseaudio.org/])
 
 AC_SUBST(PA_API_VERSION, 12)
-AC_SUBST(PA_PROTOCOL_VERSION, 16)
+AC_SUBST(PA_PROTOCOL_VERSION, 17)
 
 # The stable ABI for client applications, for the version info x:y:z
 # always will hold y=z
@@ -61,23 +61,12 @@ AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:4:0])
 AC_CANONICAL_HOST
 AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.])
 
-if type -p stow > /dev/null && test -d /usr/local/stow ; then
+AC_CHECK_PROG([STOW], [stow], [yes], [no])
+
+AS_IF([test "x$STOW" = "xyes" && test -d /usr/local/stow], [
    AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***])
    ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}"
-fi
-
-#### Platform hacks ####
-
-case $host in
-   *-*-solaris* )
-      AC_DEFINE(_XOPEN_SOURCE,        600, Needed to get declarations for msg_control and msg_controllen on Solaris)
-      AC_DEFINE(__EXTENSIONS__,         1, Needed to get declarations for msg_control and msg_controllen on Solaris)
-      ;;
-   *-*-darwin* )
-      AC_DEFINE([_POSIX_C_SOURCE], [200112L], [Needed to get clock_gettime on Mac OS X])
-      AC_DEFINE([_DARWIN_C_SOURCE], [200112L], [Needed to get NSIG on Mac OS X])
-      ;;
-esac
+])
 
 AM_SILENT_RULES([yes])
 
@@ -95,6 +84,19 @@ AM_PROG_CC_C_O
 AC_PROG_GCC_TRADITIONAL
 AC_USE_SYSTEM_EXTENSIONS
 
+#### Platform hacks ####
+
+case $host in
+   *-*-solaris* )
+      AC_DEFINE(_XOPEN_SOURCE,        600, Needed to get declarations for msg_control and msg_controllen on Solaris)
+      AC_DEFINE(__EXTENSIONS__,         1, Needed to get declarations for msg_control and msg_controllen on Solaris)
+      ;;
+   *-*-darwin* )
+      AC_DEFINE([_POSIX_C_SOURCE], [200112L], [Needed to get clock_gettime on Mac OS X])
+      AC_DEFINE([_DARWIN_C_SOURCE], [200112L], [Needed to get NSIG on Mac OS X])
+      ;;
+esac
+
 # M4
 
 AC_CHECK_PROGS([M4], gm4 m4, no)
@@ -164,27 +166,12 @@ AC_ARG_ENABLE([atomic-arm-memory-barrier],
             esac
         ],)
 
-AC_ARG_ENABLE([netbsd-atomic-ops],
-    AS_HELP_STRING([--enable-netbsd-atomic-ops],[Use the native NetBSD atomic_ops implementation]),
-        [
-            case "${enableval}" in
-                yes) atomic_netbsd_helpers=yes ;;
-                no) atomic_netbsd_helpers=no ;;
-                *) AC_MSG_ERROR(bad value ${enableval} for --enable-netbsd-atomic-ops) ;;
-            esac
-        ],
-        [atomic_netbsd_helpers=auto])
-
 AC_MSG_CHECKING([target operating system])
 case $host in
         *-*-linux*)
             AC_MSG_RESULT([linux])
             pulse_target_os=linux
         ;;
-        *-*-netbsd*)
-            AC_MSG_RESULT([netbsd])
-            pulse_target_os=netbsd
-        ;;
         *)
             AC_MSG_RESULT([unknown])
             pulse_target_os=unknown
@@ -208,7 +195,7 @@ if test "$pulseaudio_cv_sync_bool_compare_and_swap" = "yes" ; then
 else
     # HW specific atomic ops stuff
     AC_MSG_CHECKING([architecture for native atomic operations])
-    case $host_cpu in
+    case $host in
         arm*)
             AC_MSG_RESULT([arm])
             AC_MSG_CHECKING([whether we can use Linux kernel helpers])
@@ -244,14 +231,16 @@ else
                  ])
            fi
         ;;
+       *-netbsdelf5*)
+            AC_MSG_RESULT([yes])
+            need_libatomic_ops=no
+       ;;
+       *-freebsd*)
+            AC_MSG_RESULT([yes])
+            need_libatomic_ops=no
+       ;;
         *)
-            if test "x$pulse_target_os" = "xnetbsd" && test "x$atomic_netbsd_helpers" = "xyes"; then
-                AC_MSG_RESULT([yes])
-                AC_DEFINE_UNQUOTED(NETBSD_ATOMIC_OPS, 1, [netbsd implementation])
-                need_libatomic_ops=no
-            else
-                AC_MSG_RESULT([unknown])
-            fi
+            AC_MSG_RESULT([unknown])
         ;;
     esac
 fi
@@ -445,7 +434,7 @@ AC_CHECK_FUNCS_ONCE([lstat])
 
 # Non-standard
 
-AC_CHECK_FUNCS_ONCE([setresuid setresgid setreuid setregid seteuid setegid ppoll strsignal sig2str strtof_l])
+AC_CHECK_FUNCS_ONCE([setresuid setresgid setreuid setregid seteuid setegid ppoll strsignal sig2str strtof_l pipe2 accept4])
 
 AC_FUNC_ALLOCA
 
@@ -742,6 +731,28 @@ AC_SUBST(HAVE_OSS)
 AM_CONDITIONAL([HAVE_OSS_OUTPUT], [test "x$HAVE_OSS" = x1 && test "x${oss_output}" != "xno"])
 AM_CONDITIONAL([HAVE_OSS_WRAPPER], [test "x$HAVE_OSS" = x1 && test "x${oss_wrapper}" != "xno"])
 
+#### CoreAudio support (optional) ####
+
+AC_ARG_ENABLE([coreaudio-output],
+    AS_HELP_STRING([--disable-coreaudio-output],[Disable optional CoreAudio output support]),
+        [
+            case "${enableval}" in
+                yes) coreaudio_enabled=yes ;;
+                no) coreaudio_enabled=no ;;
+                *) AC_MSG_ERROR(bad value ${enableval} for --disable-coreaudio-output) ;;
+            esac
+        ],
+        [coreaudio_enabled=auto])
+
+if test "x${coreaudio_enabled}" != xno ; then
+    AC_CHECK_HEADERS([CoreAudio/CoreAudio.h], HAVE_COREAUDIO=1)
+else
+    HAVE_COREAUDIO=0
+fi
+
+AC_SUBST(HAVE_COREAUDIO)
+AM_CONDITIONAL([HAVE_COREAUDIO], [test "x$HAVE_COREAUDIO" = x1 && test "x${coreaudio_enabled}" != "xno"])
+
 #### ALSA support (optional) ####
 
 AC_ARG_ENABLE([alsa],
@@ -1423,6 +1434,11 @@ if test "x$HAVE_OSS" = "x1" ; then
    fi
 fi
 
+ENABLE_COREAUDIO=no
+if test "x$HAVE_COREAUDIO" = "x1" ; then
+   ENABLE_COREAUDIO=yes
+fi
+
 ENABLE_ALSA=no
 if test "x$HAVE_ALSA" = "x1" ; then
    ENABLE_ALSA=yes
@@ -1513,6 +1529,11 @@ if test "x${HAVE_SIMPLEDB}" = "x1" ; then
     ENABLE_SIMPLEDB=yes
 fi
 
+ENABLE_FFTW=no
+if test "x${HAVE_FFTW}" = "x1" ; then
+   ENABLE_FFTW=yes
+fi
+
 ENABLE_OPENSSL=no
 if test "x${HAVE_OPENSSL}" = "x1" ; then
    ENABLE_OPENSSL=yes
@@ -1543,6 +1564,7 @@ echo "
     Have X11:                      ${ENABLE_X11}
     Enable OSS Output:             ${ENABLE_OSS_OUTPUT}
     Enable OSS Wrapper:            ${ENABLE_OSS_WRAPPER}
+    Enable CoreAudio:              ${ENABLE_COREAUDIO}
     Enable Alsa:                   ${ENABLE_ALSA}
     Enable Solaris:                ${ENABLE_SOLARIS}
     Enable GLib 2.0:               ${ENABLE_GLIB20}
@@ -1563,6 +1585,7 @@ echo "
     Enable tdb:                    ${ENABLE_TDB}
     Enable gdbm:                   ${ENABLE_GDBM}
     Enable simple database:        ${ENABLE_SIMPLEDB}
+    Enable fftw:                   ${ENABLE_FFTW}
 
     System User:                   ${PA_SYSTEM_USER}
     System Group:                  ${PA_SYSTEM_GROUP}
index 9b229f52a8856a15d8470f75ac82baa9a6d9a3a1..7793fe7d4df14cbcc6bce56cfc3000c124bff871 100644 (file)
@@ -20,21 +20,6 @@ pulseconfdir=$(sysconfdir)/pulse
 CLEANFILES = \
        $(noinst_DATA)
 
-dist_man_MANS = \
-       pulseaudio.1 \
-       esdcompat.1 \
-       pax11publish.1 \
-       paplay.1 \
-       pacat.1 \
-       pacmd.1 \
-       pactl.1 \
-       pasuspender.1 \
-       padsp.1 \
-       pabrowse.1 \
-       pulse-daemon.conf.5 \
-       pulse-client.conf.5 \
-       default.pa.5
-
 noinst_DATA = \
        pulseaudio.1.xml \
        esdcompat.1.xml \
@@ -50,24 +35,39 @@ noinst_DATA = \
        pulse-client.conf.5.xml \
        default.pa.5.xml
 
-if BUILD_MANPAGES
-
-CLEANFILES += \
-       $(dist_man_MANS)
-
 %.xml: %.xml.in Makefile
        sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \
            -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \
             -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@
 
-%: %.xml Makefile
-       perl $(srcdir)/xmltoman $< > $@ || rm -f $@
-
 xmllint: $(noinst_DATA)
        for f in $(noinst_DATA) ; do \
                        xmllint --noout --valid "$$f" || exit 1 ; \
        done
 
+if BUILD_MANPAGES
+
+dist_man_MANS = \
+       pulseaudio.1 \
+       esdcompat.1 \
+       pax11publish.1 \
+       paplay.1 \
+       pacat.1 \
+       pacmd.1 \
+       pactl.1 \
+       pasuspender.1 \
+       padsp.1 \
+       pabrowse.1 \
+       pulse-daemon.conf.5 \
+       pulse-client.conf.5 \
+       default.pa.5
+
+CLEANFILES += \
+       $(dist_man_MANS)
+
+%: %.xml Makefile
+       perl $(srcdir)/xmltoman $< > $@ || rm -f $@
+
 endif
 
 EXTRA_DIST = \
index 6cd173c067777e4b87dc103c3a2ef5432848bb92..64ab29739ffa78a7445ebf9e609aacd707b75f43 100644 (file)
@@ -63,4 +63,5 @@ thread-test
 utf8-test
 voltest
 start-pulseaudio-x11
+start-pulseaudio-kde
 vector-test
index 98c04683157538efc047033f2c5b87d820276762..3be28692d4d8778cb71064e1022f4ecfd41249db 100644 (file)
@@ -125,26 +125,7 @@ EXTRA_DIST = \
                daemon/pulseaudio.desktop.in \
                daemon/pulseaudio-kde.desktop.in \
                map-file \
-               daemon/pulseaudio-system.conf \
-               modules/alsa/mixer/profile-sets/default.conf \
-               modules/alsa/mixer/profile-sets/native-instruments-audio4dj.conf \
-               modules/alsa/mixer/profile-sets/native-instruments-audio8dj.conf \
-               modules/alsa/mixer/profile-sets/90-pulseaudio.rules \
-               modules/alsa/mixer/paths/analog-input-aux.conf \
-               modules/alsa/mixer/paths/analog-input.conf \
-               modules/alsa/mixer/paths/analog-input.conf.common \
-               modules/alsa/mixer/paths/analog-input-fm.conf \
-               modules/alsa/mixer/paths/analog-input-linein.conf \
-               modules/alsa/mixer/paths/analog-input-mic.conf \
-               modules/alsa/mixer/paths/analog-input-mic.conf.common \
-               modules/alsa/mixer/paths/analog-input-mic-line.conf \
-               modules/alsa/mixer/paths/analog-input-tvtuner.conf \
-               modules/alsa/mixer/paths/analog-input-video.conf \
-               modules/alsa/mixer/paths/analog-output.conf \
-               modules/alsa/mixer/paths/analog-output.conf.common \
-               modules/alsa/mixer/paths/analog-output-headphones.conf \
-               modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf \
-               modules/alsa/mixer/paths/analog-output-mono.conf
+               daemon/pulseaudio-system.conf
 
 pulseconf_DATA = \
                default.pa \
@@ -1086,17 +1067,17 @@ modlibexec_LTLIBRARIES += \
                module-alsa-source.la \
                module-alsa-card.la
 
-alsaprofilesets_DATA = \
+dist_alsaprofilesets_DATA = \
                modules/alsa/mixer/profile-sets/default.conf \
                modules/alsa/mixer/profile-sets/native-instruments-audio4dj.conf \
                modules/alsa/mixer/profile-sets/native-instruments-audio8dj.conf
 
 if HAVE_UDEV
-udevrules_DATA = \
+dist_udevrules_DATA = \
                modules/alsa/mixer/profile-sets/90-pulseaudio.rules
 endif
 
-alsapaths_DATA = \
+dist_alsapaths_DATA = \
                modules/alsa/mixer/paths/analog-input-aux.conf \
                modules/alsa/mixer/paths/analog-input.conf \
                modules/alsa/mixer/paths/analog-input.conf.common \
@@ -1108,8 +1089,10 @@ alsapaths_DATA = \
                modules/alsa/mixer/paths/analog-input-tvtuner.conf \
                modules/alsa/mixer/paths/analog-input-video.conf \
                modules/alsa/mixer/paths/analog-output.conf \
+               modules/alsa/mixer/paths/analog-output-speaker.conf \
                modules/alsa/mixer/paths/analog-output.conf.common \
                modules/alsa/mixer/paths/analog-output-headphones.conf \
+               modules/alsa/mixer/paths/analog-output-headphones-2.conf \
                modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf \
                modules/alsa/mixer/paths/analog-output-mono.conf
 
@@ -1202,6 +1185,7 @@ endif
 if HAVE_FFTW
 modlibexec_LTLIBRARIES += \
                module-equalizer-sink.la
+bin_SCRIPTS += utils/qpaeq
 endif
 
 # These are generated by an M4 script
index 0efa55ba8e94c90c3e893d3e1e790285c639d96c..54e4299bbf023ac2f19944a5f0ee613a8c6e6a0e 100644 (file)
@@ -1,2 +1,3 @@
 org.pulseaudio.policy
 pulseaudio.desktop
+pulseaudio-kde.desktop
index c2877ecfb2a326256f71663d73e44ec0924ff00b..f5042a754ded24ac4237d8196354bf3e96bde0e4 100644 (file)
@@ -188,15 +188,13 @@ int pa_cpu_limit_init(pa_mainloop_api *m) {
     last_time = pa_rtclock_now();
 
     /* Prepare the main loop pipe */
-    if (pipe(the_pipe) < 0) {
+    if (pa_pipe_cloexec(the_pipe) < 0) {
         pa_log("pipe() failed: %s", pa_cstrerror(errno));
         return -1;
     }
 
     pa_make_fd_nonblock(the_pipe[0]);
     pa_make_fd_nonblock(the_pipe[1]);
-    pa_make_fd_cloexec(the_pipe[0]);
-    pa_make_fd_cloexec(the_pipe[1]);
 
     api = m;
     io_event = api->io_new(m, the_pipe[0], PA_IO_EVENT_INPUT, callback, NULL);
index 571faae450eee27f73085f3c355706d87e16a558..bfd5c118de91384b3acd9f8dd52f92ea5bca103f 100644 (file)
@@ -577,7 +577,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
     c->config_file = NULL;
 
     f = filename ?
-        fopen(c->config_file = pa_xstrdup(filename), "r") :
+        pa_fopen_cloexec(c->config_file = pa_xstrdup(filename), "r") :
         pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file);
 
     if (!f && errno != ENOENT) {
@@ -652,7 +652,7 @@ FILE *pa_daemon_conf_open_default_script_file(pa_daemon_conf *c) {
         else
             f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file);
     } else
-        f = fopen(c->default_script_file, "r");
+        f = pa_fopen_cloexec(c->default_script_file, "r");
 
     return f;
 }
index 9e5647a84a390329522b0d8f64d360ef616d90f9..e656836452c03f4d9f13eddd9ece0a29cddfb766 100644 (file)
@@ -425,21 +425,24 @@ int main(int argc, char *argv[]) {
 
         pa_set_env("LD_BIND_NOW", "1");
 
-        canonical_rp = pa_realpath(PA_BINARY);
+        if ((canonical_rp = pa_realpath(PA_BINARY))) {
 
-        if ((rp = pa_readlink("/proc/self/exe"))) {
+            if ((rp = pa_readlink("/proc/self/exe"))) {
 
-            if (pa_streq(rp, canonical_rp))
-                pa_assert_se(execv(rp, argv) == 0);
-            else
-                pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp);
+                if (pa_streq(rp, canonical_rp))
+                    pa_assert_se(execv(rp, argv) == 0);
+                else
+                    pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp);
 
-            pa_xfree(rp);
+                pa_xfree(rp);
 
-        } else
-            pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?");
+            } else
+                pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?");
+
+            pa_xfree(canonical_rp);
 
-        pa_xfree(canonical_rp);
+        } else
+            pa_log_warn("Couldn't canonicalize binary path, cannot self execute.");
     }
 #endif
 
@@ -534,6 +537,12 @@ int main(int argc, char *argv[]) {
             goto finish;
 
         case PA_CMD_DUMP_CONF: {
+
+            if (d < argc) {
+                pa_log("Too many arguments.\n");
+                goto finish;
+            }
+
             s = pa_daemon_conf_dump(conf);
             fputs(s, stdout);
             pa_xfree(s);
@@ -544,6 +553,11 @@ int main(int argc, char *argv[]) {
         case PA_CMD_DUMP_RESAMPLE_METHODS: {
             int i;
 
+            if (d < argc) {
+                pa_log("Too many arguments.\n");
+                goto finish;
+            }
+
             for (i = 0; i < PA_RESAMPLER_MAX; i++)
                 if (pa_resample_method_supported(i))
                     printf("%s\n", pa_resample_method_to_string(i));
@@ -558,6 +572,12 @@ int main(int argc, char *argv[]) {
             goto finish;
 
         case PA_CMD_VERSION :
+
+            if (d < argc) {
+                pa_log("Too many arguments.\n");
+                goto finish;
+            }
+
             printf(PACKAGE_NAME" "PACKAGE_VERSION"\n");
             retval = 0;
             goto finish;
@@ -565,6 +585,11 @@ int main(int argc, char *argv[]) {
         case PA_CMD_CHECK: {
             pid_t pid;
 
+            if (d < argc) {
+                pa_log("Too many arguments.\n");
+                goto finish;
+            }
+
             if (pa_pid_file_check_running(&pid, "pulseaudio") < 0)
                 pa_log_info(_("Daemon not running"));
             else {
@@ -577,6 +602,11 @@ int main(int argc, char *argv[]) {
         }
         case PA_CMD_KILL:
 
+            if (d < argc) {
+                pa_log("Too many arguments.\n");
+                goto finish;
+            }
+
             if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0)
                 pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno));
             else
@@ -586,6 +616,11 @@ int main(int argc, char *argv[]) {
 
         case PA_CMD_CLEANUP_SHM:
 
+            if (d < argc) {
+                pa_log("Too many arguments.\n");
+                goto finish;
+            }
+
             if (pa_shm_cleanup() >= 0)
                 retval = 0;
 
@@ -595,6 +630,11 @@ int main(int argc, char *argv[]) {
             pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START);
     }
 
+    if (d < argc) {
+        pa_log("Too many arguments.\n");
+        goto finish;
+    }
+
     if (getuid() == 0 && !conf->system_instance)
         pa_log_warn(_("This program is not intended to be run as root (unless --system is specified)."));
 #ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */
@@ -645,7 +685,6 @@ int main(int argc, char *argv[]) {
 
     if (conf->daemonize) {
         pid_t child;
-        int tty_fd;
 
         if (pa_stdio_acquire() < 0) {
             pa_log(_("Failed to acquire stdio."));
@@ -654,7 +693,7 @@ int main(int argc, char *argv[]) {
 
 #ifdef HAVE_FORK
         if (pipe(daemon_pipe) < 0) {
-            pa_log(_("pipe failed: %s"), pa_cstrerror(errno));
+            pa_log(_("pipe() failed: %s"), pa_cstrerror(errno));
             goto finish;
         }
 
@@ -705,22 +744,27 @@ int main(int argc, char *argv[]) {
             pa_log_set_target(PA_LOG_SYSLOG);
 
 #ifdef HAVE_SETSID
-        setsid();
-#endif
-#ifdef HAVE_SETPGID
-        setpgid(0,0);
+        if (setsid() < 0) {
+            pa_log(_("setsid() failed: %s"), pa_cstrerror(errno));
+            goto finish;
+        }
 #endif
 
-#ifndef OS_IS_WIN32
-        pa_close(0);
-        pa_close(1);
-        pa_close(2);
+        /* We now are a session and process group leader. Let's fork
+         * again and let the father die, so that we'll become a
+         * process that can never acquire a TTY again, in a session and
+         * process group without leader */
 
-        pa_assert_se(open("/dev/null", O_RDONLY) == 0);
-        pa_assert_se(open("/dev/null", O_WRONLY) == 1);
-        pa_assert_se(open("/dev/null", O_WRONLY) == 2);
-#else
-        FreeConsole();
+#ifdef HAVE_FORK
+        if ((child = fork()) < 0) {
+            pa_log(_("fork() failed: %s"), pa_cstrerror(errno));
+            goto finish;
+        }
+
+        if (child != 0) {
+            retval = 0;
+            goto finish;
+        }
 #endif
 
 #ifdef SIGTTOU
@@ -733,12 +777,7 @@ int main(int argc, char *argv[]) {
         signal(SIGTSTP, SIG_IGN);
 #endif
 
-#ifdef TIOCNOTTY
-        if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
-            ioctl(tty_fd, TIOCNOTTY, (char*) 0);
-            pa_assert_se(pa_close(tty_fd) == 0);
-        }
-#endif
+        pa_nullify_stdfds();
     }
 
     pa_set_env_and_record("PULSE_INTERNAL", "1");
@@ -778,6 +817,8 @@ int main(int argc, char *argv[]) {
 
     pa_log_debug(_("Running in valgrind mode: %s"), pa_yes_no(pa_in_valgrind()));
 
+    pa_log_debug(_("Running in VM: %s"), pa_yes_no(pa_running_in_vm()));
+
 #ifdef __OPTIMIZE__
     pa_log_debug(_("Optimized build: yes"));
 #else
index 6f7bdace6079da94f51abcd90c6821aa3aad2026..1fffaff986982d33cc314e2683455cd30e80c6c9 100644 (file)
@@ -66,6 +66,7 @@ pa_context_get_source_info_list;
 pa_context_get_source_output_info;
 pa_context_get_source_output_info_list;
 pa_context_get_state;
+pa_context_get_tile_size;
 pa_context_is_local;
 pa_context_is_pending;
 pa_context_kill_client;
@@ -129,6 +130,7 @@ pa_cvolume_get_balance;
 pa_cvolume_get_fade;
 pa_cvolume_get_position;
 pa_cvolume_inc;
+pa_cvolume_inc_clamp;
 pa_cvolume_init;
 pa_cvolume_max;
 pa_cvolume_max_mask;
index f3ce681f55124ed9d253f730272ec73f0564be4c..8b13239ca566e016d630c8e8008161cddd0185bc 100644 (file)
@@ -1712,7 +1712,9 @@ static int option_verify(pa_alsa_option *o) {
         { "input-boost-on",            N_("Boost") },
         { "input-boost-off",           N_("No Boost") },
         { "output-amplifier-on",       N_("Amplifier") },
-        { "output-amplifier-off",      N_("No Amplifier") }
+        { "output-amplifier-off",      N_("No Amplifier") },
+        { "output-speaker",            N_("Speaker") },
+        { "output-headphones",         N_("Headphones") }
     };
 
     pa_assert(o);
@@ -1770,15 +1772,17 @@ static int element_verify(pa_alsa_element *e) {
 
 static int path_verify(pa_alsa_path *p) {
     static const struct description_map well_known_descriptions[] = {
-        { "analog-input",              N_("Analog Input") },
-        { "analog-input-microphone",   N_("Analog Microphone") },
-        { "analog-input-linein",       N_("Analog Line-In") },
-        { "analog-input-radio",        N_("Analog Radio") },
-        { "analog-input-video",        N_("Analog Video") },
-        { "analog-output",             N_("Analog Output") },
-        { "analog-output-headphones",  N_("Analog Headphones") },
-        { "analog-output-lfe-on-mono", N_("Analog Output (LFE)") },
-        { "analog-output-mono",        N_("Analog Mono Output") }
+        { "analog-input",               N_("Analog Input") },
+        { "analog-input-microphone",    N_("Analog Microphone") },
+        { "analog-input-linein",        N_("Analog Line-In") },
+        { "analog-input-radio",         N_("Analog Radio") },
+        { "analog-input-video",         N_("Analog Video") },
+        { "analog-output",              N_("Analog Output") },
+        { "analog-output-headphones",   N_("Analog Headphones") },
+        { "analog-output-lfe-on-mono",  N_("Analog Output (LFE)") },
+        { "analog-output-mono",         N_("Analog Mono Output") },
+        { "analog-output-headphones-2", N_("Analog Headphones 2") },
+        { "analog-output-speaker",      N_("Analog Speaker") }
     };
 
     pa_alsa_element *e;
index 37419d98c426f21d7cb2860b66667e7495ff2351..ed16c8348e4e281ffdb6ce92856e4761c4e97df9 100644 (file)
@@ -983,7 +983,7 @@ static int unsuspend(struct userdata *u) {
         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));
+                    (unsigned long) (buffer_size*u->frame_size), (unsigned long) (period_size*u->frame_size));
         goto fail;
     }
 
@@ -1698,10 +1698,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
         goto fail;
     }
 
-    if (use_tsched && !pa_rtclock_hrtimer()) {
-        pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
-        use_tsched = FALSE;
-    }
+    use_tsched = pa_alsa_may_tsched(use_tsched);
 
     u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
index 37dd64765bbed33cd5f2d0a6651a24dd3f6ef720..157698e3d007d52650d6f4d2dc8caa708a2b7e95 100644 (file)
@@ -930,7 +930,7 @@ static int unsuspend(struct userdata *u) {
         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));
+                    (unsigned long) (buffer_size*u->frame_size), (unsigned long) (period_size*u->frame_size));
         goto fail;
     }
 
@@ -1541,10 +1541,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
         goto fail;
     }
 
-    if (use_tsched && !pa_rtclock_hrtimer()) {
-        pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
-        use_tsched = FALSE;
-    }
+    use_tsched = pa_alsa_may_tsched(use_tsched);
 
     u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
index 0e22d17e467aaca47d8f004940a3a5461717204d..52f12599e9122895b220896e89d74bd8475f3cb7 100644 (file)
@@ -43,6 +43,7 @@
 #include <pulsecore/once.h>
 #include <pulsecore/thread.h>
 #include <pulsecore/conf-parser.h>
+#include <pulsecore/core-rtclock.h>
 
 #include "alsa-util.h"
 #include "alsa-mixer.h"
@@ -258,6 +259,10 @@ int pa_alsa_set_hw_params(
         goto finish;
     }
 
+    /* We ignore very small sampling rate deviations */
+    if (_ss.rate >= ss->rate*.95 && _ss.rate <= ss->rate*1.05)
+        _ss.rate = ss->rate;
+
     if (require_exact_channel_number) {
         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));
@@ -302,7 +307,7 @@ int pa_alsa_set_hw_params(
             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.");
+                pa_log_debug("Set buffer size first (to %lu samples), period size second (to %lu samples).", (unsigned long) _buffer_size, (unsigned long) _period_size);
                 goto success;
             }
 
@@ -310,7 +315,7 @@ int pa_alsa_set_hw_params(
             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.");
+                pa_log_debug("Set period size first (to %lu samples), buffer size second (to %lu samples).", (unsigned long) _period_size, (unsigned long) _buffer_size);
                 goto success;
             }
         }
@@ -321,7 +326,7 @@ int pa_alsa_set_hw_params(
             /* 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.");
+                pa_log_debug("Set only buffer size (to %lu samples).", (unsigned long) _buffer_size);
                 goto success;
             }
         }
@@ -332,7 +337,7 @@ int pa_alsa_set_hw_params(
             /* 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.");
+                pa_log_debug("Set only period size (to %lu samples).", (unsigned long) _period_size);
                 goto success;
             }
         }
@@ -373,9 +378,7 @@ success:
         goto finish;
     }
 
-    /* If the sample rate deviates too much, we need to resample */
-    if (_ss.rate < ss->rate*.95 || _ss.rate > ss->rate*1.05)
-        ss->rate = _ss.rate;
+    ss->rate = _ss.rate;
     ss->channels = _ss.channels;
     ss->format = _ss.format;
 
@@ -1308,3 +1311,26 @@ const char* pa_alsa_strerror(int errnum) {
 
     return translated;
 }
+
+pa_bool_t pa_alsa_may_tsched(pa_bool_t want) {
+
+    if (!want)
+        return FALSE;
+
+    if (!pa_rtclock_hrtimer()) {
+        /* We cannot depend on being woken up in time when the timers
+        are inaccurate, so let's fallback to classic IO based playback
+        then. */
+        pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
+        return FALSE; }
+
+    if (pa_running_in_vm()) {
+        /* We cannot depend on being woken up when we ask for in a VM,
+         * so let's fallback to classic IO based playback then. */
+        pa_log_notice("Disabling timer-based scheduling because running inside a VM.");
+        return FALSE;
+    }
+
+
+    return TRUE;
+}
index f6206fe23631a71e43fe76320ccbf5df46a792a0..1d1256bd38dfde7b71b5452bb95cbf9b7316ca4b 100644 (file)
@@ -142,4 +142,6 @@ pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm);
 
 const char* pa_alsa_strerror(int errnum);
 
+pa_bool_t pa_alsa_may_tsched(pa_bool_t want);
+
 #endif
index 87af38b3ed57a93c118c0268eb451ee0ba6fdfb2..951e11fa86a84b5373f420d18ae9cd4a761e9a82 100644 (file)
@@ -98,7 +98,11 @@ priority = 18
 name = input-docking
 priority = 17
 
-;;; ' Capture Source'
+[Option Input Source:AUX IN]
+name = input
+priority = 10
+
+;;; 'Capture Source'
 
 [Element Capture Source]
 enumeration = select
@@ -244,6 +248,31 @@ name = input-docking
 [Option Capture Source:Dock Mic]
 name = input-docking-microphone
 
+;;; 'Mic Jack Mode'
+
+[Element Mic Jack Mode]
+enumeration = select
+
+[Option Mic Jack Mode:Mic In]
+name = input-microphone
+
+[Option Mic Jack Mode:Line In]
+name = input-linein
+
+;;; 'Digital Input Source'
+
+[Element Digital Input Source]
+enumeration = select
+
+[Option Digital Input Source:Analog Inputs]
+name = input
+
+[Option Digital Input Source:Digital Mic 1]
+name = input-microphone
+
+[Option Digital Input Source:Digital Mic 2]
+name = input-microphone
+
 ;;; Various Boosts
 
 [Element Capture Boost]
diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf b/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
new file mode 100644 (file)
index 0000000..f2fd31c
--- /dev/null
@@ -0,0 +1,82 @@
+# 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
+# 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.
+
+; Path for mixers that have a 'Headphone2' control
+;
+; See analog-output.conf.common for an explanation on the directives
+
+[General]
+priority = 89
+
+[Element Hardware Master]
+switch = mute
+volume = merge
+override-map.1 = all
+override-map.2 = all-left,all-right
+
+[Element Master]
+switch = mute
+volume = merge
+override-map.1 = all
+override-map.2 = all-left,all-right
+
+[Element Master Mono]
+switch = off
+volume = off
+
+; This profile path is intended to control the second headphones, not
+; the first headphones. But it should not hurt if we leave the
+; headphone jack enabled nonetheless.
+[Element Headphone]
+switch = mute
+volume = zero
+
+[Element Headphone2]
+required = any
+switch = mute
+volume = merge
+override-map.1 = all
+override-map.2 = all-left,all-right
+
+[Element Speaker]
+switch = off
+volume = off
+
+[Element Front]
+switch = off
+volume = off
+
+[Element Rear]
+switch = off
+volume = off
+
+[Element Surround]
+switch = off
+volume = off
+
+[Element Side]
+switch = off
+volume = off
+
+[Element Center]
+switch = off
+volume = off
+
+[Element LFE]
+switch = off
+volume = off
+
+.include analog-output.conf.common
index 61d2e297406a4b86116f4451322c537a14fcb51d..2131cfe81e2f9a6481fff71ac2023d9cf98229d8 100644 (file)
@@ -44,6 +44,13 @@ volume = merge
 override-map.1 = all
 override-map.2 = all-left,all-right
 
+; This profile path is intended to control the first headphones, not
+; the second headphones. But it should not hurt if we leave the second
+; headphone jack enabled nonetheless.
+[Element Headphone2]
+switch = mute
+volume = zero
+
 [Element Speaker]
 switch = off
 volume = off
index 911361d7cd2d4b749db9172b6bcd158da3b3295c..0a43e2715fbac6d4fd043634f0a57cba37be9a89 100644 (file)
@@ -48,6 +48,10 @@ override-map.2 = lfe,lfe
 switch = mute
 volume = zero
 
+[Element Headphone2]
+switch = mute
+volume = zero
+
 [Element Speaker]
 switch = mute
 volume = merge
index 2fbc60b74f38de1cefbdd0441b2647f00c14a4f1..542edc401d177e00a7c743917514f407aa7441e5 100644 (file)
@@ -45,6 +45,10 @@ override-map.2 = all-left,all-right
 switch = mute
 volume = zero
 
+[Element Headphone2]
+switch = mute
+volume = zero
+
 [Element Speaker]
 switch = mute
 volume = merge
diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker.conf b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
new file mode 100644 (file)
index 0000000..aea7853
--- /dev/null
@@ -0,0 +1,94 @@
+# 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
+# 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.
+
+; Path for mixers that have a 'Speaker' control
+;
+; See analog-output.conf.common for an explanation on the directives
+
+[General]
+priority = 100
+
+[Element Hardware Master]
+switch = mute
+volume = merge
+override-map.1 = all
+override-map.2 = all-left,all-right
+
+[Element Master]
+switch = mute
+volume = merge
+override-map.1 = all
+override-map.2 = all-left,all-right
+
+[Element Master Mono]
+switch = off
+volume = off
+
+; This profile path is intended to control the speaker, not the
+; headphones. But it should not hurt if we leave the headphone jack
+; enabled nonetheless.
+[Element Headphone]
+switch = mute
+volume = zero
+
+[Element Headphone2]
+switch = mute
+volume = zero
+
+[Element Speaker]
+required = any
+switch = mute
+volume = merge
+override-map.1 = all
+override-map.2 = all-left,all-right
+
+[Element Front]
+switch = mute
+volume = merge
+override-map.1 = all-front
+override-map.2 = front-left,front-right
+
+[Element Rear]
+switch = mute
+volume = merge
+override-map.1 = all-rear
+override-map.2 = rear-left,rear-right
+
+[Element Surround]
+switch = mute
+volume = merge
+override-map.1 = all-rear
+override-map.2 = rear-left,rear-right
+
+[Element Side]
+switch = mute
+volume = merge
+override-map.1 = all-side
+override-map.2 = side-left,side-right
+
+[Element Center]
+switch = mute
+volume = merge
+override-map.1 = all-center
+override-map.2 = all-center,all-center
+
+[Element LFE]
+switch = mute
+volume = merge
+override-map.1 = lfe
+override-map.2 = lfe,lfe
+
+.include analog-output.conf.common
index f71a05a1d199a832bc295d9ea92babbd6e477d36..d7c1223b9a16e6b9b8dfb081de01b92fd772fc24 100644 (file)
 # along with PulseAudio; if not, write to the Free Software Foundation,
 # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 
-; Intended for the 'default' output
+; Intended for the 'default' output. Note that a-o-speaker.conf has a
+; higher priority than this
 ;
 ; See analog-output.conf.common for an explanation on the directives
 
 [General]
-priority = 100
+priority = 99
 
 [Element Hardware Master]
 switch = mute
@@ -37,18 +38,20 @@ override-map.2 = all-left,all-right
 switch = off
 volume = off
 
-; This profile path is intended to control the speaker, not the
+; This profile path is intended to control the default output, not the
 ; headphones. But it should not hurt if we leave the headphone jack
 ; enabled nonetheless.
 [Element Headphone]
 switch = mute
 volume = zero
 
+[Element Headphone2]
+switch = mute
+volume = zero
+
 [Element Speaker]
 switch = mute
-volume = merge
-override-map.1 = all
-override-map.2 = all-left,all-right
+volume = off
 
 [Element Front]
 switch = mute
index 3c6ce80366fde0b74a2a56efe4bef4d50d7b1305..fd7f0cfb1c759b19cfd2daf7ecdf7b7392a4621d 100644 (file)
@@ -109,3 +109,20 @@ priority = 10
 [Option External Amplifier:off]
 name = output-amplifier-off
 priority = 0
+
+;;; 'Analog Output'
+
+[Element Analog Output]
+enumeration = select
+
+[Option Analog Output:Speakers]
+name = output-speaker
+priority = 10
+
+[Option Analog Output:Headphones]
+name = output-headphones
+priority = 9
+
+[Option Analog Output:FP Headphones]
+name = output-headphones
+priority = 8
index ac41a8d3eedbfcd0c6df827008300f4e46f96347..046938fcab021a9160c4765862ab9404e3e02ef0 100644 (file)
@@ -62,42 +62,42 @@ auto-profiles = yes
 [Mapping analog-mono]
 device-strings = hw:%f
 channel-map = mono
-paths-output = analog-output analog-output-headphones analog-output-mono analog-output-lfe-on-mono
+paths-output = analog-output analog-output-speaker analog-output-headphones analog-output-headphones-2 analog-output-mono analog-output-lfe-on-mono
 paths-input = analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line
 priority = 1
 
 [Mapping analog-stereo]
 device-strings = front:%f hw:%f
 channel-map = left,right
-paths-output = analog-output analog-output-headphones analog-output-mono analog-output-lfe-on-mono
+paths-output = analog-output analog-output-speaker analog-output-headphones analog-output-headphones-2 analog-output-mono analog-output-lfe-on-mono
 paths-input = analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line
 priority = 10
 
 [Mapping analog-surround-40]
 device-strings = surround40:%f
 channel-map = front-left,front-right,rear-left,rear-right
-paths-output = analog-output analog-output-lfe-on-mono
+paths-output = analog-output analog-output-speaker analog-output-lfe-on-mono
 priority = 7
 direction = output
 
 [Mapping analog-surround-41]
 device-strings = surround41:%f
 channel-map = front-left,front-right,rear-left,rear-right,lfe
-paths-output = analog-output analog-output-lfe-on-mono
+paths-output = analog-output analog-output-speaker analog-output-lfe-on-mono
 priority = 8
 direction = output
 
 [Mapping analog-surround-50]
 device-strings = surround50:%f
 channel-map = front-left,front-right,rear-left,rear-right,front-center
-paths-output = analog-output analog-output-lfe-on-mono
+paths-output = analog-output analog-output-speaker analog-output-lfe-on-mono
 priority = 7
 direction = output
 
 [Mapping analog-surround-51]
 device-strings = surround51:%f
 channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe
-paths-output = analog-output analog-output-lfe-on-mono
+paths-output = analog-output analog-output-speaker analog-output-lfe-on-mono
 priority = 8
 direction = output
 
@@ -105,7 +105,7 @@ direction = output
 device-strings = surround71:%f
 channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right
 description = Analog Surround 7.1
-paths-output = analog-output analog-output-lfe-on-mono
+paths-output = analog-output analog-output-speaker analog-output-lfe-on-mono
 priority = 7
 direction = output
 
index f8c5b778201231cc75ad37db6af30a6ead272339..47d6200575c399558f4b4d8c1effde00a5208d61 100644 (file)
@@ -723,12 +723,14 @@ const pa_bluetooth_device* pa_bluetooth_discovery_get_by_address(pa_bluetooth_di
 
     while ((d = pa_hashmap_iterate(y->devices, &state, NULL)))
         if (pa_streq(d->address, address))
-            return d;
+            return device_is_audio(d) ? d : NULL;
 
     return NULL;
 }
 
 const pa_bluetooth_device* pa_bluetooth_discovery_get_by_path(pa_bluetooth_discovery *y, const char* path) {
+    pa_bluetooth_device *d;
+
     pa_assert(y);
     pa_assert(PA_REFCNT_VALUE(y) > 0);
     pa_assert(path);
@@ -736,7 +738,11 @@ const pa_bluetooth_device* pa_bluetooth_discovery_get_by_path(pa_bluetooth_disco
     if (!pa_hook_is_firing(&y->hook))
         pa_bluetooth_discovery_sync(y);
 
-    return pa_hashmap_get(y->devices, path);
+    if ((d = pa_hashmap_get(y->devices, path)))
+        if (device_is_audio(d))
+            return d;
+
+    return NULL;
 }
 
 static int setup_dbus(pa_bluetooth_discovery *y) {
index 1714df365a35abe40a33430464b31b44cc359828..d99c8b95b286c6a6c100d15c615858c8931420c7 100644 (file)
@@ -452,7 +452,7 @@ static void handle_get_profile_by_name(DBusConnection *conn, DBusMessage *msg, v
 
 static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
     pa_dbusiface_card *c = userdata;
-    DBusMessage *signal = NULL;
+    DBusMessage *signal_msg = NULL;
 
     pa_assert(core);
     pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_CARD);
@@ -472,14 +472,14 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
         c->active_profile = c->card->active_profile;
         object_path = pa_dbusiface_card_profile_get_path(pa_hashmap_get(c->profiles, c->active_profile->name));
 
-        pa_assert_se(signal = dbus_message_new_signal(c->path,
-                                                      PA_DBUSIFACE_CARD_INTERFACE,
-                                                      signals[SIGNAL_ACTIVE_PROFILE_UPDATED].name));
-        pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+        pa_assert_se(signal_msg = dbus_message_new_signal(c->path,
+                                                         PA_DBUSIFACE_CARD_INTERFACE,
+                                                         signals[SIGNAL_ACTIVE_PROFILE_UPDATED].name));
+        pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
-        pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 
     if (!pa_proplist_equal(c->proplist, c->card->proplist)) {
@@ -487,15 +487,15 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
         pa_proplist_update(c->proplist, PA_UPDATE_SET, c->card->proplist);
 
-        pa_assert_se(signal = dbus_message_new_signal(c->path,
-                                                      PA_DBUSIFACE_CARD_INTERFACE,
-                                                      signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
-        dbus_message_iter_init_append(signal, &msg_iter);
+        pa_assert_se(signal_msg = dbus_message_new_signal(c->path,
+                                                         PA_DBUSIFACE_CARD_INTERFACE,
+                                                         signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
+        dbus_message_iter_init_append(signal_msg, &msg_iter);
         pa_dbus_append_proplist(&msg_iter, c->proplist);
 
-        pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 }
 
index 2b6f0d0d17d88f8a06c4a3768cfd7b214bf59b0c..e6675449d96c7a8802e6956b2cd782c843f9e87c 100644 (file)
@@ -391,7 +391,7 @@ static void handle_remove_properties(DBusConnection *conn, DBusMessage *msg, voi
 
 static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
     pa_dbusiface_client *c = userdata;
-    DBusMessage *signal = NULL;
+    DBusMessage *signal_msg = NULL;
 
     pa_assert(core);
     pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_CLIENT);
@@ -410,15 +410,15 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
         pa_proplist_update(c->proplist, PA_UPDATE_SET, c->client->proplist);
 
-        pa_assert_se(signal = dbus_message_new_signal(c->path,
-                                                      PA_DBUSIFACE_CLIENT_INTERFACE,
-                                                      signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
-        dbus_message_iter_init_append(signal, &msg_iter);
+        pa_assert_se(signal_msg = dbus_message_new_signal(c->path,
+                                                         PA_DBUSIFACE_CLIENT_INTERFACE,
+                                                         signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
+        dbus_message_iter_init_append(signal_msg, &msg_iter);
         pa_dbus_append_proplist(&msg_iter, c->proplist);
 
-        pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 }
 
index 169e8e553210e80ca044faea701edf37315d00f4..497b59b5f2abd8fbaf490536995592bebef0f298 100644 (file)
@@ -1488,7 +1488,7 @@ static void handle_exit(DBusConnection *conn, DBusMessage *msg, void *userdata)
 
 static void handle_listen_for_signal(DBusConnection *conn, DBusMessage *msg, void *userdata) {
     pa_dbusiface_core *c = userdata;
-    const char *signal;
+    const char *signal_str;
     char **objects = NULL;
     int n_objects;
 
@@ -1497,11 +1497,11 @@ static void handle_listen_for_signal(DBusConnection *conn, DBusMessage *msg, voi
     pa_assert(c);
 
     pa_assert_se(dbus_message_get_args(msg, NULL,
-                                       DBUS_TYPE_STRING, &signal,
+                                       DBUS_TYPE_STRING, &signal_str,
                                        DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &objects, &n_objects,
                                        DBUS_TYPE_INVALID));
 
-    pa_dbus_protocol_add_signal_listener(c->dbus_protocol, conn, *signal ? signal : NULL, objects, n_objects);
+    pa_dbus_protocol_add_signal_listener(c->dbus_protocol, conn, *signal_str ? signal_str : NULL, objects, n_objects);
 
     pa_dbus_send_empty_reply(conn, msg);
 
@@ -1510,15 +1510,15 @@ static void handle_listen_for_signal(DBusConnection *conn, DBusMessage *msg, voi
 
 static void handle_stop_listening_for_signal(DBusConnection *conn, DBusMessage *msg, void *userdata) {
     pa_dbusiface_core *c = userdata;
-    const char *signal;
+    const char *signal_str;
 
     pa_assert(conn);
     pa_assert(msg);
     pa_assert(c);
 
-    pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &signal, DBUS_TYPE_INVALID));
+    pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &signal_str, DBUS_TYPE_INVALID));
 
-    pa_dbus_protocol_remove_signal_listener(c->dbus_protocol, conn, *signal ? signal : NULL);
+    pa_dbus_protocol_remove_signal_listener(c->dbus_protocol, conn, *signal_str ? signal_str : NULL);
 
     pa_dbus_send_empty_reply(conn, msg);
 }
@@ -1531,7 +1531,7 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
     pa_dbusiface_sample *sample_iface = NULL;
     pa_dbusiface_module *module_iface = NULL;
     pa_dbusiface_client *client_iface = NULL;
-    DBusMessage *signal = NULL;
+    DBusMessage *signal_msg = NULL;
     const char *object_path = NULL;
     pa_sink *new_fallback_sink = NULL;
     pa_source *new_fallback_source = NULL;
@@ -1552,21 +1552,21 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
                     && (device_iface = pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(new_fallback_sink->index)))) {
                     object_path = pa_dbusiface_device_get_path(device_iface);
 
-                    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                                   PA_DBUS_CORE_INTERFACE,
-                                                                   signals[SIGNAL_FALLBACK_SINK_UPDATED].name)));
-                    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
-                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-                    dbus_message_unref(signal);
-                    signal = NULL;
+                    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                      PA_DBUS_CORE_INTERFACE,
+                                                                      signals[SIGNAL_FALLBACK_SINK_UPDATED].name)));
+                    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+                    dbus_message_unref(signal_msg);
+                    signal_msg = NULL;
 
                 } else if (!new_fallback_sink) {
-                    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                                   PA_DBUS_CORE_INTERFACE,
-                                                                   signals[SIGNAL_FALLBACK_SINK_UNSET].name)));
-                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-                    dbus_message_unref(signal);
-                    signal = NULL;
+                    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                      PA_DBUS_CORE_INTERFACE,
+                                                                      signals[SIGNAL_FALLBACK_SINK_UNSET].name)));
+                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+                    dbus_message_unref(signal_msg);
+                    signal_msg = NULL;
                 }
             }
 
@@ -1579,21 +1579,21 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
                     && (device_iface = pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(new_fallback_source->index)))) {
                     object_path = pa_dbusiface_device_get_path(device_iface);
 
-                    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                                   PA_DBUS_CORE_INTERFACE,
-                                                                   signals[SIGNAL_FALLBACK_SOURCE_UPDATED].name)));
-                    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
-                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-                    dbus_message_unref(signal);
-                    signal = NULL;
+                    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                      PA_DBUS_CORE_INTERFACE,
+                                                                      signals[SIGNAL_FALLBACK_SOURCE_UPDATED].name)));
+                    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+                    dbus_message_unref(signal_msg);
+                    signal_msg = NULL;
 
                 } else if (!new_fallback_source) {
-                    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                                   PA_DBUS_CORE_INTERFACE,
-                                                                   signals[SIGNAL_FALLBACK_SOURCE_UNSET].name)));
-                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-                    dbus_message_unref(signal);
-                    signal = NULL;
+                    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                      PA_DBUS_CORE_INTERFACE,
+                                                                      signals[SIGNAL_FALLBACK_SOURCE_UNSET].name)));
+                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+                    dbus_message_unref(signal_msg);
+                    signal_msg = NULL;
                 }
             }
             break;
@@ -1612,10 +1612,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_card_get_path(card_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_NEW_CARD].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_NEW_CARD].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
             } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
                 if (!(card_iface = pa_hashmap_remove(c->cards, PA_UINT32_TO_PTR(idx))))
@@ -1623,10 +1623,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_card_get_path(card_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_CARD_REMOVED].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_CARD_REMOVED].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
                 pa_dbusiface_card_free(card_iface);
             }
@@ -1647,28 +1647,28 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_device_get_path(device_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_NEW_SINK].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_NEW_SINK].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
-                pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-                dbus_message_unref(signal);
-                signal = NULL;
+                pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+                dbus_message_unref(signal_msg);
+                signal_msg = NULL;
 
                 if (c->fallback_sink && pa_streq(c->fallback_sink->name, sink->name)) {
                     /* We have got default sink change event, but at that point
                      * the D-Bus sink object wasn't created yet. Now that the
                      * object is created, let's send the fallback sink change
                      * signal. */
-                    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                                   PA_DBUS_CORE_INTERFACE,
-                                                                   signals[SIGNAL_FALLBACK_SINK_UPDATED].name)));
-                    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
-
-                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-                    dbus_message_unref(signal);
-                    signal = NULL;
+                    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                      PA_DBUS_CORE_INTERFACE,
+                                                                      signals[SIGNAL_FALLBACK_SINK_UPDATED].name)));
+                    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+
+                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+                    dbus_message_unref(signal_msg);
+                    signal_msg = NULL;
                 }
 
             } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
@@ -1678,10 +1678,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
                 object_path = pa_dbusiface_device_get_path(device_iface);
                 pa_assert_se(pa_hashmap_remove(c->sinks_by_path, object_path));
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_SINK_REMOVED].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_SINK_REMOVED].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
                 pa_dbusiface_device_free(device_iface);
             }
@@ -1702,28 +1702,28 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_device_get_path(device_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_NEW_SOURCE].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_NEW_SOURCE].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
-                pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-                dbus_message_unref(signal);
-                signal = NULL;
+                pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+                dbus_message_unref(signal_msg);
+                signal_msg = NULL;
 
                 if (c->fallback_source && pa_streq(c->fallback_source->name, source->name)) {
                     /* We have got default source change event, but at that
                      * point the D-Bus source object wasn't created yet. Now
                      * that the object is created, let's send the fallback
                      * source change signal. */
-                    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                                   PA_DBUS_CORE_INTERFACE,
-                                                                   signals[SIGNAL_FALLBACK_SOURCE_UPDATED].name)));
-                    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
-
-                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-                    dbus_message_unref(signal);
-                    signal = NULL;
+                    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                      PA_DBUS_CORE_INTERFACE,
+                                                                      signals[SIGNAL_FALLBACK_SOURCE_UPDATED].name)));
+                    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+
+                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+                    dbus_message_unref(signal_msg);
+                    signal_msg = NULL;
                 }
 
             } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
@@ -1733,10 +1733,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
                 object_path = pa_dbusiface_device_get_path(device_iface);
                 pa_assert_se(pa_hashmap_remove(c->sources_by_path, object_path));
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_SOURCE_REMOVED].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_SOURCE_REMOVED].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
                 pa_dbusiface_device_free(device_iface);
             }
@@ -1756,10 +1756,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_stream_get_path(stream_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_NEW_PLAYBACK_STREAM].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_NEW_PLAYBACK_STREAM].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
             } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
                 if (!(stream_iface = pa_hashmap_remove(c->playback_streams, PA_UINT32_TO_PTR(idx))))
@@ -1767,10 +1767,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_stream_get_path(stream_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_PLAYBACK_STREAM_REMOVED].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_PLAYBACK_STREAM_REMOVED].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
                 pa_dbusiface_stream_free(stream_iface);
             }
@@ -1790,10 +1790,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_stream_get_path(stream_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_NEW_RECORD_STREAM].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_NEW_RECORD_STREAM].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
             } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
                 if (!(stream_iface = pa_hashmap_remove(c->record_streams, PA_UINT32_TO_PTR(idx))))
@@ -1801,10 +1801,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_stream_get_path(stream_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_RECORD_STREAM_REMOVED].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_RECORD_STREAM_REMOVED].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
                 pa_dbusiface_stream_free(stream_iface);
             }
@@ -1824,10 +1824,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_sample_get_path(sample_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_NEW_SAMPLE].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_NEW_SAMPLE].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
             } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
                 if (!(sample_iface = pa_hashmap_remove(c->samples, PA_UINT32_TO_PTR(idx))))
@@ -1835,10 +1835,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_sample_get_path(sample_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_SAMPLE_REMOVED].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_SAMPLE_REMOVED].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
                 pa_dbusiface_sample_free(sample_iface);
             }
@@ -1858,10 +1858,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_module_get_path(module_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_NEW_MODULE].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_NEW_MODULE].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
             } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
                 if (!(module_iface = pa_hashmap_remove(c->modules, PA_UINT32_TO_PTR(idx))))
@@ -1869,10 +1869,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_module_get_path(module_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_MODULE_REMOVED].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_MODULE_REMOVED].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
                 pa_dbusiface_module_free(module_iface);
             }
@@ -1892,10 +1892,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_client_get_path(client_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_NEW_CLIENT].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_NEW_CLIENT].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
             } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
                 if (!(client_iface = pa_hashmap_remove(c->clients, PA_UINT32_TO_PTR(idx))))
@@ -1903,37 +1903,37 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
                 object_path = pa_dbusiface_client_get_path(client_iface);
 
-                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                               PA_DBUS_CORE_INTERFACE,
-                                                               signals[SIGNAL_CLIENT_REMOVED].name)));
-                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                                  PA_DBUS_CORE_INTERFACE,
+                                                                  signals[SIGNAL_CLIENT_REMOVED].name)));
+                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
                 pa_dbusiface_client_free(client_iface);
             }
             break;
     }
 
-    if (signal) {
-        pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-        dbus_message_unref(signal);
+    if (signal_msg) {
+        pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
     }
 }
 
 static pa_hook_result_t extension_registered_cb(void *hook_data, void *call_data, void *slot_data) {
     pa_dbusiface_core *c = slot_data;
     const char *ext_name = call_data;
-    DBusMessage *signal = NULL;
+    DBusMessage *signal_msg = NULL;
 
     pa_assert(c);
     pa_assert(ext_name);
 
-    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                   PA_DBUS_CORE_INTERFACE,
-                                                   signals[SIGNAL_NEW_EXTENSION].name)));
-    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID));
+    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                      PA_DBUS_CORE_INTERFACE,
+                                                      signals[SIGNAL_NEW_EXTENSION].name)));
+    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID));
 
-    pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-    dbus_message_unref(signal);
+    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+    dbus_message_unref(signal_msg);
 
     return PA_HOOK_OK;
 }
@@ -1941,18 +1941,18 @@ static pa_hook_result_t extension_registered_cb(void *hook_data, void *call_data
 static pa_hook_result_t extension_unregistered_cb(void *hook_data, void *call_data, void *slot_data) {
     pa_dbusiface_core *c = slot_data;
     const char *ext_name = call_data;
-    DBusMessage *signal = NULL;
+    DBusMessage *signal_msg = NULL;
 
     pa_assert(c);
     pa_assert(ext_name);
 
-    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
-                                                   PA_DBUS_CORE_INTERFACE,
-                                                   signals[SIGNAL_EXTENSION_REMOVED].name)));
-    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID));
+    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
+                                                      PA_DBUS_CORE_INTERFACE,
+                                                      signals[SIGNAL_EXTENSION_REMOVED].name)));
+    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID));
 
-    pa_dbus_protocol_send_signal(c->dbus_protocol, signal);
-    dbus_message_unref(signal);
+    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
+    dbus_message_unref(signal_msg);
 
     return PA_HOOK_OK;
 }
index 3a747a4472e2ea3e9309b2d9f543d4940dfa666d..bb91d71f746293f36ca393e53c079d3d3bb5a5bd 100644 (file)
@@ -1063,7 +1063,7 @@ static void handle_source_get_all(DBusConnection *conn, DBusMessage *msg, void *
 
 static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
     pa_dbusiface_device *d = userdata;
-    DBusMessage *signal = NULL;
+    DBusMessage *signal_msg = NULL;
     const pa_cvolume *new_volume = NULL;
     pa_bool_t new_mute = FALSE;
     pa_sink_state_t new_sink_state = 0;
@@ -1099,16 +1099,16 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
         for (i = 0; i < d->volume.channels; ++i)
             volume[i] = d->volume.values[i];
 
-        pa_assert_se(signal = dbus_message_new_signal(d->path,
-                                                      PA_DBUSIFACE_DEVICE_INTERFACE,
-                                                      signals[SIGNAL_VOLUME_UPDATED].name));
-        pa_assert_se(dbus_message_append_args(signal,
+        pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
+                                                         PA_DBUSIFACE_DEVICE_INTERFACE,
+                                                         signals[SIGNAL_VOLUME_UPDATED].name));
+        pa_assert_se(dbus_message_append_args(signal_msg,
                                               DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, d->volume.channels,
                                               DBUS_TYPE_INVALID));
 
-        pa_dbus_protocol_send_signal(d->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 
     new_mute = (d->type == DEVICE_TYPE_SINK) ? pa_sink_get_mute(d->sink, FALSE) : pa_source_get_mute(d->source, FALSE);
@@ -1116,14 +1116,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
     if (d->mute != new_mute) {
         d->mute = new_mute;
 
-        pa_assert_se(signal = dbus_message_new_signal(d->path,
-                                                      PA_DBUSIFACE_DEVICE_INTERFACE,
-                                                      signals[SIGNAL_MUTE_UPDATED].name));
-        pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &d->mute, DBUS_TYPE_INVALID));
+        pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
+                                                         PA_DBUSIFACE_DEVICE_INTERFACE,
+                                                         signals[SIGNAL_MUTE_UPDATED].name));
+        pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &d->mute, DBUS_TYPE_INVALID));
 
-        pa_dbus_protocol_send_signal(d->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 
     if (d->type == DEVICE_TYPE_SINK)
@@ -1142,14 +1142,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
 
         state = (d->type == DEVICE_TYPE_SINK) ? d->sink_state : d->source_state;
 
-        pa_assert_se(signal = dbus_message_new_signal(d->path,
-                                                      PA_DBUSIFACE_DEVICE_INTERFACE,
-                                                      signals[SIGNAL_STATE_UPDATED].name));
-        pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID));
+        pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
+                                                         PA_DBUSIFACE_DEVICE_INTERFACE,
+                                                         signals[SIGNAL_STATE_UPDATED].name));
+        pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID));
 
-        pa_dbus_protocol_send_signal(d->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 
     new_active_port = (d->type == DEVICE_TYPE_SINK) ? d->sink->active_port : d->source->active_port;
@@ -1160,14 +1160,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
         d->active_port = new_active_port;
         object_path = pa_dbusiface_device_port_get_path(pa_hashmap_get(d->ports, d->active_port->name));
 
-        pa_assert_se(signal = dbus_message_new_signal(d->path,
-                                                      PA_DBUSIFACE_DEVICE_INTERFACE,
-                                                      signals[SIGNAL_ACTIVE_PORT_UPDATED].name));
-        pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+        pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
+                                                         PA_DBUSIFACE_DEVICE_INTERFACE,
+                                                         signals[SIGNAL_ACTIVE_PORT_UPDATED].name));
+        pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
-        pa_dbus_protocol_send_signal(d->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 
     new_proplist = (d->type == DEVICE_TYPE_SINK) ? d->sink->proplist : d->source->proplist;
@@ -1177,15 +1177,15 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
 
         pa_proplist_update(d->proplist, PA_UPDATE_SET, new_proplist);
 
-        pa_assert_se(signal = dbus_message_new_signal(d->path,
-                                                      PA_DBUSIFACE_DEVICE_INTERFACE,
-                                                      signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
-        dbus_message_iter_init_append(signal, &msg_iter);
+        pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
+                                                         PA_DBUSIFACE_DEVICE_INTERFACE,
+                                                         signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
+        dbus_message_iter_init_append(signal_msg, &msg_iter);
         pa_dbus_append_proplist(&msg_iter, d->proplist);
 
-        pa_dbus_protocol_send_signal(d->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 }
 
index e8aea50fcc415afe5f5e4bbbf815400003afcf4a..9973166c6058f9d12b28bc2b3a3d27306676629c 100644 (file)
@@ -268,7 +268,7 @@ static void handle_unload(DBusConnection *conn, DBusMessage *msg, void *userdata
 
 static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
     pa_dbusiface_module *m = userdata;
-    DBusMessage *signal = NULL;
+    DBusMessage *signal_msg = NULL;
 
     pa_assert(core);
     pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_MODULE);
@@ -287,15 +287,15 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3
 
         pa_proplist_update(m->proplist, PA_UPDATE_SET, m->module->proplist);
 
-        pa_assert_se(signal = dbus_message_new_signal(m->path,
-                                                      PA_DBUSIFACE_MODULE_INTERFACE,
-                                                      signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
-        dbus_message_iter_init_append(signal, &msg_iter);
+        pa_assert_se(signal_msg = dbus_message_new_signal(m->path,
+                                                         PA_DBUSIFACE_MODULE_INTERFACE,
+                                                         signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
+        dbus_message_iter_init_append(signal_msg, &msg_iter);
         pa_dbus_append_proplist(&msg_iter, m->proplist);
 
-        pa_dbus_protocol_send_signal(m->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(m->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 }
 
index b0542a609b20fb98ddf7984107f24602318176e0..c1fa193cdb90e73769d92b751f61420804a7711f 100644 (file)
@@ -450,7 +450,7 @@ static void handle_remove(DBusConnection *conn, DBusMessage *msg, void *userdata
 
 static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
     pa_dbusiface_sample *s = userdata;
-    DBusMessage *signal = NULL;
+    DBusMessage *signal_msg = NULL;
 
     pa_assert(c);
     pa_assert(s);
@@ -468,15 +468,15 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
 
         pa_proplist_update(s->proplist, PA_UPDATE_SET, s->sample->proplist);
 
-        pa_assert_se(signal = dbus_message_new_signal(s->path,
-                                                      PA_DBUSIFACE_SAMPLE_INTERFACE,
-                                                      signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
-        dbus_message_iter_init_append(signal, &msg_iter);
+        pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
+                                                         PA_DBUSIFACE_SAMPLE_INTERFACE,
+                                                         signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
+        dbus_message_iter_init_append(signal_msg, &msg_iter);
         pa_dbus_append_proplist(&msg_iter, s->proplist);
 
-        pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 }
 
index 04a45e6c159942c6019781c58afb4b0c81da4499..0255be4bb44fb181d879c68052ffc403719fadc1 100644 (file)
@@ -632,7 +632,7 @@ static void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata)
 
 static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
     pa_dbusiface_stream *s = userdata;
-    DBusMessage *signal = NULL;
+    DBusMessage *signal_msg = NULL;
     const char *new_device_path = NULL;
     uint32_t new_sample_rate = 0;
     pa_proplist *new_proplist = NULL;
@@ -662,14 +662,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
 
             new_device_path = pa_dbusiface_core_get_sink_path(s->core, new_sink);
 
-            pa_assert_se(signal = dbus_message_new_signal(s->path,
-                                                          PA_DBUSIFACE_STREAM_INTERFACE,
-                                                          signals[SIGNAL_DEVICE_UPDATED].name));
-            pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
+            pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
+                                                             PA_DBUSIFACE_STREAM_INTERFACE,
+                                                             signals[SIGNAL_DEVICE_UPDATED].name));
+            pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
 
-            pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
-            dbus_message_unref(signal);
-            signal = NULL;
+            pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
+            dbus_message_unref(signal_msg);
+            signal_msg = NULL;
         }
     } else {
         pa_source *new_source = s->source_output->source;
@@ -680,14 +680,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
 
             new_device_path = pa_dbusiface_core_get_source_path(s->core, new_source);
 
-            pa_assert_se(signal = dbus_message_new_signal(s->path,
-                                                          PA_DBUSIFACE_STREAM_INTERFACE,
-                                                          signals[SIGNAL_DEVICE_UPDATED].name));
-            pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
+            pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
+                                                             PA_DBUSIFACE_STREAM_INTERFACE,
+                                                             signals[SIGNAL_DEVICE_UPDATED].name));
+            pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
 
-            pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
-            dbus_message_unref(signal);
-            signal = NULL;
+            pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
+            dbus_message_unref(signal_msg);
+            signal_msg = NULL;
         }
     }
 
@@ -696,14 +696,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
     if (s->sample_rate != new_sample_rate) {
         s->sample_rate = new_sample_rate;
 
-        pa_assert_se(signal = dbus_message_new_signal(s->path,
-                                                      PA_DBUSIFACE_STREAM_INTERFACE,
-                                                      signals[SIGNAL_SAMPLE_RATE_UPDATED].name));
-        pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_UINT32, &s->sample_rate, DBUS_TYPE_INVALID));
+        pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
+                                                         PA_DBUSIFACE_STREAM_INTERFACE,
+                                                         signals[SIGNAL_SAMPLE_RATE_UPDATED].name));
+        pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_UINT32, &s->sample_rate, DBUS_TYPE_INVALID));
 
-        pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 
     if (s->type == STREAM_TYPE_PLAYBACK) {
@@ -721,16 +721,16 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
             for (i = 0; i < s->volume.channels; ++i)
                 volume[i] = s->volume.values[i];
 
-            pa_assert_se(signal = dbus_message_new_signal(s->path,
-                                                          PA_DBUSIFACE_STREAM_INTERFACE,
-                                                          signals[SIGNAL_VOLUME_UPDATED].name));
-            pa_assert_se(dbus_message_append_args(signal,
+            pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
+                                                             PA_DBUSIFACE_STREAM_INTERFACE,
+                                                             signals[SIGNAL_VOLUME_UPDATED].name));
+            pa_assert_se(dbus_message_append_args(signal_msg,
                                                   DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, s->volume.channels,
                                                   DBUS_TYPE_INVALID));
 
-            pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
-            dbus_message_unref(signal);
-            signal = NULL;
+            pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
+            dbus_message_unref(signal_msg);
+            signal_msg = NULL;
         }
 
         new_mute = pa_sink_input_get_mute(s->sink_input);
@@ -738,14 +738,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
         if (s->mute != new_mute) {
             s->mute = new_mute;
 
-            pa_assert_se(signal = dbus_message_new_signal(s->path,
-                                                          PA_DBUSIFACE_STREAM_INTERFACE,
-                                                          signals[SIGNAL_MUTE_UPDATED].name));
-            pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &s->mute, DBUS_TYPE_INVALID));
+            pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
+                                                             PA_DBUSIFACE_STREAM_INTERFACE,
+                                                             signals[SIGNAL_MUTE_UPDATED].name));
+            pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &s->mute, DBUS_TYPE_INVALID));
 
-            pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
-            dbus_message_unref(signal);
-            signal = NULL;
+            pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
+            dbus_message_unref(signal_msg);
+            signal_msg = NULL;
         }
     }
 
@@ -756,21 +756,21 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
 
         pa_proplist_update(s->proplist, PA_UPDATE_SET, new_proplist);
 
-        pa_assert_se(signal = dbus_message_new_signal(s->path,
-                                                      PA_DBUSIFACE_STREAM_INTERFACE,
-                                                      signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
-        dbus_message_iter_init_append(signal, &msg_iter);
+        pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
+                                                         PA_DBUSIFACE_STREAM_INTERFACE,
+                                                         signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
+        dbus_message_iter_init_append(signal_msg, &msg_iter);
         pa_dbus_append_proplist(&msg_iter, s->proplist);
 
-        pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 }
 
 static pa_hook_result_t send_event_cb(void *hook_data, void *call_data, void *slot_data) {
     pa_dbusiface_stream *s = slot_data;
-    DBusMessage *signal = NULL;
+    DBusMessage *signal_msg = NULL;
     DBusMessageIter msg_iter;
     const char *name = NULL;
     pa_proplist *property_list = NULL;
@@ -796,15 +796,15 @@ static pa_hook_result_t send_event_cb(void *hook_data, void *call_data, void *sl
         property_list = data->data;
     }
 
-    pa_assert_se(signal = dbus_message_new_signal(s->path,
-                                                  PA_DBUSIFACE_STREAM_INTERFACE,
-                                                  signals[SIGNAL_STREAM_EVENT].name));
-    dbus_message_iter_init_append(signal, &msg_iter);
+    pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
+                                                     PA_DBUSIFACE_STREAM_INTERFACE,
+                                                     signals[SIGNAL_STREAM_EVENT].name));
+    dbus_message_iter_init_append(signal_msg, &msg_iter);
     pa_assert_se(dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name));
     pa_dbus_append_proplist(&msg_iter, property_list);
 
-    pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
-    dbus_message_unref(signal);
+    pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
+    dbus_message_unref(signal_msg);
 
     return PA_HOOK_OK;
 }
index 11064c332243f4b4edb3337b2d2aff756979e9c6..acc6ca045f78fc47fdf43ab5b3182408590a049b 100644 (file)
@@ -126,7 +126,7 @@ static void client_kill_cb(pa_client *c) {
 /* Called from pa_client_send_event(). */
 static void client_send_event_cb(pa_client *c, const char *name, pa_proplist *data) {
     struct connection *conn = NULL;
-    DBusMessage *signal = NULL;
+    DBusMessage *signal_msg = NULL;
     DBusMessageIter msg_iter;
 
     pa_assert(c);
@@ -136,15 +136,15 @@ static void client_send_event_cb(pa_client *c, const char *name, pa_proplist *da
 
     conn = c->userdata;
 
-    pa_assert_se(signal = dbus_message_new_signal(pa_dbusiface_core_get_client_path(conn->server->userdata->core_iface, c),
-                                                  PA_DBUSIFACE_CLIENT_INTERFACE,
-                                                  "ClientEvent"));
-    dbus_message_iter_init_append(signal, &msg_iter);
+    pa_assert_se(signal_msg = dbus_message_new_signal(pa_dbusiface_core_get_client_path(conn->server->userdata->core_iface, c),
+                                                     PA_DBUSIFACE_CLIENT_INTERFACE,
+                                                     "ClientEvent"));
+    dbus_message_iter_init_append(signal_msg, &msg_iter);
     pa_assert_se(dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name));
     pa_dbus_append_proplist(&msg_iter, data);
 
-    pa_assert_se(dbus_connection_send(pa_dbus_wrap_connection_get(conn->wrap_conn), signal, NULL));
-    dbus_message_unref(signal);
+    pa_assert_se(dbus_connection_send(pa_dbus_wrap_connection_get(conn->wrap_conn), signal_msg, NULL));
+    dbus_message_unref(signal_msg);
 }
 
 /* Called by D-Bus at the authentication phase. */
index fc976fa72a6d1def62e5e0817e1596df6e637895..9f3e071fd6d0a073e0546c7abeff82c3d0c7f58c 100644 (file)
@@ -334,7 +334,7 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
+    ports = jack_get_ports(u->client, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical|JackPortIsInput);
 
     channels = 0;
     for (p = ports; *p; p++)
index a898e0e5ac8430df5d637fb475981caea41c3eb0..6c68527b63932a4e65683c72cbcb15e564a2663c 100644 (file)
@@ -286,7 +286,7 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput);
+    ports = jack_get_ports(u->client, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical|JackPortIsOutput);
 
     channels = 0;
     for (p = ports; *p; p++)
index 6bd0f4fc8520dc3887fbb659a3743fa7f7299f5d..c5ff456464b8c9d37228b8af82d537c86e4c60f3 100644 (file)
@@ -105,7 +105,7 @@ int pa__init(pa_module*m) {
      * 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) {
+    if ((fd = pa_open_cloexec("/dev/tty", O_RDWR|O_NONBLOCK, 0)) >= 0) {
         io = pa_iochannel_new(m->core->mainloop, fd, fd);
         pa_log_debug("Managed to open /dev/tty.");
     } else {
index 27ae60e538aaa8a572fae05d2b0ac16574df1688..94f589e90c9334853115bc47efabf69048a9ce46 100644 (file)
@@ -60,7 +60,7 @@ static void load(struct userdata *u) {
 
     if (u->core->default_sink)
         pa_log_info("Manually configured default sink, not overwriting.");
-    else if ((f = fopen(u->sink_filename, "r"))) {
+    else if ((f = pa_fopen_cloexec(u->sink_filename, "r"))) {
         char ln[256] = "";
         pa_sink *s;
 
@@ -81,7 +81,7 @@ static void load(struct userdata *u) {
 
     if (u->core->default_source)
         pa_log_info("Manually configured default source, not overwriting.");
-    else if ((f = fopen(u->source_filename, "r"))) {
+    else if ((f = pa_fopen_cloexec(u->source_filename, "r"))) {
         char ln[256] = "";
         pa_source *s;
 
@@ -108,7 +108,7 @@ static void save(struct userdata *u) {
         return;
 
     if (u->sink_filename) {
-        if ((f = fopen(u->sink_filename, "w"))) {
+        if ((f = pa_fopen_cloexec(u->sink_filename, "w"))) {
             pa_sink *s = pa_namereg_get_default_sink(u->core);
             fprintf(f, "%s\n", s ? s->name : "");
             fclose(f);
@@ -117,7 +117,7 @@ static void save(struct userdata *u) {
     }
 
     if (u->source_filename) {
-        if ((f = fopen(u->source_filename, "w"))) {
+        if ((f = pa_fopen_cloexec(u->source_filename, "w"))) {
             pa_source *s = pa_namereg_get_default_source(u->core);
             fprintf(f, "%s\n", s ? s->name : "");
             fclose(f);
index b1f24e1582ed85e00a2b6a3fe4395f4944adc43d..1fe8eb8b63a1a46ade9ef53b0ec51d52904b8764 100644 (file)
@@ -63,7 +63,7 @@ static int detect_alsa(pa_core *c, int just_one) {
     FILE *f;
     int n = 0, n_sink = 0, n_source = 0;
 
-    if (!(f = fopen("/proc/asound/devices", "r"))) {
+    if (!(f = pa_fopen_cloexec("/proc/asound/devices", "r"))) {
 
         if (errno != ENOENT)
             pa_log_error("open(\"/proc/asound/devices\") failed: %s", pa_cstrerror(errno));
@@ -124,9 +124,9 @@ static int detect_oss(pa_core *c, int just_one) {
     FILE *f;
     int n = 0, b = 0;
 
-    if (!(f = fopen("/dev/sndstat", "r")) &&
-        !(f = fopen("/proc/sndstat", "r")) &&
-        !(f = fopen("/proc/asound/oss/sndstat", "r"))) {
+    if (!(f = pa_fopen_cloexec("/dev/sndstat", "r")) &&
+        !(f = pa_fopen_cloexec("/proc/sndstat", "r")) &&
+        !(f = pa_fopen_cloexec("/proc/asound/oss/sndstat", "r"))) {
 
         if (errno != ENOENT)
             pa_log_error("failed to open OSS sndstat device: %s", pa_cstrerror(errno));
index e31586447de719bc3e1d5470b98022dd646982c3..8d61ff4c8464bdec7624968dafc4ad51f7259d79 100644 (file)
@@ -1032,33 +1032,33 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
 
         if ((e = read_entry(u, name))) {
             uint32_t idx;
-            char *devname;
-            uint32_t index = PA_INVALID_INDEX;
+            char *device_name;
+            uint32_t found_index = PA_INVALID_INDEX;
 
-            if ((devname = get_name(name, "sink:"))) {
+            if ((device_name = get_name(name, "sink:"))) {
                 pa_sink* s;
                 PA_IDXSET_FOREACH(s, u->core->sinks, idx) {
-                    if (strcmp(s->name, devname) == 0) {
-                        index = s->index;
+                    if (strcmp(s->name, device_name) == 0) {
+                        found_index = s->index;
                         break;
                     }
                 }
-                pa_xfree(devname);
-            } else if ((devname = get_name(name, "source:"))) {
+                pa_xfree(device_name);
+            } else if ((device_name = get_name(name, "source:"))) {
                 pa_source* s;
                 PA_IDXSET_FOREACH(s, u->core->sources, idx) {
-                    if (strcmp(s->name, devname) == 0) {
-                        index = s->index;
+                    if (strcmp(s->name, device_name) == 0) {
+                        found_index = s->index;
                         break;
                     }
                 }
-                pa_xfree(devname);
+                pa_xfree(device_name);
             }
 
             pa_tagstruct_puts(reply, name);
             pa_tagstruct_puts(reply, e->description);
             pa_tagstruct_puts(reply, e->icon);
-            pa_tagstruct_putu32(reply, index);
+            pa_tagstruct_putu32(reply, found_index);
             pa_tagstruct_putu32(reply, NUM_ROLES);
 
             for (uint32_t i = ROLE_NONE; i < NUM_ROLES; ++i) {
old mode 100755 (executable)
new mode 100644 (file)
index 3a28b49..0a2860b
@@ -113,8 +113,11 @@ struct userdata {
     float **Xs;
     float ***Hs;//thread updatable copies of the freq response filters (magintude based)
     pa_aupdate **a_H;
-    pa_memchunk conv_buffer;
     pa_memblockq *input_q;
+    char *output_buffer;
+    size_t output_buffer_length;
+    size_t output_buffer_max_length;
+    pa_memblockq *output_q;
     pa_bool_t first_iteration;
 
     pa_dbus_protocol *dbus_protocol;
@@ -250,10 +253,11 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of
                 pa_sink_get_latency_within_thread(u->sink_input->sink) +
 
                 /* Add the latency internal to our sink input on top */
-                pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->sink_input->sink->sample_spec);
+                pa_bytes_to_usec(pa_memblockq_get_length(u->output_q), &u->sink_input->sink->sample_spec) +
+                pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->sink_input->sink->sample_spec) +
+                pa_bytes_to_usec(pa_memblockq_get_length(u->input_q), &u->sink_input->sink->sample_spec);
             //    pa_bytes_to_usec(u->samples_gathered * fs, &u->sink->sample_spec);
             //+ pa_bytes_to_usec(u->latency * fs, ss)
-            //+ pa_bytes_to_usec(pa_memblockq_get_length(u->input_q), ss);
             return 0;
         }
     }
@@ -337,7 +341,7 @@ static void sink_set_mute_cb(pa_sink *s) {
     pa_sink_input_set_mute(u->sink_input, s->muted, s->save_muted);
 }
 
-
+#if 1
 //reference implementation
 static void dsp_logic(
     float * restrict dst,//used as a temp array too, needs to be fft_length!
@@ -351,12 +355,12 @@ static void dsp_logic(
     fftwf_complex * restrict output_window,//The transformed window'd src
     struct userdata *u){
     //use a linear-phase sliding STFT and overlap-add method (for each channel)
-    //zero padd the data
-    memset(dst + u->window_size, 0, (u->fft_size - u->window_size) * sizeof(float));
     //window the data
     for(size_t j = 0; j < u->window_size; ++j){
         dst[j] = X * W[j] * src[j];
     }
+    //zero padd the the remaining fft window
+    memset(dst + u->window_size, 0, (u->fft_size - u->window_size) * sizeof(float));
     //Processing is done here!
     //do fft
     fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
@@ -390,125 +394,141 @@ static void dsp_logic(
         (u->samples_gathered - u->R) * sizeof(float)
     );
 }
-
+#else
 typedef float v4sf __attribute__ ((__aligned__(v_size * sizeof(float))));
 typedef union float_vector {
     float f[v_size];
     v4sf v;
-#ifdef __SSE2__
     __m128 m;
-#endif
 } float_vector_t;
 
-////regardless of sse enabled, the loops in here assume
-////16 byte aligned addresses and memory allocations divisible by v_size
-//void dsp_logic(
-//    float * restrict dst,//used as a temp array too, needs to be fft_length!
-//    float * restrict src,/*input data w/ overlap at start,
-//                               *automatically cycled in routine
-//                               */
-//    float * restrict overlap,//The size of the overlap
-//    const float X,//multipliar
-//    const float * restrict H,//The freq. magnitude scalers filter
-//    const float * restrict W,//The windowing function
-//    fftwf_complex * restrict output_window,//The transformed window'd src
-//    struct userdata *u){//Collection of constants
-      //float_vector_t x = {X, X, X, X};
-//    const size_t window_size = PA_ROUND_UP(u->window_size,v_size);
-//    const size_t fft_h = PA_ROUND_UP(FILTER_SIZE, v_size / 2);
-//    //const size_t R = PA_ROUND_UP(u->R, v_size);
-//    const size_t overlap_size = PA_ROUND_UP(u->overlap_size, v_size);
-//     overlap_size = PA_ROUND_UP(u->overlap_size, v_size);
-//
-//    //assert(u->samples_gathered >= u->R);
-//    //zero out the bit beyond the real overlap so we don't add garbage
-//    for(size_t j = overlap_size; j > u->overlap_size; --j){
-//       overlap[j-1] = 0;
-//    }
-//    //use a linear-phase sliding STFT and overlap-add method
-//    //zero padd the data
-//    memset(dst + u->window_size, 0, (u->fft_size - u->window_size)*sizeof(float));
-//    //window the data
-//    for(size_t j = 0; j < window_size; j += v_size){
-//        //dst[j] = W[j]*src[j];
-//        float_vector_t *d = (float_vector_t*) (dst+j);
-//        float_vector_t *w = (float_vector_t*) (W+j);
-//        float_vector_t *s = (float_vector_t*) (src+j);
+//regardless of sse enabled, the loops in here assume
+//16 byte aligned addresses and memory allocations divisible by v_size
+static void dsp_logic(
+    float * restrict dst,//used as a temp array too, needs to be fft_length!
+    float * restrict src,/*input data w/ overlap at start,
+                               *automatically cycled in routine
+                               */
+    float * restrict overlap,//The size of the overlap
+    const float X,//multipliar
+    const float * restrict H,//The freq. magnitude scalers filter
+    const float * restrict W,//The windowing function
+    fftwf_complex * restrict output_window,//The transformed window'd src
+    struct userdata *u){//Collection of constants
+    const size_t overlap_size = PA_ROUND_UP(u->overlap_size, v_size);
+    float_vector_t x;
+    x.f[0] = x.f[1] = x.f[2] = x.f[3] = X;
+
+    //assert(u->samples_gathered >= u->R);
+    //use a linear-phase sliding STFT and overlap-add method
+    for(size_t j = 0; j < u->window_size; j += v_size){
+        //dst[j] = W[j] * src[j];
+        float_vector_t *d = (float_vector_t*) (dst + j);
+        float_vector_t *w = (float_vector_t*) (W + j);
+        float_vector_t *s = (float_vector_t*) (src + j);
 //#if __SSE2__
-//        d->m = _mm_mul_ps(x->m, _mm_mul_ps(w->m, s->m));
-//#else
+        d->m = _mm_mul_ps(x.m, _mm_mul_ps(w->m, s->m));
 //        d->v = x->v * w->v * s->v;
 //#endif
-//    }
-//    //Processing is done here!
-//    //do fft
-//    fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
-//
-//
-//    //perform filtering - purely magnitude based
-//    for(size_t j = 0;j < fft_h; j+=v_size/2){
-//        //output_window[j][0]*=H[j];
-//        //output_window[j][1]*=H[j];
-//        float_vector_t *d = (float_vector_t*)(output_window+j);
-//        float_vector_t h;
-//        h.f[0] = h.f[1] = H[j];
-//        h.f[2] = h.f[3] = H[j+1];
+    }
+    //zero padd the the remaining fft window
+    memset(dst + u->window_size, 0, (u->fft_size - u->window_size) * sizeof(float));
+
+    //Processing is done here!
+    //do fft
+    fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
+    //perform filtering - purely magnitude based
+    for(size_t j = 0; j < FILTER_SIZE; j += v_size / 2){
+        //output_window[j][0]*=H[j];
+        //output_window[j][1]*=H[j];
+        float_vector_t *d = (float_vector_t*)( ((float *) output_window) + 2 * j);
+        float_vector_t h;
+        h.f[0] = h.f[1] = H[j];
+        h.f[2] = h.f[3] = H[j + 1];
 //#if __SSE2__
-//        d->m = _mm_mul_ps(d->m, h.m);
+        d->m = _mm_mul_ps(d->m, h.m);
 //#else
-//        d->v = d->v*h->v;
+//        d->v = d->v * h.v;
 //#endif
-//    }
-//    //inverse fft
-//    fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst);
-//
-//    ////debug: tests overlaping add
-//    ////and negates ALL PREVIOUS processing
-//    ////yields a perfect reconstruction if COLA is held
-//    //for(size_t j = 0; j < u->window_size; ++j){
-//    //    dst[j] = W[j]*src[j];
-//    //}
-//
-//    //overlap add and preserve overlap component from this window (linear phase)
-//    for(size_t j = 0; j < overlap_size; j+=v_size){
-//        //dst[j]+=overlap[j];
-//        //overlap[j]+=dst[j+R];
-//        float_vector_t *d = (float_vector_t*)(dst+j);
-//        float_vector_t *o = (float_vector_t*)(overlap+j);
+    }
+
+    //inverse fft
+    fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst);
+
+    ////debug: tests overlaping add
+    ////and negates ALL PREVIOUS processing
+    ////yields a perfect reconstruction if COLA is held
+    //for(size_t j = 0; j < u->window_size; ++j){
+    //    dst[j] = W[j] * src[j];
+    //}
+
+    //overlap add and preserve overlap component from this window (linear phase)
+    for(size_t j = 0; j < overlap_size; j += v_size){
+        //dst[j]+=overlap[j];
+        //overlap[j]+=dst[j+R];
+        float_vector_t *d = (float_vector_t*)(dst + j);
+        float_vector_t *o = (float_vector_t*)(overlap + j);
 //#if __SSE2__
-//        d->m = _mm_add_ps(d->m, o->m);
-//        o->m = ((float_vector_t*)(dst+u->R+j))->m;
+        d->m = _mm_add_ps(d->m, o->m);
+        o->m = ((float_vector_t*)(dst + u->R + j))->m;
 //#else
-//        d->v = d->v+o->v;
-//        o->v = ((float_vector_t*)(dst+u->R+j))->v;
+//        d->v = d->v + o->v;
+//        o->v = ((float_vector_t*)(dst + u->R + j))->v;
 //#endif
-//    }
-//    //memcpy(overlap, dst+u->R, u->overlap_size*sizeof(float));
-//
-//    //////debug: tests if basic buffering works
-//    //////shouldn't modify the signal AT ALL (beyond roundoff)
-//    //for(size_t j = 0; j < u->window_size; ++j){
-//    //    dst[j] = src[j];
-//    //}
-//
-//    //preseve the needed input for the next window's overlap
-//    memmove(src, src + u->R,
-//        u->overlap_size * sizeof(float)
-//    );
-//}
-
-static void process_samples(struct userdata *u, pa_memchunk *tchunk){
+    }
+    //memcpy(overlap, dst+u->R, u->overlap_size * sizeof(float)); //overlap preserve (debug)
+    //zero out the bit beyond the real overlap so we don't add garbage next iteration
+    memset(overlap + u->overlap_size, 0, overlap_size - u->overlap_size);
+
+    ////debug: tests if basic buffering works
+    ////shouldn't modify the signal AT ALL (beyond roundoff)
+    //for(size_t j = 0; j < u->window_size; ++j){
+    //    dst[j] = src[j];
+    //}
+
+    //preseve the needed input for the next window's overlap
+    memmove(src, src + u->R,
+        (u->samples_gathered - u->R) * sizeof(float)
+    );
+}
+#endif
+
+static void flatten_to_memblockq(struct userdata *u){
+    size_t mbs = pa_mempool_block_size_max(u->sink->core->mempool);
+    pa_memchunk tchunk;
+    char *dst;
+    size_t i = 0;
+    while(i < u->output_buffer_length){
+        tchunk.index = 0;
+        tchunk.length = PA_MIN((u->output_buffer_length - i), mbs);
+        tchunk.memblock = pa_memblock_new(u->sink->core->mempool, tchunk.length);
+        //pa_log_debug("pushing %ld into the q", tchunk.length);
+        dst = pa_memblock_acquire(tchunk.memblock);
+        memcpy(dst, u->output_buffer + i, tchunk.length);
+        pa_memblock_release(tchunk.memblock);
+        pa_memblockq_push(u->output_q, &tchunk);
+        pa_memblock_unref(tchunk.memblock);
+        i += tchunk.length;
+    }
+}
+
+static void process_samples(struct userdata *u){
     size_t fs = pa_frame_size(&(u->sink->sample_spec));
-    float *dst;
     unsigned a_i;
     float *H, X;
     size_t iterations, offset;
     pa_assert(u->samples_gathered >= u->window_size);
     iterations = (u->samples_gathered - u->overlap_size) / u->R;
-    tchunk->index = 0;
-    tchunk->length = iterations * u->R * fs;
-    tchunk->memblock = pa_memblock_new(u->sink->core->mempool, tchunk->length);
-    dst = ((float*) pa_memblock_acquire(tchunk->memblock));
+    //make sure there is enough buffer memory allocated
+    if(iterations * u->R * fs > u->output_buffer_max_length){
+        u->output_buffer_max_length = iterations * u->R * fs;
+        if(u->output_buffer){
+            pa_xfree(u->output_buffer);
+        }
+        u->output_buffer = pa_xmalloc(u->output_buffer_max_length);
+    }
+    u->output_buffer_length = iterations * u->R * fs;
+
     for(size_t iter = 0; iter < iterations; ++iter){
         offset = iter * u->R * fs;
         for(size_t c = 0;c < u->channels; c++) {
@@ -534,14 +554,14 @@ static void process_samples(struct userdata *u, pa_memchunk *tchunk){
                     u->work_buffer[i] = u->W[i] <= FLT_EPSILON ? u->work_buffer[i] : u->work_buffer[i] / u->W[i];
                 }
             }
-            pa_sample_clamp(PA_SAMPLE_FLOAT32NE, (uint8_t *) (dst + c) + offset, fs, u->work_buffer, sizeof(float), u->R);
+            pa_sample_clamp(PA_SAMPLE_FLOAT32NE, (uint8_t *) (((float *)u->output_buffer) + c) + offset, fs, u->work_buffer, sizeof(float), u->R);
         }
         if(u->first_iteration){
             u->first_iteration = FALSE;
         }
         u->samples_gathered -= u->R;
     }
-    pa_memblock_release(tchunk->memblock);
+    flatten_to_memblockq(u);
 }
 
 static void input_buffer(struct userdata *u, pa_memchunk *in){
@@ -565,36 +585,49 @@ static void input_buffer(struct userdata *u, pa_memchunk *in){
 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
     struct userdata *u;
     size_t fs, target_samples;
-    struct timeval start, end;
+    size_t mbs;
+    //struct timeval start, end;
     pa_memchunk tchunk;
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
     pa_assert(chunk);
     pa_assert(u->sink);
     fs = pa_frame_size(&(u->sink->sample_spec));
+    mbs = pa_mempool_block_size_max(u->sink->core->mempool);
+    if(pa_memblockq_get_length(u->output_q) > 0){
+        //pa_log_debug("qsize is %ld", pa_memblockq_get_length(u->output_q));
+        goto END;
+    }
+    //nbytes = PA_MIN(nbytes, pa_mempool_block_size_max(u->sink->core->mempool));
     target_samples = PA_ROUND_UP(nbytes / fs, u->R);
+    ////pa_log_debug("vanilla mbs = %ld",mbs);
+    //mbs = PA_ROUND_DOWN(mbs / fs, u->R);
+    //mbs = PA_MAX(mbs, u->R);
+    //target_samples = PA_MAX(target_samples, mbs);
+    //pa_log_debug("target samples: %ld", target_samples);
     if(u->first_iteration){
         //allocate request_size
         target_samples = PA_MAX(target_samples, u->window_size);
     }else{
         //allocate request_size + overlap
         target_samples += u->overlap_size;
-        alloc_input_buffers(u, target_samples);
     }
     alloc_input_buffers(u, target_samples);
+    //pa_log_debug("post target samples: %ld", target_samples);
     chunk->memblock = NULL;
 
     /* Hmm, process any rewind request that might be queued up */
     pa_sink_process_rewind(u->sink, 0);
 
     //pa_log_debug("start output-buffered %ld, input-buffered %ld, requested %ld",buffered_samples,u->samples_gathered,samples_requested);
-    pa_rtclock_get(&start);
+    //pa_rtclock_get(&start);
     do{
         size_t input_remaining = target_samples - u->samples_gathered;
+       // pa_log_debug("input remaining %ld samples", input_remaining);
         pa_assert(input_remaining > 0);
         while(pa_memblockq_peek(u->input_q, &tchunk) < 0){
             //pa_sink_render(u->sink, input_remaining * fs, &tchunk);
-            pa_sink_render_full(u->sink, input_remaining * fs, &tchunk);
+            pa_sink_render_full(u->sink, PA_MIN(input_remaining * fs, mbs), &tchunk);
             pa_assert(tchunk.memblock);
             pa_memblockq_push(u->input_q, &tchunk);
             pa_memblock_unref(tchunk.memblock);
@@ -605,25 +638,27 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
         //pa_log_debug("asked for %ld input samples, got %ld samples",input_remaining,buffer->length/fs);
         /* copy new input */
         //pa_rtclock_get(start);
+       // pa_log_debug("buffering %ld bytes", tchunk.length);
         input_buffer(u, &tchunk);
         //pa_rtclock_get(&end);
         //pa_log_debug("Took %0.5f seconds to setup", pa_timeval_diff(end, start) / (double) PA_USEC_PER_SEC);
         pa_memblock_unref(tchunk.memblock);
     }while(u->samples_gathered < target_samples);
 
-    pa_rtclock_get(&end);
-    pa_log_debug("Took %0.6f seconds to get data", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
+    //pa_rtclock_get(&end);
+    //pa_log_debug("Took %0.6f seconds to get data", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
 
     pa_assert(u->fft_size >= u->window_size);
     pa_assert(u->R < u->window_size);
-    /* set the H filter */
-    pa_rtclock_get(&start);
+    //pa_rtclock_get(&start);
     /* process a block */
-    process_samples(u, chunk);
-    pa_rtclock_get(&end);
-    pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
-
+    process_samples(u);
+    //pa_rtclock_get(&end);
+    //pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
+END:
+    pa_assert_se(pa_memblockq_peek(u->output_q, chunk) >= 0);
     pa_assert(chunk->memblock);
+    pa_memblockq_drop(u->output_q, chunk->length);
     //pa_log_debug("gave %ld", chunk->length/fs);
     //pa_log_debug("end pop");
     return 0;
@@ -685,7 +720,7 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
             //invalidate the output q
             pa_memblockq_seek(u->input_q, - (int64_t) amount, PA_SEEK_RELATIVE, TRUE);
             pa_log("Resetting filter");
-            reset_filter(u);
+            //reset_filter(u); //this is the "proper" thing to do...
         }
     }
 
@@ -814,33 +849,35 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s
 static void pack(char **strs, size_t len, char **packed, size_t *length){
     size_t t_len = 0;
     size_t headers = (1+len) * sizeof(uint16_t);
-    size_t offset = sizeof(uint16_t);
+    char *p;
     for(size_t i = 0; i < len; ++i){
         t_len += strlen(strs[i]);
     }
     *length = headers + t_len;
-    *packed = pa_xmalloc0(*length);
-    ((uint16_t *) *packed)[0] = (uint16_t) len;
+    p = *packed = pa_xmalloc0(*length);
+    *((uint16_t *) p) = (uint16_t) len;
+    p += sizeof(uint16_t);
     for(size_t i = 0; i < len; ++i){
         uint16_t l = strlen(strs[i]);
-        *((uint16_t *)(*packed + offset)) = l;
-        offset += sizeof(uint16_t);
-        memcpy(*packed + offset, strs[i], l);
-        offset += l;
+        *((uint16_t *) p) = (uint16_t) l;
+        p += sizeof(uint16_t);
+        memcpy(p, strs[i], l);
+        p += l;
     }
 }
 static void unpack(char *str, size_t length, char ***strs, size_t *len){
-    size_t offset = sizeof(uint16_t);
-    *len = ((uint16_t *)str)[0];
+    char *p = str;
+    *len = *((uint16_t *) p);
+    p += sizeof(uint16_t);
     *strs = pa_xnew(char *, *len);
+
     for(size_t i = 0; i < *len; ++i){
-        size_t l = *((uint16_t *)(str+offset));
-        size_t e = PA_MIN(offset + l, length) - offset;
-        offset = PA_MIN(offset + sizeof(uint16_t), length);
-        (*strs)[i] = pa_xnew(char, e + 1);
-        memcpy((*strs)[i], str + offset, e);
-        (*strs)[i][e] = '\0';
-        offset += l;
+        size_t l = *((uint16_t *) p);
+        p += sizeof(uint16_t);
+        (*strs)[i] = pa_xnew(char, l + 1);
+        memcpy((*strs)[i], p, l);
+        (*strs)[i][l] = '\0';
+        p += l;
     }
 }
 static void save_profile(struct userdata *u, size_t channel, char *name){
@@ -885,17 +922,17 @@ static void save_state(struct userdata *u){
 
     pack(u->base_profiles, u->channels, &packed, &packed_length);
     state = (float *) pa_xmalloc0(filter_state_size + packed_length);
+    memcpy(state + FILTER_STATE_SIZE, packed, packed_length);
+    pa_xfree(packed);
 
     for(size_t c = 0; c < u->channels; ++c){
         a_i = pa_aupdate_read_begin(u->a_H[c]);
-        state[c * CHANNEL_PROFILE_SIZE] = u->Xs[a_i][c];
+        state[c * CHANNEL_PROFILE_SIZE] = u->Xs[c][a_i];
         H = u->Hs[c][a_i];
-        H_n = state + c * CHANNEL_PROFILE_SIZE + 1;
+        H_n = &state[c * CHANNEL_PROFILE_SIZE + 1];
         memcpy(H_n, H, FILTER_SIZE * sizeof(float));
         pa_aupdate_read_end(u->a_H[c]);
     }
-    memcpy(((char *)state) + filter_state_size, packed, packed_length);
-    pa_xfree(packed);
 
     key.data = state_name;
     key.size = strlen(key.data);
@@ -978,13 +1015,13 @@ static void load_state(struct userdata *u){
                 memcpy(u->Hs[c][a_i], H, FILTER_SIZE * sizeof(float));
                 pa_aupdate_write_end(u->a_H[c]);
             }
-            //unpack(((char *)value.data) + FILTER_STATE_SIZE, value.size - FILTER_STATE_SIZE, &names, &n_profs);
-            //n_profs = PA_MIN(n_profs, u->channels);
-            //for(size_t c = 0; c < n_profs; ++c){
-            //    pa_xfree(u->base_profiles[c]);
-            //    u->base_profiles[c] = names[c];
-            //}
-            //pa_xfree(names);
+            unpack(((char *)value.data) + FILTER_STATE_SIZE * sizeof(float), value.size - FILTER_STATE_SIZE * sizeof(float), &names, &n_profs);
+            n_profs = PA_MIN(n_profs, u->channels);
+            for(size_t c = 0; c < n_profs; ++c){
+                pa_xfree(u->base_profiles[c]);
+                u->base_profiles[c] = names[c];
+            }
+            pa_xfree(names);
         }
         pa_datum_free(&value);
     }else{
@@ -1062,9 +1099,12 @@ int pa__init(pa_module*m) {
     pa_modargs_get_value_boolean(ma, "set_default", &u->set_default);
 
     u->channels = ss.channels;
-    u->fft_size = pow(2, ceil(log(ss.rate)/log(2)));//probably unstable near corner cases of powers of 2
+    u->fft_size = pow(2, ceil(log(ss.rate) / log(2)));//probably unstable near corner cases of powers of 2
     pa_log_debug("fft size: %ld", u->fft_size);
     u->window_size = 15999;
+    if(u->window_size % 2 == 0){
+        u->window_size--;
+    }
     u->R = (u->window_size + 1) / 2;
     u->overlap_size = u->window_size - u->R;
     u->samples_gathered = 0;
@@ -1088,7 +1128,6 @@ int pa__init(pa_module*m) {
         u->a_H[c] = pa_aupdate_new();
         u->input[c] = NULL;
         u->overlap_accum[c] = alloc(u->overlap_size, sizeof(float));
-        memset(u->overlap_accum[c], 0, u->overlap_size*sizeof(float));
     }
     u->output_window = alloc((FILTER_SIZE), sizeof(fftwf_complex));
     u->forward_plan = fftwf_plan_dft_r2c_1d(u->fft_size, u->work_buffer, u->output_window, FFTW_ESTIMATE);
@@ -1139,6 +1178,10 @@ int pa__init(pa_module*m) {
     u->sink->set_mute = sink_set_mute_cb;
     u->sink->userdata = u;
     u->input_q = pa_memblockq_new(0,  MEMBLOCKQ_MAXLENGTH, 0, fs, 1, 1, 0, &u->sink->silence);
+    u->output_q = pa_memblockq_new(0,  MEMBLOCKQ_MAXLENGTH, 0, fs, 1, 1, 0, NULL);
+    u->output_buffer = NULL;
+    u->output_buffer_length = 0;
+    u->output_buffer_max_length = 0;
 
     pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
     //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss));
@@ -1251,6 +1294,10 @@ void pa__done(pa_module*m) {
     if (u->sink)
         pa_sink_unref(u->sink);
 
+    if(u->output_buffer){
+        pa_xfree(u->output_buffer);
+    }
+    pa_memblockq_free(u->output_q);
     pa_memblockq_free(u->input_q);
 
     fftwf_destroy_plan(u->inverse_plan);
index d0e902f69b3b080e34b9005d68d30af49aa9fbc5..e97786206066c2412a27063ff95c68798085cd62 100644 (file)
@@ -45,12 +45,14 @@ PA_MODULE_AUTHOR("Lennart Poettering");
 PA_MODULE_DESCRIPTION("LIRC volume control");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(TRUE);
-PA_MODULE_USAGE("config=<config file> sink=<sink name> appname=<lirc application name>");
+PA_MODULE_USAGE("config=<config file> sink=<sink name> appname=<lirc application name> volume_limit=<volume limit> volume_step=<volume change step>");
 
 static const char* const valid_modargs[] = {
     "config",
     "sink",
     "appname",
+    "volume_limit",
+    "volume_step",
     NULL,
 };
 
@@ -61,10 +63,10 @@ struct userdata {
     char *sink_name;
     pa_module *module;
     float mute_toggle_save;
+    pa_volume_t volume_limit;
+    pa_volume_t volume_step;
 };
 
-#define DELTA (PA_VOLUME_NORM/20)
-
 static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) {
     struct userdata *u = userdata;
     char *name = NULL, *code = NULL;
@@ -125,12 +127,12 @@ static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event
 
                     switch (volchange) {
                         case UP:
-                            pa_cvolume_inc(&cv, DELTA);
+                            pa_cvolume_inc_clamp(&cv, u->volume_step, u->volume_limit);
                             pa_sink_set_volume(s, &cv, TRUE, TRUE);
                             break;
 
                         case DOWN:
-                            pa_cvolume_dec(&cv, DELTA);
+                            pa_cvolume_dec(&cv, u->volume_step);
                             pa_sink_set_volume(s, &cv, TRUE, TRUE);
                             break;
 
@@ -170,6 +172,8 @@ fail:
 int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u;
+    pa_volume_t volume_limit = PA_VOLUME_NORM*3/2;
+    pa_volume_t volume_step = PA_VOLUME_NORM/20;
 
     pa_assert(m);
 
@@ -178,6 +182,16 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    if (pa_modargs_get_value_u32(ma, "volume_limit", &volume_limit) < 0) {
+        pa_log("Failed to parse volume limit");
+        goto fail;
+    }
+
+    if (pa_modargs_get_value_u32(ma, "volume_step", &volume_step) < 0) {
+        pa_log("Failed to parse volume step");
+        goto fail;
+    }
+
     m->userdata = u = pa_xnew(struct userdata, 1);
     u->module = m;
     u->io = NULL;
@@ -185,6 +199,8 @@ int pa__init(pa_module*m) {
     u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
     u->lirc_fd = -1;
     u->mute_toggle_save = 0;
+    u->volume_limit = volume_limit;
+    u->volume_step = volume_step;
 
     if ((u->lirc_fd = lirc_init((char*) pa_modargs_get_value(ma, "appname", "pulseaudio"), 1)) < 0) {
         pa_log("lirc_init() failed.");
index 0bd781d2b2beae0a441e42b26bc996abf08ea324..b1693f18c53fa7f704d2de2b57681c4f243bcea1 100644 (file)
@@ -85,7 +85,7 @@ static int load_rules(struct userdata *u, const char *filename) {
     pa_assert(u);
 
     if (filename)
-        f = fopen(fn = pa_xstrdup(filename), "r");
+        f = pa_fopen_cloexec(fn = pa_xstrdup(filename), "r");
     else
         f = pa_open_config_file(DEFAULT_MATCH_TABLE_FILE, DEFAULT_MATCH_TABLE_FILE_USER, NULL, &fn);
 
index 516bf41374f953d796f6a48690c0d24cde620262..193c1f40ae7f89f0a80717c9c51b450bfa879047 100644 (file)
@@ -48,13 +48,15 @@ PA_MODULE_AUTHOR("Lennart Poettering");
 PA_MODULE_DESCRIPTION("Multimedia keyboard support via Linux evdev");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
-PA_MODULE_USAGE("device=<evdev device> sink=<sink name>");
+PA_MODULE_USAGE("device=<evdev device> sink=<sink name> volume_limit=<volume limit> volume_step=<volume change step>");
 
 #define DEFAULT_DEVICE "/dev/input/event0"
 
 static const char* const valid_modargs[] = {
     "device",
     "sink",
+    "volume_limit",
+    "volume_step",
     NULL,
 };
 
@@ -63,10 +65,10 @@ struct userdata {
     pa_io_event *io;
     char *sink_name;
     pa_module *module;
+    pa_volume_t volume_limit;
+    pa_volume_t volume_step;
 };
 
-#define DELTA (PA_VOLUME_NORM/20)
-
 static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) {
     struct userdata *u = userdata;
 
@@ -120,12 +122,12 @@ static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event
 
                     switch (volchange) {
                         case UP:
-                            pa_cvolume_inc(&cv, DELTA);
+                            pa_cvolume_inc_clamp(&cv, u->volume_step, u->volume_limit);
                             pa_sink_set_volume(s, &cv, TRUE, TRUE);
                             break;
 
                         case DOWN:
-                            pa_cvolume_dec(&cv, DELTA);
+                            pa_cvolume_dec(&cv, u->volume_step);
                             pa_sink_set_volume(s, &cv, TRUE, TRUE);
                             break;
 
@@ -160,6 +162,8 @@ int pa__init(pa_module*m) {
     struct input_id input_id;
     char name[256];
     uint8_t evtype_bitmask[EV_MAX/8 + 1];
+    pa_volume_t volume_limit = PA_VOLUME_NORM*3/2;
+    pa_volume_t volume_step = PA_VOLUME_NORM/20;
 
     pa_assert(m);
 
@@ -168,14 +172,26 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    if (pa_modargs_get_value_u32(ma, "volume_limit", &volume_limit) < 0) {
+        pa_log("Failed to parse volume limit");
+        goto fail;
+    }
+
+    if (pa_modargs_get_value_u32(ma, "volume_step", &volume_step) < 0) {
+        pa_log("Failed to parse volume step");
+        goto fail;
+    }
+
     m->userdata = u = pa_xnew(struct userdata, 1);
     u->module = m;
     u->io = NULL;
     u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
     u->fd = -1;
     u->fd_type = 0;
+    u->volume_limit = volume_limit;
+    u->volume_step = volume_step;
 
-    if ((u->fd = open(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY|O_NOCTTY)) < 0) {
+    if ((u->fd = pa_open_cloexec(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY, 0)) < 0) {
         pa_log("Failed to open evdev device: %s", pa_cstrerror(errno));
         goto fail;
     }
index 9c1693270fe3799e14450bd20d843b58297dd347..7a4e730f837d1a40c382866b2ce78c104a5fed26 100644 (file)
 #include <sys/ioctl.h>
 #include <poll.h>
 
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/core-error.h>
@@ -101,9 +105,10 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
         case PA_SINK_MESSAGE_GET_LATENCY: {
             size_t n = 0;
-            int l;
 
 #ifdef FIONREAD
+            int l;
+
             if (ioctl(u->fd, FIONREAD, &l) >= 0 && l > 0)
                 n = (size_t) l;
 #endif
@@ -253,12 +258,11 @@ int pa__init(pa_module*m) {
     u->filename = pa_runtime_path(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
 
     mkfifo(u->filename, 0666);
-    if ((u->fd = open(u->filename, O_RDWR|O_NOCTTY)) < 0) {
+    if ((u->fd = pa_open_cloexec(u->filename, O_RDWR, 0)) < 0) {
         pa_log("open('%s'): %s", u->filename, pa_cstrerror(errno));
         goto fail;
     }
 
-    pa_make_fd_cloexec(u->fd);
     pa_make_fd_nonblock(u->fd);
 
     if (fstat(u->fd, &st) < 0) {
index 49104f8d53698c2161ed8a54a1532c6a63d66c6c..933f0294631777f89f4cecd89389a818f3e1e1af 100644 (file)
 #include <sys/ioctl.h>
 #include <sys/poll.h>
 
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/core-error.h>
@@ -105,9 +109,10 @@ static int source_process_msg(
 
         case PA_SOURCE_MESSAGE_GET_LATENCY: {
             size_t n = 0;
-            int l;
 
 #ifdef FIONREAD
+            int l;
+
             if (ioctl(u->fd, FIONREAD, &l) >= 0 && l > 0)
                 n = (size_t) l;
 #endif
@@ -238,12 +243,11 @@ int pa__init(pa_module*m) {
     u->filename = pa_runtime_path(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
 
     mkfifo(u->filename, 0666);
-    if ((u->fd = open(u->filename, O_RDWR|O_NOCTTY)) < 0) {
+    if ((u->fd = pa_open_cloexec(u->filename, O_RDWR, 0)) < 0) {
         pa_log("open('%s'): %s", u->filename, pa_cstrerror(errno));
         goto fail;
     }
 
-    pa_make_fd_cloexec(u->fd);
     pa_make_fd_nonblock(u->fd);
 
     if (fstat(u->fd, &st) < 0) {
index 4c02e958ef9421f31dc9fb207b4cc7d04411d267..82bcd14cef4d5a95798b6e7801c00176dcd92679 100644 (file)
@@ -464,8 +464,18 @@ static char **child_array(struct userdata *u, const char *path, unsigned *n) {
 
     if (pa_streq(path, OBJECT_SINKS))
         m = pa_idxset_size(u->core->sinks);
-    else
+    else {
+        unsigned k;
+
         m = pa_idxset_size(u->core->sources);
+        k = pa_idxset_size(u->core->sinks);
+
+        pa_assert(m >= k);
+
+        /* Subtract the monitor sources from the numbers of
+         * sources. There is one monitor source for each sink */
+        m -= k;
+    }
 
     array = pa_xnew(char*, m);
     *n = 0;
@@ -473,14 +483,20 @@ static char **child_array(struct userdata *u, const char *path, unsigned *n) {
     if (pa_streq(path, OBJECT_SINKS)) {
         pa_sink *sink;
 
-        PA_IDXSET_FOREACH(sink, u->core->sinks, idx)
+        PA_IDXSET_FOREACH(sink, u->core->sinks, idx) {
+            pa_assert((*n) < m);
             array[(*n)++] = pa_sprintf_malloc(OBJECT_SINKS "/%u", sink->index);
+        }
     } else {
         pa_source *source;
 
-        PA_IDXSET_FOREACH(source, u->core->sources, idx)
-            if (!source->monitor_of)
+        PA_IDXSET_FOREACH(source, u->core->sources, idx) {
+
+            if (!source->monitor_of) {
+                pa_assert((*n) < m);
                 array[(*n)++] = pa_sprintf_malloc(OBJECT_SOURCES "/%u", source->index);
+            }
+        }
     }
 
     pa_assert((*n) <= m);
@@ -529,16 +545,20 @@ static DBusHandlerResult sinks_and_sources_handler(DBusConnection *c, DBusMessag
             free_child_array(array, n);
 
         } else if (message_is_property_get(m, "org.gnome.UPnP.MediaContainer1", "ItemCount")) {
+            unsigned n, k;
+
+            n = pa_idxset_size(u->core->sinks);
+            k = pa_idxset_size(u->core->sources);
+            pa_assert(k >= n);
+
             pa_assert_se(r = dbus_message_new_method_return(m));
             append_variant_unsigned(r, NULL,
-                                    pa_streq(path, OBJECT_SINKS) ?
-                                    pa_idxset_size(u->core->sinks) :
-                                    pa_idxset_size(u->core->sources));
+                                    pa_streq(path, OBJECT_SINKS) ? n : k - n);
 
         } else if (message_is_property_get_all(m, "org.gnome.UPnP.MediaContainer1")) {
             DBusMessageIter iter, sub;
             char **array;
-            unsigned n;
+            unsigned n, k;
 
             pa_assert_se(r = dbus_message_new_method_return(m));
             dbus_message_iter_init_append(r, &iter);
@@ -550,10 +570,13 @@ static DBusHandlerResult sinks_and_sources_handler(DBusConnection *c, DBusMessag
             array = child_array(u, path, &n);
             append_property_dict_entry_object_array(r, &sub, "Items", (const char**) array, n);
             free_child_array(array, n);
+
+            n = pa_idxset_size(u->core->sinks);
+            k = pa_idxset_size(u->core->sources);
+            pa_assert(k >= n);
+
             append_property_dict_entry_unsigned(r, &sub, "ItemCount",
-                                                pa_streq(path, OBJECT_SINKS) ?
-                                                pa_idxset_size(u->core->sinks) :
-                                                pa_idxset_size(u->core->sources));
+                                                pa_streq(path, OBJECT_SINKS) ? n : k - n);
 
             pa_assert_se(dbus_message_iter_close_container(&iter, &sub));
 
index b0d4db43e89992b82ecc8453cdb1a891615f26c0..396094ce8a686b1cfd1aca5aa52fbdb28d747989 100644 (file)
@@ -327,7 +327,7 @@ static int open_audio_device(struct userdata *u, pa_sample_spec *ss) {
     pa_assert(u);
     pa_assert(ss);
 
-    if ((u->fd = open(u->device_name, u->mode | O_NONBLOCK)) < 0) {
+    if ((u->fd = pa_open_cloexec(u->device_name, u->mode | O_NONBLOCK, 0)) < 0) {
         pa_log_warn("open %s failed (%s)", u->device_name, pa_cstrerror(errno));
         return -1;
     }
index 788f458b78e12224bfcef9aa0d3e41eff15bee11..02c312e306e62cc4faee5dd95e881216e2352fde 100644 (file)
@@ -433,29 +433,29 @@ static void append_volume_variant(DBusMessageIter *iter, struct entry *e) {
 }
 
 static void send_new_entry_signal(struct dbus_entry *entry) {
-    DBusMessage *signal;
+    DBusMessage *signal_msg;
 
     pa_assert(entry);
 
-    pa_assert_se(signal = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_NEW_ENTRY].name));
-    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
-    pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal);
-    dbus_message_unref(signal);
+    pa_assert_se(signal_msg = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_NEW_ENTRY].name));
+    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
+    pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal_msg);
+    dbus_message_unref(signal_msg);
 }
 
 static void send_entry_removed_signal(struct dbus_entry *entry) {
-    DBusMessage *signal;
+    DBusMessage *signal_msg;
 
     pa_assert(entry);
 
-    pa_assert_se(signal = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_ENTRY_REMOVED].name));
-    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
-    pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal);
-    dbus_message_unref(signal);
+    pa_assert_se(signal_msg = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_ENTRY_REMOVED].name));
+    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
+    pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal_msg);
+    dbus_message_unref(signal_msg);
 }
 
 static void send_device_updated_signal(struct dbus_entry *de, struct entry *e) {
-    DBusMessage *signal;
+    DBusMessage *signal_msg;
     const char *device;
 
     pa_assert(de);
@@ -463,28 +463,28 @@ static void send_device_updated_signal(struct dbus_entry *de, struct entry *e) {
 
     device = e->device_valid ? e->device : "";
 
-    pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_DEVICE_UPDATED].name));
-    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID));
-    pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal);
-    dbus_message_unref(signal);
+    pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_DEVICE_UPDATED].name));
+    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID));
+    pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
+    dbus_message_unref(signal_msg);
 }
 
 static void send_volume_updated_signal(struct dbus_entry *de, struct entry *e) {
-    DBusMessage *signal;
+    DBusMessage *signal_msg;
     DBusMessageIter msg_iter;
 
     pa_assert(de);
     pa_assert(e);
 
-    pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_VOLUME_UPDATED].name));
-    dbus_message_iter_init_append(signal, &msg_iter);
+    pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_VOLUME_UPDATED].name));
+    dbus_message_iter_init_append(signal_msg, &msg_iter);
     append_volume(&msg_iter, e);
-    pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal);
-    dbus_message_unref(signal);
+    pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
+    dbus_message_unref(signal_msg);
 }
 
 static void send_mute_updated_signal(struct dbus_entry *de, struct entry *e) {
-    DBusMessage *signal;
+    DBusMessage *signal_msg;
     dbus_bool_t muted;
 
     pa_assert(de);
@@ -494,10 +494,10 @@ static void send_mute_updated_signal(struct dbus_entry *de, struct entry *e) {
 
     muted = e->muted;
 
-    pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_MUTE_UPDATED].name));
-    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &muted, DBUS_TYPE_INVALID));
-    pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal);
-    dbus_message_unref(signal);
+    pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_MUTE_UPDATED].name));
+    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &muted, DBUS_TYPE_INVALID));
+    pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
+    dbus_message_unref(signal_msg);
 }
 
 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata) {
index 1b1e9c1a62624b7da7cc9adff92a9d74cede4b2d..a12f7c936c43854032b479c375dcc804e05a9dd0 100644 (file)
@@ -172,7 +172,7 @@ static pa_bool_t is_card_busy(const char *id) {
             if (status_file)
                 fclose(status_file);
 
-            if (!(status_file = fopen(sub_status, "r"))) {
+            if (!(status_file = pa_fopen_cloexec(sub_status, "r"))) {
                 pa_log_warn("Failed to open %s: %s", sub_status, pa_cstrerror(errno));
                 continue;
             }
index 5a109ae98196ee374196fa04e7824e4e26d485e5..b95023c35d57b404dd546e705a9e3bbdeebd586a 100644 (file)
@@ -55,7 +55,7 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) {
         pcaps = &caps;
 
     if (*mode == O_RDWR) {
-        if ((fd = open(device, O_RDWR|O_NDELAY|O_NOCTTY)) >= 0) {
+        if ((fd = pa_open_cloexec(device, O_RDWR|O_NDELAY, 0)) >= 0) {
             ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
 
             if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) {
@@ -71,14 +71,14 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) {
             pa_close(fd);
         }
 
-        if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY|O_NOCTTY)) < 0) {
-            if ((fd = open(device, (*mode = O_RDONLY)|O_NDELAY|O_NOCTTY)) < 0) {
+        if ((fd = pa_open_cloexec(device, (*mode = O_WRONLY)|O_NDELAY, 0)) < 0) {
+            if ((fd = pa_open_cloexec(device, (*mode = O_RDONLY)|O_NDELAY, 0)) < 0) {
                 pa_log("open('%s'): %s", device, pa_cstrerror(errno));
                 goto fail;
             }
         }
     } else {
-        if ((fd = open(device, *mode|O_NDELAY|O_NOCTTY)) < 0) {
+        if ((fd = pa_open_cloexec(device, *mode|O_NDELAY, 0)) < 0) {
             pa_log("open('%s'): %s", device, pa_cstrerror(errno));
             goto fail;
         }
@@ -145,8 +145,6 @@ success:
     pa_log_debug("capabilities:%s", t);
     pa_xfree(t);
 
-    pa_make_fd_cloexec(fd);
-
     return fd;
 
 fail:
@@ -351,9 +349,9 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) {
     if ((n = get_device_number(dev)) < 0)
         return -1;
 
-    if (!(f = fopen("/dev/sndstat", "r")) &&
-        !(f = fopen("/proc/sndstat", "r")) &&
-        !(f = fopen("/proc/asound/oss/sndstat", "r"))) {
+    if (!(f = pa_fopen_cloexec("/dev/sndstat", "r")) &&
+        !(f = pa_fopen_cloexec("/proc/sndstat", "r")) &&
+        !(f = pa_fopen_cloexec("/proc/asound/oss/sndstat", "r"))) {
 
         if (errno != ENOENT)
             pa_log_warn("failed to open OSS sndstat device: %s", pa_cstrerror(errno));
@@ -403,7 +401,7 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) {
 static int open_mixer(const char *mixer) {
     int fd;
 
-    if ((fd = open(mixer, O_RDWR|O_NDELAY|O_NOCTTY)) >= 0)
+    if ((fd = pa_open_cloexec(mixer, O_RDWR|O_NDELAY, 0)) >= 0)
         return fd;
 
     return -1;
index 1a05f57d1cf80a6005f396a2ef673f2505ad6f6c..7dbb1efa698938382aa3108c946d6f799dc2174f 100644 (file)
@@ -390,7 +390,7 @@ static int mcast_socket(const struct sockaddr* sa, socklen_t salen) {
     pa_assert(salen > 0);
 
     af = sa->sa_family;
-    if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) {
+    if ((fd = pa_socket_cloexec(af, SOCK_DGRAM, 0)) < 0) {
         pa_log("Failed to create socket: %s", pa_cstrerror(errno));
         goto fail;
     }
index 8e1cfe3615065703ea48a31b8ecfe989d2cf82d2..ab8152234b1d545db2e005bd8369535094836675 100644 (file)
@@ -262,7 +262,7 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) {
+    if ((fd = pa_socket_cloexec(af, SOCK_DGRAM, 0)) < 0) {
         pa_log("socket() failed: %s", pa_cstrerror(errno));
         goto fail;
     }
@@ -277,7 +277,7 @@ int pa__init(pa_module*m) {
 #endif
     }
 
-    if ((sap_fd = socket(af, SOCK_DGRAM, 0)) < 0) {
+    if ((sap_fd = pa_socket_cloexec(af, SOCK_DGRAM, 0)) < 0) {
         pa_log("socket() failed: %s", pa_cstrerror(errno));
         goto fail;
     }
@@ -316,8 +316,6 @@ int pa__init(pa_module*m) {
     /* If the socket queue is full, let's drop packets */
     pa_make_fd_nonblock(fd);
     pa_make_udp_socket_low_delay(fd);
-    pa_make_fd_cloexec(fd);
-    pa_make_fd_cloexec(sap_fd);
 
     pa_source_output_new_data_init(&data);
     pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, "RTP Monitor Stream");
index 62c06f6aa7f8530a6a491c67d4b6c7b67b12a3bf..3eaca4d9d3024b400a30fab69b569bacefce2912 100644 (file)
@@ -110,7 +110,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
 
     if (filename) {
 
-        if (!(f = fopen(filename, "r"))) {
+        if (!(f = pa_fopen_cloexec(filename, "r"))) {
             pa_log(_("Failed to open configuration file '%s': %s"), fn, pa_cstrerror(errno));
             goto finish;
         }
index 7468d0a94fe254cd6bdfb83b87c635ac26885b38..e33143d95a20a52848a834e2730f4f3a1e8ac9c0 100644 (file)
@@ -1488,6 +1488,7 @@ pa_time_event* pa_context_rttime_new(pa_context *c, pa_usec_t usec, pa_time_even
     struct timeval tv;
 
     pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
     pa_assert(c->mainloop);
 
     if (usec == PA_USEC_INVALID)
@@ -1502,8 +1503,10 @@ void pa_context_rttime_restart(pa_context *c, pa_time_event *e, pa_usec_t usec)
     struct timeval tv;
 
     pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
     pa_assert(c->mainloop);
 
+
     if (usec == PA_USEC_INVALID)
         c->mainloop->time_restart(e, NULL);
     else {
@@ -1511,3 +1514,17 @@ void pa_context_rttime_restart(pa_context *c, pa_time_event *e, pa_usec_t usec)
         c->mainloop->time_restart(e, &tv);
     }
 }
+
+size_t pa_context_get_tile_size(pa_context *c, const pa_sample_spec *ss) {
+    size_t fs, mbs;
+
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, (size_t) -1);
+    PA_CHECK_VALIDITY_RETURN_ANY(c, !ss || pa_sample_spec_valid(ss), PA_ERR_INVALID, (size_t) -1);
+
+    fs = ss ? pa_frame_size(ss) : 1;
+    mbs = PA_ROUND_DOWN(pa_mempool_block_size_max(c->mempool), fs);
+    return PA_MAX(mbs, fs);
+}
index ecff58dfcce060918c71e8f981c1e62751f07e9f..6ac8ee566bd90748992e076fcaf5d418a4f721c1 100644 (file)
@@ -255,12 +255,28 @@ pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[]
 uint32_t pa_context_get_index(pa_context *s);
 
 /** Create a new timer event source for the specified time (wrapper
   for mainloop->time_new). \since 0.9.16 */
* for mainloop->time_new). \since 0.9.16 */
 pa_time_event* pa_context_rttime_new(pa_context *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata);
-/** Restart a running or expired timer event source (wrapper
-    for mainloop->time_restart). \since 0.9.16 */
+
+/** Restart a running or expired timer event source (wrapper for
+ * mainloop->time_restart). \since 0.9.16 */
 void pa_context_rttime_restart(pa_context *c, pa_time_event *e, pa_usec_t usec);
 
+/* Return the optimal block size for passing around audio buffers. It
+ * is recommended to allocate buffers of the size returned here when
+ * writing audio data to playback streams, if the latency constraints
+ * permit this. It is not recommended writing larger blocks than this
+ * because usually they will then be split up internally into chunks
+ * of this size. It is not recommended writing smaller blocks than
+ * this (unless required due to latency demands) because this
+ * increases CPU usage. If ss is NULL you will be returned the
+ * byte-exact tile size. If you pass a valid ss, then the tile size
+ * will be rounded down to multiple of the frame size. This is
+ * supposed to be used in a construct such as
+ * pa_context_get_tile_size(pa_stream_get_context(s),
+ * pa_stream_get_sample_spec(ss)); \since 0.9.20 */
+size_t pa_context_get_tile_size(pa_context *c, const pa_sample_spec *ss);
+
 PA_C_DECL_END
 
 #endif
index 5d0a0b4b5114868726ebefe31d9ef2115c23e05a..30a076d55323ce859b41c0fa94e45a400f8ae2c4 100644 (file)
@@ -276,11 +276,18 @@ typedef enum pa_stream_flags {
      * whether to create the stream in muted or in unmuted
      * state. \since 0.9.15 */
 
-    PA_STREAM_FAIL_ON_SUSPEND = 0x20000U
+    PA_STREAM_FAIL_ON_SUSPEND = 0x20000U,
     /**< If the sink/source this stream is connected to is suspended
      * during the creation of this stream, cause it to fail. If the
      * sink/source is being suspended during creation of this stream,
      * make sure this stream is terminated. \since 0.9.15 */
+
+    PA_STREAM_RELATIVE_VOLUME = 0x40000U,
+    /**< If a volume is passed when this stream is created, consider
+     * it relative to the sink's current volume, never as absolute
+     * device volume. If this is not specified the volume will be
+     * consider absolute when the sink is in flat volume mode,
+     * relative otherwise. \since 0.9.20 */
 } pa_stream_flags_t;
 
 /** \cond fulldocs */
@@ -307,6 +314,7 @@ typedef enum pa_stream_flags {
 #define PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
 #define PA_STREAM_START_UNMUTED PA_STREAM_START_UNMUTED
 #define PA_STREAM_FAIL_ON_SUSPEND PA_STREAM_FAIL_ON_SUSPEND
+#define PA_STREAM_RELATIVE_VOLUME PA_STREAM_RELATIVE_VOLUME
 
 /** \endcond */
 
index 1442a1a9e94fa2fa7cccd65ef7c46db3f2143216..df0ab92f568bd42dbe26209ae44f4abf13eac4f5 100644 (file)
@@ -39,7 +39,7 @@ typedef struct pa_ext_device_manager_role_priority_info {
 } pa_ext_device_manager_role_priority_info;
 
 /** Stores information about one device in the device database that is
- * maintained by module-device-manager. \since 0.9.19 */
+ * maintained by module-device-manager. \since 0.9.21 */
 typedef struct pa_ext_device_manager_info {
     const char *name;            /**< Identifier string of the device. A string like "sink:" or similar followed by the name of the device. */
     const char *description;     /**< The description of the device when it was last seen, if applicable and saved */
@@ -49,32 +49,32 @@ typedef struct pa_ext_device_manager_info {
     pa_ext_device_manager_role_priority_info *role_priorities; /**< An array of role priority structures or NULL */
 } pa_ext_device_manager_info;
 
-/** Callback prototype for pa_ext_device_manager_test(). \since 0.9.19 */
+/** Callback prototype for pa_ext_device_manager_test(). \since 0.9.21 */
 typedef void (*pa_ext_device_manager_test_cb_t)(
         pa_context *c,
         uint32_t version,
         void *userdata);
 
-/** Test if this extension module is available in the server. \since 0.9.19 */
+/** Test if this extension module is available in the server. \since 0.9.21 */
 pa_operation *pa_ext_device_manager_test(
         pa_context *c,
         pa_ext_device_manager_test_cb_t cb,
         void *userdata);
 
-/** Callback prototype for pa_ext_device_manager_read(). \since 0.9.19 */
+/** Callback prototype for pa_ext_device_manager_read(). \since 0.9.21 */
 typedef void (*pa_ext_device_manager_read_cb_t)(
         pa_context *c,
         const pa_ext_device_manager_info *info,
         int eol,
         void *userdata);
 
-/** Read all entries from the device database. \since 0.9.19 */
+/** Read all entries from the device database. \since 0.9.21 */
 pa_operation *pa_ext_device_manager_read(
         pa_context *c,
         pa_ext_device_manager_read_cb_t cb,
         void *userdata);
 
-/** Sets the description for a device. \since 0.9.19 */
+/** Sets the description for a device. \since 0.9.21 */
 pa_operation *pa_ext_device_manager_set_device_description(
         pa_context *c,
         const char* device,
@@ -82,21 +82,21 @@ pa_operation *pa_ext_device_manager_set_device_description(
         pa_context_success_cb_t cb,
         void *userdata);
 
-/** Delete entries from the device database. \since 0.9.19 */
+/** Delete entries from the device database. \since 0.9.21 */
 pa_operation *pa_ext_device_manager_delete(
         pa_context *c,
         const char *const s[],
         pa_context_success_cb_t cb,
         void *userdata);
 
-/** Enable the role-based device-priority routing mode. \since 0.9.19 */
+/** Enable the role-based device-priority routing mode. \since 0.9.21 */
 pa_operation *pa_ext_device_manager_enable_role_device_priority_routing(
         pa_context *c,
         int enable,
         pa_context_success_cb_t cb,
         void *userdata);
 
-/** Prefer a given device in the priority list. \since 0.9.19 */
+/** Prefer a given device in the priority list. \since 0.9.21 */
 pa_operation *pa_ext_device_manager_reorder_devices_for_role(
         pa_context *c,
         const char* role,
@@ -104,20 +104,20 @@ pa_operation *pa_ext_device_manager_reorder_devices_for_role(
         pa_context_success_cb_t cb,
         void *userdata);
 
-/** Subscribe to changes in the device database. \since 0.9.19 */
+/** Subscribe to changes in the device database. \since 0.9.21 */
 pa_operation *pa_ext_device_manager_subscribe(
         pa_context *c,
         int enable,
         pa_context_success_cb_t cb,
         void *userdata);
 
-/** Callback prototype for pa_ext_device_manager_set_subscribe_cb(). \since 0.9.19 */
+/** Callback prototype for pa_ext_device_manager_set_subscribe_cb(). \since 0.9.21 */
 typedef void (*pa_ext_device_manager_subscribe_cb_t)(
         pa_context *c,
         void *userdata);
 
 /** Set the subscription callback that is called when
- * pa_ext_device_manager_subscribe() was called. \since 0.9.19 */
+ * pa_ext_device_manager_subscribe() was called. \since 0.9.21 */
 void pa_ext_device_manager_set_subscribe_cb(
         pa_context *c,
         pa_ext_device_manager_subscribe_cb_t cb,
index 3dc74398182bf5ffbbda2b526aa55cf475a39f17..70c0122c2de1d710acabc1ebfe6dea94e2184c49 100644 (file)
@@ -124,15 +124,13 @@ int pa_signal_init(pa_mainloop_api *a) {
     pa_assert(signal_pipe[1] == -1);
     pa_assert(!io_event);
 
-    if (pipe(signal_pipe) < 0) {
+    if (pa_pipe_cloexec(signal_pipe) < 0) {
         pa_log("pipe(): %s", pa_cstrerror(errno));
         return -1;
     }
 
     pa_make_fd_nonblock(signal_pipe[0]);
     pa_make_fd_nonblock(signal_pipe[1]);
-    pa_make_fd_cloexec(signal_pipe[0]);
-    pa_make_fd_cloexec(signal_pipe[1]);
 
     api = a;
 
index 090ac8c2a491dd1072072d4602bc6a4618e622ad..6cd089ef568cdb465ff16a6dc87cf6ea89852416 100644 (file)
@@ -482,7 +482,7 @@ pa_mainloop *pa_mainloop_new(void) {
 
     m = pa_xnew0(pa_mainloop, 1);
 
-    if (pipe(m->wakeup_pipe) < 0) {
+    if (pa_pipe_cloexec(m->wakeup_pipe) < 0) {
         pa_log_error("ERROR: cannot create wakeup pipe");
         pa_xfree(m);
         return NULL;
@@ -490,8 +490,6 @@ pa_mainloop *pa_mainloop_new(void) {
 
     pa_make_fd_nonblock(m->wakeup_pipe[0]);
     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->rebuild_pollfds = TRUE;
 
index 2bc2b1e4ae0fd1dc189ca02ce73ae15147d2550e..4dea56707227e75205b19e98d66be3c3820b6ff8 100644 (file)
@@ -387,9 +387,26 @@ static void check_smoother_status(pa_stream *s, pa_bool_t aposteriori, pa_bool_t
 
     if (s->suspended || s->corked || force_stop)
         pa_smoother_pause(s->smoother, x);
-    else if (force_start || s->buffer_attr.prebuf == 0)
-        pa_smoother_resume(s->smoother, x, TRUE);
+    else if (force_start || s->buffer_attr.prebuf == 0) {
+
+        if (!s->timing_info_valid &&
+            !aposteriori &&
+            !force_start &&
+            !force_stop &&
+            s->context->version >= 13) {
+
+            /* If the server supports STARTED events we take them as
+             * indications when audio really starts/stops playing, if
+             * we don't have any timing info yet -- instead of trying
+             * to be smart and guessing the server time. Otherwise the
+             * unknown transport delay add too much noise to our time
+             * calculations. */
+
+            return;
+        }
 
+        pa_smoother_resume(s->smoother, x, TRUE);
+    }
 
     /* Please note that we have no idea if playback actually started
      * if prebuf is non-zero! */
@@ -1025,7 +1042,8 @@ static int create_stream(
                                               PA_STREAM_EARLY_REQUESTS|
                                               PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND|
                                               PA_STREAM_START_UNMUTED|
-                                              PA_STREAM_FAIL_ON_SUSPEND)), PA_ERR_INVALID);
+                                              PA_STREAM_FAIL_ON_SUSPEND|
+                                              PA_STREAM_RELATIVE_VOLUME)), PA_ERR_INVALID);
 
     PA_CHECK_VALIDITY(s->context, s->context->version >= 12 || !(flags & PA_STREAM_VARIABLE_RATE), PA_ERR_NOTSUPPORTED);
     PA_CHECK_VALIDITY(s->context, s->context->version >= 13 || !(flags & PA_STREAM_PEAK_DETECT), PA_ERR_NOTSUPPORTED);
@@ -1158,6 +1176,13 @@ static int create_stream(
         pa_tagstruct_put_boolean(t, flags & PA_STREAM_FAIL_ON_SUSPEND);
     }
 
+    if (s->context->version >= 17) {
+
+        if (s->direction == PA_STREAM_PLAYBACK)
+            pa_tagstruct_put_boolean(t, flags & PA_STREAM_RELATIVE_VOLUME);
+
+    }
+
     pa_pstream_send_tagstruct(s->context->pstream, t);
     pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL);
 
@@ -1457,6 +1482,11 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
 
+    /* Ask for a timing update before we cork/uncork to get the best
+     * accuracy for the transport latency suitable for the
+     * check_smoother_status() call in the started callback */
+    request_auto_timing_update(s, TRUE);
+
     o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
 
     t = pa_tagstruct_command(s->context, PA_COMMAND_DRAIN_PLAYBACK_STREAM, &tag);
@@ -1464,6 +1494,10 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us
     pa_pstream_send_tagstruct(s->context->pstream, t);
     pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
 
+    /* This might cause the read index to conitnue again, hence
+     * let's request a timing update */
+    request_auto_timing_update(s, TRUE);
+
     return o;
 }
 
@@ -2012,6 +2046,11 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
 
+    /* Ask for a timing update before we cork/uncork to get the best
+     * accuracy for the transport latency suitable for the
+     * check_smoother_status() call in the started callback */
+    request_auto_timing_update(s, TRUE);
+
     s->corked = b;
 
     o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
@@ -2027,8 +2066,8 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi
 
     check_smoother_status(s, FALSE, FALSE, FALSE);
 
-    /* This might cause the indexes to hang/start again, hence
-     * let's request a timing update */
+    /* This might cause the indexes to hang/start again, hence let's
+     * request a timing update, after the cork/uncork, too */
     request_auto_timing_update(s, TRUE);
 
     return o;
@@ -2065,6 +2104,11 @@ pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *use
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
 
+    /* Ask for a timing update *before* the flush, so that the
+     * transport usec is as up to date as possible when we get the
+     * underflow message and update the smoother status*/
+    request_auto_timing_update(s, TRUE);
+
     if (!(o = stream_send_simple_command(s, (uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM), cb, userdata)))
         return NULL;
 
@@ -2099,6 +2143,11 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE);
 
+    /* Ask for a timing update before we cork/uncork to get the best
+     * accuracy for the transport latency suitable for the
+     * check_smoother_status() call in the started callback */
+    request_auto_timing_update(s, TRUE);
+
     if (!(o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata)))
         return NULL;
 
@@ -2120,6 +2169,11 @@ pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *u
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE);
 
+    /* Ask for a timing update before we cork/uncork to get the best
+     * accuracy for the transport latency suitable for the
+     * check_smoother_status() call in the started callback */
+    request_auto_timing_update(s, TRUE);
+
     if (!(o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata)))
         return NULL;
 
@@ -2371,6 +2425,11 @@ pa_operation* pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 12, PA_ERR_NOTSUPPORTED);
 
+    /* Ask for a timing update before we cork/uncork to get the best
+     * accuracy for the transport latency suitable for the
+     * check_smoother_status() call in the started callback */
+    request_auto_timing_update(s, TRUE);
+
     o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
 
     t = pa_tagstruct_command(
index 2e8e71a0d6bc1c51e18be013a6462a97655f946c..bc54a11892b792c8863d3a4804c3e45005ce99c6 100644 (file)
@@ -401,7 +401,22 @@ int pa_stream_is_suspended(pa_stream *s);
  * not, and negative on error. \since 0.9.11 */
 int pa_stream_is_corked(pa_stream *s);
 
-/** Connect the stream to a sink */
+/** Connect the stream to a sink. It is strongly recommended to pass
+ * NULL in both dev and volume and not to set either
+ * PA_STREAM_START_MUTED nor PA_STREAM_START_UNMUTED -- unless these
+ * options are directly dependant on user input or configuration. If
+ * you follow this rule then the sound server will have the full
+ * flexibility to choose the device, volume and mute status
+ * automatically, based on server-side policies, heuristics and stored
+ * information from previous uses. Also the server may choose to
+ * reconfigure audio devices to make other sinks/sources or
+ * capabilities available to be able to accept the stream. Before
+ * 0.9.20 it was not defined whether the 'volume' parameter was
+ * interpreted relative to the sink's current volume or treated as
+ * absolute device volume. Since 0.9.20 it is an absolute volume when
+ * the sink is in flat volume mode, and relative otherwise, thus
+ * making sure the volume passed here has always the same semantics as
+ * the volume passed to pa_context_set_sink_input_volume(). */
 int pa_stream_connect_playback(
         pa_stream *s                  /**< The stream to connect to a sink */,
         const char *dev               /**< Name of the sink to connect to, or NULL for default */ ,
index 9440f5de3fbcdce3a998b549d4ac76321f2e641d..ca766dab75dfc7966ba987d11fe411fda930083c 100644 (file)
@@ -189,7 +189,18 @@ char *pa_get_binary_name(char *s, size_t l) {
             return s;
         }
     }
+#endif
 
+#ifdef __FreeBSD__
+    {
+        char *rp;
+
+       if ((rp = pa_readlink("/proc/curproc/file"))) {
+           pa_strlcpy(s, pa_path_get_filename(rp), l);
+           pa_xfree(rp);
+           return s;
+       }
+    }
 #endif
 
 #if defined(HAVE_SYS_PRCTL_H) && defined(PR_GET_NAME)
index 2d2bba2506defa3b878040801a07880f715213d5..59e9a18906777f19b659b734986d8f9e18d2f4ab 100644 (file)
@@ -885,7 +885,7 @@ pa_cvolume* pa_cvolume_merge(pa_cvolume *dest, const pa_cvolume *a, const pa_cvo
     return dest;
 }
 
-pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc) {
+pa_cvolume* pa_cvolume_inc_clamp(pa_cvolume *v, pa_volume_t inc, pa_volume_t limit) {
     pa_volume_t m;
 
     pa_assert(v);
@@ -895,14 +895,18 @@ pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc) {
 
     m = pa_cvolume_max(v);
 
-    if (m >= PA_VOLUME_MAX - inc)
-        m = PA_VOLUME_MAX;
+    if (m >= limit - inc)
+        m = limit;
     else
         m += inc;
 
     return pa_cvolume_scale(v, m);
 }
 
+pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc){
+    return pa_cvolume_inc_clamp(v, inc, PA_VOLUME_MAX);
+}
+
 pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec) {
     pa_volume_t m;
 
index c964020ac4e5e3bda205f7483585b168793643fd..ded4422e81e60223026a1f8f0ee2e74a03199354 100644 (file)
@@ -348,6 +348,10 @@ pa_volume_t pa_cvolume_get_position(pa_cvolume *cv, const pa_channel_map *map, p
  * and dest may point to the same structure. \since 0.9.16 */
 pa_cvolume* pa_cvolume_merge(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b);
 
+/** Increase the volume passed in by 'inc', but not exceeding 'limit'.
+ * The proportions between the channels are kept. \since 0.9.19 */
+pa_cvolume* pa_cvolume_inc_clamp(pa_cvolume *v, pa_volume_t inc, pa_volume_t limit);
+
 /** Increase the volume passed in by 'inc'. The proportions between
  * the channels are kept. \since 0.9.16 */
 pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc);
index 119c445be9379402909b09f1e08c86e0695d5ec6..51d08210d6f7fd88e72090ec41907fdef13f1b89 100644 (file)
@@ -180,6 +180,110 @@ static inline pa_bool_t pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, v
     return r == old_p;
 }
 
+#elif defined(__FreeBSD__)
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <machine/atomic.h>
+
+#if __FreeBSD_version < 600000
+#if defined(__i386__) || defined(__amd64__)
+#if defined(__amd64__)
+#define atomic_load_acq_64      atomic_load_acq_long
+#endif
+static inline u_int atomic_fetchadd_int(volatile u_int *p, u_int v) {
+    __asm __volatile(
+            "   " __XSTRING(MPLOCKED) "         "
+            "   xaddl   %0, %1 ;        "
+            "# atomic_fetchadd_int"
+            : "+r" (v),
+            "=m" (*p)
+            : "m" (*p));
+
+    return (v);
+}
+#elif defined(__sparc64__)
+#define atomic_load_acq_64      atomic_load_acq_long
+#define atomic_fetchadd_int     atomic_add_int
+#elif defined(__ia64__)
+#define atomic_load_acq_64      atomic_load_acq_long
+static inline uint32_t
+atomic_fetchadd_int(volatile uint32_t *p, uint32_t v) {
+    uint32_t value;
+
+    do {
+        value = *p;
+    } while (!atomic_cmpset_32(p, value, value + v));
+    return (value);
+}
+#endif
+#endif
+
+typedef struct pa_atomic {
+    volatile unsigned long value;
+} pa_atomic_t;
+
+#define PA_ATOMIC_INIT(v) { .value = (v) }
+
+static inline int pa_atomic_load(const pa_atomic_t *a) {
+    return (int) atomic_load_acq_int((unsigned int *) &a->value);
+}
+
+static inline void pa_atomic_store(pa_atomic_t *a, int i) {
+    atomic_store_rel_int((unsigned int *) &a->value, i);
+}
+
+static inline int pa_atomic_add(pa_atomic_t *a, int i) {
+    return atomic_fetchadd_int((unsigned int *) &a->value, i);
+}
+
+static inline int pa_atomic_sub(pa_atomic_t *a, int i) {
+    return atomic_fetchadd_int((unsigned int *) &a->value, -(i));
+}
+
+static inline int pa_atomic_inc(pa_atomic_t *a) {
+    return atomic_fetchadd_int((unsigned int *) &a->value, 1);
+}
+
+static inline int pa_atomic_dec(pa_atomic_t *a) {
+    return atomic_fetchadd_int((unsigned int *) &a->value, -1);
+}
+
+static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) {
+    return atomic_cmpset_int((unsigned int *) &a->value, old_i, new_i);
+}
+
+typedef struct pa_atomic_ptr {
+    volatile unsigned long value;
+} pa_atomic_ptr_t;
+
+#define PA_ATOMIC_PTR_INIT(v) { .value = (unsigned long) (v) }
+
+static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) {
+#ifdef atomic_load_acq_64
+    return (void*) atomic_load_acq_ptr((unsigned long *) &a->value);
+#else
+    return (void*) atomic_load_acq_ptr((unsigned int *) &a->value);
+#endif
+}
+
+static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) {
+#ifdef atomic_load_acq_64
+    atomic_store_rel_ptr(&a->value, (unsigned long) p);
+#else
+    atomic_store_rel_ptr((unsigned int *) &a->value, (unsigned int) p);
+#endif
+}
+
+static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) {
+#ifdef atomic_load_acq_64
+    return atomic_cmpset_ptr(&a->value, (unsigned long) old_p, (unsigned long) new_p);
+#else
+    return atomic_cmpset_ptr((unsigned int *) &a->value, (unsigned int) old_p, (unsigned int) new_p);
+#endif
+}
+
 #elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__))
 
 #warn "The native atomic operations implementation for AMD64 has not been tested thoroughly. libatomic_ops is known to not work properly on AMD64 and your gcc version is too old for the gcc-builtin atomic ops support. You have three options now: test the native atomic operations implementation for AMD64, fix libatomic_ops, or upgrade your GCC."
index 15613e273015dfedb4e592808a5254f109fe4808..d671e367c30a41ff46120e8bfab42e594b89224e 100644 (file)
@@ -70,10 +70,6 @@ static int generate(int fd, void *ret_data, size_t length) {
 #define O_BINARY 0
 #endif
 
-#ifndef O_NOCTTY
-#define O_NOCTTY 0
-#endif
-
 /* Load an euthorization cookie from file fn and store it in data. If
  * the cookie file doesn't exist, create it */
 static int load(const char *fn, void *data, size_t length) {
@@ -86,9 +82,9 @@ static int load(const char *fn, void *data, size_t length) {
     pa_assert(data);
     pa_assert(length > 0);
 
-    if ((fd = open(fn, O_RDWR|O_CREAT|O_BINARY|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) {
+    if ((fd = pa_open_cloexec(fn, O_RDWR|O_CREAT|O_BINARY, S_IRUSR|S_IWUSR)) < 0) {
 
-        if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY|O_NOCTTY)) < 0) {
+        if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY)) < 0) {
             pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
             goto finish;
         } else
@@ -204,7 +200,7 @@ int pa_authkey_save(const char *fn, const void *data, size_t length) {
     if (!(p = normalize_path(fn)))
         return -2;
 
-    if ((fd = open(p, O_RDWR|O_CREAT|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) {
+    if ((fd = pa_open_cloexec(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
         pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
         goto finish;
     }
index b57919a44e5f7da98957dcf431419cd57196cf0b..82a44d84e877826c13341558dd7e45f05ff64de4 100644 (file)
@@ -1804,7 +1804,7 @@ int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_b
     if (!fail)
         fail = &_fail;
 
-    if (!(f = fopen(fn, "r"))) {
+    if (!(f = pa_fopen_cloexec(fn, "r"))) {
         pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, pa_cstrerror(errno));
         if (!*fail)
             ret = 0;
index dd4a99ee9e167a6e1c013a880564aa5104c9211d..34b4d6fe21b5752feebd72d12930dd3a689c7696 100644 (file)
@@ -168,7 +168,7 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void
     pa_assert(filename);
     pa_assert(t);
 
-    if (!f && !(f = fopen(filename, "r"))) {
+    if (!f && !(f = pa_fopen_cloexec(filename, "r"))) {
         if (errno == ENOENT) {
             pa_log_debug("Failed to open configuration file '%s': %s", filename, pa_cstrerror(errno));
             r = 0;
index 1420470a595ca5599c88be34e07b74d55d2cd894..4fe0a47ba041367ed73bd828b55257bf71e08cbb 100644 (file)
 #include <sys/prctl.h>
 #endif
 
+#ifdef OS_IS_DARWIN
+#include <CoreServices/CoreServices.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#endif
+
 #include <pulse/timeval.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/core-error.h>
@@ -47,7 +53,8 @@ pa_usec_t pa_rtclock_age(const struct timeval *tv) {
 }
 
 struct timeval *pa_rtclock_get(struct timeval *tv) {
-#ifdef HAVE_CLOCK_GETTIME
+
+#if defined(HAVE_CLOCK_GETTIME)
     struct timespec ts;
 
 #ifdef CLOCK_MONOTONIC
@@ -59,7 +66,7 @@ struct timeval *pa_rtclock_get(struct timeval *tv) {
             no_monotonic = TRUE;
 
     if (no_monotonic)
-#endif
+#endif /* CLOCK_MONOTONIC */
         pa_assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
 
     pa_assert(tv);
@@ -69,7 +76,30 @@ struct timeval *pa_rtclock_get(struct timeval *tv) {
 
     return tv;
 
-#else /* HAVE_CLOCK_GETTIME */
+#elif defined(OS_IS_DARWIN)
+    static mach_timebase_info_data_t   tbi;
+    uint64_t nticks;
+    uint64_t time_nsec;
+
+    /* Refer Apple ADC QA1398
+       Also: http://devworld.apple.com/documentation/Darwin/Conceptual/KernelProgramming/services/services.html
+
+       Note: argument is timespec NOT timeval (timespec uses nsec, timeval uses usec)
+    */
+
+    /* try and be a mite efficient - maybe I should keep the N/D as a float !? */
+    if (tbi.denom == 0)
+        mach_timebase_info(&tbi);
+
+    nticks = mach_absolute_time();
+    time_nsec = nticks * tbi.numer / tbi.denom; // see above
+
+    tv->tv_sec = time_nsec / PA_NSEC_PER_SEC;
+    tv->tv_usec = time_nsec / PA_NSEC_PER_USEC;
+
+    return tv;
+
+#else /* OS_IS_DARWIN */
 
     return pa_gettimeofday(tv);
 
@@ -77,19 +107,30 @@ struct timeval *pa_rtclock_get(struct timeval *tv) {
 }
 
 pa_bool_t pa_rtclock_hrtimer(void) {
-#ifdef HAVE_CLOCK_GETTIME
+
+#if defined(HAVE_CLOCK_GETTIME)
     struct timespec ts;
 
 #ifdef CLOCK_MONOTONIC
+
     if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0)
         return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
-#endif
+#endif /* CLOCK_MONOTONIC */
 
     pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0);
     return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
 
-#else /* HAVE_CLOCK_GETTIME */
+#elif defined (OS_IS_DARWIN)
+    mach_timebase_info_data_t tbi;
+    uint64_t time_nsec;
+
+    mach_timebase_info(&tbi);
 
+    /* nsec = nticks * (N/D) - we want 1 tick == resolution !? */
+    time_nsec = tbi.numer / tbi.denom;
+    return time_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
+
+#else /* OS_IS_DARWIN */
     return FALSE;
 
 #endif
@@ -98,6 +139,7 @@ pa_bool_t pa_rtclock_hrtimer(void) {
 #define TIMER_SLACK_NS (int) ((500 * PA_NSEC_PER_USEC))
 
 void pa_rtclock_hrtimer_enable(void) {
+
 #ifdef PR_SET_TIMERSLACK
     int slack_ns;
 
index 27e09cbce6622dae80d9d4d98a5dd3d49e0e25ad..d596c481a9b3c1f5336867b8854b2b9a3a34fbcc 100644 (file)
 #include <pulsecore/strbuf.h>
 #include <pulsecore/usergroup.h>
 #include <pulsecore/strlist.h>
+#include <pulsecore/cpu-x86.h>
 
 #include "core-util.h"
 
@@ -1200,10 +1201,7 @@ int pa_lock_lockfile(const char *fn) {
     for (;;) {
         struct stat st;
 
-        if ((fd = open(fn, O_CREAT|O_RDWR
-#ifdef O_NOCTTY
-                       |O_NOCTTY
-#endif
+        if ((fd = pa_open_cloexec(fn, O_CREAT|O_RDWR
 #ifdef O_NOFOLLOW
                        |O_NOFOLLOW
 #endif
@@ -1603,7 +1601,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
         fn = buf;
 #endif
 
-        if ((f = fopen(fn, "r"))) {
+        if ((f = pa_fopen_cloexec(fn, "r"))) {
             if (result)
                 *result = pa_xstrdup(fn);
 
@@ -1637,7 +1635,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
         fn = buf;
 #endif
 
-        if ((f = fopen(fn, "r"))) {
+        if ((f = pa_fopen_cloexec(fn, "r"))) {
             if (result)
                 *result = pa_xstrdup(fn);
 
@@ -1664,7 +1662,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
         global = buf;
 #endif
 
-        if ((f = fopen(global, "r"))) {
+        if ((f = pa_fopen_cloexec(global, "r"))) {
 
             if (result)
                 *result = pa_xstrdup(global);
@@ -2563,7 +2561,7 @@ char *pa_machine_id(void) {
      * since it fits perfectly our needs and is not as volatile as the
      * hostname which might be set from dhcp. */
 
-    if ((f = fopen(PA_MACHINE_ID, "r"))) {
+    if ((f = pa_fopen_cloexec(PA_MACHINE_ID, "r"))) {
         char ln[34] = "", *r;
 
         r = fgets(ln, sizeof(ln)-1, f);
@@ -2889,3 +2887,224 @@ const char *pa_get_temp_dir(void) {
 
     return "/tmp";
 }
+
+int pa_open_cloexec(const char *fn, int flags, mode_t mode) {
+    int fd;
+
+#ifdef O_NOCTTY
+    flags |= O_NOCTTY;
+#endif
+
+#ifdef O_CLOEXEC
+    if ((fd = open(fn, flags|O_CLOEXEC, mode)) >= 0)
+        goto finish;
+
+    if (errno != EINVAL)
+        return fd;
+#endif
+
+    if ((fd = open(fn, flags, mode)) < 0)
+        return fd;
+
+finish:
+    /* Some implementations might simply ignore O_CLOEXEC if it is not
+     * understood, make sure FD_CLOEXEC is enabled anyway */
+
+    pa_make_fd_cloexec(fd);
+    return fd;
+}
+
+int pa_socket_cloexec(int domain, int type, int protocol) {
+    int fd;
+
+#ifdef SOCK_CLOEXEC
+    if ((fd = socket(domain, type | SOCK_CLOEXEC, protocol)) >= 0)
+        goto finish;
+
+    if (errno != EINVAL)
+        return fd;
+#endif
+
+    if ((fd = socket(domain, type, protocol)) < 0)
+        return fd;
+
+finish:
+    /* Some implementations might simply ignore SOCK_CLOEXEC if it is
+     * not understood, make sure FD_CLOEXEC is enabled anyway */
+
+    pa_make_fd_cloexec(fd);
+    return fd;
+}
+
+int pa_pipe_cloexec(int pipefd[2]) {
+    int r;
+
+#ifdef HAVE_PIPE2
+    if ((r = pipe2(pipefd, O_CLOEXEC)) >= 0)
+        goto finish;
+
+    if (errno != EINVAL && errno != ENOSYS)
+        return r;
+
+#endif
+
+    if ((r = pipe(pipefd)) < 0)
+        return r;
+
+finish:
+    pa_make_fd_cloexec(pipefd[0]);
+    pa_make_fd_cloexec(pipefd[1]);
+
+    return 0;
+}
+
+int pa_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
+    int fd;
+
+#ifdef HAVE_ACCEPT4
+    if ((fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC)) >= 0)
+        goto finish;
+
+    if (errno != EINVAL && errno != ENOSYS)
+        return fd;
+
+#endif
+
+    if ((fd = accept(sockfd, addr, addrlen)) < 0)
+        return fd;
+
+finish:
+    pa_make_fd_cloexec(fd);
+    return fd;
+}
+
+FILE* pa_fopen_cloexec(const char *path, const char *mode) {
+    FILE *f;
+    char *m;
+
+    m = pa_sprintf_malloc("%se", mode);
+
+    errno = 0;
+    if ((f = fopen(path, m))) {
+        pa_xfree(m);
+        goto finish;
+    }
+
+    pa_xfree(m);
+
+    if (errno != EINVAL)
+        return NULL;
+
+    if (!(f = fopen(path, mode)))
+        return NULL;
+
+finish:
+    pa_make_fd_cloexec(fileno(f));
+    return f;
+}
+
+void pa_nullify_stdfds(void) {
+
+#ifndef OS_IS_WIN32
+        pa_close(STDIN_FILENO);
+        pa_close(STDOUT_FILENO);
+        pa_close(STDERR_FILENO);
+
+        pa_assert_se(open("/dev/null", O_RDONLY) == STDIN_FILENO);
+        pa_assert_se(open("/dev/null", O_WRONLY) == STDOUT_FILENO);
+        pa_assert_se(open("/dev/null", O_WRONLY) == STDERR_FILENO);
+#else
+        FreeConsole();
+#endif
+
+}
+
+char *pa_read_line_from_file(const char *fn) {
+    FILE *f;
+    char ln[256] = "", *r;
+
+    if (!(f = pa_fopen_cloexec(fn, "r")))
+        return NULL;
+
+    r = fgets(ln, sizeof(ln)-1, f);
+    fclose(f);
+
+    if (!r) {
+        errno = EIO;
+        return NULL;
+    }
+
+    pa_strip_nl(ln);
+    return pa_xstrdup(ln);
+}
+
+pa_bool_t pa_running_in_vm(void) {
+
+#if defined(__i386__) || defined(__x86_64__)
+
+    /* Both CPUID and DMI are x86 specific interfaces... */
+
+    uint32_t eax = 0x40000000;
+    union {
+        uint32_t sig32[3];
+        char text[13];
+    } sig;
+
+#ifdef __linux__
+    const char *const dmi_vendors[] = {
+        "/sys/class/dmi/id/sys_vendor",
+        "/sys/class/dmi/id/board_vendor",
+        "/sys/class/dmi/id/bios_vendor"
+    };
+
+    unsigned i;
+
+    for (i = 0; i < PA_ELEMENTSOF(dmi_vendors); i++) {
+        char *s;
+
+        if ((s = pa_read_line_from_file(dmi_vendors[i]))) {
+
+            if (pa_startswith(s, "QEMU") ||
+                /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
+                pa_startswith(s, "VMware") ||
+                pa_startswith(s, "VMW") ||
+                pa_startswith(s, "Microsoft Corporation") ||
+                pa_startswith(s, "innotek GmbH") ||
+                pa_startswith(s, "Xen")) {
+
+                pa_xfree(s);
+                return TRUE;
+            }
+
+            pa_xfree(s);
+        }
+    }
+
+#endif
+
+    /* http://lwn.net/Articles/301888/ */
+    pa_zero(sig);
+
+    __asm__ __volatile__ (
+        /* ebx/rbx is being used for PIC! */
+        "  push %%"PA_REG_b"         \n\t"
+        "  cpuid                     \n\t"
+        "  mov %%ebx, %1             \n\t"
+        "  pop %%"PA_REG_b"          \n\t"
+
+        : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
+        : "0" (eax)
+    );
+
+    if (pa_streq(sig.text, "XenVMMXenVMM") ||
+        pa_streq(sig.text, "KVMKVMKVM") ||
+        /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
+        pa_streq(sig.text, "VMwareVMware") ||
+        /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
+        pa_streq(sig.text, "Microsoft Hv"))
+        return TRUE;
+
+#endif
+
+    return FALSE;
+}
index 9986b14a022e46f41c0effdcdeede20450f8f533..31a83bcc2336e0cb304395899cd901edeeeee4cb 100644 (file)
@@ -28,6 +28,7 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/socket.h>
 
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
@@ -258,4 +259,15 @@ pa_bool_t pa_run_from_build_tree(void);
 
 const char *pa_get_temp_dir(void);
 
+int pa_open_cloexec(const char *fn, int flags, mode_t mode);
+int pa_socket_cloexec(int domain, int type, int protocol);
+int pa_pipe_cloexec(int pipefd[2]);
+int pa_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+FILE* pa_fopen_cloexec(const char *path, const char *mode);
+
+void pa_nullify_stdfds(void);
+
+char *pa_read_line_from_file(const char *fn);
+pa_bool_t pa_running_in_vm(void);
+
 #endif
index 453b7848a7405c250caaea00898cd77a322e5d98..6bb2eadd101f29b9b624592c19edba36b92ab4e2 100644 (file)
@@ -62,7 +62,7 @@ static char *get_cpuinfo(void) {
 
     cpuinfo = pa_xmalloc(MAX_BUFFER);
 
-    if ((fd = open("/proc/cpuinfo", O_RDONLY)) < 0) {
+    if ((fd = pa_open_cloexec("/proc/cpuinfo", O_RDONLY, 0)) < 0) {
         pa_xfree(cpuinfo);
         return NULL;
     }
index 1f4caf717f83f4006f43c4110042000621ee4b96..754930db5d77663df4216f6c83adc0401cb83826 100644 (file)
@@ -237,7 +237,7 @@ pa_database* pa_database_open(const char *fn, pa_bool_t for_write) {
     path = pa_sprintf_malloc("%s."CANONICAL_HOST".simple", fn);
     errno = 0;
 
-    f = fopen(path, "r");
+    f = pa_fopen_cloexec(path, "r");
 
     if (f || errno == ENOENT) { /* file not found is ok */
         db = pa_xnew0(simple_data, 1);
@@ -480,7 +480,7 @@ int pa_database_sync(pa_database *database) {
 
     errno = 0;
 
-    f = fopen(db->tmp_filename, "w");
+    f = pa_fopen_cloexec(db->tmp_filename, "w");
 
     if (!f)
         goto fail;
index b79d2837dc40110cb82101700d4619dfdf6bae65..4e782d65c94648e16994a429c89a8c88c9aef824 100644 (file)
@@ -66,6 +66,39 @@ void pa_datum_free(pa_datum *d) {
     pa_zero(d);
 }
 
+static struct tdb_context *tdb_open_cloexec(
+        const char *name,
+        int hash_size,
+        int tdb_flags,
+        int open_flags,
+        mode_t mode) {
+
+    /* Mimics pa_open_cloexec() */
+
+    struct tdb_context *c;
+
+#ifdef O_NOCTTY
+    open_flags |= O_NOCTTY;
+#endif
+
+#ifdef O_CLOEXEC
+    errno = 0;
+    if ((c = tdb_open(name, hash_size, tdb_flags, open_flags | O_CLOEXEC, mode)))
+        goto finish;
+
+    if (errno != EINVAL)
+        return NULL;
+#endif
+
+    errno = 0;
+    if (!(c = tdb_open(name, hash_size, tdb_flags, open_flags, mode)))
+        return NULL;
+
+finish:
+    pa_make_fd_cloexec(tdb_fd(c));
+    return c;
+}
+
 pa_database* pa_database_open(const char *fn, pa_bool_t for_write) {
     struct tdb_context *c;
     char *path;
@@ -73,15 +106,7 @@ pa_database* pa_database_open(const char *fn, pa_bool_t for_write) {
     pa_assert(fn);
 
     path = pa_sprintf_malloc("%s.tdb", fn);
-    errno = 0;
-    c = tdb_open(path, 0, TDB_NOSYNC|TDB_NOLOCK,
-                 (for_write ? O_RDWR|O_CREAT : O_RDONLY)|O_NOCTTY
-#ifdef O_CLOEXEC
-                 |O_CLOEXEC
-#endif
-                 , 0644);
-
-    if (c)
+    if ((c = tdb_open_cloexec(path, 0, TDB_NOSYNC|TDB_NOLOCK, (for_write ? O_RDWR|O_CREAT : O_RDONLY), 0644)))
         pa_log_debug("Opened TDB database '%s'", path);
 
     pa_xfree(path);
index fd6a948721cac9e0ec85a15dc5aa451b7269c8c8..0eca81157ca693da8d997dd57a6ff932dba7a68a 100644 (file)
@@ -177,7 +177,7 @@ static int32_t item_get_int(pa_envelope_item *i, pa_usec_t x) {
 
     pa_assert(i->j > 0);
     pa_assert(i->def->points_x[i->j-1] <= x);
-    pa_assert(x < i->def->points_x[i->j]);
+    pa_assert(x <= i->def->points_x[i->j]);
 
     return linear_interpolate_int(i->def->points_x[i->j-1], i->def->points_y.i[i->j-1],
                                   i->def->points_x[i->j], i->def->points_y.i[i->j], x);
@@ -200,7 +200,7 @@ static float item_get_float(pa_envelope_item *i, pa_usec_t x) {
 
     pa_assert(i->j > 0);
     pa_assert(i->def->points_x[i->j-1] <= x);
-    pa_assert(x < i->def->points_x[i->j]);
+    pa_assert(x <= i->def->points_x[i->j]);
 
     return linear_interpolate_float(i->def->points_x[i->j-1], i->def->points_y.f[i->j-1],
                                     i->def->points_x[i->j], i->def->points_y.f[i->j], x);
@@ -550,7 +550,7 @@ static int32_t linear_get_int(pa_envelope *e, int v) {
         e->points[v].cached_valid = TRUE;
     }
 
-    return e->points[v].y.i[e->points[v].n_current] + (e->points[v].cached_dy_i * (int32_t) (e->x - e->points[v].x[e->points[v].n_current])) / (int32_t) e->points[v].cached_dx;
+       return e->points[v].y.i[e->points[v].n_current] + ((float)e->points[v].cached_dy_i * (int32_t) (e->x - e->points[v].x[e->points[v].n_current])) / (int32_t) e->points[v].cached_dx;
 }
 
 static float linear_get_float(pa_envelope *e, int v) {
@@ -597,34 +597,60 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {
         fs = pa_frame_size(&e->sample_spec);
         n = chunk->length;
 
+        pa_log_debug("Envelop position %d applying factor %d=%f, sample spec is %d, chunk's length is %d, fs is %d\n", e->x, linear_get_int(e, v), ((float) linear_get_int(e,v))/0x10000, e->sample_spec.format, n, fs);
+
         switch (e->sample_spec.format) {
 
             case PA_SAMPLE_U8: {
-                uint8_t *t;
+                uint8_t *d, *s;
+                unsigned channel;
+                int32_t factor = linear_get_int(e, v);
 
-                for (t = p; n > 0; n -= fs) {
-                    int32_t factor = linear_get_int(e, v);
-                    unsigned c;
-                    e->x += fs;
+                s = (uint8_t*) p + n;
 
-                    for (c = 0; c < e->sample_spec.channels; c++, t++)
-                        *t = (uint8_t) (((factor * ((int16_t) *t - 0x80)) / 0x10000) + 0x80);
+                for (channel = 0, d = p; d < s; d++) {
+                    int32_t t, hi, lo;
+
+                    hi = factor >> 16;
+                    lo = factor & 0xFFFF;
+
+                    t = (int32_t) *d - 0x80;
+                    t = ((t * lo) >> 16) + (t * hi);
+                    t = PA_CLAMP_UNLIKELY(t, -0x80, 0x7F);
+                    *d = (uint8_t) (t + 0x80);
+
+                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) {
+                        channel = 0;
+                        e->x += fs;
+                        factor = linear_get_int(e, v);
+                    }
                 }
 
                 break;
             }
 
             case PA_SAMPLE_ULAW: {
-                uint8_t *t;
+                uint8_t *d, *s;
+                unsigned channel;
+                int32_t factor = linear_get_int(e, v);
 
-                for (t = p; n > 0; n -= fs) {
-                    int32_t factor = linear_get_int(e, v);
-                    unsigned c;
-                    e->x += fs;
+                s = (uint8_t*) p + n;
 
-                    for (c = 0; c < e->sample_spec.channels; c++, t++) {
-                        int16_t k = st_ulaw2linear16(*t);
-                        *t = (uint8_t) st_14linear2ulaw((int16_t) (((factor * k) / 0x10000) >> 2));
+                for (channel = 0, d = p; d < s; d++) {
+                    int32_t t, hi, lo;
+
+                    hi = factor >> 16;
+                    lo = factor & 0xFFFF;
+
+                    t = (int32_t) st_ulaw2linear16(*d);
+                    t = ((t * lo) >> 16) + (t * hi);
+                    t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
+                    *d = (uint8_t) st_14linear2ulaw((int16_t) t >> 2);
+
+                     if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) {
+                        channel = 0;
+                        e->x += fs;
+                        factor = linear_get_int(e, v);
                     }
                 }
 
@@ -632,16 +658,27 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {
             }
 
             case PA_SAMPLE_ALAW: {
-                uint8_t *t;
+                uint8_t *d, *s;
+                unsigned channel;
+                int32_t factor = linear_get_int(e, v);
 
-                for (t = p; n > 0; n -= fs) {
-                    int32_t factor = linear_get_int(e, v);
-                    unsigned c;
-                    e->x += fs;
+                s = (uint8_t*) p + n;
 
-                    for (c = 0; c < e->sample_spec.channels; c++, t++) {
-                        int16_t k = st_alaw2linear16(*t);
-                        *t = (uint8_t) st_13linear2alaw((int16_t) (((factor * k) / 0x10000) >> 3));
+                for (channel = 0, d = p; d < s; d++) {
+                    int32_t t, hi, lo;
+
+                    hi = factor >> 16;
+                    lo = factor & 0xFFFF;
+
+                    t = (int32_t) st_alaw2linear16(*d);
+                    t = ((t * lo) >> 16) + (t * hi);
+                    t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
+                    *d = (uint8_t) st_13linear2alaw((int16_t) t >> 3);
+
+                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) {
+                        channel = 0;
+                        e->x += fs;
+                        factor = linear_get_int(e, v);
                     }
                 }
 
@@ -649,31 +686,55 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {
             }
 
             case PA_SAMPLE_S16NE: {
-                int16_t *t;
+                int16_t *d, *s;
+                unsigned channel;
+                int32_t factor = linear_get_int(e, v);
 
-                for (t = p; n > 0; n -= fs) {
-                    int32_t factor = linear_get_int(e, v);
-                    unsigned c;
-                    e->x += fs;
+                s = (int16_t*) p + n/sizeof(int16_t);
 
-                    for (c = 0; c < e->sample_spec.channels; c++, t++)
-                        *t = (int16_t) ((factor * *t) / 0x10000);
+                for (channel = 0, d = p; d < s; d++) {
+                    int32_t t, hi, lo;
+
+                    hi = factor >> 16;
+                    lo = factor & 0xFFFF;
+
+                    t = (int32_t)(*d);
+                    t = ((t * lo) >> 16) + (t * hi);
+                    t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
+                    *d = (int16_t) t;
+
+                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) {
+                        channel = 0;
+                        e->x += fs;
+                        factor = linear_get_int(e, v);
+                    }
                 }
 
                 break;
             }
 
             case PA_SAMPLE_S16RE: {
-                int16_t *t;
+                int16_t *d, *s;
+                unsigned channel;
+                int32_t factor = linear_get_int(e, v);
 
-                for (t = p; n > 0; n -= fs) {
-                    int32_t factor = linear_get_int(e, v);
-                    unsigned c;
-                    e->x += fs;
+                s = (int16_t*) p + n/sizeof(int16_t);
 
-                    for (c = 0; c < e->sample_spec.channels; c++, t++) {
-                        int16_t r = (int16_t) ((factor * PA_INT16_SWAP(*t)) / 0x10000);
-                        *t = PA_INT16_SWAP(r);
+                for (channel = 0, d = p; d < s; d++) {
+                    int32_t t, hi, lo;
+
+                    hi = factor >> 16;
+                    lo = factor & 0xFFFF;
+
+                    t = (int32_t) PA_INT16_SWAP(*d);
+                    t = ((t * lo) >> 16) + (t * hi);
+                    t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
+                    *d = PA_INT16_SWAP((int16_t) t);
+
+                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) {
+                        channel = 0;
+                        e->x += fs;
+                        factor = linear_get_int(e, v);
                     }
                 }
 
@@ -681,31 +742,49 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {
             }
 
             case PA_SAMPLE_S32NE: {
-                int32_t *t;
+                int32_t *d, *s;
+                unsigned channel;
+                int32_t factor = linear_get_int(e, v);
 
-                for (t = p; n > 0; n -= fs) {
-                    int32_t factor = linear_get_int(e, v);
-                    unsigned c;
-                    e->x += fs;
+                s = (int32_t*) p + n/sizeof(int32_t);
 
-                    for (c = 0; c < e->sample_spec.channels; c++, t++)
-                        *t = (int32_t) (((int64_t) factor * (int64_t) *t) / 0x10000);
+                for (channel = 0, d = p; d < s; d++) {
+                    int64_t t;
+
+                    t = (int64_t)(*d);
+                    t = (t * factor) >> 16;
+                    t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
+                    *d = (int32_t) t;
+
+                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) {
+                        channel = 0;
+                        e->x += fs;
+                        factor = linear_get_int(e, v);
+                    }
                 }
 
                 break;
             }
 
             case PA_SAMPLE_S32RE: {
-                int32_t *t;
+                int32_t *d, *s;
+                unsigned channel;
+                int32_t factor = linear_get_int(e, v);
 
-                for (t = p; n > 0; n -= fs) {
-                    int32_t factor = linear_get_int(e, v);
-                    unsigned c;
-                    e->x += fs;
+                s = (int32_t*) p + n/sizeof(int32_t);
 
-                    for (c = 0; c < e->sample_spec.channels; c++, t++) {
-                        int32_t r = (int32_t) (((int64_t) factor * (int64_t) PA_INT32_SWAP(*t)) / 0x10000);
-                        *t = PA_INT32_SWAP(r);
+                for (channel = 0, d = p; d < s; d++) {
+                    int64_t t;
+
+                    t = (int64_t) PA_INT32_SWAP(*d);
+                    t = (t * factor) >> 16;
+                    t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
+                    *d = PA_INT32_SWAP((int32_t) t);
+
+                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) {
+                        channel = 0;
+                        e->x += fs;
+                        factor = linear_get_int(e, v);
                     }
                 }
 
@@ -713,6 +792,7 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {
             }
 
             case PA_SAMPLE_FLOAT32NE: {
+            /*Seems the FLOAT32NE part of pa_volume_memchunk not right, do not reuse here*/
                 float *t;
 
                 for (t = p; n > 0; n -= fs) {
@@ -728,6 +808,7 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {
             }
 
             case PA_SAMPLE_FLOAT32RE: {
+            /*Seems the FLOAT32RE part of pa_volume_memchunk not right, do not reuse here*/
                 float *t;
 
                 for (t = p; n > 0; n -= fs) {
@@ -744,10 +825,101 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {
                 break;
             }
 
-            case PA_SAMPLE_S24LE:
-            case PA_SAMPLE_S24BE:
-            case PA_SAMPLE_S24_32LE:
-            case PA_SAMPLE_S24_32BE:
+            case PA_SAMPLE_S24NE: {
+                uint8_t *d, *s;
+                unsigned channel;
+                int32_t factor = linear_get_int(e, v);
+
+                s = (uint8_t*) p + n/3;
+
+                for (channel = 0, d = p; d < s; d++) {
+                    int64_t t;
+
+                    t = (int64_t)((int32_t) (PA_READ24NE(d) << 8));
+                    t = (t * factor) >> 16;
+                    t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
+                    PA_WRITE24NE(d, ((uint32_t) (int32_t) t) >> 8);
+
+                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) {
+                            channel = 0;
+                            e->x += fs;
+                            factor = linear_get_int(e, v);
+                    }
+                }
+
+                break;
+            }
+            case PA_SAMPLE_S24RE: {
+                uint8_t *d, *s;
+                unsigned channel;
+                int32_t factor = linear_get_int(e, v);
+
+                s = (uint8_t*) p + n/3;
+
+                for (channel = 0, d = p; d < s; d++) {
+                    int64_t t;
+
+                    t = (int64_t)((int32_t) (PA_READ24RE(d) << 8));
+                    t = (t * factor) >> 16;
+                    t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
+                    PA_WRITE24RE(d, ((uint32_t) (int32_t) t) >> 8);
+
+                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) {
+                            channel = 0;
+                            e->x += fs;
+                            factor = linear_get_int(e, v);
+                    }
+                }
+
+                break;
+            }
+            case PA_SAMPLE_S24_32NE: {
+                uint32_t *d, *s;
+                unsigned channel;
+                int32_t factor = linear_get_int(e, v);
+
+                s = (uint32_t*) p + n/sizeof(uint32_t);
+
+                for (channel = 0, d = p; d < s; d++) {
+                    int64_t t;
+
+                    t = (int64_t) ((int32_t) (*d << 8));
+                    t = (t * factor) >> 16;
+                    t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
+                    *d = ((uint32_t) ((int32_t) t)) >> 8;
+
+                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) {
+                            channel = 0;
+                            e->x += fs;
+                            factor = linear_get_int(e, v);
+                    }
+                }
+
+                break;
+            }
+            case PA_SAMPLE_S24_32RE: {
+                uint32_t *d, *s;
+                unsigned channel;
+                int32_t factor = linear_get_int(e, v);
+
+                s = (uint32_t*) p + n/sizeof(uint32_t);
+
+                for (channel = 0, d = p; d < s; d++) {
+                    int64_t t;
+
+                    t = (int64_t) ((int32_t) (PA_UINT32_SWAP(*d) << 8));
+                    t = (t * factor) >> 16;
+                    t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
+                    *d = PA_UINT32_SWAP(((uint32_t) ((int32_t) t)) >> 8);
+
+                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) {
+                            channel = 0;
+                            e->x += fs;
+                            factor = linear_get_int(e, v);
+                    }
+                }
+                break;
+            }
                 /* FIXME */
                 pa_assert_not_reached();
 
@@ -757,8 +929,6 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {
         }
 
         pa_memblock_release(chunk->memblock);
-
-        e->x += chunk->length;
     } else {
         /* When we have no envelope to apply we reset our origin */
         e->x = 0;
@@ -774,13 +944,48 @@ void pa_envelope_rewind(pa_envelope *e, size_t n_bytes) {
 
     envelope_begin_read(e, &v);
 
-    if (n_bytes < e->x)
-        e->x -= n_bytes;
+    if (e->x - n_bytes <= e->points[v].x[0])
+        e->x = e->points[v].x[0];
     else
-        e->x = 0;
+        e->x -= n_bytes;
 
     e->points[v].n_current = 0;
     e->points[v].cached_valid = FALSE;
 
     envelope_commit_read(e, v);
 }
+
+void pa_envelope_restart(pa_envelope* e) {
+    int v;
+    pa_assert(e);
+
+    envelope_begin_read(e, &v);
+    e->x = e->points[v].x[0];
+    envelope_commit_read(e, v);
+}
+
+pa_bool_t pa_envelope_is_finished(pa_envelope* e) {
+    pa_assert(e);
+
+    int v;
+    pa_bool_t finished;
+
+    envelope_begin_read(e, &v);
+    finished = (e->x >=  e->points[v].x[e->points[v].n_points-1]);
+    envelope_commit_read(e, v);
+
+    return finished;
+}
+
+int32_t pa_envelope_length(pa_envelope *e) {
+    pa_assert(e);
+
+    int v;
+    size_t size;
+
+    envelope_begin_read(e, &v);
+    size = e->points[v].x[e->points[v].n_points-1] - e->points[v].x[0];
+    envelope_commit_read(e, v);
+
+    return size;
+}
index 5296415ae743632ceb773f609da4eb7084b7da7f..4fa36579600ae25fd5e6dfb8856ecf025d3bfbb9 100644 (file)
@@ -49,5 +49,8 @@ pa_envelope_item *pa_envelope_replace(pa_envelope *e, pa_envelope_item *i, const
 void pa_envelope_remove(pa_envelope *e, pa_envelope_item *i);
 void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk);
 void pa_envelope_rewind(pa_envelope *e, size_t n_bytes);
+void pa_envelope_restart(pa_envelope* e);
+pa_bool_t pa_envelope_is_finished(pa_envelope* e);
+int32_t pa_envelope_length(pa_envelope *e);
 
 #endif
index 380f34f543b320cd7c8b17ff8bbd83315369f114..ea14e8a71f0b147dc0803ead31cce1a890b44608 100644 (file)
@@ -62,19 +62,15 @@ pa_fdsem *pa_fdsem_new(void) {
     f = pa_xmalloc(PA_ALIGN(sizeof(pa_fdsem)) + PA_ALIGN(sizeof(pa_fdsem_data)));
 
 #ifdef HAVE_SYS_EVENTFD_H
-    if ((f->efd = eventfd(0, 0)) >= 0) {
-        pa_make_fd_cloexec(f->efd);
+    if ((f->efd = eventfd(0, EFD_CLOEXEC)) >= 0)
         f->fds[0] = f->fds[1] = -1;
-    else
+    else
 #endif
     {
-        if (pipe(f->fds) < 0) {
+        if (pa_pipe_cloexec(f->fds) < 0) {
             pa_xfree(f);
             return NULL;
         }
-
-        pa_make_fd_cloexec(f->fds[0]);
-        pa_make_fd_cloexec(f->fds[1]);
     }
 
     f->data = (pa_fdsem_data*) ((uint8_t*) f + PA_ALIGN(sizeof(pa_fdsem)));
@@ -114,12 +110,11 @@ pa_fdsem *pa_fdsem_new_shm(pa_fdsem_data *data, int* event_fd) {
 
     f = pa_xnew(pa_fdsem, 1);
 
-    if ((f->efd = eventfd(0, 0)) < 0) {
+    if ((f->efd = eventfd(0, EFD_CLOEXEC)) < 0) {
         pa_xfree(f);
         return NULL;
     }
 
-    pa_make_fd_cloexec(f->efd);
     f->fds[0] = f->fds[1] = -1;
     f->data = data;
 
index c0df79383a571d86cf63790ad05dcafb20cf430a..65e356347ed4da101190f81d274e856917918310 100644 (file)
@@ -87,12 +87,9 @@ static int ref(void) {
     pa_assert(pipe_fd[0] < 0);
     pa_assert(pipe_fd[1] < 0);
 
-    if (pipe(pipe_fd) < 0)
+    if (pa_pipe_cloexec(pipe_fd) < 0)
         return -1;
 
-    pa_make_fd_cloexec(pipe_fd[0]);
-    pa_make_fd_cloexec(pipe_fd[1]);
-
     pa_make_fd_nonblock(pipe_fd[1]);
     pa_make_fd_nonblock(pipe_fd[0]);
 
index eac4a59b75accf10612e3dfc1a1ea4820ff12785..f38b17c6a2d0afd5be8b372dc0381cce3f559c43 100644 (file)
@@ -54,7 +54,7 @@
  * stored in SHM and our OS does not commit the memory before we use
  * it for the first time. */
 #define PA_MEMPOOL_SLOTS_MAX 1024
-#define PA_MEMPOOL_SLOT_SIZE (128*1024)
+#define PA_MEMPOOL_SLOT_SIZE (64*1024)
 
 #define PA_MEMEXPORT_SLOTS_MAX 128
 
index 996946c284c86794e58a7c4bd2372e5c384c6cce..213e798383d05cd90ea44ca604c5975afa653ed0 100644 (file)
@@ -88,10 +88,7 @@ static int open_pid_file(const char *fn, int mode) {
     for (;;) {
         struct stat st;
 
-        if ((fd = open(fn, mode
-#ifdef O_NOCTTY
-                       |O_NOCTTY
-#endif
+        if ((fd = pa_open_cloexec(fn, mode
 #ifdef O_NOFOLLOW
                        |O_NOFOLLOW
 #endif
@@ -146,7 +143,7 @@ static int proc_name_ours(pid_t pid, const char *procname) {
 
     pa_snprintf(bn, sizeof(bn), "/proc/%lu/stat", (unsigned long) pid);
 
-    if (!(f = fopen(bn, "r"))) {
+    if (!(f = pa_fopen_cloexec(bn, "r"))) {
         pa_log_info("Failed to open %s: %s", bn, pa_cstrerror(errno));
         return -1;
     } else {
index 5c1127beffe5094f1877ed940f6e602ee7928100..e427bb19f4288cd529b6a0601e9b160e083009cc 100644 (file)
@@ -958,7 +958,7 @@ pa_client *pa_dbus_protocol_get_client(pa_dbus_protocol *p, DBusConnection *conn
 void pa_dbus_protocol_add_signal_listener(
         pa_dbus_protocol *p,
         DBusConnection *conn,
-        const char *signal,
+        const char *signal_name,
         char **objects,
         unsigned n_objects) {
     struct connection_entry *conn_entry;
@@ -978,18 +978,18 @@ void pa_dbus_protocol_add_signal_listener(
     while ((object_path = pa_idxset_steal_first(conn_entry->all_signals_objects, NULL)))
         pa_xfree(object_path);
 
-    if (signal) {
+    if (signal_name) {
         conn_entry->listening_for_all_signals = FALSE;
 
         /* Replace the old object list with a new one. */
-        if ((object_set = pa_hashmap_remove(conn_entry->listening_signals, signal)))
+        if ((object_set = pa_hashmap_remove(conn_entry->listening_signals, signal_name)))
             pa_idxset_free(object_set, free_listened_object_name_cb, NULL);
         object_set = pa_idxset_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
 
         for (i = 0; i < n_objects; ++i)
             pa_idxset_put(object_set, pa_xstrdup(objects[i]), NULL);
 
-        pa_hashmap_put(conn_entry->listening_signals, signal, object_set);
+        pa_hashmap_put(conn_entry->listening_signals, signal_name, object_set);
 
     } else {
         conn_entry->listening_for_all_signals = TRUE;
@@ -1004,7 +1004,7 @@ void pa_dbus_protocol_add_signal_listener(
     }
 }
 
-void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection *conn, const char *signal) {
+void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection *conn, const char *signal_name) {
     struct connection_entry *conn_entry;
     pa_idxset *object_set;
 
@@ -1013,8 +1013,8 @@ void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection
 
     pa_assert_se((conn_entry = pa_hashmap_get(p->connections, conn)));
 
-    if (signal) {
-        if ((object_set = pa_hashmap_get(conn_entry->listening_signals, signal)))
+    if (signal_name) {
+        if ((object_set = pa_hashmap_get(conn_entry->listening_signals, signal_name)))
             pa_idxset_free(object_set, free_listened_object_name_cb, NULL);
 
     } else {
@@ -1030,7 +1030,7 @@ void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection
     }
 }
 
-void pa_dbus_protocol_send_signal(pa_dbus_protocol *p, DBusMessage *signal) {
+void pa_dbus_protocol_send_signal(pa_dbus_protocol *p, DBusMessage *signal_name) {
     struct connection_entry *conn_entry;
     void *state = NULL;
     pa_idxset *object_set;
@@ -1038,24 +1038,24 @@ void pa_dbus_protocol_send_signal(pa_dbus_protocol *p, DBusMessage *signal) {
     char *signal_string;
 
     pa_assert(p);
-    pa_assert(signal);
-    pa_assert(dbus_message_get_type(signal) == DBUS_MESSAGE_TYPE_SIGNAL);
-    pa_assert_se(dbus_message_get_interface(signal));
-    pa_assert_se(dbus_message_get_member(signal));
+    pa_assert(signal_name);
+    pa_assert(dbus_message_get_type(signal_name) == DBUS_MESSAGE_TYPE_SIGNAL);
+    pa_assert_se(dbus_message_get_interface(signal_name));
+    pa_assert_se(dbus_message_get_member(signal_name));
 
-    signal_string = pa_sprintf_malloc("%s.%s", dbus_message_get_interface(signal), dbus_message_get_member(signal));
+    signal_string = pa_sprintf_malloc("%s.%s", dbus_message_get_interface(signal_name), dbus_message_get_member(signal_name));
 
     PA_HASHMAP_FOREACH(conn_entry, p->connections, state) {
         if ((conn_entry->listening_for_all_signals /* Case 1: listening for all signals */
-             && (pa_idxset_get_by_data(conn_entry->all_signals_objects, dbus_message_get_path(signal), NULL)
+             && (pa_idxset_get_by_data(conn_entry->all_signals_objects, dbus_message_get_path(signal_name), NULL)
                  || pa_idxset_isempty(conn_entry->all_signals_objects)))
 
             || (!conn_entry->listening_for_all_signals /* Case 2: not listening for all signals */
                 && (object_set = pa_hashmap_get(conn_entry->listening_signals, signal_string))
-                && (pa_idxset_get_by_data(object_set, dbus_message_get_path(signal), NULL)
+                && (pa_idxset_get_by_data(object_set, dbus_message_get_path(signal_name), NULL)
                     || pa_idxset_isempty(object_set)))) {
 
-            pa_assert_se(signal_copy = dbus_message_copy(signal));
+            pa_assert_se(signal_copy = dbus_message_copy(signal_name));
             pa_assert_se(dbus_connection_send(conn_entry->connection, signal_copy, NULL));
             dbus_message_unref(signal_copy);
         }
index d06dd4ebed76265c90e1b7f7a099e201dbd56ea0..d49a78e5d3b902b453893b1b3e21953312264087 100644 (file)
@@ -1002,6 +1002,7 @@ static playback_stream* playback_stream_new(
         pa_proplist *p,
         pa_bool_t adjust_latency,
         pa_bool_t early_requests,
+        pa_bool_t relative_volume,
         int *ret) {
 
     playback_stream *s, *ssync;
@@ -1044,13 +1045,21 @@ static playback_stream* playback_stream_new(
     data.driver = __FILE__;
     data.module = c->options->module;
     data.client = c->client;
-    data.sink = sink;
+    if (sink) {
+        data.sink = sink;
+        data.save_sink = TRUE;
+    }
     pa_sink_input_new_data_set_sample_spec(&data, ss);
     pa_sink_input_new_data_set_channel_map(&data, map);
-    if (volume)
+    if (volume) {
         pa_sink_input_new_data_set_volume(&data, volume);
-    if (muted_set)
+        data.volume_is_absolute = !relative_volume;
+        data.save_volume = TRUE;
+    }
+    if (muted_set) {
         pa_sink_input_new_data_set_muted(&data, muted);
+        data.save_muted = TRUE;
+    }
     data.sync_base = ssync ? ssync->sink_input : NULL;
     data.flags = flags;
 
@@ -1838,7 +1847,8 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
         early_requests = FALSE,
         dont_inhibit_auto_suspend = FALSE,
         muted_set = FALSE,
-        fail_on_suspend = FALSE;
+        fail_on_suspend = FALSE,
+        relative_volume = FALSE;
     pa_sink_input_flags_t flags = 0;
     pa_proplist *p;
     pa_bool_t volume_set = TRUE;
@@ -1931,6 +1941,15 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
         }
     }
 
+    if (c->version >= 17) {
+
+        if (pa_tagstruct_get_boolean(t, &relative_volume) < 0) {
+            protocol_error(c);
+            pa_proplist_free(p);
+            return;
+        }
+    }
+
     if (!pa_tagstruct_eof(t)) {
         protocol_error(c);
         pa_proplist_free(p);
@@ -1970,7 +1989,7 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
      * flag. For older versions we synthesize it here */
     muted_set = muted_set || muted;
 
-    s = playback_stream_new(c, sink, &ss, &map, &attr, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, &ret);
+    s = playback_stream_new(c, sink, &ss, &map, &attr, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, relative_volume, &ret);
     pa_proplist_free(p);
 
     CHECK_VALIDITY(c->pstream, s, tag, ret);
@@ -2612,7 +2631,7 @@ static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint3
     pa_tagstruct_put_usec(reply, s->current_monitor_latency);
     pa_tagstruct_put_usec(reply,
                           s->current_source_latency +
-                          pa_bytes_to_usec(s->on_the_fly_snapshot, &s->source_output->sample_spec));
+                          pa_bytes_to_usec(s->on_the_fly_snapshot, &s->source_output->source->sample_spec));
     pa_tagstruct_put_boolean(reply,
                              pa_source_get_state(s->source_output->source) == PA_SOURCE_RUNNING &&
                              pa_source_output_get_state(s->source_output) == PA_SOURCE_OUTPUT_RUNNING);
index 518c281aa370509f70de75fa458d0cb6c2188c7a..a87d24e31cd77c3aee9d753a81801abefdd2abfd 100644 (file)
@@ -62,11 +62,7 @@ static int random_proper(void *ret_data, size_t length) {
     while (*device) {
         ret = 0;
 
-        if ((fd = open(*device, O_RDONLY
-#ifdef O_NOCTTY
-                       | O_NOCTTY
-#endif
-             )) >= 0) {
+        if ((fd = pa_open_cloexec(*device, O_RDONLY, 0)) >= 0) {
 
             if ((r = pa_loop_read(fd, ret_data, length, NULL)) < 0 || (size_t) r != length)
                 ret = -1;
index a26dc876ad24a3915ef83beac25df611db24e4e9..74600deca206a1036cc75cb86c3422ed99bef569 100644 (file)
@@ -1007,7 +1007,7 @@ void pa_memchunk_dump_to_file(pa_memchunk *c, const char *fn) {
 
     /* Only for debugging purposes */
 
-    f = fopen(fn, "a");
+    f = pa_fopen_cloexec(fn, "a");
 
     if (!f) {
         pa_log_warn("Failed to open '%s': %s", fn, pa_cstrerror(errno));
diff --git a/src/pulsecore/semaphore-osx.c b/src/pulsecore/semaphore-osx.c
new file mode 100644 (file)
index 0000000..73f4355
--- /dev/null
@@ -0,0 +1,63 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2009 Kim Lester <kim@dfusion.com.au>
+
+  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 <Multiprocessing.h>
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
+
+#include "semaphore.h"
+
+struct pa_semaphore
+{
+    MPSemaphoreID sema;
+};
+
+pa_semaphore* pa_semaphore_new(unsigned int value) {
+    /* NOTE: Can't assume boolean - ie value = 0,1, so use UINT_MAX (boolean more efficient ?) */
+    pa_semaphore *s;
+
+    s = pa_xnew(pa_semaphore, 1);
+    pa_assert_se(MPCreateSemaphore(UINT_MAX, value, &s->sema) == 0);
+
+    return s;
+}
+
+void pa_semaphore_free(pa_semaphore *s) {
+    pa_assert(s);
+    pa_assert_se(MPDeleteSemaphore(s->sema) == 0);
+    pa_xfree(s);
+}
+
+void pa_semaphore_post(pa_semaphore *s) {
+    pa_assert(s);
+    pa_assert_se(MPSignalSemaphore(s->sema) == 0);
+}
+
+void pa_semaphore_wait(pa_semaphore *s) {
+    pa_assert(s);
+    /* should probably check return value (-ve is error), noErr is ok. */
+    pa_assert_se(MPWaitOnSemaphore(s->sema, kDurationForever) == 0);
+}
index 1af2823f91a06cfbf4651d036f60d07c9b46db45..35e3d4a9fe9d47aeda577104ef7e42489df5d260 100644 (file)
@@ -38,6 +38,7 @@
 #include <pulsecore/play-memblockq.h>
 #include <pulsecore/namereg.h>
 #include <pulsecore/core-util.h>
+#include <pulse/timeval.h>
 
 #include "sink-input.h"
 
@@ -48,6 +49,11 @@ PA_DEFINE_PUBLIC_CLASS(pa_sink_input, pa_msgobject);
 
 static void sink_input_free(pa_object *o);
 static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v);
+static void sink_input_set_ramping_info(pa_sink_input* i, pa_volume_t  pre_virtual_volume, pa_volume_t target_virtual_volume, pa_usec_t t);
+static void sink_input_set_ramping_info_for_mute(pa_sink_input* i, pa_bool_t mute, pa_usec_t t);
+static void sink_input_volume_ramping(pa_sink_input* i, pa_memchunk* chunk);
+static void sink_input_rewind_ramp_info(pa_sink_input *i, size_t nbytes);
+static void sink_input_release_envelope(pa_sink_input *i);
 
 pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data) {
     pa_assert(data);
@@ -323,6 +329,16 @@ int pa_sink_input_new(
     reset_callbacks(i);
     i->userdata = NULL;
 
+    /* Set Ramping info */
+    i->thread_info.ramp_info.is_ramping = FALSE;
+    i->thread_info.ramp_info.envelope_dead = TRUE;
+    i->thread_info.ramp_info.envelope = NULL;
+    i->thread_info.ramp_info.item = NULL;
+    i->thread_info.ramp_info.envelope_dying = 0;
+
+    pa_atomic_store(&i->before_ramping_v, 0);
+    pa_atomic_store(&i->before_ramping_m, 0);
+
     i->thread_info.state = i->state;
     i->thread_info.attached = FALSE;
     pa_atomic_store(&i->thread_info.drained, 1);
@@ -510,6 +526,12 @@ static void sink_input_free(pa_object *o) {
      * "half-moved" or are connected to sinks that have no asyncmsgq
      * and are hence half-destructed themselves! */
 
+    if (i->thread_info.ramp_info.envelope) {
+        pa_log_debug ("Freeing envelope\n");
+        pa_envelope_free(i->thread_info.ramp_info.envelope);
+        i->thread_info.ramp_info.envelope = NULL;
+    }
+
     if (i->thread_info.render_memblockq)
         pa_memblockq_free(i->thread_info.render_memblockq);
 
@@ -597,6 +619,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {
 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, need_volume_factor_sink;
     pa_bool_t volume_is_norm;
+    pa_bool_t ramping;
     size_t block_size_max_sink, block_size_max_sink_input;
     size_t ilength;
 
@@ -641,7 +664,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p
      * to adjust the volume *before* we resample. Otherwise we can do
      * it after and leave it for the sink code */
 
-    do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
+    do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map) || i->thread_info.ramp_info.is_ramping;
     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);
 
@@ -684,7 +707,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p
                 wchunk.length = block_size_max_sink_input;
 
             /* It might be necessary to adjust the volume here */
-            if (do_volume_adj_here && !volume_is_norm) {
+            if (do_volume_adj_here && !volume_is_norm && !i->thread_info.ramp_info.is_ramping) {
                 pa_memchunk_make_writable(&wchunk, 0);
 
                 if (i->thread_info.muted) {
@@ -717,14 +740,15 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p
                 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) {
+
+                    if (nvfs) {
+                        pa_memchunk_make_writable(&rchunk, 0);
+                        pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink);
+                    }
+
                     pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
                     pa_memblock_unref(rchunk.memblock);
                 }
@@ -749,6 +773,23 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p
     if (chunk->length > block_size_max_sink)
         chunk->length = block_size_max_sink;
 
+    ramping = i->thread_info.ramp_info.is_ramping;
+    if (ramping)
+        sink_input_volume_ramping(i, chunk);
+
+    if (!i->thread_info.ramp_info.envelope_dead) {
+        i->thread_info.ramp_info.envelope_dying += chunk->length;
+        pa_log_debug("Envelope dying is %d, chunk length is %d, dead thresholder is %d\n", i->thread_info.ramp_info.envelope_dying,
+                chunk->length,
+                i->sink->thread_info.max_rewind + pa_envelope_length(i->thread_info.ramp_info.envelope));
+
+        if (i->thread_info.ramp_info.envelope_dying >= (i->sink->thread_info.max_rewind + pa_envelope_length(i->thread_info.ramp_info.envelope))) {
+            pa_log_debug("RELEASE Envelop");
+            i->thread_info.ramp_info.envelope_dead = TRUE;
+            sink_input_release_envelope(i);
+        }
+    }
+
     /* Let's see if we had to apply the volume adjustment ourselves,
      * or if this can be done by the sink for us */
 
@@ -793,6 +834,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
     if (nbytes > 0 && !i->thread_info.dont_rewind_render) {
         pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
         pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
+        sink_input_rewind_ramp_info(i, nbytes);
     }
 
     if (i->thread_info.rewrite_nbytes == (size_t) -1) {
@@ -978,59 +1020,8 @@ static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) {
 
 /* Called from main context */
 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute) {
-    pa_cvolume v;
-
-    pa_sink_input_assert_ref(i);
-    pa_assert_ctl_context();
-    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
-    pa_assert(volume);
-    pa_assert(pa_cvolume_valid(volume));
-    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);
-
-        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)) {
-        i->save_volume = i->save_volume || save;
-        return;
-    }
-
-    i->volume = *volume;
-    i->save_volume = save;
-
-    if (i->sink->flags & PA_SINK_FLAT_VOLUME)
-        /* We are in flat volume mode, so let's update all sink input
-         * volumes and update the flat volume of the sink */
-
-        pa_sink_set_volume(i->sink, NULL, TRUE, save);
-
-    else {
-        /* OK, we are in normal volume mode. The volume only affects
-         * ourselves */
-        set_real_ratio(i, volume);
-
-        /* Copy the new soft_volume to the thread_info struct */
-        pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
-    }
-
-    /* The volume changed, let's tell people so */
-    if (i->volume_changed)
-        i->volume_changed(i);
-
-    pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+    /* test ramping -> return pa_sink_input_set_volume_with_ramping(i, volume, save, absolute, 2000 * PA_USEC_PER_MSEC); */
+    return pa_sink_input_set_volume_with_ramping(i, volume, save, absolute, 0);
 }
 
 /* Called from main context */
@@ -1049,23 +1040,8 @@ pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, pa_bo
 
 /* Called from main context */
 void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute, pa_bool_t save) {
-    pa_sink_input_assert_ref(i);
-    pa_assert_ctl_context();
-    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
-
-    if (!i->muted == !mute)
-        return;
-
-    i->muted = mute;
-    i->save_muted = save;
-
-    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0);
-
-    /* The mute status changed, let's tell people so */
-    if (i->mute_changed)
-        i->mute_changed(i);
-
-    pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+    /* test ramping -> return pa_sink_input_set_mute_with_ramping(i, mute, save, 2000 * PA_USEC_PER_MSEC); */
+    return pa_sink_input_set_mute_with_ramping(i, mute, save, 0);
 }
 
 /* Called from main context */
@@ -1441,15 +1417,23 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
     switch (code) {
 
         case PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME:
+            if (pa_atomic_load(&i->before_ramping_v))
+                i->thread_info.future_soft_volume = i->soft_volume;
+
             if (!pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume)) {
-                i->thread_info.soft_volume = i->soft_volume;
+                if (!pa_atomic_load(&i->before_ramping_v))
+                    i->thread_info.soft_volume = i->soft_volume;
                 pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
             }
             return 0;
 
         case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE:
+            if (pa_atomic_load(&i->before_ramping_m))
+                i->thread_info.future_muted = i->muted;
+
             if (i->thread_info.muted != i->muted) {
-                i->thread_info.muted = i->muted;
+                if (!pa_atomic_load(&i->before_ramping_m))
+                    i->thread_info.muted = i->muted;
                 pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
             }
             return 0;
@@ -1497,6 +1481,26 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
             *r = i->thread_info.requested_sink_latency;
             return 0;
         }
+
+        case PA_SINK_INPUT_MESSAGE_SET_ENVELOPE: {
+            if (!i->thread_info.ramp_info.envelope)
+                i->thread_info.ramp_info.envelope = pa_envelope_new(&i->sink->sample_spec);
+
+            if (i->thread_info.ramp_info.envelope && i->thread_info.ramp_info.item) {
+                pa_envelope_remove(i->thread_info.ramp_info.envelope, i->thread_info.ramp_info.item);
+                i->thread_info.ramp_info.item = NULL;
+            }
+
+            i->thread_info.ramp_info.item = pa_envelope_add(i->thread_info.ramp_info.envelope, &i->using_def);
+            i->thread_info.ramp_info.is_ramping = TRUE;
+            i->thread_info.ramp_info.envelope_dead = FALSE;
+            i->thread_info.ramp_info.envelope_dying = 0;
+
+            if (i->thread_info.ramp_info.envelope)
+                pa_envelope_restart(i->thread_info.ramp_info.envelope);
+
+            return 0;
+        }
     }
 
     return -PA_ERR_NOTIMPLEMENTED;
@@ -1659,3 +1663,235 @@ finish:
     if (pl)
         pa_proplist_free(pl);
 }
+
+/* Called from IO context */
+static void sink_input_volume_ramping(pa_sink_input* i, pa_memchunk* chunk) {
+    pa_assert(i);
+    pa_assert(chunk);
+    pa_assert(chunk->memblock);
+    pa_assert(i->thread_info.ramp_info.is_ramping);
+
+    /* Volume is adjusted with ramping effect here */
+    pa_envelope_apply(i->thread_info.ramp_info.envelope, chunk);
+
+    if (pa_envelope_is_finished(i->thread_info.ramp_info.envelope)) {
+        i->thread_info.ramp_info.is_ramping = FALSE;
+        if (pa_atomic_load(&i->before_ramping_v)) {
+            i->thread_info.soft_volume = i->thread_info.future_soft_volume;
+            pa_atomic_store(&i->before_ramping_v, 0);
+        }
+        else if (pa_atomic_load(&i->before_ramping_m)) {
+            i->thread_info.muted = i->thread_info.future_muted;
+            pa_atomic_store(&i->before_ramping_m, 0);
+        }
+    }
+}
+
+/*
+ * Called from main context
+ * This function should be called inside pa_sink_input_set_volume_with_ramping
+ * should be called after soft_volume of sink_input and sink are all adjusted
+ */
+static void sink_input_set_ramping_info(pa_sink_input* i, pa_volume_t  pre_virtual_volume, pa_volume_t target_virtual_volume, pa_usec_t t) {
+
+    int32_t target_abs_vol, target_apply_vol, pre_apply_vol;
+    pa_assert(i);
+
+    pa_log_debug("Sink input's soft volume is %d= %f ", pa_cvolume_avg(&i->soft_volume), pa_sw_volume_to_linear(pa_cvolume_avg(&i->soft_volume)));
+
+    /* Calculation formula are target_abs_vol := i->soft_volume
+     *                                   target_apply_vol := lrint(pa_sw_volume_to_linear(target_abs_vol) * 0x10000)
+     *                                   pre_apply_vol := ( previous_virtual_volume / target_virtual_volume ) * target_apply_vol
+     *
+     * Will do volume adjustment inside pa_sink_input_peek
+     */
+    target_abs_vol = pa_cvolume_avg(&i->soft_volume);
+    target_apply_vol = (int32_t) lrint(pa_sw_volume_to_linear(target_abs_vol) * 0x10000);
+    pre_apply_vol = (int32_t) ((pa_sw_volume_to_linear(pre_virtual_volume) / pa_sw_volume_to_linear(target_virtual_volume)) * target_apply_vol);
+
+    i->using_def.n_points = 2;
+    i->using_def.points_x[0] = 0;
+    i->using_def.points_x[1] = t;
+    i->using_def.points_y.i[0] = pre_apply_vol;
+    i->using_def.points_y.i[1] = target_apply_vol;
+    i->using_def.points_y.f[0] = ((float) i->using_def.points_y.i[0]) /0x10000;
+    i->using_def.points_y.f[1] = ((float) i->using_def.points_y.i[1]) /0x10000;
+
+    pa_log_debug("Volume Ramping: Point 1 is %d=%f, Point 2 is %d=%f\n", i->using_def.points_y.i[0], i->using_def.points_y.f[0],
+                                   i->using_def.points_y.i[1], i->using_def.points_y.f[1]);
+
+    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_ENVELOPE, NULL, 0, NULL) == 0);
+}
+
+/* Called from main context */
+static void sink_input_set_ramping_info_for_mute(pa_sink_input* i, pa_bool_t mute, pa_usec_t t) {
+
+    int32_t cur_vol;
+    pa_assert(i);
+
+    i->using_def.n_points = 2;
+    i->using_def.points_x[0] = 0;
+    i->using_def.points_x[1] = t;
+    cur_vol = (int32_t) lrint( pa_sw_volume_to_linear(pa_cvolume_avg(&i->soft_volume)) * 0x10000);
+
+    if (mute) {
+        i->using_def.points_y.i[0] = cur_vol;
+        i->using_def.points_y.i[1] = 0;
+    } else {
+        i->using_def.points_y.i[0] = 0;
+        i->using_def.points_y.i[1] = cur_vol;
+    }
+
+    i->using_def.points_y.f[0] = ((float) i->using_def.points_y.i[0]) /0x10000;
+    i->using_def.points_y.f[1] = ((float) i->using_def.points_y.i[1]) /0x10000;
+
+    pa_log_debug("Mute Ramping: Point 1 is %d=%f, Point 2 is %d=%f\n", i->using_def.points_y.i[0], i->using_def.points_y.f[0],
+                   i->using_def.points_y.i[1], i->using_def.points_y.f[1]);
+
+    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_ENVELOPE, NULL, 0, NULL) == 0);
+}
+
+/* Called from IO context */
+static void sink_input_release_envelope(pa_sink_input *i) {
+    pa_assert(i);
+    pa_assert(!i->thread_info.ramp_info.is_ramping);
+    pa_assert(i->thread_info.ramp_info.envelope_dead);
+
+    pa_envelope_free(i->thread_info.ramp_info.envelope);
+    i->thread_info.ramp_info.envelope = NULL;
+    i->thread_info.ramp_info.item = NULL;
+}
+
+/* Called from IO context */
+static void sink_input_rewind_ramp_info(pa_sink_input *i, size_t nbytes) {
+    pa_assert(i);
+
+    if (!i->thread_info.ramp_info.envelope_dead) {
+        pa_assert(i->thread_info.ramp_info.envelope);
+
+        int32_t envelope_length = pa_envelope_length(i->thread_info.ramp_info.envelope);
+
+        if (i->thread_info.ramp_info.envelope_dying > envelope_length) {
+            if ((i->thread_info.ramp_info.envelope_dying - nbytes) < envelope_length) {
+                pa_log_debug("Envelope Become Alive");
+                pa_envelope_rewind(i->thread_info.ramp_info.envelope, envelope_length - (i->thread_info.ramp_info.envelope_dying - nbytes));
+                i->thread_info.ramp_info.is_ramping = TRUE;
+            }
+        } else if (i->thread_info.ramp_info.envelope_dying < envelope_length) {
+            if ((i->thread_info.ramp_info.envelope_dying - nbytes) <= 0) {
+                pa_log_debug("Envelope Restart");
+                pa_envelope_restart(i->thread_info.ramp_info.envelope);
+            }
+            else {
+                pa_log_debug("Envelope Simple Rewind");
+                pa_envelope_rewind(i->thread_info.ramp_info.envelope, nbytes);
+            }
+        }
+
+        i->thread_info.ramp_info.envelope_dying -= nbytes;
+        if (i->thread_info.ramp_info.envelope_dying <= 0)
+            i->thread_info.ramp_info.envelope_dying = 0;
+    }
+}
+
+void pa_sink_input_set_volume_with_ramping(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute, pa_usec_t t){
+    pa_cvolume v;
+    pa_volume_t previous_virtual_volume, target_virtual_volume;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert_ctl_context();
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
+    pa_assert(volume);
+    pa_assert(pa_cvolume_valid(volume));
+    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);
+
+        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)) {
+        i->save_volume = i->save_volume || save;
+        return;
+    }
+
+    previous_virtual_volume = pa_cvolume_avg(&i->volume);
+    target_virtual_volume = pa_cvolume_avg(volume);
+
+    if (t > 0 && target_virtual_volume > 0)
+        pa_log_debug("SetVolumeWithRamping: Virtual Volume From %u=%f to %u=%f\n", previous_virtual_volume, pa_sw_volume_to_linear(previous_virtual_volume),
+                                             target_virtual_volume, pa_sw_volume_to_linear(target_virtual_volume));
+
+    i->volume = *volume;
+    i->save_volume = save;
+
+    /* Set this flag before the following code modify i->thread_info.soft_volume */
+    if (t > 0 && target_virtual_volume > 0)
+        pa_atomic_store(&i->before_ramping_v, 1);
+
+    if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
+        /* We are in flat volume mode, so let's update all sink input
+         * volumes and update the flat volume of the sink */
+
+        pa_sink_set_volume(i->sink, NULL, TRUE, save);
+
+    } else {
+        /* OK, we are in normal volume mode. The volume only affects
+         * ourselves */
+        set_real_ratio(i, volume);
+
+        /* Copy the new soft_volume to the thread_info struct */
+        pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
+    }
+
+    if (t > 0 && target_virtual_volume > 0)
+        sink_input_set_ramping_info(i, previous_virtual_volume, target_virtual_volume, t);
+
+    /* The volume changed, let's tell people so */
+    if (i->volume_changed)
+        i->volume_changed(i);
+
+    /* The virtual volume changed, let's tell people so */
+    pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+}
+
+void pa_sink_input_set_mute_with_ramping(pa_sink_input *i, pa_bool_t mute, pa_bool_t save, pa_usec_t t){
+
+    pa_sink_input_assert_ref(i);
+    pa_assert_ctl_context();
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
+
+    if (!i->muted == !mute) {
+        i->save_muted = i->save_muted || mute;
+        return;
+    }
+
+    i->muted = mute;
+    i->save_muted = save;
+
+    /* Set this flag before the following code modify i->thread_info.muted, otherwise distortion will be heard */
+    if (t > 0)
+        pa_atomic_store(&i->before_ramping_m, 1);
+
+    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0);
+
+    if (t > 0)
+        sink_input_set_ramping_info_for_mute(i, mute, t);
+
+    /* The mute status changed, let's tell people so */
+    if (i->mute_changed)
+        i->mute_changed(i);
+
+    pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+}
index 415a801fb9878ec2db6345cba04f42b55f9e75bb..56ac3d606aa14d1621ca864b27a2ff55f6fa5ac9 100644 (file)
@@ -35,6 +35,7 @@ typedef struct pa_sink_input pa_sink_input;
 #include <pulsecore/client.h>
 #include <pulsecore/sink.h>
 #include <pulsecore/core.h>
+#include <pulsecore/envelope.h>
 
 typedef enum pa_sink_input_state {
     PA_SINK_INPUT_INIT,         /*< The stream is not active yet, because pa_sink_put() has not been called yet */
@@ -232,8 +233,23 @@ struct pa_sink_input {
         pa_usec_t requested_sink_latency;
 
         pa_hashmap *direct_outputs;
+
+        struct {
+            pa_bool_t is_ramping:1;
+            pa_bool_t envelope_dead:1;
+            int32_t envelope_dying; /* Increasing while envelop is not dead.  Reduce it while process_rewind. */
+            pa_envelope *envelope;
+            pa_envelope_item *item;
+        } ramp_info;
+        pa_cvolume future_soft_volume;
+        pa_bool_t future_muted;
+
     } thread_info;
 
+    pa_atomic_t before_ramping_v;  /* Indicates future volume */
+    pa_atomic_t before_ramping_m;  /* Indicates future mute */
+    pa_envelope_def using_def;
+
     void *userdata;
 };
 
@@ -248,6 +264,7 @@ enum {
     PA_SINK_INPUT_MESSAGE_SET_STATE,
     PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY,
     PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY,
+    PA_SINK_INPUT_MESSAGE_SET_ENVELOPE,
     PA_SINK_INPUT_MESSAGE_MAX
 };
 
@@ -384,4 +401,8 @@ pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret);
 #define pa_sink_input_assert_io_context(s) \
     pa_assert(pa_thread_mq_get() || !PA_SINK_INPUT_IS_LINKED((s)->state))
 
+/* Volume ramping*/
+void pa_sink_input_set_volume_with_ramping(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute, pa_usec_t t);
+void pa_sink_input_set_mute_with_ramping(pa_sink_input *i, pa_bool_t mute, pa_bool_t save, pa_usec_t t);
+
 #endif
index bda92fccb4ec6e34cdc0a5b5b457a0eae0d8194b..24fad34dd049897f4a8dc2866fd35d91c5a5bf6d 100644 (file)
@@ -926,18 +926,16 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
 
         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, 0);
-                pa_volume_memchunk(result, &s->sample_spec, &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 if (!pa_cvolume_is_norm(&volume)) {
+            pa_memchunk_make_writable(result, 0);
+            pa_volume_memchunk(result, &s->sample_spec, &volume);
         }
     } else {
         void *ptr;
@@ -1342,7 +1340,7 @@ static void propagate_reference_volume(pa_sink *s) {
 void pa_sink_set_volume(
         pa_sink *s,
         const pa_cvolume *volume,
-        pa_bool_t sendmsg,
+        pa_bool_t send_msg,
         pa_bool_t save) {
 
     pa_cvolume old_reference_volume;
@@ -1411,7 +1409,7 @@ void pa_sink_set_volume(
         s->soft_volume = s->real_volume;
 
     /* This tells the sink that soft and/or virtual volume changed */
-    if (sendmsg)
+    if (send_msg)
         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
 
     if (reference_changed)
@@ -1733,10 +1731,14 @@ static void sync_input_volumes_within_thread(pa_sink *s) {
     pa_sink_assert_io_context(s);
 
     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
+        if (pa_atomic_load(&i->before_ramping_v))
+            i->thread_info.future_soft_volume = i->soft_volume;
+
         if (pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume))
             continue;
 
-        i->thread_info.soft_volume = i->soft_volume;
+        if (!pa_atomic_load(&i->before_ramping_v))
+            i->thread_info.soft_volume = i->soft_volume;
         pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
     }
 }
index b9d695055c2a56a9f5c8f2e6e1c787b5afa836ef..ef3c29ee3e9a49f604e3cab4d19ad01b454b93c1 100644 (file)
@@ -257,13 +257,11 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size
 
     c->local = pa_socket_address_is_local(sa);
 
-    if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) {
+    if ((c->fd = pa_socket_cloexec(sa->sa_family, SOCK_STREAM, 0)) < 0) {
         pa_log("socket(): %s", pa_cstrerror(errno));
         return -1;
     }
 
-    pa_make_fd_cloexec(c->fd);
-
 #ifdef HAVE_IPV6
     if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)
 #else
index e660700cbe2ab249e2b6c97aa94f79374dfe1452..5d55de3e8f75047259ccfcc99cc3fda838938d69 100644 (file)
@@ -104,13 +104,11 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, pa_io_ev
 
     pa_socket_server_ref(s);
 
-    if ((nfd = accept(fd, NULL, NULL)) < 0) {
+    if ((nfd = pa_accept_cloexec(fd, NULL, NULL)) < 0) {
         pa_log("accept(): %s", pa_cstrerror(errno));
         goto finish;
     }
 
-    pa_make_fd_cloexec(nfd);
-
     if (!s->on_connection) {
         pa_close(nfd);
         goto finish;
@@ -186,13 +184,11 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file
     pa_assert(m);
     pa_assert(filename);
 
-    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+    if ((fd = pa_socket_cloexec(PF_UNIX, SOCK_STREAM, 0)) < 0) {
         pa_log("socket(): %s", pa_cstrerror(errno));
         goto fail;
     }
 
-    pa_make_fd_cloexec(fd);
-
     memset(&sa, 0, sizeof(sa));
     sa.sun_family = AF_UNIX;
     pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
@@ -246,13 +242,11 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address
     pa_assert(m);
     pa_assert(port);
 
-    if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+    if ((fd = pa_socket_cloexec(PF_INET, SOCK_STREAM, 0)) < 0) {
         pa_log("socket(PF_INET): %s", pa_cstrerror(errno));
         goto fail;
     }
 
-    pa_make_fd_cloexec(fd);
-
 #ifdef SO_REUSEADDR
     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
         pa_log("setsockopt(): %s", pa_cstrerror(errno));
@@ -299,13 +293,11 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad
     pa_assert(m);
     pa_assert(port > 0);
 
-    if ((fd = socket(PF_INET6, SOCK_STREAM, 0)) < 0) {
+    if ((fd = pa_socket_cloexec(PF_INET6, SOCK_STREAM, 0)) < 0) {
         pa_log("socket(PF_INET6): %s", pa_cstrerror(errno));
         goto fail;
     }
 
-    pa_make_fd_cloexec(fd);
-
 #ifdef IPV6_V6ONLY
     on = 1;
     if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0)
index 5fd5dd6763266ce79b7daada12eb95131064b45f..2cc9882a1c63301a4a900f25afd7fff31509da42 100644 (file)
@@ -85,12 +85,11 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
 
 #ifndef OS_IS_WIN32
     pa_assert_se(fstat(fd, &st) == 0);
-#endif
 
-#ifndef OS_IS_WIN32
     if (S_ISSOCK(st.st_mode)) {
 #endif
         union {
+            struct sockaddr_storage storage;
             struct sockaddr sa;
             struct sockaddr_in in;
 #ifdef HAVE_IPV6
@@ -152,7 +151,7 @@ void pa_make_socket_low_delay(int fd) {
     pa_assert(fd >= 0);
 
     priority = 6;
-    if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, sizeof(priority)) < 0)
+    if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0)
         pa_log_warn("SO_PRIORITY failed: %s", pa_cstrerror(errno));
 #endif
 }
@@ -166,9 +165,9 @@ void pa_make_tcp_socket_low_delay(int fd) {
     {
         int on = 1;
 #if defined(SOL_TCP)
-        if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0)
+        if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
 #else
-        if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0)
+        if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
 #endif
             pa_log_warn("TCP_NODELAY failed: %s", pa_cstrerror(errno));
     }
@@ -178,9 +177,9 @@ void pa_make_tcp_socket_low_delay(int fd) {
     {
         int tos = IPTOS_LOWDELAY;
 #ifdef SOL_IP
-        if (setsockopt(fd, SOL_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
+        if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0)
 #else
-        if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
+        if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
 #endif
             pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno));
     }
@@ -196,9 +195,9 @@ void pa_make_udp_socket_low_delay(int fd) {
     {
         int tos = IPTOS_LOWDELAY;
 #ifdef SOL_IP
-        if (setsockopt(fd, SOL_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
+        if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0)
 #else
-        if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
+        if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
 #endif
             pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno));
     }
@@ -206,11 +205,11 @@ void pa_make_udp_socket_low_delay(int fd) {
 }
 
 int pa_socket_set_rcvbuf(int fd, size_t l) {
-    int bufsz = (int)l;
+    int bufsz = (int) l;
 
     pa_assert(fd >= 0);
 
-    if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void*)&bufsz, sizeof(bufsz)) < 0) {
+    if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsz, sizeof(bufsz)) < 0) {
         pa_log_warn("SO_RCVBUF: %s", pa_cstrerror(errno));
         return -1;
     }
@@ -219,12 +218,12 @@ int pa_socket_set_rcvbuf(int fd, size_t l) {
 }
 
 int pa_socket_set_sndbuf(int fd, size_t l) {
-    int bufsz = (int)l;
+    int bufsz = (int) l;
 
     pa_assert(fd >= 0);
 
-    if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void*)&bufsz, sizeof(bufsz)) < 0) {
-        pa_log("SO_SNDBUF: %s", pa_cstrerror(errno));
+    if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsz, sizeof(bufsz)) < 0) {
+        pa_log_warn("SO_SNDBUF: %s", pa_cstrerror(errno));
         return -1;
     }
 
@@ -239,7 +238,7 @@ int pa_unix_socket_is_stale(const char *fn) {
 
     pa_assert(fn);
 
-    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+    if ((fd = pa_socket_cloexec(PF_UNIX, SOCK_STREAM, 0)) < 0) {
         pa_log("socket(): %s", pa_cstrerror(errno));
         goto finish;
     }
@@ -315,6 +314,7 @@ pa_bool_t pa_socket_address_is_local(const struct sockaddr *sa) {
 pa_bool_t pa_socket_is_local(int fd) {
 
     union {
+        struct sockaddr_storage storage;
         struct sockaddr sa;
         struct sockaddr_in in;
 #ifdef HAVE_IPV6
index 16de492332bd1c89cea7b0e959f0fd0ed4956097..53674ba1c67a9645b4202b6d174086aa4eb8d48b 100644 (file)
@@ -252,11 +252,7 @@ int pa_play_file(
     u->readf_function = NULL;
     u->memblockq = NULL;
 
-    if ((fd = open(fname, O_RDONLY
-#ifdef O_NOCTTY
-                   |O_NOCTTY
-#endif
-                   )) < 0) {
+    if ((fd = pa_open_cloexec(fname, O_RDONLY, 0)) < 0) {
         pa_log("Failed to open file %s: %s", fname, pa_cstrerror(errno));
         goto fail;
     }
index 2d9b76ad6e4597deb836e78f3837c96f28b2efa0..d8c10b1e2ffc23fc440071f402d44bbd9e49dead 100644 (file)
@@ -62,11 +62,7 @@ int pa_sound_file_load(
 
     pa_memchunk_reset(chunk);
 
-    if ((fd = open(fname, O_RDONLY
-#ifdef O_NOCTTY
-                   |O_NOCTTY
-#endif
-                   )) < 0) {
+    if ((fd = pa_open_cloexec(fname, O_RDONLY, 0)) < 0) {
         pa_log("Failed to open file %s: %s", fname, pa_cstrerror(errno));
         goto finish;
     }
index 745c7de04e5d333db651b7c553a5a9bc02d0d780..a011789c3606c149d0e57bab92aee43c3028987f 100644 (file)
@@ -25,6 +25,8 @@
 #endif
 
 #include <pulse/timeval.h>
+#include <pulse/rtclock.h>
+
 #include <pulsecore/random.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/g711.h>
@@ -60,7 +62,9 @@
       " movq "#s", %%mm5             \n\t"                                              \
       " pmulhw "#v", "#s"            \n\t" /* .. |    0  | vl*p0 | */                   \
       " paddw %%mm4, "#s"            \n\t" /* .. |    0  | vl*p0 | + sign correct */    \
+      " pslld $16, "#s"              \n\t" /* .. | vl*p0 |   0   | */                   \
       " psrld $16, "#v"              \n\t" /* .. |    0  |   vh  | */                   \
+      " psrad $16, "#s"              \n\t" /* .. |     vl*p0     | sign extend */       \
       " pmaddwd %%mm5, "#v"          \n\t" /* .. |    p0 * vh    | */                   \
       " paddd "#s", "#v"             \n\t" /* .. |    p0 * v0    | */                   \
       " packssdw "#v", "#v"          \n\t" /* .. | p1*v1 | p0*v0 | */
@@ -255,11 +259,14 @@ static void run_test (void) {
     printf ("checking MMX %zd\n", sizeof (samples));
 
     pa_random (samples, sizeof (samples));
+    /* for (i = 0; i < SAMPLES; i++)
+       samples[i] = -1; */
     memcpy (samples_ref, samples, sizeof (samples));
     memcpy (samples_orig, samples, sizeof (samples));
 
     for (i = 0; i < CHANNELS; i++)
         volumes[i] = rand() >> 1;
+        /* volumes[i] = 0x0000ffff; */
     for (padding = 0; padding < PADDING; padding++, i++)
         volumes[i] = volumes[padding];
 
@@ -267,7 +274,7 @@ static void run_test (void) {
     pa_volume_s16ne_mmx (samples, volumes, CHANNELS, sizeof (samples));
     for (i = 0; i < SAMPLES; i++) {
         if (samples[i] != samples_ref[i]) {
-            printf ("%d: %04x != %04x (%04x * %04x)\n", i, samples[i], samples_ref[i],
+            printf ("%d: %04x != %04x (%04x * %08x)\n", i, samples[i], samples_ref[i],
                   samples_orig[i], volumes[i % CHANNELS]);
         }
     }
@@ -287,6 +294,8 @@ static void run_test (void) {
     }
     stop = pa_rtclock_now();
     pa_log_info("ref: %llu usec.", (long long unsigned int)(stop - start));
+
+    pa_assert_se(memcmp(samples_ref, samples, sizeof(samples)) == 0);
 }
 #endif
 
index 1cc4e0aa925f45db366fa9bea210cf6e154ec277..620524fa6cb166c3e73b9063b958d73bbd57b061 100644 (file)
@@ -25,6 +25,8 @@
 #endif
 
 #include <pulse/timeval.h>
+#include <pulse/rtclock.h>
+
 #include <pulsecore/random.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/g711.h>
@@ -261,7 +263,7 @@ static void run_test (void) {
 
     func = pa_get_volume_func (PA_SAMPLE_S16NE);
 
-    printf ("checking SSE %zd\n", sizeof (samples));
+    printf ("checking SSE2 %zd\n", sizeof (samples));
 
     pa_random (samples, sizeof (samples));
     memcpy (samples_ref, samples, sizeof (samples));
@@ -273,7 +275,7 @@ static void run_test (void) {
         volumes[i] = volumes[padding];
 
     func (samples_ref, volumes, CHANNELS, sizeof (samples));
-    pa_volume_s16ne_sse (samples, volumes, CHANNELS, sizeof (samples));
+    pa_volume_s16ne_sse2 (samples, volumes, CHANNELS, sizeof (samples));
     for (i = 0; i < SAMPLES; i++) {
         if (samples[i] != samples_ref[i]) {
             printf ("%d: %04x != %04x (%04x * %04x)\n", i, samples[i], samples_ref[i],
@@ -284,7 +286,7 @@ static void run_test (void) {
     start = pa_rtclock_now();
     for (j = 0; j < TIMES; j++) {
         memcpy (samples, samples_orig, sizeof (samples));
-        pa_volume_s16ne_sse (samples, volumes, CHANNELS, sizeof (samples));
+        pa_volume_s16ne_sse2 (samples, volumes, CHANNELS, sizeof (samples));
     }
     stop = pa_rtclock_now();
     pa_log_info("SSE: %llu usec.", (long long unsigned int)(stop - start));
@@ -296,6 +298,8 @@ static void run_test (void) {
     }
     stop = pa_rtclock_now();
     pa_log_info("ref: %llu usec.", (long long unsigned int)(stop - start));
+
+    pa_assert_se(memcmp(samples_ref, samples, sizeof(samples)) == 0);
 }
 #endif
 #endif /* defined (__i386__) || defined (__amd64__) */
index d6c37878523702bd126c9851dcd394ee6b073091..1371ad562ef51f058cdc27434938ad051c284f91 100644 (file)
@@ -196,6 +196,13 @@ static double avg_gradient(pa_smoother *s, pa_usec_t x) {
     int64_t ax = 0, ay = 0, k, t;
     double r;
 
+    /* FIXME: Optimization: Jason Newton suggested that instead of
+     * going through the history on each iteration we could calculated
+     * avg_gradient() as we go.
+     *
+     * Second idea: it might make sense to weight history entries:
+     * more recent entries should matter more than old ones. */
+
     /* Too few measurements, assume gradient of 1 */
     if (s->n_history < s->min_history)
         return 1;
index 873a76e7d4ef6468663ff03094d48fd1070a3c9d..dc8ec2947650e35f6906e6c790e12daccf84da13 100644 (file)
 
 void pa_x11_set_prop(Display *d, const char *name, const char *data) {
     Atom a = XInternAtom(d, name, False);
-    XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (const unsigned char*) data, (int) (strlen(data)+1));
+    XChangeProperty(d, DefaultRootWindow(d), a, XA_STRING, 8, PropModeReplace, (const unsigned char*) data, (int) (strlen(data)+1));
 }
 
 void pa_x11_del_prop(Display *d, const char *name) {
     Atom a = XInternAtom(d, name, False);
-    XDeleteProperty(d, RootWindow(d, 0), a);
+    XDeleteProperty(d, DefaultRootWindow(d), a);
 }
 
 char* pa_x11_get_prop(Display *d, const char *name, char *p, size_t l) {
@@ -47,13 +47,21 @@ char* pa_x11_get_prop(Display *d, const char *name, char *p, size_t l) {
     unsigned long nbytes_after;
     unsigned char *prop = NULL;
     char *ret = NULL;
+    int window_ret;
 
     Atom a = XInternAtom(d, name, False);
-    if (XGetWindowProperty(d, RootWindow(d, 0), a, 0, (long) ((l+2)/4), False, XA_STRING, &actual_type, &actual_format, &nitems, &nbytes_after, &prop) != Success)
-        goto finish;
 
-    if (actual_type != XA_STRING)
-        goto finish;
+    window_ret = XGetWindowProperty(d, DefaultRootWindow(d), a, 0, (long) ((l+2)/4), False, XA_STRING, &actual_type, &actual_format, &nitems, &nbytes_after, &prop);
+
+    if (window_ret != Success || actual_type != XA_STRING) {
+        if (DefaultScreen(d) != 0) {
+            window_ret = XGetWindowProperty(d, RootWindow(d, 0), a, 0, (long) ((l+2)/4), False, XA_STRING, &actual_type, &actual_format, &nitems, &nbytes_after, &prop);
+
+            if (window_ret != Success || actual_type != XA_STRING)
+                goto finish;
+        } else
+            goto finish;
+    }
 
     memcpy(p, prop, nitems);
     p[nitems] = 0;
index 5f29ba39995b7f12be6b29b582610cd1352fd192..d348c16a100a0e4bd6d2e594e447e36155c50807 100644 (file)
@@ -906,7 +906,7 @@ int main(int argc, char *argv[]) {
 
         filename = argv[optind];
 
-        if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
+        if ((fd = pa_open_cloexec(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
             pa_log(_("open(): %s"), strerror(errno));
             goto quit;
         }
index 5ef57e3b5b9ed310c64ed2cdf4cde08bbd046627..ef58e9ce317858b6cca912e19bf17f87bf880e25 100644 (file)
@@ -70,7 +70,7 @@ int main(int argc, char*argv[]) {
         goto fail;
     }
 
-    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+    if ((fd = pa_socket_cloexec(PF_UNIX, SOCK_STREAM, 0)) < 0) {
         pa_log(_("socket(PF_UNIX, SOCK_STREAM, 0): %s"), strerror(errno));
         goto fail;
     }
index 141ab5b163930782296edf22a294b5b0f482b55c..ee67c4259196bf77881d897547cb2ef1eaf232a1 100644 (file)
@@ -44,8 +44,6 @@
 #include <pulsecore/log.h>
 #include <pulsecore/sndfile-util.h>
 
-#define BUFSIZE (16*1024)
-
 static pa_context *context = NULL;
 static pa_mainloop_api *mainloop_api = NULL;
 
@@ -158,10 +156,23 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
         return;
     }
 
+    printf(_("Server String: %s\n"
+             "Library Protocol Version: %u\n"
+             "Server Protocol Version: %u\n"
+             "Is Local: %s\n"
+             "Client Index: %u\n"
+             "Tile Size: %zu\n"),
+             pa_context_get_server(c),
+             pa_context_get_protocol_version(c),
+             pa_context_get_server_protocol_version(c),
+             pa_yes_no(pa_context_is_local(c)),
+             pa_context_get_index(c),
+             pa_context_get_tile_size(c, NULL));
+
     pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec);
     pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map);
 
-    printf(_("User name: %s\n"
+    printf(_("User Name: %s\n"
              "Host Name: %s\n"
              "Server Name: %s\n"
              "Server Version: %s\n"
@@ -169,7 +180,7 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
              "Default Channel Map: %s\n"
              "Default Sink: %s\n"
              "Default Source: %s\n"
-             "Cookie: %08x\n"),
+             "Cookie: %04x:%04x\n"),
            i->user_name,
            i->host_name,
            i->server_name,
@@ -178,7 +189,8 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
            cm,
            i->default_sink_name,
            i->default_source_name,
-           i->cookie);
+           i->cookie >> 16,
+           i->cookie & 0xFFFFU);
 
     complete_action();
 }
index c327ee4153457375a568a49990dae72f7e3b7f39..534b77b4a0933eadd369ec148550c826c96f5ba5 100644 (file)
@@ -45,8 +45,6 @@
 #include <pulse/pulseaudio.h>
 #include <pulsecore/macro.h>
 
-#define BUFSIZE 1024
-
 static pa_context *context = NULL;
 static pa_mainloop_api *mainloop_api = NULL;
 static char **child_argv = NULL;
diff --git a/src/utils/qpaeq b/src/utils/qpaeq
new file mode 100755 (executable)
index 0000000..a8a9fda
--- /dev/null
@@ -0,0 +1,560 @@
+#!/usr/bin/env python
+#    qpaeq is a equalizer interface for pulseaudio's equalizer sinks
+#    Copyright (C) 2009  Jason Newton <nevion@gmail.com
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program 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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+import os,math,sys
+try:
+    import PyQt4,sip
+    from PyQt4 import QtGui,QtCore
+    import dbus.mainloop.qt
+    import dbus
+except ImportError,e:
+    print 'There was an error importing need libraries'
+    print 'Make sure you haveqt4 and dbus forthon installed'
+    print 'The error that occured was'
+    print '\t%s' %(str(e))
+    import sys
+    sys.exit(-1)
+
+from functools import partial
+
+import signal
+signal.signal(signal.SIGINT, signal.SIG_DFL)
+SYNC_TIMEOUT = 4*1000
+
+CORE_PATH = "/org/pulseaudio/core1"
+CORE_IFACE = "org.PulseAudio.Core1"
+def connect():
+    try:
+        if 'PULSE_DBUS_SERVER' in os.environ:
+            address = os.environ['PULSE_DBUS_SERVER']
+        else:
+            bus = dbus.SessionBus() # Should be UserBus, but D-Bus doesn't implement that yet.
+            server_lookup = bus.get_object('org.PulseAudio1', '/org/pulseaudio/server_lookup1')
+            address = server_lookup.Get('org.PulseAudio.ServerLookup1', 'Address', dbus_interface='org.freedesktop.DBus.Properties')
+        return dbus.connection.Connection(address)
+    except Exception,e:
+        print 'There was an error connecting to pulseaudio, please make sure you have the pulseaudio dbus'
+        print 'and equalizer modules loaded, exiting...'
+        import sys
+        sys.exit(-1)
+
+
+#TODO: signals: sink Filter changed, sink reconfigured (window size) (sink iface)
+#TODO: manager signals: new sink, removed sink, new profile, removed profile
+#TODO: add support for changing of window_size 1000-fft_size (adv option)
+#TODO: reconnect support loop 1 second trying to reconnect
+#TODO: just resample the filters for profiles when loading to different sizes
+#TODO: add preamp
+prop_iface='org.freedesktop.DBus.Properties'
+eq_iface='org.PulseAudio.Ext.Equalizing1.Equalizer'
+device_iface='org.PulseAudio.Core1.Device'
+class QPaeq(QtGui.QWidget):
+    manager_path='/org/pulseaudio/equalizing1'
+    manager_iface='org.PulseAudio.Ext.Equalizing1.Manager'
+    core_iface='org.PulseAudio.Core1'
+    core_path='/org/pulseaudio/core1'
+    def __init__(self):
+        QtGui.QWidget.__init__(self)
+        self.setWindowTitle('qpaeq')
+        self.slider_widget=None
+        self.sink_name=None
+        self.filter_state=None
+
+        self.create_layout()
+
+        self.set_connection()
+        self.connect_to_sink(self.sinks[0])
+        self.set_callbacks()
+        self.setMinimumSize(self.sizeHint())
+
+    def create_layout(self):
+        self.main_layout=QtGui.QVBoxLayout()
+        self.setLayout(self.main_layout)
+        toprow_layout=QtGui.QHBoxLayout()
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        #sizePolicy.setHeightForWidth(self.profile_box.sizePolicy().hasHeightForWidth())
+
+        toprow_layout.addWidget(QtGui.QLabel('Sink'))
+        self.sink_box = QtGui.QComboBox()
+        self.sink_box.setSizePolicy(sizePolicy)
+        self.sink_box.setDuplicatesEnabled(False)
+        self.sink_box.setInsertPolicy(QtGui.QComboBox.InsertAlphabetically)
+        #self.sink_box.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
+        toprow_layout.addWidget(self.sink_box)
+
+        toprow_layout.addWidget(QtGui.QLabel('Channel'))
+        self.channel_box = QtGui.QComboBox()
+        self.channel_box.setSizePolicy(sizePolicy)
+        toprow_layout.addWidget(self.channel_box)
+
+        toprow_layout.addWidget(QtGui.QLabel('Preset'))
+        self.profile_box = QtGui.QComboBox()
+        self.profile_box.setSizePolicy(sizePolicy)
+        self.profile_box.setInsertPolicy(QtGui.QComboBox.InsertAlphabetically)
+        #self.profile_box.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
+        toprow_layout.addWidget(self.profile_box)
+
+        large_icon_size=self.style().pixelMetric(QtGui.QStyle.PM_LargeIconSize)
+        large_icon_size=QtCore.QSize(large_icon_size,large_icon_size)
+        save_profile=QtGui.QToolButton()
+        save_profile.setIcon(self.style().standardIcon(QtGui.QStyle.SP_DriveFDIcon))
+        save_profile.setIconSize(large_icon_size)
+        save_profile.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
+        save_profile.clicked.connect(self.save_profile)
+        remove_profile=QtGui.QToolButton()
+        remove_profile.setIcon(self.style().standardIcon(QtGui.QStyle.SP_TrashIcon))
+        remove_profile.setIconSize(large_icon_size)
+        remove_profile.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
+        remove_profile.clicked.connect(self.remove_profile)
+        toprow_layout.addWidget(save_profile)
+        toprow_layout.addWidget(remove_profile)
+
+        reset_button = QtGui.QPushButton('Reset')
+        reset_button.clicked.connect(self.reset)
+        toprow_layout.addStretch()
+        toprow_layout.addWidget(reset_button)
+        self.layout().addLayout(toprow_layout)
+
+        self.profile_box.activated.connect(self.load_profile)
+        self.channel_box.activated.connect(self.select_channel)
+    def connect_to_sink(self,name):
+        #TODO: clear slots for profile buttons
+
+        #flush any pending saves for other sinks
+        if self.filter_state is not None:
+            self.filter_state.flush_state()
+        sink=self.connection.get_object(object_path=name)
+        self.sink_props=dbus.Interface(sink,dbus_interface=prop_iface)
+        self.sink=dbus.Interface(sink,dbus_interface=eq_iface)
+        self.filter_state=FilterState(sink)
+        #sample_rate,filter_rate,channels,channel)
+
+        self.channel_box.clear()
+        self.channel_box.addItem('All',self.filter_state.channels)
+        for i in xrange(self.filter_state.channels):
+            self.channel_box.addItem('%d' %(i+1,),i)
+        self.setMinimumSize(self.sizeHint())
+
+        self.set_slider_widget(SliderArray(self.filter_state))
+
+        self.sink_name=name
+        #set the signal listener for this sink
+        core=self._get_core()
+        #temporary hack until signal filtering works properly
+        core.ListenForSignal('',[dbus.ObjectPath(self.sink_name),dbus.ObjectPath(self.manager_path)])
+        #for x in ['FilterChanged']:
+        #    core.ListenForSignal("%s.%s" %(self.eq_iface,x),[dbus.ObjectPath(self.sink_name)])
+        #core.ListenForSignal(self.eq_iface,[dbus.ObjectPath(self.sink_name)])
+        self.sink.connect_to_signal('FilterChanged',self.read_filter)
+
+    def set_slider_widget(self,widget):
+        layout=self.layout()
+        if self.slider_widget is not None:
+            i=layout.indexOf(self.slider_widget)
+            layout.removeWidget(self.slider_widget)
+            self.slider_widget.deleteLater()
+            layout.insertWidget(i,self.slider_widget)
+        else:
+            layout.addWidget(widget)
+        self.slider_widget=widget
+        self.read_filter()
+    def _get_core(self):
+        core_obj=self.connection.get_object(object_path=self.core_path)
+        core=dbus.Interface(core_obj,dbus_interface=self.core_iface)
+        return core
+    def sink_added(self,sink):
+        #TODO: preserve selected sink
+        self.update_sinks()
+    def sink_removed(self,sink):
+        #TODO: preserve selected sink, try connecting to backup otherwise
+        if sink==self.sink_name:
+            #connect to new sink?
+            pass
+        self.update_sinks()
+    def save_profile(self):
+        #popup dialog box for name
+        current=self.profile_box.currentIndex()
+        profile,ok=QtGui.QInputDialog.getItem(self,'Preset Name','Preset',self.profiles,current)
+        if not ok or profile=='':
+            return
+        if profile in self.profiles:
+            mbox=QtGui.QMessageBox(self)
+            mbox.setText('%s preset already exists'%(profile,))
+            mbox.setInformativeText('Do you want to save over it?')
+            mbox.setStandardButtons(mbox.Save|mbox.Discard|mbox.Cancel)
+            mbox.setDefaultButton(mbox.Save)
+            ret=mbox.exec_()
+            if ret!=mbox.Save:
+                return
+        self.sink.SaveProfile(self.filter_state.channel,dbus.String(profile))
+        if self.filter_state.channel==self.filter_state.channels:
+            for x in range(1,self.filter_state.channels):
+                self.sink.LoadProfile(x,dbus.String(profile))
+    def remove_profile(self):
+        #find active profile name, remove it
+        profile=self.profile_box.currentText()
+        manager=dbus.Interface(self.manager_obj,dbus_interface=self.manager_iface)
+        manager.RemoveProfile(dbus.String(profile))
+    def load_profile(self,x):
+        profile=self.profile_box.itemText(x)
+        self.filter_state.load_profile(profile)
+    def select_channel(self,x):
+        self.filter_state.channel = self.channel_box.itemData(x).toPyObject()
+        self._set_profile_name()
+        self.filter_state.readback()
+
+    #TODO: add back in preamp!
+    #print frequencies
+    #main_layout.addLayout(self.create_slider(partial(self.update_coefficient,0),
+    #    'Preamp')[0]
+    #)
+    def set_connection(self):
+        self.connection=connect()
+        self.manager_obj=self.connection.get_object(object_path=self.manager_path)
+        manager_props=dbus.Interface(self.manager_obj,dbus_interface=prop_iface)
+        self.sinks=manager_props.Get(self.manager_iface,'EqualizedSinks')
+    def set_callbacks(self):
+        manager=dbus.Interface(self.manager_obj,dbus_interface=self.manager_iface)
+        manager.connect_to_signal('ProfilesChanged',self.update_profiles)
+        manager.connect_to_signal('SinkAdded',self.sink_added)
+        manager.connect_to_signal('SinkRemoved',self.sink_removed)
+        #self._get_core().ListenForSignal(self.manager_iface,[])
+        #self._get_core().ListenForSignal(self.manager_iface,[dbus.ObjectPath(self.manager_path)])
+        #core=self._get_core()
+        #for x in ['ProfilesChanged','SinkAdded','SinkRemoved']:
+        #    core.ListenForSignal("%s.%s" %(self.manager_iface,x),[dbus.ObjectPath(self.manager_path)])
+        self.update_profiles()
+        self.update_sinks()
+    def update_profiles(self):
+        #print 'update profiles called!'
+        manager_props=dbus.Interface(self.manager_obj,dbus_interface=prop_iface)
+        self.profiles=manager_props.Get(self.manager_iface,'Profiles')
+        self.profile_box.blockSignals(True)
+        self.profile_box.clear()
+        self.profile_box.addItems(self.profiles)
+        self.profile_box.blockSignals(False)
+        self._set_profile_name()
+    def update_sinks(self):
+        self.sink_box.blockSignals(True)
+        self.sink_box.clear()
+        for x in self.sinks:
+            sink=self.connection.get_object(object_path=x)
+            sink_props=dbus.Interface(sink,dbus_interface=prop_iface)
+            simple_name=sink_props.Get(device_iface,'Name')
+            self.sink_box.addItem(simple_name,x)
+        self.sink_box.blockSignals(False)
+        self.sink_box.setMinimumSize(self.sink_box.sizeHint())
+    def read_filter(self):
+        #print self.filter_frequencies
+        self.filter_state.readback()
+    def reset(self):
+        coefs=dbus.Array([1/math.sqrt(2.0)]*(self.filter_state.filter_rate//2+1))
+        preamp=1.0
+        self.filter_state.set_filter(preamp,coefs)
+    def _set_profile_name(self):
+        self.profile_box.blockSignals(True)
+        profile_name=self.sink.BaseProfile(self.filter_state.channel)
+        if profile_name is not None:
+            i=self.profile_box.findText(profile_name)
+            if i>=0:
+                self.profile_box.setCurrentIndex(i)
+        self.profile_box.blockSignals(False)
+
+
+class SliderArray(QtGui.QWidget):
+    def __init__(self,filter_state,parent=None):
+        super(SliderArray,self).__init__(parent)
+        #self.setStyleSheet('padding: 0px; border-width: 0px; margin: 0px;')
+        #self.setStyleSheet('font-size: 7pt; font-family: monospace;'+outline%('blue'))
+        self.filter_state=filter_state
+        self.setLayout(QtGui.QHBoxLayout())
+        self.sub_array=None
+        self.set_sub_array(SliderArraySub(self.filter_state))
+        self.inhibit_resize=0
+    def set_sub_array(self,widget):
+        if self.sub_array is not None:
+            self.layout().removeWidget(self.sub_array)
+            self.sub_array.disconnect_signals()
+            self.sub_array.deleteLater()
+        self.sub_array=widget
+        self.layout().addWidget(self.sub_array)
+        self.sub_array.connect_signals()
+        self.filter_state.readback()
+    def resizeEvent(self,event):
+        super(SliderArray,self).resizeEvent(event)
+        if self.inhibit_resize==0:
+            self.inhibit_resize+=1
+            #self.add_sliders_to_fit()
+            t=QtCore.QTimer(self)
+            t.setSingleShot(True)
+            t.setInterval(0)
+            t.timeout.connect(partial(self.add_sliders_to_fit,event))
+            t.start()
+    def add_sliders_to_fit(self,event):
+        if event.oldSize().width()>0 and event.size().width()>0:
+            i=len(self.filter_state.frequencies)*int(round(float(event.size().width())/event.oldSize().width()))
+        else:
+            i=len(self.filter_state.frequencies)
+
+        t_w=self.size().width()
+        def evaluate(filter_state, target, variable):
+            base_freqs=self.filter_state.freq_proper(self.filter_state.DEFAULT_FREQUENCIES)
+            filter_state._set_frequency_values(subdivide(base_freqs,variable))
+            new_widget=SliderArraySub(filter_state)
+            w=new_widget.sizeHint().width()
+            return w-target
+        def searcher(initial,evaluator):
+            i=initial
+            def d(e): return 1 if e>=0 else -1
+            error=evaluator(i)
+            old_direction=d(error)
+            i-=old_direction
+            while True:
+                error=evaluator(i)
+                direction=d(error)
+                if direction!=old_direction:
+                    k=i-1
+                    #while direction<0 and error!=0:
+                    #    k-=1
+                    #    error=evaluator(i)
+                    #    direction=d(error)
+                    return k, evaluator(k)
+                i-=direction
+                old_direction=direction
+        searcher(i,partial(evaluate,self.filter_state,t_w))
+        self.set_sub_array(SliderArraySub(self.filter_state))
+        self.inhibit_resize-=1
+
+class SliderArraySub(QtGui.QWidget):
+    def __init__(self,filter_state,parent=None):
+        super(SliderArraySub,self).__init__(parent)
+        self.filter_state=filter_state
+        self.setLayout(QtGui.QGridLayout())
+        self.slider=[None]*len(self.filter_state.frequencies)
+        self.label=[None]*len(self.slider)
+        #self.setStyleSheet('padding: 0px; border-width: 0px; margin: 0px;')
+        #self.setStyleSheet('font-size: 7pt; font-family: monospace;'+outline%('blue'))
+        qt=QtCore.Qt
+        #self.layout().setHorizontalSpacing(1)
+        def add_slider(slider,label, c):
+            self.layout().addWidget(slider,0,c,qt.AlignHCenter)
+            self.layout().addWidget(label,1,c,qt.AlignHCenter)
+            self.layout().setColumnMinimumWidth(c,max(label.sizeHint().width(),slider.sizeHint().width()))
+        def create_slider(slider_label):
+            slider=QtGui.QSlider(QtCore.Qt.Vertical,self)
+            label=SliderLabel(slider_label,filter_state,self)
+            slider.setRange(-1000,2000)
+            slider.setSingleStep(1)
+            return (slider,label)
+        self.preamp_slider,self.preamp_label=create_slider('Preamp')
+        add_slider(self.preamp_slider,self.preamp_label,0)
+        for i,hz in enumerate(self.filter_state.frequencies):
+            slider,label=create_slider(self.hz2label(hz))
+            self.slider[i]=slider
+            #slider.setStyleSheet('font-size: 7pt; font-family: monospace;'+outline%('red',))
+            self.label[i]=label
+            c=i+1
+            add_slider(slider,label,i+1)
+    def hz2label(self, hz):
+        if hz==0:
+            label_text='DC'
+        elif hz==self.filter_state.sample_rate//2:
+            label_text='Coda'
+        else:
+            label_text=hz2str(hz)
+        return label_text
+
+    def connect_signals(self):
+        def connect(writer,reader,slider,label):
+            slider.valueChanged.connect(writer)
+            self.filter_state.readFilter.connect(reader)
+            label_cb=partial(slider.setValue,0)
+            label.clicked.connect(label_cb)
+            return label_cb
+
+        self.preamp_writer_cb=self.write_preamp
+        self.preamp_reader_cb=self.sync_preamp
+        self.preamp_label_cb=connect(self.preamp_writer_cb,
+                self.preamp_reader_cb,
+                self.preamp_slider,
+                self.preamp_label)
+        self.writer_callbacks=[None]*len(self.slider)
+        self.reader_callbacks=[None]*len(self.slider)
+        self.label_callbacks=[None]*len(self.label)
+        for i in range(len(self.slider)):
+            self.writer_callbacks[i]=partial(self.write_coefficient,i)
+            self.reader_callbacks[i]=partial(self.sync_coefficient,i)
+            self.label_callbacks[i]=connect(self.writer_callbacks[i],
+                    self.reader_callbacks[i],
+                    self.slider[i],
+                    self.label[i])
+    def disconnect_signals(self):
+        def disconnect(writer,reader,label_cb,slider,label):
+            slider.valueChanged.disconnect(writer)
+            self.filter_state.readFilter.disconnect(reader)
+            label.clicked.disconnect(label_cb)
+        disconnect(self.preamp_writer_cb, self.preamp_reader_cb,
+                self.preamp_label_cb, self.preamp_slider, self.preamp_label)
+        for i in range(len(self.slider)):
+            disconnect(self.writer_callbacks[i],
+                    self.reader_callbacks[i],
+                    self.label_callbacks[i],
+                    self.slider[i],
+                    self.label[i])
+
+    def write_preamp(self, v):
+        self.filter_state.preamp=self.slider2coef(v)
+        self.filter_state.seed()
+    def sync_preamp(self):
+        self.preamp_slider.blockSignals(True)
+        self.preamp_slider.setValue(self.coef2slider(self.filter_state.preamp))
+        self.preamp_slider.blockSignals(False)
+
+
+    def write_coefficient(self,i,v):
+        self.filter_state.coefficients[i]=self.slider2coef(v)/math.sqrt(2.0)
+        self.filter_state.seed()
+    def sync_coefficient(self,i):
+        slider=self.slider[i]
+        slider.blockSignals(True)
+        slider.setValue(self.coef2slider(math.sqrt(2.0)*self.filter_state.coefficients[i]))
+        slider.blockSignals(False)
+    @staticmethod
+    def slider2coef(x):
+        return (1.0+(x/1000.0))
+    @staticmethod
+    def coef2slider(x):
+        return int((x-1.0)*1000)
+outline='border-width: 1px; border-style: solid; border-color: %s;'
+
+class SliderLabel(QtGui.QLabel):
+    clicked=QtCore.pyqtSignal()
+    def __init__(self,label_text,filter_state,parent=None):
+        super(SliderLabel,self).__init__(parent)
+        self.setStyleSheet('font-size: 7pt; font-family: monospace;')
+        self.setText(label_text)
+        self.setMinimumSize(self.sizeHint())
+    def mouseDoubleClickEvent(self, event):
+        self.clicked.emit()
+        super(SliderLabel,self).mouseDoubleClickEvent(event)
+
+#until there are server side state savings, do it in the client but try and avoid
+#simulaneous broadcasting situations
+class FilterState(QtCore.QObject):
+    #DEFAULT_FREQUENCIES=map(float,[25,50,75,100,150,200,300,400,500,800,1e3,1.5e3,3e3,5e3,7e3,10e3,15e3,20e3])
+    DEFAULT_FREQUENCIES=[31.75,63.5,125,250,500,1e3,2e3,4e3,8e3,16e3]
+    readFilter=QtCore.pyqtSignal()
+    def __init__(self,sink):
+        super(FilterState,self).__init__()
+        self.sink_props=dbus.Interface(sink,dbus_interface=prop_iface)
+        self.sink=dbus.Interface(sink,dbus_interface=eq_iface)
+        self.sample_rate=self.get_eq_attr('SampleRate')
+        self.filter_rate=self.get_eq_attr('FilterSampleRate')
+        self.channels=self.get_eq_attr('NChannels')
+        self.channel=self.channels
+        self.set_frequency_values(self.DEFAULT_FREQUENCIES)
+        self.sync_timer=QtCore.QTimer()
+        self.sync_timer.setSingleShot(True)
+        self.sync_timer.timeout.connect(self.save_state)
+
+    def get_eq_attr(self,attr):
+        return self.sink_props.Get(eq_iface,attr)
+    def freq_proper(self,xs):
+        return [0]+xs+[self.sample_rate//2]
+    def _set_frequency_values(self,freqs):
+        self.frequencies=freqs
+        #print 'base',self.frequencies
+        self.filter_frequencies=map(lambda x: int(round(x)), \
+                self.translate_rates(self.filter_rate,self.sample_rate,
+                    self.frequencies) \
+                )
+        self.coefficients=[0.0]*len(self.frequencies)
+        self.preamp=1.0
+    def set_frequency_values(self,freqs):
+        self._set_frequency_values(self.freq_proper(freqs))
+    @staticmethod
+    def translate_rates(dst,src,rates):
+        return list(map(lambda x: x*dst/src,rates))
+    def seed(self):
+        self.sink.SeedFilter(self.channel,self.filter_frequencies,self.coefficients,self.preamp)
+        self.sync_timer.start(SYNC_TIMEOUT)
+    def readback(self):
+        coefs,preamp=self.sink.FilterAtPoints(self.channel,self.filter_frequencies)
+        self.coefficients=coefs
+        self.preamp=preamp
+        self.readFilter.emit()
+    def set_filter(self,preamp,coefs):
+        self.sink.SetFilter(self.channel,dbus.Array(coefs),self.preamp)
+        self.sync_timer.start(SYNC_TIMEOUT)
+    def save_state(self):
+        print 'saving state'
+        self.sink.SaveState()
+    def load_profile(self,profile):
+        self.sink.LoadProfile(self.channel,dbus.String(profile))
+        self.sync_timer.start(SYNC_TIMEOUT)
+    def flush_state(self):
+        if self.sync_timer.isActive():
+            self.sync_timer.stop()
+            self.save_state()
+
+
+def safe_log(k,b):
+    i=0
+    while k//b!=0:
+        i+=1
+        k=k//b
+    return i
+def hz2str(hz):
+    p=safe_log(hz,10.0)
+    if p<3:
+        return '%dHz' %(hz,)
+    elif hz%1000==0:
+        return '%dKHz' %(hz/(10.0**3),)
+    else:
+        return '%.1fKHz' %(hz/(10.0**3),)
+
+def subdivide(xs, t_points):
+    while len(xs)<t_points:
+        m=[0]*(2*len(xs)-1)
+        m[0:len(m):2]=xs
+        for i in range(1,len(m),2):
+            m[i]=(m[i-1]+m[i+1])//2
+        xs=m
+    p_drop=len(xs)-t_points
+    p_drop_left=p_drop//2
+    p_drop_right=p_drop-p_drop_left
+    #print 'xs',xs
+    #print 'dropping %d, %d left, %d right' %(p_drop,p_drop_left,p_drop_right)
+    c=len(xs)//2
+    left=xs[0:p_drop_left*2:2]+xs[p_drop_left*2:c]
+    right=list(reversed(xs[c:]))
+    right=right[0:p_drop_right*2:2]+right[p_drop_right*2:]
+    right=list(reversed(right))
+    return left+right
+
+def main():
+    dbus.mainloop.qt.DBusQtMainLoop(set_as_default=True)
+    app=QtGui.QApplication(sys.argv)
+    qpaeq_main=QPaeq()
+    qpaeq_main.show()
+    sys.exit(app.exec_())
+
+if __name__=='__main__':
+    main()