mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	Merge branch 'master' of git://0pointer.de/pulseaudio
This commit is contained in:
		
						commit
						d5d488e33d
					
				
					 32 changed files with 1858 additions and 578 deletions
				
			
		
							
								
								
									
										61
									
								
								configure.ac
									
										
									
									
									
								
							
							
						
						
									
										61
									
								
								configure.ac
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
        ;;
 | 
			
		||||
        *)
 | 
			
		||||
            if test "x$pulse_target_os" = "xnetbsd" && test "x$atomic_netbsd_helpers" = "xyes"; then
 | 
			
		||||
	*-netbsdelf5*)
 | 
			
		||||
            AC_MSG_RESULT([yes])
 | 
			
		||||
                AC_DEFINE_UNQUOTED(NETBSD_ATOMIC_OPS, 1, [netbsd implementation])
 | 
			
		||||
            need_libatomic_ops=no
 | 
			
		||||
            else
 | 
			
		||||
	;;
 | 
			
		||||
	*-freebsd*)
 | 
			
		||||
            AC_MSG_RESULT([yes])
 | 
			
		||||
            need_libatomic_ops=no
 | 
			
		||||
	;;
 | 
			
		||||
        *)
 | 
			
		||||
            AC_MSG_RESULT([unknown])
 | 
			
		||||
            fi
 | 
			
		||||
        ;;
 | 
			
		||||
    esac
 | 
			
		||||
fi
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -125,28 +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-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
 | 
			
		||||
		daemon/pulseaudio-system.conf
 | 
			
		||||
 | 
			
		||||
pulseconf_DATA = \
 | 
			
		||||
		default.pa \
 | 
			
		||||
| 
						 | 
				
			
			@ -1088,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 \
 | 
			
		||||
| 
						 | 
				
			
			@ -1110,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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1204,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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -537,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);
 | 
			
		||||
| 
						 | 
				
			
			@ -547,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));
 | 
			
		||||
| 
						 | 
				
			
			@ -561,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;
 | 
			
		||||
| 
						 | 
				
			
			@ -568,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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -580,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
 | 
			
		||||
| 
						 | 
				
			
			@ -589,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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -598,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. */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -259,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));
 | 
			
		||||
| 
						 | 
				
			
			@ -303,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;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -311,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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -322,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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -333,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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -374,8 +378,6 @@ 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->channels = _ss.channels;
 | 
			
		||||
    ss->format = _ss.format;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
        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_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_iter);
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_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_iter);
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_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, 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(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_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);
 | 
			
		||||
                    dbus_message_unref(signal);
 | 
			
		||||
                    signal = NULL;
 | 
			
		||||
                    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_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, 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(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_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);
 | 
			
		||||
                    dbus_message_unref(signal);
 | 
			
		||||
                    signal = NULL;
 | 
			
		||||
                    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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                    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;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            } 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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                    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;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            } 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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
                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_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, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID));
 | 
			
		||||
    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_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, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID));
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_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,
 | 
			
		||||
        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_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, DBUS_TYPE_BOOLEAN, &d->mute, DBUS_TYPE_INVALID));
 | 
			
		||||
        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_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, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID));
 | 
			
		||||
        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_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, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 | 
			
		||||
        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_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_iter);
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_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_iter);
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_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_iter);
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_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, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
 | 
			
		||||
            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_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, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
 | 
			
		||||
            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_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, DBUS_TYPE_UINT32, &s->sample_rate, DBUS_TYPE_INVALID));
 | 
			
		||||
        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_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,
 | 
			
		||||
            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_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, DBUS_TYPE_BOOLEAN, &s->mute, DBUS_TYPE_INVALID));
 | 
			
		||||
            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_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_iter);
 | 
			
		||||
        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_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_iter);
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_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_iter);
 | 
			
		||||
    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. */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1032,27 +1032,27 @@ 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;
 | 
			
		||||
            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) {
 | 
			
		||||
                    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) {
 | 
			
		||||
                    if (strcmp(s->name, device_name) == 0) {
 | 
			
		||||
                        found_index = s->index;
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                pa_xfree(devname);
 | 
			
		||||
                pa_xfree(device_name);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            pa_tagstruct_puts(reply, name);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef __SSE2__
 | 
			
		||||
#if 1
 | 
			
		||||
//reference implementation
 | 
			
		||||
static void dsp_logic(
 | 
			
		||||
    float * restrict dst,//used as a temp array too, needs to be fft_length!
 | 
			
		||||
| 
						 | 
				
			
			@ -489,18 +493,42 @@ static void dsp_logic(
 | 
			
		|||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void process_samples(struct userdata *u, pa_memchunk *tchunk){
 | 
			
		||||
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++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -526,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){
 | 
			
		||||
| 
						 | 
				
			
			@ -556,7 +584,8 @@ static void input_buffer(struct userdata *u, pa_memchunk *in){
 | 
			
		|||
/* Called from I/O thread context */
 | 
			
		||||
static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
 | 
			
		||||
    struct userdata *u;
 | 
			
		||||
    size_t fs, target_samples, mbs;
 | 
			
		||||
    size_t fs, target_samples;
 | 
			
		||||
    size_t mbs;
 | 
			
		||||
    //struct timeval start, end;
 | 
			
		||||
    pa_memchunk tchunk;
 | 
			
		||||
    pa_sink_input_assert_ref(i);
 | 
			
		||||
| 
						 | 
				
			
			@ -564,13 +593,17 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
 | 
			
		|||
    pa_assert(chunk);
 | 
			
		||||
    pa_assert(u->sink);
 | 
			
		||||
    fs = pa_frame_size(&(u->sink->sample_spec));
 | 
			
		||||
    nbytes = PA_MIN(nbytes, pa_mempool_block_size_max(u->sink->core->mempool));
 | 
			
		||||
    target_samples = PA_ROUND_UP(nbytes / fs, u->R);
 | 
			
		||||
    mbs = pa_mempool_block_size_max(u->sink->core->mempool);
 | 
			
		||||
    //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);
 | 
			
		||||
    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
 | 
			
		||||
| 
						 | 
				
			
			@ -594,7 +627,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
 | 
			
		|||
        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);
 | 
			
		||||
| 
						 | 
				
			
			@ -619,11 +652,13 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
 | 
			
		|||
    pa_assert(u->R < u->window_size);
 | 
			
		||||
    //pa_rtclock_get(&start);
 | 
			
		||||
    /* process a block */
 | 
			
		||||
    process_samples(u, chunk);
 | 
			
		||||
    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;
 | 
			
		||||
| 
						 | 
				
			
			@ -1143,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));
 | 
			
		||||
| 
						 | 
				
			
			@ -1255,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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,10 @@
 | 
			
		|||
#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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,10 @@
 | 
			
		|||
#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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,15 +483,21 @@ 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));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 = pa_open_cloexec(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;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.20 */
 | 
			
		||||
 * 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.20 */
 | 
			
		||||
/** 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.20 */
 | 
			
		||||
/** 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.20 */
 | 
			
		||||
/** 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.20 */
 | 
			
		||||
/** 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.20 */
 | 
			
		||||
/** 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.20 */
 | 
			
		||||
/** 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.20 */
 | 
			
		||||
/** 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.20 */
 | 
			
		||||
/** 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.20 */
 | 
			
		||||
/** 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.20 */
 | 
			
		||||
/** 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.20 */
 | 
			
		||||
 * 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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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! */
 | 
			
		||||
| 
						 | 
				
			
			@ -1465,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);
 | 
			
		||||
| 
						 | 
				
			
			@ -1472,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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2020,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);
 | 
			
		||||
| 
						 | 
				
			
			@ -2035,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;
 | 
			
		||||
| 
						 | 
				
			
			@ -2073,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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2107,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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2128,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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2379,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(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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."
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
                for (t = p; n > 0; n -= fs) {
 | 
			
		||||
                uint8_t *d, *s;
 | 
			
		||||
                unsigned channel;
 | 
			
		||||
                int32_t factor = linear_get_int(e, v);
 | 
			
		||||
                    unsigned c;
 | 
			
		||||
                    e->x += fs;
 | 
			
		||||
 | 
			
		||||
                    for (c = 0; c < e->sample_spec.channels; c++, t++)
 | 
			
		||||
                        *t = (uint8_t) (((factor * ((int16_t) *t - 0x80)) / 0x10000) + 0x80);
 | 
			
		||||
                s = (uint8_t*) p + n;
 | 
			
		||||
 | 
			
		||||
                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;
 | 
			
		||||
 | 
			
		||||
                for (t = p; n > 0; n -= fs) {
 | 
			
		||||
                uint8_t *d, *s;
 | 
			
		||||
                unsigned channel;
 | 
			
		||||
                int32_t factor = linear_get_int(e, v);
 | 
			
		||||
                    unsigned c;
 | 
			
		||||
                    e->x += fs;
 | 
			
		||||
 | 
			
		||||
                    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));
 | 
			
		||||
                s = (uint8_t*) p + n;
 | 
			
		||||
 | 
			
		||||
                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;
 | 
			
		||||
 | 
			
		||||
                for (t = p; n > 0; n -= fs) {
 | 
			
		||||
                uint8_t *d, *s;
 | 
			
		||||
                unsigned channel;
 | 
			
		||||
                int32_t factor = linear_get_int(e, v);
 | 
			
		||||
                    unsigned c;
 | 
			
		||||
                    e->x += fs;
 | 
			
		||||
 | 
			
		||||
                    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));
 | 
			
		||||
                s = (uint8_t*) p + n;
 | 
			
		||||
 | 
			
		||||
                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;
 | 
			
		||||
 | 
			
		||||
                for (t = p; n > 0; n -= fs) {
 | 
			
		||||
                int16_t *d, *s;
 | 
			
		||||
                unsigned channel;
 | 
			
		||||
                int32_t factor = linear_get_int(e, v);
 | 
			
		||||
                    unsigned c;
 | 
			
		||||
                    e->x += fs;
 | 
			
		||||
 | 
			
		||||
                    for (c = 0; c < e->sample_spec.channels; c++, t++)
 | 
			
		||||
                        *t = (int16_t) ((factor * *t) / 0x10000);
 | 
			
		||||
                s = (int16_t*) p + n/sizeof(int16_t);
 | 
			
		||||
 | 
			
		||||
                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;
 | 
			
		||||
 | 
			
		||||
                for (t = p; n > 0; n -= fs) {
 | 
			
		||||
                int16_t *d, *s;
 | 
			
		||||
                unsigned channel;
 | 
			
		||||
                int32_t factor = linear_get_int(e, v);
 | 
			
		||||
                    unsigned c;
 | 
			
		||||
                    e->x += fs;
 | 
			
		||||
 | 
			
		||||
                    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);
 | 
			
		||||
                s = (int16_t*) p + n/sizeof(int16_t);
 | 
			
		||||
 | 
			
		||||
                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;
 | 
			
		||||
 | 
			
		||||
                for (t = p; n > 0; n -= fs) {
 | 
			
		||||
                int32_t *d, *s;
 | 
			
		||||
                unsigned channel;
 | 
			
		||||
                int32_t factor = linear_get_int(e, v);
 | 
			
		||||
                    unsigned c;
 | 
			
		||||
                    e->x += fs;
 | 
			
		||||
 | 
			
		||||
                    for (c = 0; c < e->sample_spec.channels; c++, t++)
 | 
			
		||||
                        *t = (int32_t) (((int64_t) factor * (int64_t) *t) / 0x10000);
 | 
			
		||||
                s = (int32_t*) p + n/sizeof(int32_t);
 | 
			
		||||
 | 
			
		||||
                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;
 | 
			
		||||
 | 
			
		||||
                for (t = p; n > 0; n -= fs) {
 | 
			
		||||
                int32_t *d, *s;
 | 
			
		||||
                unsigned channel;
 | 
			
		||||
                int32_t factor = linear_get_int(e, v);
 | 
			
		||||
                    unsigned c;
 | 
			
		||||
                    e->x += fs;
 | 
			
		||||
 | 
			
		||||
                    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);
 | 
			
		||||
                s = (int32_t*) p + n/sizeof(int32_t);
 | 
			
		||||
 | 
			
		||||
                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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			@ -750,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 */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -794,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) {
 | 
			
		||||
| 
						 | 
				
			
			@ -979,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 */
 | 
			
		||||
| 
						 | 
				
			
			@ -1050,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 */
 | 
			
		||||
| 
						 | 
				
			
			@ -1442,14 +1417,22 @@ 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)) {
 | 
			
		||||
                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) {
 | 
			
		||||
                if (!pa_atomic_load(&i->before_ramping_m))
 | 
			
		||||
                    i->thread_info.muted = i->muted;
 | 
			
		||||
                pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -1498,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;
 | 
			
		||||
| 
						 | 
				
			
			@ -1660,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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1731,9 +1731,13 @@ 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;
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										560
									
								
								src/utils/qpaeq
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										560
									
								
								src/utils/qpaeq
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -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()
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue