diff options
240 files changed, 24122 insertions, 4370 deletions
@@ -1,5 +1,4 @@ ABOUT-NLS -common/ intltool-extract.in intltool-merge.in intltool-update.in diff --git a/Makefile.am b/Makefile.am index b5e638bd..b27f9e65 100644 --- a/Makefile.am +++ b/Makefile.am @@ -58,7 +58,7 @@ dist-hook: if test -d .git ; then \ git pull ; \ chmod u+w ${distdir}/ChangeLog || true ; \ - git-changelog.perl > ${distdir}/ChangeLog ; \ + ( git-changelog.perl || echo "git-changelog.perl failed." ) > ${distdir}/ChangeLog 2>&1 ; \ fi .PHONY: homepage distcleancheck doxygen @@ -126,7 +126,7 @@ New field for PA_COMMAND_CREATE_PLAYBACK_STREAM at the end: Buffer attributes for PA_COMMAND_CREATE_PLAYBACK_STREAM and PA_COMMAND_CREATE_RECORD_STREAM may now be 0 for default values. -New filed for PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR, +New field for PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR, PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR at the end: adjust_latency (bool) @@ -140,3 +140,27 @@ new message: new message: PA_COMMAND_EXTENSION + +PA_COMMAND_CREATE_PLAYBACK_STREAM: + + bool volume_set at the end + +PA_COMMAND_CREATE_RECORD_STREAM, PA_COMMAND_CREATE_PLAYBACK_STREAM: + + bool early_requests at the end + +New field for PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR, +PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR at the end: + + early_requests (bool) + + +### v15, implemented by >= 0.9.14 + +PA_COMMAND_CREATE_PLAYBACK_STREAM + + bool muted at the end + +PA_COMMAND_CREATE_PLAYBACK_STREAM, PA_COMMAND_CREATE_RECORD_STREAM: + + bool dont_inhibit_auto_suspend ate the end diff --git a/bootstrap.sh b/bootstrap.sh index e5f1ac59..5dfcdf20 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -59,8 +59,8 @@ else intltoolize --copy --force --automake "$LIBTOOLIZE" -c --force --ltdl run_versioned aclocal "$VERSION" -I m4 - run_versioned autoconf 2.59 -Wall - run_versioned autoheader 2.59 + run_versioned autoconf 2.62 -Wall + run_versioned autoheader 2.62 run_versioned automake "$VERSION" --copy --foreign --add-missing if test "x$NOCONFIGURE" = "x"; then diff --git a/configure.ac b/configure.ac index 8bb3f8ac..95ac9c2e 100644 --- a/configure.ac +++ b/configure.ac @@ -24,27 +24,28 @@ AC_PREREQ(2.62) m4_define(PA_MAJOR, [0]) m4_define(PA_MINOR, [9]) -m4_define(PA_MICRO, [11]) +m4_define(PA_MICRO, [14]) -AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzchyfrnhqvb (at) 0pointer (dot) net]) +AC_INIT([pulseaudio],[PA_MAJOR.PA_MINOR.PA_MICRO],[mzchyfrnhqvb (at) 0pointer (dot) net]) AC_CONFIG_SRCDIR([src/daemon/main.c]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign 1.10 -Wall]) -AC_SUBST(PA_MAJORMINOR, "PA_MAJOR.PA_MINOR") +AC_SUBST(PA_MAJORMINOR, PA_MAJOR.PA_MINOR) +AC_SUBST(PA_MAJORMINORMICRO, PA_MAJOR.PA_MINOR.PA_MICRO) AC_SUBST(PACKAGE_URL, [http://pulseaudio.org/]) AC_SUBST(PA_API_VERSION, 12) -AC_SUBST(PA_PROTOCOL_VERSION, 14) +AC_SUBST(PA_PROTOCOL_VERSION, 15) # The stable ABI for client applications, for the version info x:y:z # always will hold y=z -AC_SUBST(LIBPULSE_VERSION_INFO, [5:0:5]) +AC_SUBST(LIBPULSE_VERSION_INFO, [7:0:7]) # A simplified, synchronous, ABI-stable interface for client # applications, for the version info x:y:z always will hold y=z -AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:1:0]) +AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:2:0]) # The ABI-stable network browsing interface for client applications, # for the version info x:y:z always will hold y=z @@ -52,12 +53,7 @@ AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [1:1:1]) # The ABI-stable GLib adapter for client applications, for the version # info x:y:z always will hold y=z -AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:3:0]) - -# An internally used, ABI-unstable library that contains the -# PulseAudio core, SONAMEs are bumped on every release, version info -# suffix will always be 0:0 -AC_SUBST(LIBPULSECORE_VERSION_INFO, [6:0:0]) +AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:4:0]) AC_CANONICAL_HOST AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.]) @@ -86,9 +82,10 @@ AC_PROG_MKDIR_P # CC AC_PROG_CC +AC_PROG_CC_C99 AM_PROG_CC_C_O AC_PROG_GCC_TRADITIONAL -AC_GNU_SOURCE +AC_USE_SYSTEM_EXTENSIONS # M4 @@ -97,37 +94,16 @@ if test "x$M4" = xno ; then AC_MSG_ERROR([m4 missing]) fi -# GCC flags - -test_gcc_flag() { - AC_LANG_CONFTEST([int main(int argc, char*argv[]) {}]) - $CC -c conftest.c $CFLAGS -o conftest.o > /dev/null 2> /dev/null - ret=$? - rm -f conftest.o - return $ret -} - -# If using GCC specify some additional parameters -if test "x$GCC" = "xyes" ; then - - # We use gnu99 instead of c99 because many have interpreted the standard - # in a way that int64_t isn't defined on non-64 bit platforms. - DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter -ffast-math" - - for flag in $DESIRED_FLAGS ; do - AC_MSG_CHECKING([whether $CC accepts $flag]) - if test_gcc_flag $flag ; then - CFLAGS="$CFLAGS $flag" - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - done -fi +dnl Compiler flags +DESIRED_FLAGS="-Wall -W -Wextra -pedantic -pipe -Wno-long-long -Wvla -Wno-overlength-strings -Wconversion -Wundef -Wformat -Wlogical-op -Wpacked -Wformat-security -Wmissing-include-dirs -Wformat-nonliteral -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Wno-unused-parameter -ffast-math" + +for flag in $DESIRED_FLAGS ; do + CC_CHECK_CFLAGS([$flag], [CFLAGS="$CFLAGS $flag"]) +done # Native atomic operation support AC_ARG_ENABLE([atomic-arm-linux-helpers], - AC_HELP_STRING([--disable-atomic-arm-linux-helpers], [use inline asm or libatomic_ops instead]), + AS_HELP_STRING([--disable-atomic-arm-linux-helpers],[use inline asm or libatomic_ops instead]), [ case "${enableval}" in yes) atomic_arm_linux_helpers=yes ;; @@ -138,7 +114,7 @@ AC_ARG_ENABLE([atomic-arm-linux-helpers], [atomic_arm_linux_helpers=auto]) AC_ARG_ENABLE([atomic-arm-memory-barrier], - AC_HELP_STRING([--enable-atomic-arm-memory-barrier], [only really needed in SMP arm systems]), + AS_HELP_STRING([--enable-atomic-arm-memory-barrier],[only really needed in SMP arm systems]), [ case "${enableval}" in yes) AC_DEFINE_UNQUOTED(ATOMIC_ARM_MEMORY_BARRIER_ENABLED, 1, [Enable memory barriers]) ;; @@ -162,17 +138,18 @@ esac # If everything else fails use libatomic_ops need_libatomic_ops=yes -AC_MSG_CHECKING([whether $CC knows __sync_bool_compare_and_swap()]) -AC_LANG_CONFTEST([int main() { int a = 4; __sync_bool_compare_and_swap(&a, 4, 5); }]) -$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null -ret=$? -rm -f conftest.o conftest -if test $ret -eq 0 ; then +AC_CACHE_CHECK([whether $CC knows __sync_bool_compare_and_swap()], + pulseaudio_cv_sync_bool_compare_and_swap, + [AC_LINK_IFELSE( + AC_LANG_PROGRAM([], [[int a = 4; __sync_bool_compare_and_swap(&a, 4, 5);]]), + [pulseaudio_cv_sync_bool_compare_and_swap=yes], + [pulseaudio_cv_sync_bool_compare_and_swap=no]) + ]) + +if test "$pulseaudio_cv_sync_bool_compare_and_swap" = "yes" ; then AC_DEFINE([HAVE_ATOMIC_BUILTINS], 1, [Have __sync_bool_compare_and_swap() and friends.]) - AC_MSG_RESULT([yes]) need_libatomic_ops=no else - AC_MSG_RESULT([no]) # HW specific atomic ops stuff AC_MSG_CHECKING([architecture for native atomic operations]) case $host_cpu in @@ -188,29 +165,27 @@ else need_libatomic_ops=no else AC_MSG_RESULT([no]) - AC_MSG_CHECKING([compiler support for arm inline asm atomic operations]) - AC_LANG_CONFTEST([[int main() - { - volatile int a=0; - int o=0, n=1, r; - asm volatile ("ldrex %0, [%1]\n" - "subs %0, %0, %2\n" - "strexeq %0, %3, [%1]\n" - : "=&r" (r) - : "r" (&a), "Ir" (o), "r" (n) - : "cc"); - return (a==1 ? 0 : -1); - }]]) - $CC conftest.c $CFLAGS -o conftest > /dev/null 2>&1 - ret=$? - rm -f conftest.o conftest - if test $ret -eq 0 ; then + AC_CACHE_CHECK([compiler support for arm inline asm atomic operations], + pulseaudio_cv_support_arm_atomic_ops, + [AC_COMPILE_IFELSE( + AC_LANG_PROGRAM([], + [[volatile int a=0; + int o=0, n=1, r; + asm volatile ("ldrex %0, [%1]\n" + "subs %0, %0, %2\n" + "strexeq %0, %3, [%1]\n" + : "=&r" (r) + : "r" (&a), "Ir" (o), "r" (n) + : "cc"); + return (a==1 ? 0 : -1); + ]]), + [pulseaudio_cv_support_arm_atomic_ops=yes], + [pulseaudio_cv_support_arm_atomic_ops=no]) + ]) + AS_IF([test "$pulseaudio_cv_support_arm_atomic_ops" = "yes"], [ AC_DEFINE([ATOMIC_ARM_INLINE_ASM], 1, [Have ARMv6 instructions.]) - AC_MSG_RESULT([yes]) need_libatomic_ops=no - else - AC_MSG_RESULT([no]) - fi + ]) fi ;; *) @@ -219,29 +194,19 @@ else esac fi -AC_MSG_CHECKING([whether $CC knows __thread]) -AC_LANG_CONFTEST([static __thread int a = 6; int main() { a = 5; }]) -$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null -ret=$? -rm -f conftest.o conftest -if test $ret -eq 0 ; then - AC_DEFINE([HAVE_TLS_BUILTIN], 1, [Have __thread().]) - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi +CC_CHECK_TLS + +AC_CACHE_CHECK([whether $CC knows _Bool], + pulseaudio_cv__Bool, + [AC_COMPILE_IFELSE( + AC_LANG_PROGRAM([], [[_Bool b;]]), + [pulseaudio_cv__Bool=yes], + [pulseaudio_cv__Bool=no]) + ]) -AC_MSG_CHECKING([whether $CC knows _Bool]) -AC_LANG_CONFTEST([int main() { _Bool b; }]) -$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null -ret=$? -rm -f conftest.o conftest -if test $ret -eq 0 ; then +AS_IF([test "$pulseaudio_cv__Bool" = "yes"], [ AC_DEFINE([HAVE_STD_BOOL], 1, [Have _Bool.]) - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi + ]) #### libtool stuff #### LT_CONFIG_LTDL_DIR([libltdl]) @@ -307,6 +272,8 @@ AC_CHECK_HEADERS([windows.h winsock2.h ws2tcpip.h]) AC_CHECK_HEADERS([sys/ioctl.h]) AC_CHECK_HEADERS([byteswap.h]) AC_CHECK_HEADERS([sys/syscall.h]) +AC_CHECK_HEADERS([sys/eventfd.h]) +AC_CHECK_HEADERS([execinfo.h]) #### Typdefs, structures, etc. #### @@ -395,20 +362,29 @@ AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid ppoll strs AC_FUNC_ALLOCA -AC_MSG_CHECKING([for PTHREAD_PRIO_INHERIT]) -AC_LANG_CONFTEST([AC_LANG_SOURCE([[ -#include <pthread.h> -int main() { int i = PTHREAD_PRIO_INHERIT; }]])]) -$PTHREAD_CC conftest.c $PTHREAD_CFLAGS $CFLAGS $PTHREAD_LIBS -o conftest > /dev/null 2> /dev/null -ret=$? -rm -f conftest.o conftest - -if test $ret -eq 0 ; then +AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + pulseaudio_cv_PTHREAD_PRIO_INHERIT, + [save_CC=$CC; CC=$PTHREAD_CC + save_CFLAGS=$CFLAGS; CFLAGS=$PTHREAD_CFLAGS + save_LIBS=$LIBS; LIBS=$PTHREAD_LIBS + AC_LINK_IFELSE( + AC_LANG_PROGRAM( + [[ + #include <pthread.h> + ]], + [[int i = PTHREAD_PRIO_INHERIT;]]), + [pulseaudio_cv_PTHREAD_PRIO_INHERIT=yes], + [pulseaudio_cv_PTHREAD_PRIO_INHERIT=no]) + CC=$save_CC + CFLAGS=$save_CFLAGS + LIBS=$save_LIBS + ]) + +AS_IF([test "$pulseaudio_cv_PTHREAD_PRIO_INHERIT" = "yes"], [ AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]) - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi + ]) + +AC_DEFINE_UNQUOTED(PA_CFLAGS,"$CFLAGS", [The CFLAGS used during compilation]) #### Large File-Support (LFS) #### @@ -456,7 +432,7 @@ CAP_LIBS='' AC_ARG_WITH( [caps], - AC_HELP_STRING([--without-caps],[Omit support for POSIX capabilities.])) + AS_HELP_STRING([--without-caps],[Omit support for POSIX capabilities.])) if test "x${with_caps}" != "xno"; then AC_SEARCH_LIBS([cap_init], [cap], [], [ @@ -469,6 +445,10 @@ if test "x${with_caps}" != "xno"; then fi]) fi +#### Valgrind (optional) #### + +AC_CHECK_HEADERS([valgrind/memcheck.h]) + #### pkg-config #### # Check for pkg-config manually first, as if its not installed the @@ -511,7 +491,7 @@ fi #### Libsamplerate support (optional) #### AC_ARG_ENABLE([samplerate], - AC_HELP_STRING([--disable-samplerate], [Disable optional libsamplerate support]), + AS_HELP_STRING([--disable-samplerate],[Disable optional libsamplerate support]), [ case "${enableval}" in yes) samplerate=yes ;; @@ -546,7 +526,7 @@ AM_CONDITIONAL([HAVE_LIBSAMPLERATE], [test "x$HAVE_LIBSAMPLERATE" = x1]) #### OSS support (optional) #### AC_ARG_ENABLE([oss], - AC_HELP_STRING([--disable-oss], [Disable optional OSS support]), + AS_HELP_STRING([--disable-oss],[Disable optional OSS support]), [ case "${enableval}" in yes) oss=yes ;; @@ -579,7 +559,7 @@ AM_CONDITIONAL([HAVE_OSS], [test "x$HAVE_OSS" = x1]) #### ALSA support (optional) #### AC_ARG_ENABLE([alsa], - AC_HELP_STRING([--disable-alsa], [Disable optional ALSA support]), + AS_HELP_STRING([--disable-alsa],[Disable optional ALSA support]), [ case "${enableval}" in yes) alsa=yes ;; @@ -613,7 +593,7 @@ AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1]) #### Solaris audio support (optional) #### AC_ARG_ENABLE([solaris], - AC_HELP_STRING([--disable-solaris], [Disable optional Solaris audio support]), + AS_HELP_STRING([--disable-solaris],[Disable optional Solaris audio support]), [ case "${enableval}" in yes) solaris=yes ;; @@ -645,7 +625,7 @@ AM_CONDITIONAL([HAVE_SOLARIS], [test "x$HAVE_SOLARIS" = x1]) #### GLib 2 support (optional) #### AC_ARG_ENABLE([glib2], - AC_HELP_STRING([--disable-glib2], [Disable optional GLib 2 support]), + AS_HELP_STRING([--disable-glib2],[Disable optional GLib 2 support]), [ case "${enableval}" in yes) glib2=yes ;; @@ -676,7 +656,7 @@ AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1]) #### GConf support (optional) #### AC_ARG_ENABLE([gconf], - AC_HELP_STRING([--disable-gconf], [Disable optional GConf support]), + AS_HELP_STRING([--disable-gconf],[Disable optional GConf support]), [ case "${enableval}" in yes) gconf=yes ;; @@ -707,7 +687,7 @@ AM_CONDITIONAL([HAVE_GCONF], [test "x$HAVE_GCONF" = x1]) #### Avahi support (optional) #### AC_ARG_ENABLE([avahi], - AC_HELP_STRING([--disable-avahi], [Disable optional Avahi support]), + AS_HELP_STRING([--disable-avahi],[Disable optional Avahi support]), [ case "${enableval}" in yes) avahi=yes ;; @@ -744,7 +724,7 @@ AC_SUBST(LIBOIL_LIBS) ### JACK (optional) #### AC_ARG_ENABLE([jack], - AC_HELP_STRING([--disable-jack], [Disable optional JACK support]), + AS_HELP_STRING([--disable-jack],[Disable optional JACK support]), [ case "${enableval}" in yes) jack=yes ;; @@ -775,7 +755,7 @@ AM_CONDITIONAL([HAVE_JACK], [test "x$HAVE_JACK" = x1]) #### Async DNS support (optional) #### AC_ARG_ENABLE([asyncns], - AC_HELP_STRING([--disable-asyncns], [Disable optional Async DNS support]), + AS_HELP_STRING([--disable-asyncns],[Disable optional Async DNS support]), [ case "${enableval}" in yes) asyncns=yes ;; @@ -810,7 +790,7 @@ fi #### TCP wrappers (optional) #### AC_ARG_ENABLE([tcpwrap], - AC_HELP_STRING([--disable-tcpwrap], [Disable optional TCP wrappers support]), + AS_HELP_STRING([--disable-tcpwrap],[Disable optional TCP wrappers support]), [ case "${enableval}" in yes) tcpwrap=yes ;; @@ -834,7 +814,7 @@ AC_SUBST(LIBWRAP_LIBS) #### LIRC support (optional) #### AC_ARG_ENABLE([lirc], - AC_HELP_STRING([--disable-lirc], [Disable optional LIRC support]), + AS_HELP_STRING([--disable-lirc],[Disable optional LIRC support]), [ case "${enableval}" in yes) lirc=yes ;; @@ -860,7 +840,7 @@ AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) #### HAL support (optional) #### AC_ARG_ENABLE([hal], - AC_HELP_STRING([--disable-hal], [Disable optional HAL support]), + AS_HELP_STRING([--disable-hal],[Disable optional HAL support]), [ case "${enableval}" in yes) hal=yes ;; @@ -890,7 +870,7 @@ AM_CONDITIONAL([HAVE_HAL], [test "x$HAVE_HAL" = x1]) #### BlueZ support (optional) #### AC_ARG_ENABLE([bluez], - AC_HELP_STRING([--disable-bluez], [Disable optional BlueZ support]), + AS_HELP_STRING([--disable-bluez],[Disable optional BlueZ support]), [ case "${enableval}" in yes) bluez=yes ;; @@ -920,7 +900,7 @@ AM_CONDITIONAL([HAVE_BLUEZ], [test "x$HAVE_BLUEZ" = x1]) #### D-Bus support (optional) #### AC_ARG_ENABLE([dbus], - AC_HELP_STRING([--disable-dbus], [Disable optional D-Bus support]), + AS_HELP_STRING([--disable-dbus],[Disable optional D-Bus support]), [ case "${enableval}" in yes) dbus=yes ;; @@ -963,7 +943,7 @@ AM_CONDITIONAL([HAVE_DBUS], [test "x$HAVE_DBUS" = x1]) #### PolicyKit support (optional) #### AC_ARG_ENABLE([polkit], - AC_HELP_STRING([--disable-polkit], [Disable optional PolicyKit support]), + AS_HELP_STRING([--disable-polkit],[Disable optional PolicyKit support]), [ case "${enableval}" in yes) polkit=yes ;; @@ -997,6 +977,41 @@ AC_SUBST(POLKIT_LIBS) AC_SUBST(HAVE_POLKIT) AM_CONDITIONAL([HAVE_POLKIT], [test "x$HAVE_POLKIT" = x1]) +#### OpenSSL support (optional) #### + +AC_ARG_ENABLE([openssl], + AC_HELP_STRING([--disable-openssl], [Disable OpenSSL support (used for Airtunes/RAOP)]), + [ + case "${enableval}" in + yes) openssl=yes ;; + no) openssl=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-openssl) ;; + esac + ], + [openssl=auto]) + +if test "x${openssl}" != xno ; then + + PKG_CHECK_MODULES(OPENSSL, [ openssl > 0.9 ], + [ + HAVE_OPENSSL=1 + AC_DEFINE([HAVE_OPENSSL], 1, [Have OpenSSL]) + ], + [ + HAVE_OPENSSL=0 + if test "x$openssl" = xyes ; then + AC_MSG_ERROR([*** OpenSSL support not found]) + fi + ]) +else + HAVE_OPENSSL=0 +fi + +AC_SUBST(OPENSSL_CFLAGS) +AC_SUBST(OPENSSL_LIBS) +AC_SUBST(HAVE_OPENSSL) +AM_CONDITIONAL([HAVE_OPENSSL], [test "x$HAVE_OPENSSL" = x1]) + ### Build and Install man pages ### AC_ARG_ENABLE(manpages, AS_HELP_STRING([--disable-manpages],[Disable building and installation of man pages]), @@ -1076,13 +1091,13 @@ AC_SUBST(PA_SYSTEM_STATE_PATH) AC_ARG_ENABLE( [static-bins], - AC_HELP_STRING([--enable-static-bins],[Statically link executables.]), + AS_HELP_STRING([--enable-static-bins],[Statically link executables.]), [STATIC_BINS=1], [STATIC_BINS=0]) AM_CONDITIONAL([STATIC_BINS], [test "x$STATIC_BINS" = "x1"]) AC_ARG_WITH( [preopen-mods], - AC_HELP_STRING([--with-preopen-mods],[Modules to preopen in daemon (default: all).]), + AS_HELP_STRING([--with-preopen-mods],[Modules to preopen in daemon (default: all).]), [PREOPEN_MODS=$withval], [PREOPEN_MODS="all"]) AM_CONDITIONAL([PREOPEN_MODS], [test "x$PREOPEN_MODS" != "xall"]) if test "x$PREOPEN_MODS" != "xall" ; then @@ -1096,14 +1111,14 @@ fi AC_ARG_WITH( [module-dir], - AC_HELP_STRING([--with-module-dir],[Directory where to install the modules to (defaults to ${libdir}/pulse-${PA_MAJORMINOR}/modules/]), - [modlibexecdir=$withval], [modlibexecdir="${libdir}/pulse-${PA_MAJORMINOR}/modules/"]) + AS_HELP_STRING([--with-module-dir],[Directory where to install the modules to (defaults to ${libdir}/pulse-${PA_MAJORMINORMICRO}/modules/]), + [modlibexecdir=$withval], [modlibexecdir="${libdir}/pulse-${PA_MAJORMINORMICRO}/modules/"]) AC_SUBST(modlibexecdir) AC_ARG_ENABLE( [force-preopen], - AC_HELP_STRING([--enable-force-preopen],[Preopen modules, even when dlopen() is supported.]), + AS_HELP_STRING([--enable-force-preopen],[Preopen modules, even when dlopen() is supported.]), [FORCE_PREOPEN=1], [FORCE_PREOPEN=0]) AM_CONDITIONAL([FORCE_PREOPEN], [test "x$FORCE_PREOPEN" = "x1"]) @@ -1199,6 +1214,11 @@ if test "x${HAVE_POLKIT}" = "x1" ; then ENABLE_POLKIT=yes fi +ENABLE_OPENSSL=no +if test "x${HAVE_OPENSSL}" = "x1" ; then + ENABLE_OPENSSL=yes +fi + ENABLE_PER_USER_ESOUND_SOCKET=no if test "x$per_user_esound_socket" = "x1" ; then ENABLE_PER_USER_ESOUND_SOCKET=yes @@ -1230,6 +1250,7 @@ echo " Enable TCP Wrappers: ${ENABLE_TCPWRAP} Enable libsamplerate: ${ENABLE_LIBSAMPLERATE} Enable PolicyKit: ${ENABLE_POLKIT} + Enable OpenSSL (for Airtunes): ${ENABLE_OPENSSL} System User: ${PA_SYSTEM_USER} System Group: ${PA_SYSTEM_GROUP} Realtime Group: ${PA_REALTIME_GROUP} diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index 7ad5d2f3..6c2021ce 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -14,191 +14,191 @@ # Project related configuration options #--------------------------------------------------------------------------- -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = PulseAudio -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @PACKAGE_VERSION@ -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. -OUTPUT_DIRECTORY = +OUTPUT_DIRECTORY = -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of source -# files, where putting all generated files in the same directory would otherwise +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of source +# files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, -# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, -# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, -# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, +# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, +# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, +# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English -# This tag can be used to specify the encoding used in the generated output. -# The encoding is not always determined by the language that is chosen, -# but also whether or not the output is meant for Windows or non-Windows users. -# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES -# forces the Windows encoding (this is the default for the Windows binary), -# whereas setting the tag to NO uses a Unix-style encoding (the default for +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is used -# as the annotated text. Otherwise, the brief description is used as-is. If left -# blank, the following values are used ("$name" is automatically replaced with the -# name of the entity): "The $name class" "The $name widget" "The $name file" +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is used +# as the annotated text. Otherwise, the brief description is used as-is. If left +# blank, the following values are used ("$name" is automatically replaced with the +# name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" -ABBREVIATE_BRIEF = +ABBREVIATE_BRIEF = -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited -# members of a class in the documentation of that class as if those members were -# ordinary class members. Constructors, destructors and assignment operators of +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the # path to strip. -STRIP_FROM_PATH = +STRIP_FROM_PATH = -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. -STRIP_FROM_INC_PATH = +STRIP_FROM_INC_PATH = -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like the Qt-style comments (thus requiring an +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = YES -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO -# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. -# If set to NO, the detailed description appears after the member +# If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO -# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. -ALIASES = +ALIASES = -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources -# only. Doxygen will then generate output that is more tailored for Java. -# For instance, namespaces will be presented as packages, qualified scopes +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES @@ -207,162 +207,162 @@ SUBGROUPING = YES # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file +# If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = NO -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the +# Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = NO -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = NO -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = NO -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= NO -# The ENABLED_SECTIONS tag can be used to enable conditional +# The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. -ENABLED_SECTIONS = +ENABLED_SECTIONS = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES @@ -371,133 +371,133 @@ SHOW_USED_FILES = YES # configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated +# The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written # to stderr. -WARN_LOGFILE = +WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../src/pulse/context.h ../src/pulse/stream.h ../src/pulse/pulseaudio.h ../src/pulse/sample.h ../src/pulse/def.h ../src/pulse/subscribe.h ../src/pulse/introspect.h ../src/pulse/scache.h ../src/pulse/mainloop-api.h ../src/pulse/glib-mainloop.h ../src/pulse/mainloop.h ../src/pulse/mainloop-signal.h ../src/pulse/error.h ../src/pulse/operation.h ../src/pulse/simple.h ../src/pulse/version.h ../src/pulse/volume.h ../src/pulse/channelmap.h ../src/pulse/thread-mainloop.h ../src/pulse/xmalloc.h ../src/pulse/utf8.h ../src/pulse/util.h ../src/pulse/timeval.h ../src/pulse/proplist.h ../src/pulse/gccmacro.h +INPUT = ../src/pulse/context.h ../src/pulse/stream.h ../src/pulse/pulseaudio.h ../src/pulse/sample.h ../src/pulse/def.h ../src/pulse/subscribe.h ../src/pulse/introspect.h ../src/pulse/scache.h ../src/pulse/mainloop-api.h ../src/pulse/glib-mainloop.h ../src/pulse/mainloop.h ../src/pulse/mainloop-signal.h ../src/pulse/error.h ../src/pulse/operation.h ../src/pulse/simple.h ../src/pulse/version.h ../src/pulse/volume.h ../src/pulse/channelmap.h ../src/pulse/thread-mainloop.h ../src/pulse/xmalloc.h ../src/pulse/utf8.h ../src/pulse/util.h ../src/pulse/timeval.h ../src/pulse/proplist.h ../src/pulse/gccmacro.h ../src/pulse/ext-stream-restore.h -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm -FILE_PATTERNS = +FILE_PATTERNS = -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = +EXCLUDE = -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = ../src/utils ../src/tests -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left # blank all files are included. -EXAMPLE_PATTERNS = +EXAMPLE_PATTERNS = -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = +IMAGE_PATH = -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command <filter> <input-file>, where <filter> -# is the value of the INPUT_FILTER tag, and <input-file> is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. -INPUT_FILTER = +INPUT_FILTER = -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. -FILTER_PATTERNS = +FILTER_PATTERNS = -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO @@ -506,38 +506,38 @@ FILTER_SOURCE_FILES = NO # configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO -# Setting the INLINE_SOURCES tag to YES will include the body +# Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES @@ -546,21 +546,21 @@ VERBATIM_HEADERS = YES # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = pa_ PA_ @@ -569,110 +569,110 @@ IGNORE_PREFIX = pa_ PA_ # configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a # standard header. -HTML_HEADER = +HTML_HEADER = -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a # standard footer. -HTML_FOOTER = +HTML_FOOTER = -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! -HTML_STYLESHEET = +HTML_STYLESHEET = -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be # written to the html output directory. -CHM_FILE = +CHM_FILE = -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. -HHC_LOCATION = +HHC_LOCATION = -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO -# The TOC_EXPAND flag can be set to YES to add extra items for group members +# The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO -# This tag can be used to set the number of enum values (range [1..20]) +# This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 1 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = YES -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 @@ -681,74 +681,74 @@ TREEVIEW_WIDTH = 250 # configuration options related to the LaTeX output #--------------------------------------------------------------------------- -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. -EXTRA_PACKAGES = +EXTRA_PACKAGES = -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! -LATEX_HEADER = +LATEX_HEADER = -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO @@ -757,68 +757,68 @@ LATEX_HIDE_INDICES = NO # configuration options related to the RTF output #--------------------------------------------------------------------------- -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. -RTF_STYLESHEET_FILE = +RTF_STYLESHEET_FILE = -# Set optional variables used in the generation of an rtf document. +# Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. -RTF_EXTENSIONS_FILE = +RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man -# The MAN_EXTENSION tag determines the extension that is added to +# The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO @@ -827,33 +827,33 @@ MAN_LINKS = NO # configuration options related to the XML output #--------------------------------------------------------------------------- -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the # syntax of the XML files. -XML_SCHEMA = +XML_SCHEMA = -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the # syntax of the XML files. -XML_DTD = +XML_DTD = -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES @@ -862,10 +862,10 @@ XML_PROGRAMLISTING = YES # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO @@ -874,283 +874,282 @@ GENERATE_AUTOGEN_DEF = NO # configuration options related to the Perl module output #--------------------------------------------------------------------------- -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. -PERLMOD_MAKEVAR_PREFIX = +PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- -# Configuration options related to the preprocessor +# Configuration options related to the preprocessor #--------------------------------------------------------------------------- -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = YES -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by # the preprocessor. -INCLUDE_PATH = +INCLUDE_PATH = -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. -INCLUDE_FILE_PATTERNS = +INCLUDE_FILE_PATTERNS = -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = PA_C_DECL_BEGIN= PA_C_DECL_END= -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. #EXPAND_AS_DEFINED = PA_C_DECL_BEGIN, PA_C_DECL_END -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse the +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- -# Configuration::additions related to external references +# Configuration::additions related to external references #--------------------------------------------------------------------------- -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen +# If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. -TAGFILES = +TAGFILES = -# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. -GENERATE_TAGFILE = +GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES -# The PERL_PATH should be the absolute path and name of the perl script +# The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- -# Configuration options related to the dot tool +# Configuration options related to the dot tool #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or -# super classes. Setting the tag to NO turns the diagrams off. Note that this -# option is superseded by the HAVE_DOT option below. This is only a fallback. It is +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO -# If set to YES, the inheritance and collaboration graphs will show the +# If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES -# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will -# generate a call dependency graph for every global function or class method. -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable call graphs for selected +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png -# The tag DOT_PATH can be used to specify the path where the dot tool can be +# The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. -DOT_PATH = +DOT_PATH = -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the # \dotfile command). -DOTFILE_DIRS = +DOTFILE_DIRS = -# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 -# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes that -# lay further from the root node will be omitted. Note that setting this option to -# 1 or 2 may greatly reduce the computation time needed for large code bases. Also -# note that a graph may be further truncated if the graph's image dimensions are -# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes that +# lay further from the root node will be omitted. Note that setting this option to +# 1 or 2 may greatly reduce the computation time needed for large code bases. Also +# note that a graph may be further truncated if the graph's image dimensions are +# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- -# Configuration::additions related to the search engine +# Configuration::additions related to the search engine #--------------------------------------------------------------------------- -# The SEARCHENGINE tag specifies whether or not a search engine should be +# The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO SHOW_DIRECTORIES=NO - diff --git a/libpulse-browse.pc.in b/libpulse-browse.pc.in index 66438b2a..54705b3f 100644 --- a/libpulse-browse.pc.in +++ b/libpulse-browse.pc.in @@ -1,11 +1,12 @@ prefix=@prefix@ -exec_prefix=${prefix} +exec_prefix=@exec_prefix@ libdir=@libdir@ -includedir=${prefix}/include +includedir=@includedir@ Name: libpulse-browse -Description: PulseAudio Network Browsing API +Description: PulseAudio Network Browsing Interface Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpulse-browse @PTHREAD_LIBS@ -Cflags: -D_REENTRANT -I${includedir} +Libs.private: -lpulsecommon-@PA_MAJORMINORMICRO@ +Cflags: -I${includedir} -D_REENTRANT Requires: libpulse diff --git a/libpulse-mainloop-glib.pc.in b/libpulse-mainloop-glib.pc.in index 1a8bfa40..45ae47c7 100644 --- a/libpulse-mainloop-glib.pc.in +++ b/libpulse-mainloop-glib.pc.in @@ -1,11 +1,12 @@ prefix=@prefix@ -exec_prefix=${prefix} +exec_prefix=@exec_prefix@ libdir=@libdir@ -includedir=${prefix}/include +includedir=@includedir@ Name: libpulse-mainloop-glib -Description: GLIB 2.0 Main Loop Wrapper for PulseAudio +Description: PulseAudio GLib 2.0 Main Loop Wrapper Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpulse-mainloop-glib @PTHREAD_LIBS@ -Cflags: -D_REENTRANT -I${includedir} +Libs.private: -lpulsecommon-@PA_MAJORMINORMICRO@ +Cflags: -I${includedir} -D_REENTRANT Requires: libpulse glib-2.0 diff --git a/libpulse-simple.pc.in b/libpulse-simple.pc.in index 00d1245a..443be289 100644 --- a/libpulse-simple.pc.in +++ b/libpulse-simple.pc.in @@ -1,11 +1,12 @@ prefix=@prefix@ -exec_prefix=${prefix} +exec_prefix=@exec_prefix@ libdir=@libdir@ -includedir=${prefix}/include +includedir=@includedir@ Name: libpulse-simple -Description: Simplified Synchronous Client Interface to PulseAudio +Description: PulseAudio Simplified Synchronous Client Interface Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpulse-simple @PTHREAD_LIBS@ -Cflags: -D_REENTRANT -I${includedir} +Libs.private: -lpulsecommon-@PA_MAJORMINORMICRO@ +Cflags: -I${includedir} -D_REENTRANT Requires: libpulse diff --git a/libpulse.pc.in b/libpulse.pc.in index 2193b2b9..161599e1 100644 --- a/libpulse.pc.in +++ b/libpulse.pc.in @@ -1,10 +1,11 @@ prefix=@prefix@ -exec_prefix=${prefix} +exec_prefix=@exec_prefix@ libdir=@libdir@ -includedir=${prefix}/include +includedir=@includedir@ Name: libpulse -Description: Client Interface to PulseAudio +Description: PulseAudio Client Interface Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpulse @PTHREAD_LIBS@ -Cflags: -D_REENTRANT -I${includedir} +Libs.private: -lpulsecommon-@PA_MAJORMINORMICRO@ +Cflags: -I${includedir} -D_REENTRANT diff --git a/m4/.gitignore b/m4/.gitignore index ac5d1406..8b81e54b 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -1,3 +1,12 @@ +ChangeLog +gettext.m4 +iconv.m4 +lib-ld.m4 +lib-link.m4 +lib-prefix.m4 +nls.m4 +po.m4 +progtest.m4 argz.m4 intltool.m4 libtool.m4 diff --git a/m4/attributes.m4 b/m4/attributes.m4 new file mode 100644 index 00000000..9c4a0c89 --- /dev/null +++ b/m4/attributes.m4 @@ -0,0 +1,258 @@ +dnl Macros to check the presence of generic (non-typed) symbols. +dnl Copyright (c) 2006-2007 Diego Pettenò <flameeyes@gmail.com> +dnl Copyright (c) 2006-2007 xine project +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +dnl 02110-1301, USA. +dnl +dnl As a special exception, the copyright owners of the +dnl macro gives unlimited permission to copy, distribute and modify the +dnl configure scripts that are the output of Autoconf when processing the +dnl Macro. You need not follow the terms of the GNU General Public +dnl License when using or distributing such scripts, even though portions +dnl of the text of the Macro appear in them. The GNU General Public +dnl License (GPL) does govern all other use of the material that +dnl constitutes the Autoconf Macro. +dnl +dnl This special exception to the GPL applies to versions of the +dnl Autoconf Macro released by this project. When you make and +dnl distribute a modified version of the Autoconf Macro, you may extend +dnl this special exception to the GPL to apply to your modified version as +dnl well. + +AC_DEFUN([CC_CHECK_CFLAGS_SILENT], [ + AC_CACHE_VAL(AS_TR_SH([cc_cv_cflags_$1]), + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $1" + AC_COMPILE_IFELSE([int a;], + [eval "AS_TR_SH([cc_cv_cflags_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_cflags_$1])='no'"]) + CFLAGS="$ac_save_CFLAGS" + ]) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], + [$2], [$3]) +]) + +AC_DEFUN([CC_CHECK_CFLAGS], [ + AC_CACHE_CHECK([if $CC supports $1 flag], + AS_TR_SH([cc_cv_cflags_$1]), + CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here! + ) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], + [$2], [$3]) +]) + +AC_DEFUN([CC_CHECK_LDFLAGS], [ + AC_CACHE_CHECK([if $CC supports $1 flag], + AS_TR_SH([cc_cv_ldflags_$1]), + [ac_save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $1" + AC_LINK_IFELSE([int main() { return 1; }], + [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_ldflags_$1])="]) + LDFLAGS="$ac_save_LDFLAGS" + ]) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes], + [$2], [$3]) +]) + +dnl Check for a -Werror flag or equivalent. -Werror is the GCC +dnl and ICC flag that tells the compiler to treat all the warnings +dnl as fatal. We usually need this option to make sure that some +dnl constructs (like attributes) are not simply ignored. +dnl +dnl Other compilers don't support -Werror per se, but they support +dnl an equivalent flag: +dnl - Sun Studio compiler supports -errwarn=%all +AC_DEFUN([CC_CHECK_WERROR], [ + AC_CACHE_CHECK( + [for $CC way to treat warnings as errors], + [cc_cv_werror], + [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror], + [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])]) + ]) +]) + +AC_DEFUN([CC_CHECK_ATTRIBUTE], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))], + AS_TR_SH([cc_cv_attribute_$1]), + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + AC_COMPILE_IFELSE([$3], + [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"]) + CFLAGS="$ac_save_CFLAGS" + ]) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes], + [AC_DEFINE( + AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1, + [Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))] + ) + $4], + [$5]) +]) + +AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [ + CC_CHECK_ATTRIBUTE( + [constructor],, + [void __attribute__((constructor)) ctor() { int a; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_FORMAT], [ + CC_CHECK_ATTRIBUTE( + [format], [format(printf, n, n)], + [void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [ + CC_CHECK_ATTRIBUTE( + [format_arg], [format_arg(printf)], + [char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [ + CC_CHECK_ATTRIBUTE( + [visibility_$1], [visibility("$1")], + [void __attribute__((visibility("$1"))) $1_function() { }], + [$2], [$3]) +]) + +AC_DEFUN([CC_ATTRIBUTE_NONNULL], [ + CC_CHECK_ATTRIBUTE( + [nonnull], [nonnull()], + [void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_UNUSED], [ + CC_CHECK_ATTRIBUTE( + [unused], , + [void some_function(void *foo, __attribute__((unused)) void *bar);], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [ + CC_CHECK_ATTRIBUTE( + [sentinel], , + [void some_function(void *foo, ...) __attribute__((sentinel));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [ + CC_CHECK_ATTRIBUTE( + [deprecated], , + [void some_function(void *foo, ...) __attribute__((deprecated));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_ALIAS], [ + CC_CHECK_ATTRIBUTE( + [alias], [weak, alias], + [void other_function(void *foo) { } + void some_function(void *foo) __attribute__((weak, alias("other_function")));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_MALLOC], [ + CC_CHECK_ATTRIBUTE( + [malloc], , + [void * __attribute__((malloc)) my_alloc(int n);], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_PACKED], [ + CC_CHECK_ATTRIBUTE( + [packed], , + [struct astructure { char a; int b; long c; void *d; } __attribute__((packed));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_CONST], [ + CC_CHECK_ATTRIBUTE( + [const], , + [int __attribute__((const)) twopow(int n) { return 1 << n; } ], + [$1], [$2]) +]) + +AC_DEFUN([CC_FLAG_VISIBILITY], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([if $CC supports -fvisibility=hidden], + [cc_cv_flag_visibility], + [cc_flag_visibility_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden], + cc_cv_flag_visibility='yes', + cc_cv_flag_visibility='no') + CFLAGS="$cc_flag_visibility_save_CFLAGS"]) + + AS_IF([test "x$cc_cv_flag_visibility" = "xyes"], + [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1, + [Define this if the compiler supports the -fvisibility flag]) + $1], + [$2]) +]) + +AC_DEFUN([CC_FUNC_EXPECT], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([if compiler has __builtin_expect function], + [cc_cv_func_expect], + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + AC_COMPILE_IFELSE( + [int some_function() { + int a = 3; + return (int)__builtin_expect(a, 3); + }], + [cc_cv_func_expect=yes], + [cc_cv_func_expect=no]) + CFLAGS="$ac_save_CFLAGS" + ]) + + AS_IF([test "x$cc_cv_func_expect" = "xyes"], + [AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1, + [Define this if the compiler supports __builtin_expect() function]) + $1], + [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported], + [cc_cv_attribute_aligned], + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + for cc_attribute_align_try in 64 32 16 8 4 2; do + AC_COMPILE_IFELSE([ + int main() { + static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0; + return c; + }], [cc_cv_attribute_aligned=$cc_attribute_align_try; break]) + done + CFLAGS="$ac_save_CFLAGS" + ]) + + if test "x$cc_cv_attribute_aligned" != "x"; then + AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned], + [Define the highest alignment supported]) + fi +]) diff --git a/m4/tls.m4 b/m4/tls.m4 new file mode 100644 index 00000000..3808f06e --- /dev/null +++ b/m4/tls.m4 @@ -0,0 +1,17 @@ +AC_DEFUN([CC_CHECK_TLS], [ + AC_CACHE_CHECK([whether $CC knows __thread for Thread-Local Storage], + cc_cv_tls___thread, + [AC_COMPILE_IFELSE( + AC_LANG_PROGRAM( + [[static __thread int a = 6;]], + [[a = 5;]]), + [cc_cv_tls___thread=yes], + [cc_cv_tls___thread=no]) + ]) + + AS_IF([test "x$cc_cv_tls___thread" = "xyes"], + [AC_DEFINE([SUPPORT_TLS___THREAD], 1, + [Define this if the compiler supports __thread for Thread-Local Storage]) + $1], + [$2]) +]) diff --git a/man/Makefile.am b/man/Makefile.am index b0536d84..9b229f52 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -17,9 +17,10 @@ pulseconfdir=$(sysconfdir)/pulse -if BUILD_MANPAGES +CLEANFILES = \ + $(noinst_DATA) -man_MANS = \ +dist_man_MANS = \ pulseaudio.1 \ esdcompat.1 \ pax11publish.1 \ @@ -49,115 +50,18 @@ noinst_DATA = \ pulse-client.conf.5.xml \ default.pa.5.xml -CLEANFILES = \ - $(noinst_DATA) - -pulseaudio.1.xml: pulseaudio.1.xml.in Makefile - sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ - -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ - -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ - -esdcompat.1.xml: esdcompat.1.xml.in Makefile - sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ - -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ - -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ - -pax11publish.1.xml: pax11publish.1.xml.in Makefile - sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ - -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ - -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ - -paplay.1.xml: paplay.1.xml.in Makefile - sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ - -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ - -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ - -pacat.1.xml: pacat.1.xml.in Makefile - sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ - -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ - -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ - -pacmd.1.xml: pacmd.1.xml.in Makefile - sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ - -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ - -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ - -pactl.1.xml: pactl.1.xml.in Makefile - sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ - -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ - -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ - -pasuspender.1.xml: pasuspender.1.xml.in Makefile - sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ - -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ - -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ - -padsp.1.xml: padsp.1.xml.in Makefile - sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ - -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ - -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ - -pabrowse.1.xml: pabrowse.1.xml.in Makefile - sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ - -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ - -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ - -pulse-daemon.conf.5.xml: pulse-daemon.conf.5.xml.in Makefile - sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ - -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ - -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ +if BUILD_MANPAGES -pulse-client.conf.5.xml: pulse-client.conf.5.xml.in Makefile - sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ - -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ - -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ +CLEANFILES += \ + $(dist_man_MANS) -default.pa.5.xml: default.pa.5.xml.in Makefile +%.xml: %.xml.in Makefile sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ -CLEANFILES += \ - $(man_MANS) - -pulseaudio.1: pulseaudio.1.xml Makefile - perl xmltoman $< > $@ || rm -f $@ - -esdcompat.1: esdcompat.1.xml Makefile - perl xmltoman $< > $@ || rm -f $@ - -pax11publish.1: pax11publish.1.xml Makefile - perl xmltoman $< > $@ || rm -f $@ - -paplay.1: paplay.1.xml Makefile - perl xmltoman $< > $@ || rm -f $@ - -pacat.1: pacat.1.xml Makefile - perl xmltoman $< > $@ || rm -f $@ - -pacmd.1: pacmd.1.xml Makefile - perl xmltoman $< > $@ || rm -f $@ - -pactl.1: pactl.1.xml Makefile - perl xmltoman $< > $@ || rm -f $@ - -pasuspender.1: pasuspender.1.xml Makefile - perl xmltoman $< > $@ || rm -f $@ - -padsp.1: padsp.1.xml Makefile - perl xmltoman $< > $@ || rm -f $@ - -pabrowse.1: pabrowse.1.xml Makefile - perl xmltoman $< > $@ || rm -f $@ - -pulse-daemon.conf.5: pulse-daemon.conf.5.xml Makefile - perl xmltoman $< > $@ || rm -f $@ - -pulse-client.conf.5: pulse-client.conf.5.xml Makefile - perl xmltoman $< > $@ || rm -f $@ - -default.pa.5: default.pa.5.xml Makefile - perl xmltoman $< > $@ || rm -f $@ +%: %.xml Makefile + perl $(srcdir)/xmltoman $< > $@ || rm -f $@ xmllint: $(noinst_DATA) for f in $(noinst_DATA) ; do \ @@ -167,7 +71,6 @@ xmllint: $(noinst_DATA) endif EXTRA_DIST = \ - $(man_MANS) \ pulseaudio.1.xml.in \ esdcompat.1.xml.in \ pax11publish.1.xml.in \ diff --git a/man/pacat.1.xml.in b/man/pacat.1.xml.in index 7b0d72b9..68a3a12a 100644 --- a/man/pacat.1.xml.in +++ b/man/pacat.1.xml.in @@ -108,9 +108,11 @@ USA. <optdesc><p>Capture or play back audio with the specified sample format. Specify one of <opt>u8</opt>, <opt>s16le</opt>, - <opt>s16be</opt>, <opt>float32le</opt>, <opt>float32be</opt>, + <opt>s16be</opt>, <opt>s32le</opt>, + <opt>s32be</opt>, <opt>float32le</opt>, <opt>float32be</opt>, <opt>ulaw</opt>, <opt>alaw</opt>. Depending on the endianess of - the CPU the formats <opt>s16ne</opt>, <opt>s16re</opt>, + the CPU the + formats <opt>s16ne</opt>, <opt>s16re</opt>, <opt>s32ne</opt>, <opt>s32re</opt>, <opt>float32ne</opt>, <opt>float32re</opt> (for native, resp. reverse endian) are available as aliases. Defaults to s16ne.</p></optdesc> diff --git a/man/pulse-client.conf.5.xml.in b/man/pulse-client.conf.5.xml.in index ae8de1f8..26e38908 100644 --- a/man/pulse-client.conf.5.xml.in +++ b/man/pulse-client.conf.5.xml.in @@ -31,15 +31,15 @@ USA. <description> <p>The PulseAudio client library reads configuration directives from - a file <file>~/.pulse/client.conf</file> on startup, and when that + a file <file>~/.pulse/client.conf</file> on startup and when that file doesn't exist from <file>@pulseconfdir@/client.conf</file>.</p> <p>The configuration file is a simple collection of variable declarations. If the configuration file parser encounters either ; - or # for it ignores the rest of the line until its end.</p> + or # it ignores the rest of the line until its end.</p> - <p>For the settings that take a boolean argument, the values + <p>For the settings that take a boolean argument the values <opt>true</opt>, <opt>yes</opt>, <opt>on</opt> and <opt>1</opt> are equivalent, resp. <opt>false</opt>, <opt>no</opt>, <opt>off</opt>, <opt>0</opt>.</p> @@ -69,7 +69,7 @@ USA. <option> <p><opt>autospawn=</opt> Autospawn a PulseAudio daemon when - needed. Takes a boolean value, defaults to "no".</p> + needed. Takes a boolean value, defaults to "yes".</p> </option> <option> @@ -81,7 +81,7 @@ USA. <option> <p><opt>extra-arguments=</opt> Extra arguments to pass to the PulseAudio daemon when autospawning. Defaults to - <opt>--log-target=syslog --exit-idle-time=5</opt> + <opt>--log-target=syslog</opt> </p> </option> @@ -97,6 +97,15 @@ USA. <opt>no</opt>.</p> </option> + <option> + <p><opt>shm-size-bytes=</opt> Sets the shared memory segment + size for clients, in bytes. If left unspecified or is set to 0 + it will default to some system-specific default, usually 64 + MiB. Please note that usually there is no need to change this + value, unless you are running an OS kernel that does not do + memory overcommit.</p> + </option> + </section> <section name="Authors"> diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in index 50e24559..a516ee3f 100644 --- a/man/pulse-daemon.conf.5.xml.in +++ b/man/pulse-daemon.conf.5.xml.in @@ -31,7 +31,7 @@ USA. <description> <p>The PulseAudio sound server reads configuration directives from - a file <file>~/.pulse/daemon.conf</file> on startup, and when that + a file <file>~/.pulse/daemon.conf</file> on startup and when that file doesn't exist from <file>@pulseconfdir@/daemon.conf</file>. Please note that the server also reads a configuration script on startup @@ -40,9 +40,9 @@ USA. <p>The configuration file is a simple collection of variable declarations. If the configuration file parser encounters either ; - or # for it ignores the rest of the line until its end.</p> + or # it ignores the rest of the line until its end.</p> - <p>For the settings that take a boolean argument, the values + <p>For the settings that take a boolean argument the values <opt>true</opt>, <opt>yes</opt>, <opt>on</opt> and <opt>1</opt> are equivalent, resp. <opt>false</opt>, <opt>no</opt>, <opt>off</opt>, <opt>0</opt>.</p> @@ -77,6 +77,11 @@ USA. </option> <option> + <p><opt>disallow-exit=</opt> Disallow exit on user + request. Defaults to <opt>no</opt>.</p> + </option> + + <option> <p><opt>resample-method=</opt> The resampling algorithm to use. Use one of <opt>src-sinc-best-quality</opt>, <opt>src-sinc-medium-quality</opt>, <opt>src-sinc-fastest</opt>, @@ -106,6 +111,16 @@ USA. </option> <option> + <p><opt>disable-lfe-remixing=</opt> When upmixing or downmixing + ignore LFE channels. When this option is on the output LFE + channel will only get a signal when an input LFE channel is + available as well. If no input LFE channel is available the + output LFE channel will always be 0. If no output LFE channel is + available the signal on the input LFE channel will be + ignored. Defaults to "on".</p> + </option> + + <option> <p><opt>use-pid-file=</opt> Create a PID file in <file>/tmp/pulse-$USER/pid</file>. Of this is enabled you may use commands like <opt>--kill</opt> or <opt>--check</opt>. If @@ -141,6 +156,15 @@ USA. argument takes precedence.</p> </option> + <option> + <p><opt>shm-size-bytes=</opt> Sets the shared memory segment + size for the daemon, in bytes. If left unspecified or is set to 0 + it will default to some system-specific default, usually 64 + MiB. Please note that usually there is no need to change this + value, unless you are running an OS kernel that does not do + memory overcommit.</p> + </option> + </section> <section name="Scheduling"> @@ -230,9 +254,17 @@ USA. default script file. The default behaviour is to load <file>~/.pulse/default.pa</file>, and if that file does not exist fall back to the system wide installed version - <file>@pulseconfdir@/default.pa</file>. If <opt>-n</opt> is - passed on the command line the default configuration script is - ignored.</p> + <file>@pulseconfdir@/default.pa</file>. If run in system-wide + mode the file <file>@pulseconfdir@/system.pa</file> is used + instead. If <opt>-n</opt> is passed on the command line + or <opt>default-script-file=</opt> is disabled the default + configuration script is ignored.</p> + </option> + + <option> + <p><opt>default-script-file=</opt> Load the default + configuration script file as specified + in <opt>default-script-file=</opt>. Defaults to "yes".</p> </option> </section> @@ -272,6 +304,9 @@ USA. <p><opt>rlimit-as</opt> Defaults to -1.</p> </option> <option> + <p><opt>rlimit-rss</opt> Defaults to -1.</p> + </option> + <option> <p><opt>rlimit-core</opt> Defaults to -1.</p> </option> <option> @@ -290,6 +325,15 @@ USA. <p><opt>rlimit-nproc</opt> Defaults to -1.</p> </option> <option> + <p><opt>rlimit-locks</opt> Defaults to -1.</p> + </option> + <option> + <p><opt>rlimit-sigpending</opt> Defaults to -1.</p> + </option> + <option> + <p><opt>rlimit-msgqueue</opt> Defaults to -1.</p> + </option> + <option> <p><opt>rlimit-memlock</opt> Defaults to 16 KiB. Please note that the JACK client libraries may require more locked memory.</p> @@ -307,6 +351,9 @@ USA. <opt>realtime-scheduling</opt> is enabled. The JACK client libraries require a real-time prority of 9 by default. </p> </option> + <option> + <p><opt>rlimit-rttime</opt> Defaults to 1000000.</p> + </option> </section> @@ -319,9 +366,11 @@ USA. <option> <p><opt>default-sample-format=</opt> The default sampling format. Specify one of <opt>u8</opt>, <opt>s16le</opt>, - <opt>s16be</opt>, <opt>float32le</opt>, <opt>float32be</opt>, + <opt>s16be</opt>, <opt>s32le</opt>, + <opt>s32be</opt>, <opt>float32le</opt>, <opt>float32be</opt>, <opt>ulaw</opt>, <opt>alaw</opt>. Depending on the endianess of - the CPU the formats <opt>s16ne</opt>, <opt>s16re</opt>, + the CPU the + formats <opt>s16ne</opt>, <opt>s16re</opt>, <opt>s32ne</opt>, <opt>s32re</opt>, <opt>float32ne</opt>, <opt>float32re</opt> (for native, resp. reverse endian) are available as aliases.</p> </option> diff --git a/man/pulseaudio.1.xml.in b/man/pulseaudio.1.xml.in index 0e008c3d..df828242 100644 --- a/man/pulseaudio.1.xml.in +++ b/man/pulseaudio.1.xml.in @@ -127,7 +127,7 @@ USA. </option> <option> - <p><opt>-D | --daemon</opt><arg>[=BOOL]</arg></p> + <p><opt>-D | --daemonize</opt><arg>[=BOOL]</arg></p> <optdesc><p>Daemonize after startup, i.e. detach from the terminal.</p></optdesc> @@ -1 +1,6 @@ de +el +fr +pl +pt_BR +sv diff --git a/po/POTFILES.in b/po/POTFILES.in index fa28b6a7..c20340ea 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -17,7 +17,7 @@ src/modules/module-solaris.c src/modules/module-default-device-restore.c src/modules/module-x11-xsmp.c src/modules/module-remap-sink.c -src/modules/module-bt-proximity.c +src/modules/bluetooth/module-bluetooth-proximity.c src/modules/module-detect.c src/modules/module-always-sink.c src/modules/module-lirc.c @@ -39,7 +39,7 @@ src/modules/module-esound-compat-spawnfd.c src/modules/module-esound-compat-spawnpid.c #src/modules/module-waveout.c src/modules/module-combine.c -src/modules/bt-proximity-helper.c +src/modules/bluetooth/proximity-helper.c src/modules/module-x11-publish.c src/modules/rtp/module-rtp-recv.c src/modules/rtp/sdp.c @@ -190,3 +190,4 @@ src/utils/padsp.c src/utils/pax11publish.c src/utils/pacmd.c src/utils/paplay.c +src/pulsecore/lock-autospawn.c @@ -1,67 +1,68 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# German translation of pulseaudio +# Copyright (C) 2008 pulseaudio +# This file is distributed under the same license as the pulseaudio package. +# Fabian Affolter <fab@fedoraproject.org>, 2008. # msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" +"Project-Id-Version: pulseaudio\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-08-06 20:24+0200\n" -"PO-Revision-Date: 2008-08-06 20:34+0100\n" +"POT-Creation-Date: 2008-10-07 21:03+0200\n" +"PO-Revision-Date: 2008-10-07 21:36+0100\n" "Last-Translator: Lennart Poettering <lennart@poettering.net>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: German <fedora-trans-de@redhat.com>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Poedit-Language: German\n" -#: ../src/daemon/ltdl-bind-now.c:171 -#: ../src/daemon/ltdl-bind-now.c:191 +#: ../src/daemon/ltdl-bind-now.c:177 ../src/daemon/ltdl-bind-now.c:197 msgid "Failed to add bind-now-loader." -msgstr "" +msgstr "Hinzufügen von Bind-Now-Loader fehlgeschlagen." -#: ../src/daemon/ltdl-bind-now.c:178 +#: ../src/daemon/ltdl-bind-now.c:184 msgid "Failed to find original dlopen loader." -msgstr "" +msgstr "Finden von originalem dlopen-Loader fehlgeschlagen." #: ../src/daemon/polkit.c:55 #, c-format msgid "Cannot connect to system bus: %s" -msgstr "" +msgstr "Kann nicht mit dem System-Bus verbinden: %s" #: ../src/daemon/polkit.c:65 #, c-format msgid "Cannot get caller from PID: %s" -msgstr "" +msgstr "Kann Caller von PID nicht beziehen: %s" #: ../src/daemon/polkit.c:77 msgid "Cannot set UID on caller object." -msgstr "" +msgstr "Kann Caller-Ojekt für UID nicht setzen." #: ../src/daemon/polkit.c:82 msgid "Failed to get CK session." -msgstr "" +msgstr "Kann CK-Session nicht beziehen." #: ../src/daemon/polkit.c:90 msgid "Cannot set UID on session object." -msgstr "" +msgstr "Kann UID auf Session-Objekt nicht setzen." #: ../src/daemon/polkit.c:95 msgid "Cannot allocate PolKitAction." -msgstr "" +msgstr "Konnte PolKitAction nicht allozieren." #: ../src/daemon/polkit.c:100 msgid "Cannot set action_id" -msgstr "" +msgstr "Kann action_id nicht setzen" #: ../src/daemon/polkit.c:105 msgid "Cannot allocate PolKitContext." -msgstr "" +msgstr "Konnte PolKitContext nicht allozieren" #: ../src/daemon/polkit.c:110 #, c-format msgid "Cannot initialize PolKitContext: %s" -msgstr "" +msgstr "Konnte PolKitContect nicht initialisieren: %s" #: ../src/daemon/polkit.c:119 #, c-format @@ -71,84 +72,83 @@ msgstr "" #: ../src/daemon/polkit.c:139 #, c-format msgid "Cannot obtain auth: %s" -msgstr "" +msgstr "Erhalten der Authorisierung fehlgeschlagen: %s" #: ../src/daemon/polkit.c:148 #, c-format msgid "PolicyKit responded with '%s'" -msgstr "" +msgstr "PolicyKit antwortet mit '%s'" -#: ../src/daemon/main.c:135 +#: ../src/daemon/main.c:134 #, c-format msgid "Got signal %s." msgstr "Signal %s empfangen." -#: ../src/daemon/main.c:162 +#: ../src/daemon/main.c:161 msgid "Exiting." msgstr "Beende." -#: ../src/daemon/main.c:180 +#: ../src/daemon/main.c:179 #, c-format msgid "Failed to find user '%s'." -msgstr "" +msgstr "Kann Benutzer '%s' nicht finden." -#: ../src/daemon/main.c:185 +#: ../src/daemon/main.c:184 #, c-format msgid "Failed to find group '%s'." -msgstr "" +msgstr "Kann Gruppe '%s' nicht finden." -#: ../src/daemon/main.c:189 +#: ../src/daemon/main.c:188 #, c-format msgid "Found user '%s' (UID %lu) and group '%s' (GID %lu)." -msgstr "" +msgstr "Fand Benutzer '%s' (UID %lu) und Gruppe '%s' (GID %lu)." -#: ../src/daemon/main.c:194 +#: ../src/daemon/main.c:193 #, c-format msgid "GID of user '%s' and of group '%s' don't match." -msgstr "" +msgstr "GID von Benutzer '%s' und von Gruppe '%s' stimme nicht überein." -#: ../src/daemon/main.c:199 +#: ../src/daemon/main.c:198 #, c-format msgid "Home directory of user '%s' is not '%s', ignoring." -msgstr "" +msgstr "Benutzerverzeichnis von Benutzer '%s' ist nicht '%s', ignoriere." -#: ../src/daemon/main.c:202 -#: ../src/daemon/main.c:207 +#: ../src/daemon/main.c:201 ../src/daemon/main.c:206 #, c-format msgid "Failed to create '%s': %s" -msgstr "" +msgstr "Erzeugen von '%s' fehlgeschlagen: %s" -#: ../src/daemon/main.c:214 +#: ../src/daemon/main.c:213 #, c-format msgid "Failed to change group list: %s" -msgstr "" +msgstr "Wechseln der Gruppen-Liste fehlgeschlagen: %s" -#: ../src/daemon/main.c:230 +#: ../src/daemon/main.c:229 #, c-format msgid "Failed to change GID: %s" -msgstr "" +msgstr "Wechseln der GID fehlgeschlagen: %s" -#: ../src/daemon/main.c:246 +#: ../src/daemon/main.c:245 #, c-format msgid "Failed to change UID: %s" -msgstr "" +msgstr "Wechseln der UID fehlgeschlagen: %s" -#: ../src/daemon/main.c:260 +#: ../src/daemon/main.c:259 msgid "Successfully dropped root privileges." -msgstr "" +msgstr "Root-Berechtigungen erfolgreich zurückgesetzt." -#: ../src/daemon/main.c:268 +#: ../src/daemon/main.c:267 msgid "System wide mode unsupported on this platform." -msgstr "" +msgstr "System-Modus auf dieser Plattform nicht unterstützt." -#: ../src/daemon/main.c:286 +#: ../src/daemon/main.c:285 #, c-format msgid "setrlimit(%s, (%u, %u)) failed: %s" -msgstr "" +msgstr "setrlimit(%s, (%u, %u)) fehlgeschlagen: %s" #: ../src/daemon/main.c:425 msgid "Failed to parse command line." -msgstr "" +msgstr "Parsen der Kommandzeile fehlgeschlagen." #: ../src/daemon/main.c:441 #, c-format @@ -178,55 +178,61 @@ msgstr "" #: ../src/daemon/main.c:479 msgid "" -"Called SUID root and real-time/high-priority scheduling was requested in the configuration. However, we lack the necessary priviliges:\n" +"Called SUID root and real-time/high-priority scheduling was requested in the " +"configuration. However, we lack the necessary priviliges:\n" "We are not in group '" msgstr "" #: ../src/daemon/main.c:497 -msgid "High-priority scheduling enabled in configuration but not allowed by policy." +msgid "" +"High-priority scheduling enabled in configuration but not allowed by policy." msgstr "" #: ../src/daemon/main.c:522 msgid "Successfully increased RLIMIT_RTPRIO" -msgstr "" +msgstr "RLIMIT_RTPRIO erfolgreich erhöht" #: ../src/daemon/main.c:525 #, c-format msgid "RLIMIT_RTPRIO failed: %s" -msgstr "" +msgstr "RLIMIT_RTPRIO fehlgeschlagen: %s" #: ../src/daemon/main.c:532 msgid "Giving up CAP_NICE" -msgstr "" +msgstr "Gebe CAP_NICE auf" #: ../src/daemon/main.c:539 -msgid "Real-time scheduling enabled in configuration but not allowed by policy." +msgid "" +"Real-time scheduling enabled in configuration but not allowed by policy." msgstr "" #: ../src/daemon/main.c:597 msgid "Daemon not running" -msgstr "" +msgstr "Daemon läuft nicht" #: ../src/daemon/main.c:599 #, c-format msgid "Daemon running as PID %u" -msgstr "" +msgstr "Daemon läuft als PID %u" #: ../src/daemon/main.c:609 -msgid "Failed to kill daemon." -msgstr "" +#, c-format +msgid "Failed to kill daemon: %s" +msgstr "Konnte Prozess nicht abbrechen: %s" #: ../src/daemon/main.c:627 -msgid "This program is not intended to be run as root (unless --system is specified)." +msgid "" +"This program is not intended to be run as root (unless --system is " +"specified)." msgstr "" #: ../src/daemon/main.c:629 msgid "Root priviliges required." -msgstr "" +msgstr "Root-Berechtigungen benötigt." #: ../src/daemon/main.c:634 msgid "--start not supported for system instances." -msgstr "" +msgstr "--start nicht unterstützt für System-Instanzen." #: ../src/daemon/main.c:639 msgid "Running in system mode, but --disallow-exit not set!" @@ -244,101 +250,148 @@ msgstr "" msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" -#: ../src/daemon/main.c:668 +#: ../src/daemon/main.c:677 msgid "Failed to acquire stdio." -msgstr "" +msgstr "Reservieren von STDIO fehlgeschlagen." -#: ../src/daemon/main.c:674 +#: ../src/daemon/main.c:683 #, c-format msgid "pipe failed: %s" -msgstr "" +msgstr "pipe fehlgeschlagen: %s" -#: ../src/daemon/main.c:679 +#: ../src/daemon/main.c:688 #, c-format msgid "fork() failed: %s" -msgstr "" +msgstr "fork() fehlgeschlagen: %s" -#: ../src/daemon/main.c:693 +#: ../src/daemon/main.c:702 #, c-format msgid "read() failed: %s" -msgstr "" +msgstr "read() fehlgeschlagen: %s" -#: ../src/daemon/main.c:699 +#: ../src/daemon/main.c:708 msgid "Daemon startup failed." msgstr "Start des Dämons fehlgeschlagen." -#: ../src/daemon/main.c:701 +#: ../src/daemon/main.c:710 msgid "Daemon startup successful." msgstr "Start des Dämons erfolgreich." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:780 #, c-format msgid "This is PulseAudio %s" msgstr "Dies ist PulseAudio %s" -#: ../src/daemon/main.c:769 +#: ../src/daemon/main.c:781 +#, c-format +msgid "Compilation host: %s" +msgstr "Kompilations-Host: %s" + +#: ../src/daemon/main.c:782 +#, c-format +msgid "Compilation CFLAGS: %s" +msgstr "Kompilier-CFLAGS: %s" + +#: ../src/daemon/main.c:785 +#, c-format +msgid "Running on host: %s" +msgstr "Laufe auf Host: %s" + +#: ../src/daemon/main.c:788 #, c-format msgid "Page size is %lu bytes" msgstr "Seitengröße ist %lu Bytes." -#: ../src/daemon/main.c:772 +#: ../src/daemon/main.c:791 +msgid "Compiled with Valgrind support: yes" +msgstr "Kompiliere mit Valgrind-Unterstützung: ja" + +#: ../src/daemon/main.c:793 +msgid "Compiled with Valgrind support: no" +msgstr "Kompiliere mit Valgrind-Unterstützung: nein" + +#: ../src/daemon/main.c:796 +#, c-format +msgid "Running in valgrind mode: %s" +msgstr "Laufe im Valgrind-Modus: %s" + +#: ../src/daemon/main.c:799 +msgid "Optimized build: yes" +msgstr "Optimiertes Build: ja" + +#: ../src/daemon/main.c:801 +msgid "Optimized build: no" +msgstr "Optimiertes Build: nein" + +#: ../src/daemon/main.c:805 +msgid "Failed to get machine ID" +msgstr "Beziehen der Maschinen-ID fehlgeschlagen" + +#: ../src/daemon/main.c:808 +#, c-format +msgid "Machine ID is %s." +msgstr "System- ID ist %s." + +#: ../src/daemon/main.c:813 #, c-format msgid "Using runtime directory %s." -msgstr "" +msgstr "Nutze Laufzeit-Verzeichnis %s." -#: ../src/daemon/main.c:775 +#: ../src/daemon/main.c:818 #, c-format msgid "Using state directory %s." -msgstr "" +msgstr "Nutze Zustands-Verzeichnis %s." -#: ../src/daemon/main.c:778 +#: ../src/daemon/main.c:821 #, c-format msgid "Running in system mode: %s" -msgstr "" +msgstr "Laufe im System-Modus: %s" -#: ../src/daemon/main.c:793 +#: ../src/daemon/main.c:836 msgid "pa_pid_file_create() failed." -msgstr "" +msgstr "pa_pid_file_create() fehlgeschlagen." -#: ../src/daemon/main.c:805 +#: ../src/daemon/main.c:848 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "" -#: ../src/daemon/main.c:807 -msgid "Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!" +#: ../src/daemon/main.c:850 +msgid "" +"Dude, your kernel stinks! The chef's recommendation today is Linux with high-" +"resolution timers enabled!" msgstr "" -#: ../src/daemon/main.c:817 +#: ../src/daemon/main.c:860 msgid "pa_core_new() failed." -msgstr "" +msgstr "pa_core_new() fehlgeschlagen." -#: ../src/daemon/main.c:877 +#: ../src/daemon/main.c:921 msgid "Failed to initialize daemon." -msgstr "" +msgstr "Konnte Dämon nicht initialisieren" -#: ../src/daemon/main.c:882 +#: ../src/daemon/main.c:926 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "" -#: ../src/daemon/main.c:887 +#: ../src/daemon/main.c:931 #, c-format msgid "Default sink name (%s) does not exist in name register." msgstr "" -#: ../src/daemon/main.c:900 +#: ../src/daemon/main.c:944 msgid "Daemon startup complete." msgstr "Start des Dämons abgeschlossen." -#: ../src/daemon/main.c:906 +#: ../src/daemon/main.c:950 msgid "Daemon shutdown initiated." -msgstr "" +msgstr "Herunterfahren des Daemon gestartet." -#: ../src/daemon/main.c:923 +#: ../src/daemon/main.c:971 msgid "Daemon terminated." msgstr "Dämon beendet." #: ../src/daemon/cmdline.c:117 -#, c-format +#, fuzzy, c-format msgid "" "%s [options]\n" "\n" @@ -348,8 +401,10 @@ msgid "" " --dump-conf Dump default configuration\n" " --dump-modules Dump list of available modules\n" " --dump-resample-methods Dump available resample methods\n" -" --cleanup-shm Cleanup stale shared memory segments\n" -" --start Start the daemon if it is not running\n" +" --cleanup-shm Cleanup stale shared memory " +"segments\n" +" --start Start the daemon if it is not " +"running\n" " -k --kill Kill a running daemon\n" " --check Check for a running daemon\n" "\n" @@ -358,24 +413,31 @@ msgid "" " -D, --daemonize[=BOOL] Daemonize after startup\n" " --fail[=BOOL] Quit when startup fails\n" " --high-priority[=BOOL] Try to set high nice level\n" -" (only available as root, when SUID or\n" +" (only available as root, when SUID " +"or\n" " with elevated RLIMIT_NICE)\n" " --realtime[=BOOL] Try to enable realtime scheduling\n" -" (only available as root, when SUID or\n" +" (only available as root, when SUID " +"or\n" " with elevated RLIMIT_RTPRIO)\n" -" --disallow-module-loading[=BOOL] Disallow module user requested module\n" +" --disallow-module-loading[=BOOL] Disallow module user requested " +"module\n" " loading/unloading after startup\n" " --disallow-exit[=BOOL] Disallow user requested exit\n" -" --exit-idle-time=SECS Terminate the daemon when idle and this\n" +" --exit-idle-time=SECS Terminate the daemon when idle and " +"this\n" " time passed\n" -" --module-idle-time=SECS Unload autoloaded modules when idle and\n" +" --module-idle-time=SECS Unload autoloaded modules when idle " +"and\n" " this time passed\n" -" --scache-idle-time=SECS Unload autoloaded samples when idle and\n" +" --scache-idle-time=SECS Unload autoloaded samples when idle " +"and\n" " this time passed\n" " --log-level[=LEVEL] Increase or set verbosity level\n" " -v Increase the verbosity level\n" " --log-target={auto,syslog,stderr} Specify the log target\n" -" -p, --dl-search-path=PATH Set the search path for dynamic shared\n" +" -p, --dl-search-path=PATH Set the search path for dynamic " +"shared\n" " objects (plugins)\n" " --resample-method=METHOD Use the specified resampling method\n" " (See --dump-resample-methods for\n" @@ -386,14 +448,80 @@ msgid "" " --disable-shm[=BOOL] Disable shared memory support.\n" "\n" "STARTUP SCRIPT:\n" -" -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module with\n" +" -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module " +"with\n" " the specified argument\n" " -F, --file=FILENAME Run the specified script\n" -" -C Open a command line on the running TTY\n" +" -C Open a command line on the running " +"TTY\n" " after startup\n" "\n" " -n Don't load default script file\n" msgstr "" +"%s [options]\n" +"\n" +"COMMANDS:\n" +" -h, --help Show this help\n" +" --version Show version\n" +" --dump-conf Dump default configuration\n" +" --dump-modules Dump list of available modules\n" +" --dump-resample-methods Dump available resample methods\n" +" --cleanup-shm Cleanup stale shared memory " +"segments\n" +" --start Start the daemon if it is not " +"running\n" +" -k --kill Kill a running daemon\n" +" --check Check for a running daemon\n" +"\n" +"OPTIONS:\n" +" --system[=BOOL] Run as system-wide instance\n" +" -D, --daemonize[=BOOL] Daemonize after startup\n" +" --fail[=BOOL] Quit when startup fails\n" +" --high-priority[=BOOL] Try to set high nice level\n" +" (only available as root, when SUID " +"or\n" +" with elevated RLIMIT_NICE)\n" +" --realtime[=BOOL] Try to enable realtime scheduling\n" +" (only available as root, when SUID " +"or\n" +" with elevated RLIMIT_RTPRIO)\n" +" --disallow-module-loading[=BOOL] Disallow module user requested " +"module\n" +" loading/unloading after startup\n" +" --disallow-exit[=BOOL] Disallow user requested exit\n" +" --exit-idle-time=SECS Terminate the daemon when idle and " +"this\n" +" time passed\n" +" --module-idle-time=SECS Unload autoloaded modules when idle " +"and\n" +" this time passed\n" +" --scache-idle-time=SECS Unload autoloaded samples when idle " +"and\n" +" this time passed\n" +" --log-level[=LEVEL] Increase or set verbosity level\n" +" -v Increase the verbosity level\n" +" --log-target={auto,syslog,stderr} Specify the log target\n" +" -p, --dl-search-path=PATH Set the search path for dynamic " +"shared\n" +" objects (plugins)\n" +" --resample-method=METHOD Use the specified resampling method\n" +" (See --dump-resample-methods for\n" +" possible values)\n" +" --use-pid-file[=BOOL] Create a PID file\n" +" --no-cpu-limit[=BOOL] Do not install CPU load limiter on\n" +" platforms that support it.\n" +" --disable-shm[=BOOL] Disable shared memory support.\n" +"\n" +"STARTUP SCRIPT:\n" +" -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module " +"with\n" +" the specified argument\n" +" -F, --file=FILENAME Run the specified script\n" +" -C Open a command line on the running " +"TTY\n" +" after startup\n" +"\n" +" -n Don't load default script file\n" #: ../src/daemon/cmdline.c:245 msgid "--daemonize expects boolean argument" @@ -404,7 +532,9 @@ msgid "--fail expects boolean argument" msgstr "" #: ../src/daemon/cmdline.c:262 -msgid "--log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error)." +msgid "" +"--log-level expects log level argument (either numeric in range 0..4 or one " +"of debug, info, notice, warn, error)." msgstr "" #: ../src/daemon/cmdline.c:274 @@ -430,15 +560,16 @@ msgstr "" #: ../src/daemon/cmdline.c:319 msgid "Invalid log target: use either 'syslog', 'stderr' or 'auto'." msgstr "" +"Ungültiges Log-Ziel: Benutzen Sie entweder 'syslog', 'stderr' oder 'auto'." #: ../src/daemon/cmdline.c:338 #, c-format msgid "Invalid resample method '%s'." -msgstr "" +msgstr "Ungültige Resample-Methode '%s'." #: ../src/daemon/cmdline.c:345 msgid "--system expects boolean argument" -msgstr "" +msgstr "--System erwartet Boolean-Argument" #: ../src/daemon/cmdline.c:352 msgid "--no-cpu-limit expects boolean argument" @@ -451,113 +582,113 @@ msgstr "" #: ../src/daemon/dumpmodules.c:60 #, c-format msgid "Name: %s\n" -msgstr "" +msgstr "Name: %s\n" #: ../src/daemon/dumpmodules.c:63 #, c-format msgid "No module information available\n" -msgstr "" +msgstr "Keine Modul-Informationen verfügbar\n" #: ../src/daemon/dumpmodules.c:66 #, c-format msgid "Version: %s\n" -msgstr "" +msgstr "Version: %s\n" #: ../src/daemon/dumpmodules.c:68 #, c-format msgid "Description: %s\n" -msgstr "" +msgstr "Beschreibung: %s\n" #: ../src/daemon/dumpmodules.c:70 #, c-format msgid "Author: %s\n" -msgstr "" +msgstr "Author: %s\n" #: ../src/daemon/dumpmodules.c:72 #, c-format msgid "Usage: %s\n" -msgstr "" +msgstr "Verwendung: %s\n" #: ../src/daemon/dumpmodules.c:73 #, c-format msgid "Load Once: %s\n" -msgstr "" +msgstr "Lade einmalig: %s\n" #: ../src/daemon/dumpmodules.c:77 #, c-format msgid "Path: %s\n" -msgstr "" +msgstr "Pfad: %s\n" -#: ../src/daemon/daemon-conf.c:203 +#: ../src/daemon/daemon-conf.c:205 #, c-format msgid "[%s:%u] Invalid log target '%s'." -msgstr "" +msgstr "[%s:%u] Ungültiges Log-Ziel '%s'." -#: ../src/daemon/daemon-conf.c:219 +#: ../src/daemon/daemon-conf.c:221 #, c-format msgid "[%s:%u] Invalid log level '%s'." -msgstr "" +msgstr "[%s:%u] Ungültige Log-Stufe '%s'." -#: ../src/daemon/daemon-conf.c:235 +#: ../src/daemon/daemon-conf.c:237 #, c-format msgid "[%s:%u] Invalid resample method '%s'." -msgstr "" +msgstr "[%s:%u] Ungültige Resample-Methode '%s'." -#: ../src/daemon/daemon-conf.c:258 +#: ../src/daemon/daemon-conf.c:260 #, c-format msgid "[%s:%u] Invalid rlimit '%s'." -msgstr "" +msgstr "[%s:%u] Ungültiges rlimit '%s'." -#: ../src/daemon/daemon-conf.c:265 +#: ../src/daemon/daemon-conf.c:267 #, c-format msgid "[%s:%u] rlimit not supported on this platform." -msgstr "" +msgstr "[%s:%u] rlimit nicht unterstützt auf dieser Plattform." -#: ../src/daemon/daemon-conf.c:281 +#: ../src/daemon/daemon-conf.c:283 #, c-format msgid "[%s:%u] Invalid sample format '%s'." -msgstr "" +msgstr "[%s:%u] Ungültiges Sample-Format '%s'." -#: ../src/daemon/daemon-conf.c:299 +#: ../src/daemon/daemon-conf.c:301 #, c-format msgid "[%s:%u] Invalid sample rate '%s'." -msgstr "" +msgstr "[%s:%u] Ungültige Sample-Rate '%s'." -#: ../src/daemon/daemon-conf.c:317 +#: ../src/daemon/daemon-conf.c:319 #, c-format msgid "[%s:%u] Invalid sample channels '%s'." -msgstr "" +msgstr "[%s:%u] Ungültige Sample-Kanäle '%s'." -#: ../src/daemon/daemon-conf.c:335 +#: ../src/daemon/daemon-conf.c:337 #, c-format msgid "[%s:%u] Invalid number of fragments '%s'." -msgstr "" +msgstr "[%s:%u] Ungültige Anzahl von Fragmenten '%s'." -#: ../src/daemon/daemon-conf.c:353 +#: ../src/daemon/daemon-conf.c:355 #, c-format msgid "[%s:%u] Invalid fragment size '%s'." -msgstr "" +msgstr "[%s:%u] Ungültige Fragment-Größe '%s'." -#: ../src/daemon/daemon-conf.c:371 +#: ../src/daemon/daemon-conf.c:373 #, c-format msgid "[%s:%u] Invalid nice level '%s'." -msgstr "" +msgstr "[%s:%u] Ungültige Nice-Stufe '%s'." -#: ../src/daemon/daemon-conf.c:564 +#: ../src/daemon/daemon-conf.c:570 #, c-format msgid "Failed to open configuration file: %s" -msgstr "" +msgstr "Öffnen der Konfigurationsdatei fehlgeschlagen : %s" -#: ../src/daemon/daemon-conf.c:638 +#: ../src/daemon/daemon-conf.c:644 #, c-format msgid "### Read from configuration file: %s ###\n" -msgstr "" +msgstr "### Lesen von Konfigurationsdatei: %s ###\n" -#: ../src/daemon/caps.c:62 +#: ../src/daemon/caps.c:63 msgid "Dropping root priviliges." -msgstr "" +msgstr "Gebe Root-Privilegien auf." -#: ../src/daemon/caps.c:102 +#: ../src/daemon/caps.c:103 msgid "Limited capabilities successfully to CAP_SYS_NICE." msgstr "" @@ -611,131 +742,131 @@ msgstr "Seite Rechts" #: ../src/pulse/channelmap.c:120 msgid "Auxiliary 0" -msgstr "" +msgstr "Zusatz 0" #: ../src/pulse/channelmap.c:121 msgid "Auxiliary 1" -msgstr "" +msgstr "Zusatz 1" #: ../src/pulse/channelmap.c:122 msgid "Auxiliary 2" -msgstr "" +msgstr "Zusatz 2" #: ../src/pulse/channelmap.c:123 msgid "Auxiliary 3" -msgstr "" +msgstr "Zusatz 3" #: ../src/pulse/channelmap.c:124 msgid "Auxiliary 4" -msgstr "" +msgstr "Zusatz 4" #: ../src/pulse/channelmap.c:125 msgid "Auxiliary 5" -msgstr "" +msgstr "Zusatz 5" #: ../src/pulse/channelmap.c:126 msgid "Auxiliary 6" -msgstr "" +msgstr "Zusatz 6" #: ../src/pulse/channelmap.c:127 msgid "Auxiliary 7" -msgstr "" +msgstr "Zusatz 7" #: ../src/pulse/channelmap.c:128 msgid "Auxiliary 8" -msgstr "" +msgstr "Zusatz 8" #: ../src/pulse/channelmap.c:129 msgid "Auxiliary 9" -msgstr "" +msgstr "Zusatz 9" #: ../src/pulse/channelmap.c:130 msgid "Auxiliary 10" -msgstr "" +msgstr "Zusatz 10" #: ../src/pulse/channelmap.c:131 msgid "Auxiliary 11" -msgstr "" +msgstr "Zusatz 11" #: ../src/pulse/channelmap.c:132 msgid "Auxiliary 12" -msgstr "" +msgstr "Zusatz 12" #: ../src/pulse/channelmap.c:133 msgid "Auxiliary 13" -msgstr "" +msgstr "Zusatz 13" #: ../src/pulse/channelmap.c:134 msgid "Auxiliary 14" -msgstr "" +msgstr "Zusatz 14" #: ../src/pulse/channelmap.c:135 msgid "Auxiliary 15" -msgstr "" +msgstr "Zusatz 15" #: ../src/pulse/channelmap.c:136 msgid "Auxiliary 16" -msgstr "" +msgstr "Zusatz 16" #: ../src/pulse/channelmap.c:137 msgid "Auxiliary 17" -msgstr "" +msgstr "Zusatz 17" #: ../src/pulse/channelmap.c:138 msgid "Auxiliary 18" -msgstr "" +msgstr "Zusatz 18" #: ../src/pulse/channelmap.c:139 msgid "Auxiliary 19" -msgstr "" +msgstr "Zusatz 19" #: ../src/pulse/channelmap.c:140 msgid "Auxiliary 20" -msgstr "" +msgstr "Zusatz 20" #: ../src/pulse/channelmap.c:141 msgid "Auxiliary 21" -msgstr "" +msgstr "Zusatz 21" #: ../src/pulse/channelmap.c:142 msgid "Auxiliary 22" -msgstr "" +msgstr "Zusatz 22" #: ../src/pulse/channelmap.c:143 msgid "Auxiliary 23" -msgstr "" +msgstr "Zusatz 23" #: ../src/pulse/channelmap.c:144 msgid "Auxiliary 24" -msgstr "" +msgstr "Zusatz 24" #: ../src/pulse/channelmap.c:145 msgid "Auxiliary 25" -msgstr "" +msgstr "Zusatz 25" #: ../src/pulse/channelmap.c:146 msgid "Auxiliary 26" -msgstr "" +msgstr "Zusatz 26" #: ../src/pulse/channelmap.c:147 msgid "Auxiliary 27" -msgstr "" +msgstr "Zusatz 26" #: ../src/pulse/channelmap.c:148 msgid "Auxiliary 28" -msgstr "" +msgstr "Zusatz 28" #: ../src/pulse/channelmap.c:149 msgid "Auxiliary 29" -msgstr "" +msgstr "Zusatz 29" #: ../src/pulse/channelmap.c:150 msgid "Auxiliary 30" -msgstr "" +msgstr "Zusatz 30" #: ../src/pulse/channelmap.c:151 msgid "Auxiliary 31" -msgstr "" +msgstr "Zusatz 31" #: ../src/pulse/channelmap.c:153 msgid "Top Center" @@ -743,7 +874,7 @@ msgstr "Oben Mitte" #: ../src/pulse/channelmap.c:155 msgid "Top Front Center" -msgstr "Oben Vorne Mitter" +msgstr "Oben Vorne Mitte" #: ../src/pulse/channelmap.c:156 msgid "Top Front Left" @@ -765,9 +896,14 @@ msgstr "Oben Hinten Links" msgid "Top Rear Right" msgstr "Oben Hinten Rechts" +#: ../src/pulse/channelmap.c:472 ../src/pulse/sample.c:144 +#: ../src/pulse/volume.c:163 ../src/pulse/volume.c:194 +msgid "(invalid)" +msgstr "(ungültig)" + #: ../src/pulse/error.c:43 msgid "OK" -msgstr "" +msgstr "OK" #: ../src/pulse/error.c:44 msgid "Access denied" @@ -787,7 +923,7 @@ msgstr "Entität existiert bereits" #: ../src/pulse/error.c:48 msgid "No such entity" -msgstr "Keine Entität vorhanden" +msgstr "Entität nicht vorhanden" #: ../src/pulse/error.c:49 msgid "Connection refused" @@ -815,7 +951,7 @@ msgstr "Verbindung beendet" #: ../src/pulse/error.c:55 msgid "Entity killed" -msgstr "Entität terminiert." +msgstr "Entität terminiert" #: ../src/pulse/error.c:56 msgid "Invalid server" @@ -853,48 +989,34 @@ msgstr "Unbekannter Fehlercode" msgid "No such extension" msgstr "Erweiterung nicht vorhanden" -#: ../src/pulse/sample.c:134 -msgid "Invalid" -msgstr "Ungültig" - -#: ../src/pulse/client-conf-x11.c:55 -#: ../src/utils/pax11publish.c:100 +#: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100 msgid "XOpenDisplay() failed" -msgstr "" +msgstr "XOpenDisplay() fehlgeschlagen" #: ../src/pulse/client-conf-x11.c:78 msgid "Failed to parse cookie data" -msgstr "" +msgstr "Parsen der Cookie-Daten fehlgeschlagen" -#: ../src/pulse/client-conf.c:117 +#: ../src/pulse/client-conf.c:120 #, c-format msgid "Failed to open configuration file '%s': %s" -msgstr "" - -#: ../src/pulse/context.c:110 -msgid "Cannot unlock autospawn because runtime path is no more." -msgstr "" +msgstr "Konfigurationsdatei »%s« konnte nicht geöffnet werden: %s" -#: ../src/pulse/context.c:536 +#: ../src/pulse/context.c:516 msgid "No cookie loaded. Attempting to connect without." msgstr "" -#: ../src/pulse/context.c:590 -#, c-format -msgid "socketpair(): %s" -msgstr "" - -#: ../src/pulse/context.c:604 +#: ../src/pulse/context.c:642 #, c-format msgid "fork(): %s" -msgstr "" +msgstr "fork(): %s" -#: ../src/pulse/context.c:667 +#: ../src/pulse/context.c:695 #, c-format msgid "waitpid(): %s" -msgstr "" +msgstr "waitpid(): %s" -#: ../src/pulse/context.c:1265 +#: ../src/pulse/context.c:1256 #, c-format msgid "Received message for unknown extension '%s'" msgstr "" @@ -902,12 +1024,12 @@ msgstr "" #: ../src/utils/pacat.c:93 #, c-format msgid "pa_stream_write() failed: %s\n" -msgstr "" +msgstr "pa_stream_write() fehlgeschlagen: %s\n" #: ../src/utils/pacat.c:132 #, c-format msgid "pa_stream_peek() failed: %s\n" -msgstr "" +msgstr "pa_stream_peek() fehlgeschlagen: %s\n" #: ../src/utils/pacat.c:141 #, c-format @@ -917,17 +1039,17 @@ msgstr "" #: ../src/utils/pacat.c:143 #, c-format msgid "pa_stream_drop() failed: %s\n" -msgstr "" +msgstr "pa_stream_drop() fehlgeschlagen: %s\n" #: ../src/utils/pacat.c:169 #, c-format msgid "Stream successfully created.\n" -msgstr "" +msgstr "Stream wurde erfolgreich erstellt.\n" #: ../src/utils/pacat.c:172 #, c-format msgid "pa_stream_get_buffer_attr() failed: %s\n" -msgstr "" +msgstr "pa_stream_get_buffer_attr() fehlgeschlagen: %s\n" #: ../src/utils/pacat.c:176 #, c-format @@ -947,37 +1069,37 @@ msgstr "" #: ../src/utils/pacat.c:187 #, c-format msgid "Connected to device %s (%u, %ssuspended).\n" -msgstr "" +msgstr "Connected to device %s (%u, %ssuspended).\n" #: ../src/utils/pacat.c:197 #, c-format msgid "Stream error: %s\n" -msgstr "" +msgstr "Stream-Fehler: %s\n" #: ../src/utils/pacat.c:207 #, c-format msgid "Stream device suspended.%s \n" -msgstr "" +msgstr "Strom-Gerät eingeschlafen.%s\n" #: ../src/utils/pacat.c:209 #, c-format msgid "Stream device resumed.%s \n" -msgstr "" +msgstr "Stream-Gerät aufgeweckt.%s\n" #: ../src/utils/pacat.c:217 #, c-format msgid "Stream underrun.%s \n" -msgstr "" +msgstr "Stream underrun.%s \n" #: ../src/utils/pacat.c:224 -#, c-format +#, fuzzy, c-format msgid "Stream overrun.%s \n" -msgstr "" +msgstr "Stream overrun.%s \n" #: ../src/utils/pacat.c:231 #, c-format msgid "Stream started.%s \n" -msgstr "" +msgstr "Stream gestartet: %s\n" #: ../src/utils/pacat.c:238 #, c-format @@ -986,93 +1108,88 @@ msgstr "" #: ../src/utils/pacat.c:238 msgid "not " -msgstr "" +msgstr "nicht" #: ../src/utils/pacat.c:259 #, c-format msgid "Connection established.%s \n" -msgstr "" +msgstr "Verbindung hergestellt.%s \n" #: ../src/utils/pacat.c:262 #, c-format msgid "pa_stream_new() failed: %s\n" -msgstr "" +msgstr "pa_stream_new() fehlgeschlagen: %s\n" #: ../src/utils/pacat.c:287 #, c-format msgid "pa_stream_connect_playback() failed: %s\n" -msgstr "" +msgstr "pa_stream_connect_playback() fehlgeschlagen: %s\n" #: ../src/utils/pacat.c:293 #, c-format msgid "pa_stream_connect_record() failed: %s\n" -msgstr "" +msgstr "pa_stream_connect_record() fehlgeschlagen: %s\n" -#: ../src/utils/pacat.c:307 -#: ../src/utils/pasuspender.c:159 -#: ../src/utils/pactl.c:666 -#: ../src/utils/paplay.c:183 +#: ../src/utils/pacat.c:307 ../src/utils/pasuspender.c:159 +#: ../src/utils/pactl.c:666 ../src/utils/paplay.c:183 #, c-format msgid "Connection failure: %s\n" -msgstr "" +msgstr "Verbindungsfehler: %s\n" -#: ../src/utils/pacat.c:328 -#: ../src/utils/paplay.c:75 +#: ../src/utils/pacat.c:328 ../src/utils/paplay.c:75 #, c-format msgid "Failed to drain stream: %s\n" -msgstr "" +msgstr "Entleeren des Streams fehlgeschlagen: %s\n" -#: ../src/utils/pacat.c:333 -#: ../src/utils/paplay.c:80 +#: ../src/utils/pacat.c:333 ../src/utils/paplay.c:80 #, c-format msgid "Playback stream drained.\n" -msgstr "" +msgstr "Wiedergabe-Stream entleert.\n" -#: ../src/utils/pacat.c:343 -#: ../src/utils/paplay.c:92 +#: ../src/utils/pacat.c:343 ../src/utils/paplay.c:92 #, c-format msgid "Draining connection to server.\n" -msgstr "" +msgstr "Draining connection to server.\n" #: ../src/utils/pacat.c:369 #, c-format msgid "Got EOF.\n" -msgstr "" +msgstr "EOF empfangen.\n" #: ../src/utils/pacat.c:375 #, c-format msgid "pa_stream_drain(): %s\n" -msgstr "" +msgstr "pa_stream_drain(): %s\n" #: ../src/utils/pacat.c:385 #, c-format msgid "read() failed: %s\n" -msgstr "" +msgstr "read() fehlgeschlagen: %s\n" #: ../src/utils/pacat.c:417 #, c-format msgid "write() failed: %s\n" -msgstr "" +msgstr "write() fehlgeschlagen: %s\n" #: ../src/utils/pacat.c:438 #, c-format msgid "Got signal, exiting.\n" -msgstr "" +msgstr "Signal empfangen, beende.\n" #: ../src/utils/pacat.c:452 #, c-format msgid "Failed to get latency: %s\n" -msgstr "" +msgstr "Erhalten der Latenz fehlgeschlagen: %s\n" #: ../src/utils/pacat.c:457 #, c-format msgid "Time: %0.3f sec; Latency: %0.0f usec. \r" -msgstr "" +msgstr "Zeit: %0.3f sec; Latenz: %0.0f usec. \r" #: ../src/utils/pacat.c:477 #, c-format msgid "pa_stream_update_timing_info() failed: %s\n" -msgstr "" +msgstr "pa_stream_update_timing_info() fehlgeschlagen: %s\n" #: ../src/utils/pacat.c:490 #, c-format @@ -1087,27 +1204,44 @@ msgid "" "\n" " -v, --verbose Enable verbose operations\n" "\n" -" -s, --server=SERVER The name of the server to connect to\n" -" -d, --device=DEVICE The name of the sink/source to connect to\n" -" -n, --client-name=NAME How to call this client on the server\n" -" --stream-name=NAME How to call this stream on the server\n" -" --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n" -" --rate=SAMPLERATE The sample rate in Hz (defaults to 44100)\n" -" --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n" -" float32be, ulaw, alaw (defaults to s16ne)\n" -" --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -d, --device=DEVICE The name of the sink/source to " +"connect to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" +" --rate=SAMPLERATE The sample rate in Hz (defaults to " +"44100)\n" +" --format=SAMPLEFORMAT The sample type, one of s16le, " +"s16be, u8, float32le,\n" +" float32be, ulaw, alaw, s32le, s32be " +"(defaults to s16ne)\n" +" --channels=CHANNELS The number of channels, 1 for mono, " +"2 for stereo\n" " (defaults to 2)\n" -" --channel-map=CHANNELMAP Channel map to use instead of the default\n" -" --fix-format Take the sample format from the sink the stream is\n" +" --channel-map=CHANNELMAP Channel map to use instead of the " +"default\n" +" --fix-format Take the sample format from the sink " +"the stream is\n" " being connected to.\n" -" --fix-rate Take the sampling rate from the sink the stream is\n" +" --fix-rate Take the sampling rate from the sink " +"the stream is\n" " being connected to.\n" -" --fix-channels Take the number of channels and the channel map\n" -" from the sink the stream is being connected to.\n" +" --fix-channels Take the number of channels and the " +"channel map\n" +" from the sink the stream is being " +"connected to.\n" " --no-remix Don't upmix or downmix channels.\n" -" --no-remap Map channels by index instead of name.\n" -" --latency=BYTES Request the specified latency in bytes.\n" -" --process-time=BYTES Request the specified process time per request in bytes.\n" +" --no-remap Map channels by index instead of " +"name.\n" +" --latency=BYTES Request the specified latency in " +"bytes.\n" +" --process-time=BYTES Request the specified process time " +"per request in bytes.\n" msgstr "" #: ../src/utils/pacat.c:591 @@ -1117,26 +1251,29 @@ msgid "" "Compiled with libpulse %s\n" "Linked with libpulse %s\n" msgstr "" +"pacat %s\n" +"Kompiliert mit libpulse %s\n" +"Gelinkt mit libpulse %s\n" #: ../src/utils/pacat.c:647 #, c-format msgid "Invalid channel map '%s'\n" -msgstr "" +msgstr "Ungültige Kanal-Zuweisung '%s'\n" #: ../src/utils/pacat.c:676 #, c-format msgid "Invalid latency specification '%s'\n" -msgstr "" +msgstr "Ungültige Latenz-Angaben '%s'\n" #: ../src/utils/pacat.c:683 #, c-format msgid "Invalid process time specification '%s'\n" -msgstr "" +msgstr "Ungültige Prozesszeit-Angaben '%s'\n" #: ../src/utils/pacat.c:694 #, c-format msgid "Invalid sample specification\n" -msgstr "" +msgstr "Ungültige Sample-Spezifikationen\n" #: ../src/utils/pacat.c:699 #, c-format @@ -1150,108 +1287,114 @@ msgstr "" #: ../src/utils/pacat.c:706 msgid "recording" -msgstr "" +msgstr "aufnehmen" #: ../src/utils/pacat.c:706 msgid "playback" -msgstr "" +msgstr "abspielen" #: ../src/utils/pacat.c:714 #, c-format msgid "open(): %s\n" -msgstr "" +msgstr "open(): %s\n" #: ../src/utils/pacat.c:719 #, c-format msgid "dup2(): %s\n" -msgstr "" +msgstr "dup2(): %s\n" #: ../src/utils/pacat.c:729 #, c-format msgid "Too many arguments.\n" -msgstr "" +msgstr "Zu viele Argumente.\n" -#: ../src/utils/pacat.c:742 -#: ../src/utils/pasuspender.c:280 -#: ../src/utils/pactl.c:909 -#: ../src/utils/paplay.c:381 +#: ../src/utils/pacat.c:742 ../src/utils/pasuspender.c:280 +#: ../src/utils/pactl.c:909 ../src/utils/paplay.c:381 #, c-format msgid "pa_mainloop_new() failed.\n" -msgstr "" +msgstr "pa_mainloop_new() fehlgeschlagen.\n" #: ../src/utils/pacat.c:763 #, c-format msgid "io_new() failed.\n" -msgstr "" +msgstr "io_new() fehlgeschlagen.\n" -#: ../src/utils/pacat.c:769 -#: ../src/utils/pasuspender.c:293 -#: ../src/utils/pactl.c:923 -#: ../src/utils/paplay.c:396 +#: ../src/utils/pacat.c:769 ../src/utils/pasuspender.c:293 +#: ../src/utils/pactl.c:923 ../src/utils/paplay.c:396 #, c-format msgid "pa_context_new() failed.\n" -msgstr "" +msgstr "pa_context_new() fehlgeschlagen.\n" + +#: ../src/utils/pacat.c:777 +#, c-format +msgid "pa_context_connect() failed: %s" +msgstr "pa_context_new() fehlgeschlagen: %s" -#: ../src/utils/pacat.c:785 +#: ../src/utils/pacat.c:788 #, c-format msgid "time_new() failed.\n" -msgstr "" +msgstr "time_new() fehlgeschlagen.\n" -#: ../src/utils/pacat.c:792 -#: ../src/utils/pasuspender.c:301 -#: ../src/utils/pactl.c:931 -#: ../src/utils/paplay.c:407 +#: ../src/utils/pacat.c:795 ../src/utils/pasuspender.c:301 +#: ../src/utils/pactl.c:931 ../src/utils/paplay.c:407 #, c-format msgid "pa_mainloop_run() failed.\n" -msgstr "" +msgstr "pa_mainloop_run() fehlgeschlagen.\n" #: ../src/utils/pasuspender.c:81 #, c-format msgid "fork(): %s\n" -msgstr "" +msgstr "fork(): %s\n" #: ../src/utils/pasuspender.c:92 #, c-format msgid "execvp(): %s\n" -msgstr "" +msgstr "execvp(): %s\n" #: ../src/utils/pasuspender.c:109 #, c-format msgid "Failure to suspend: %s\n" -msgstr "" +msgstr "Suspend fehlgeschlagen: %s\n" #: ../src/utils/pasuspender.c:124 #, c-format msgid "Failure to resume: %s\n" -msgstr "" +msgstr "Resume fehlgeschlagen: %s\n" #: ../src/utils/pasuspender.c:147 #, c-format msgid "WARNING: Sound server is not local, not suspending.\n" msgstr "" -#: ../src/utils/pasuspender.c:176 -#: ../src/utils/pactl.c:672 +#: ../src/utils/pasuspender.c:176 ../src/utils/pactl.c:672 #: ../src/utils/paplay.c:191 #, c-format msgid "Got SIGINT, exiting.\n" -msgstr "" +msgstr "SIGINT empfangen, beende.\n" #: ../src/utils/pasuspender.c:194 #, c-format msgid "WARNING: Child process terminated by signal %u\n" -msgstr "" +msgstr "WARNUNG: Kind-Prozess durch Signal %u beendet\n" #: ../src/utils/pasuspender.c:212 -#, c-format +#, fuzzy, c-format msgid "" "%s [options] ... \n" "\n" " -h, --help Show this help\n" " --version Show version\n" -" -s, --server=SERVER The name of the server to connect to\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" "\n" msgstr "" +"%s [options] ... \n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +"\n" #: ../src/utils/pasuspender.c:251 #, c-format @@ -1264,7 +1407,7 @@ msgstr "" #: ../src/utils/pactl.c:107 #, c-format msgid "Failed to get statistics: %s\n" -msgstr "" +msgstr "Beziehen der Statistik fehlgeschlagen: %s\n" #: ../src/utils/pactl.c:113 #, c-format @@ -1279,12 +1422,12 @@ msgstr "" #: ../src/utils/pactl.c:119 #, c-format msgid "Sample cache size: %s\n" -msgstr "" +msgstr "Sample-Pufferspeichergrösse: %s\n" #: ../src/utils/pactl.c:128 #, c-format msgid "Failed to get server information: %s\n" -msgstr "" +msgstr "Beziehen der Server-Information fehlgeschlagen: %s\n" #: ../src/utils/pactl.c:135 #, c-format @@ -1302,7 +1445,7 @@ msgstr "" #: ../src/utils/pactl.c:160 #, c-format msgid "Failed to get sink information: %s\n" -msgstr "" +msgstr "Erhalten der Sink-Information fehlgeschlagen: %s\n" #: ../src/utils/pactl.c:176 #, c-format @@ -1321,15 +1464,14 @@ msgid "" "%s" msgstr "" -#: ../src/utils/pactl.c:193 -#: ../src/utils/pactl.c:371 +#: ../src/utils/pactl.c:193 ../src/utils/pactl.c:371 msgid "muted" -msgstr "" +msgstr "stumm" #: ../src/utils/pactl.c:212 #, c-format msgid "Failed to get source information: %s\n" -msgstr "" +msgstr "Beziehen der Quellen-Information fehlgeschlagen: %s\n" #: ../src/utils/pactl.c:228 #, c-format @@ -1348,25 +1490,17 @@ msgid "" "%s" msgstr "" -#: ../src/utils/pactl.c:246 -#: ../src/utils/pactl.c:289 -#: ../src/utils/pactl.c:322 -#: ../src/utils/pactl.c:366 -#: ../src/utils/pactl.c:367 -#: ../src/utils/pactl.c:374 -#: ../src/utils/pactl.c:418 -#: ../src/utils/pactl.c:419 -#: ../src/utils/pactl.c:425 -#: ../src/utils/pactl.c:468 -#: ../src/utils/pactl.c:469 -#: ../src/utils/pactl.c:473 +#: ../src/utils/pactl.c:246 ../src/utils/pactl.c:289 ../src/utils/pactl.c:322 +#: ../src/utils/pactl.c:366 ../src/utils/pactl.c:367 ../src/utils/pactl.c:374 +#: ../src/utils/pactl.c:418 ../src/utils/pactl.c:419 ../src/utils/pactl.c:425 +#: ../src/utils/pactl.c:468 ../src/utils/pactl.c:469 ../src/utils/pactl.c:473 msgid "n/a" -msgstr "" +msgstr "k.A." #: ../src/utils/pactl.c:263 #, c-format msgid "Failed to get module information: %s\n" -msgstr "" +msgstr "Beziehen der Modul-Information fehlgeschlagen: %s\n" #: ../src/utils/pactl.c:281 #, c-format @@ -1381,7 +1515,7 @@ msgstr "" #: ../src/utils/pactl.c:298 #, c-format msgid "Failed to get client information: %s\n" -msgstr "" +msgstr "Beziehen der Client-Information fehlgeschlagen: %s\n" #: ../src/utils/pactl.c:316 #, c-format @@ -1441,7 +1575,7 @@ msgstr "" #: ../src/utils/pactl.c:436 #, c-format msgid "Failed to get sample information: %s\n" -msgstr "" +msgstr "Beziehen der Sample-Information fehlgeschlagen: %s\n" #: ../src/utils/pactl.c:455 #, c-format @@ -1462,7 +1596,7 @@ msgstr "" #: ../src/utils/pactl.c:481 #, c-format msgid "Failed to get autoload information: %s\n" -msgstr "" +msgstr "Beziehen der Autoload-Information fehlgeschlagen: %s\n" #: ../src/utils/pactl.c:497 #, c-format @@ -1480,26 +1614,25 @@ msgstr "" #: ../src/utils/pactl.c:504 msgid "source" -msgstr "" +msgstr "Quelle" -#: ../src/utils/pactl.c:511 -#: ../src/utils/pactl.c:521 +#: ../src/utils/pactl.c:511 ../src/utils/pactl.c:521 #, c-format msgid "Failure: %s\n" -msgstr "" +msgstr "Fehlgeschlagen: %s\n" #: ../src/utils/pactl.c:545 #, c-format msgid "Failed to upload sample: %s\n" -msgstr "" +msgstr "Hochladen des Sample fehlgeschlagen: %s\n" #: ../src/utils/pactl.c:562 #, c-format msgid "Premature end of file\n" -msgstr "" +msgstr "Dateiende ist zu früh aufgetreten\n" #: ../src/utils/pactl.c:678 -#, c-format +#, fuzzy, c-format msgid "" "%s [options] stat\n" "%s [options] list\n" @@ -1517,9 +1650,31 @@ msgid "" " -h, --help Show this help\n" " --version Show version\n" "\n" -" -s, --server=SERVER The name of the server to connect to\n" -" -n, --client-name=NAME How to call this client on the server\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" msgstr "" +"%s [options] stat\n" +"%s [options] list\n" +"%s [options] exit\n" +"%s [options] upload-sample FILENAME [NAME]\n" +"%s [options] play-sample NAME [SINK]\n" +"%s [options] remove-sample NAME\n" +"%s [options] move-sink-input ID SINK\n" +"%s [options] move-source-output ID SOURCE\n" +"%s [options] load-module NAME [ARGS ...]\n" +"%s [options] unload-module ID\n" +"%s [options] suspend-sink [SINK] 1|0\n" +"%s [options] suspend-source [SOURCE] 1|0\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" #: ../src/utils/pactl.c:729 #, c-format @@ -1528,6 +1683,9 @@ msgid "" "Compiled with libpulse %s\n" "Linked with libpulse %s\n" msgstr "" +"pactl %s\n" +"Kompiliert mit libpulse %s\n" +"Gelinkt mit libpulse %s\n" #: ../src/utils/pactl.c:768 #, c-format @@ -1537,17 +1695,17 @@ msgstr "" #: ../src/utils/pactl.c:790 #, c-format msgid "Failed to open sound file.\n" -msgstr "" +msgstr "Öffnen der Audio-Datei fehlgeschlagen.\n" #: ../src/utils/pactl.c:802 #, c-format msgid "You have to specify a sample name to play\n" -msgstr "" +msgstr "You have to specify a sample name to play\n" #: ../src/utils/pactl.c:814 #, c-format msgid "You have to specify a sample name to remove\n" -msgstr "" +msgstr "You have to specify a sample name to remove\n" #: ../src/utils/pactl.c:822 #, c-format @@ -1562,53 +1720,65 @@ msgstr "" #: ../src/utils/pactl.c:845 #, c-format msgid "You have to specify a module name and arguments.\n" -msgstr "" +msgstr "You have to specify a module name and arguments.\n" #: ../src/utils/pactl.c:865 #, c-format msgid "You have to specify a module index\n" -msgstr "" +msgstr "You have to specify a module index\n" #: ../src/utils/pactl.c:875 #, c-format -msgid "You may not specify more than one sink. You have to specify at least one boolean value.\n" +msgid "" +"You may not specify more than one sink. You have to specify at least one " +"boolean value.\n" msgstr "" #: ../src/utils/pactl.c:888 #, c-format -msgid "You may not specify more than one source. You have to specify at least one boolean value.\n" +msgid "" +"You may not specify more than one source. You have to specify at least one " +"boolean value.\n" msgstr "" #: ../src/utils/pactl.c:904 #, c-format msgid "No valid command specified.\n" -msgstr "" +msgstr "Keinen gültigen Befehl angegeben.\n" #: ../src/utils/pax11publish.c:61 -#, c-format +#, fuzzy, c-format msgid "" "%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n" "\n" " -d Show current PulseAudio data attached to X11 display (default)\n" " -e Export local PulseAudio data to X11 display\n" -" -i Import PulseAudio data from X11 display to local environment variables and cookie file.\n" +" -i Import PulseAudio data from X11 display to local environment " +"variables and cookie file.\n" " -r Remove PulseAudio data from X11 display\n" msgstr "" +"%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n" +"\n" +" -d Show current PulseAudio data attached to X11 display (default)\n" +" -e Export local PulseAudio data to X11 display\n" +" -i Import PulseAudio data from X11 display to local environment " +"variables and cookie file.\n" +" -r Remove PulseAudio data from X11 display\n" #: ../src/utils/pax11publish.c:94 #, c-format msgid "Failed to parse command line.\n" -msgstr "" +msgstr "Parsen der Kommandozeile fehlgeschlagen.\n" #: ../src/utils/pax11publish.c:108 #, c-format msgid "Server: %s\n" -msgstr "" +msgstr "Server: %s\n" #: ../src/utils/pax11publish.c:110 #, c-format msgid "Source: %s\n" -msgstr "" +msgstr "Quelle: %s\n" #: ../src/utils/pax11publish.c:112 #, c-format @@ -1618,95 +1788,93 @@ msgstr "" #: ../src/utils/pax11publish.c:114 #, c-format msgid "Cookie: %s\n" -msgstr "" +msgstr "Cookie: %s\n" #: ../src/utils/pax11publish.c:132 #, c-format msgid "Failed to parse cookie data\n" -msgstr "" +msgstr "Paresen der Cookie-Daten fehlgeschlagen.\n" #: ../src/utils/pax11publish.c:137 #, c-format msgid "Failed to save cookie data\n" -msgstr "" +msgstr "Speichern der Cookie-Daten fehlgeschlagen\n" #: ../src/utils/pax11publish.c:152 #, c-format msgid "Failed to load client configuration file.\n" -msgstr "" +msgstr "Laden der Client-Konfigurationsdatei fehlgeschlagen.\n" #: ../src/utils/pax11publish.c:157 #, c-format msgid "Failed to read environment configuration data.\n" -msgstr "" +msgstr "Lesen the Umgebungsdaten fehlgeschlagen.\n" #: ../src/utils/pax11publish.c:174 #, c-format msgid "Failed to get FQDN.\n" -msgstr "" +msgstr "Beziehen des FQDN fehlgeschlagen.\n" #: ../src/utils/pax11publish.c:194 #, c-format msgid "Failed to load cookie data\n" -msgstr "" +msgstr "Laden der Cookie-Daten fehlgeschlagen\n" #: ../src/utils/pax11publish.c:211 #, c-format msgid "Not yet implemented.\n" -msgstr "" +msgstr "Noch nicht implementiert.\n" #: ../src/utils/pacmd.c:64 #, c-format msgid "socket(PF_UNIX, SOCK_STREAM, 0): %s" -msgstr "" +msgstr "socket(PF_UNIX, SOCK_STREAM, 0): %s" #: ../src/utils/pacmd.c:81 #, c-format msgid "connect(): %s" -msgstr "" +msgstr "connect(): %s" #: ../src/utils/pacmd.c:89 msgid "Failed to kill PulseAudio daemon." -msgstr "" +msgstr "Terminieren des PulseAudio-Daemon fehlgeschlagen." #: ../src/utils/pacmd.c:97 msgid "Daemon not responding." -msgstr "" +msgstr "Daemon antwortet nicht." #: ../src/utils/pacmd.c:112 #, c-format msgid "select(): %s" -msgstr "" +msgstr "select(): %s" -#: ../src/utils/pacmd.c:124 -#: ../src/utils/pacmd.c:140 +#: ../src/utils/pacmd.c:124 ../src/utils/pacmd.c:140 #, c-format msgid "read(): %s" -msgstr "" +msgstr "read(): %s" -#: ../src/utils/pacmd.c:153 -#: ../src/utils/pacmd.c:167 +#: ../src/utils/pacmd.c:153 ../src/utils/pacmd.c:167 #, c-format msgid "write(): %s" -msgstr "" +msgstr "write(): %s" #: ../src/utils/paplay.c:139 #, c-format msgid "Stream successfully created\n" -msgstr "" +msgstr "Stream erfolgreich erzeugt\n" #: ../src/utils/paplay.c:144 #, c-format msgid "Stream errror: %s\n" -msgstr "" +msgstr "Stream-Fehler: %s\n" #: ../src/utils/paplay.c:165 #, c-format msgid "Connection established.\n" -msgstr "" +msgstr "Verbindung hergestellt.\n" #: ../src/utils/paplay.c:198 -#, c-format +#, fuzzy, c-format msgid "" "%s [options] [FILE]\n" "\n" @@ -1715,13 +1883,34 @@ msgid "" "\n" " -v, --verbose Enable verbose operation\n" "\n" -" -s, --server=SERVER The name of the server to connect to\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" " -d, --device=DEVICE The name of the sink to connect to\n" -" -n, --client-name=NAME How to call this client on the server\n" -" --stream-name=NAME How to call this stream on the server\n" -" --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" " --channel-map=CHANNELMAP Set the channel map to the use\n" msgstr "" +"%s [options] [FILE]\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -v, --verbose Enable verbose operation\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -d, --device=DEVICE The name of the sink to connect to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" +" --channel-map=CHANNELMAP Set the channel map to the use\n" #: ../src/utils/paplay.c:255 #, c-format @@ -1730,24 +1919,33 @@ msgid "" "Compiled with libpulse %s\n" "Linked with libpulse %s\n" msgstr "" +"paplay %s\n" +"Kompliert mit libpulse %s\n" +"Gelinkt mit libpulse %s\n" #: ../src/utils/paplay.c:292 #, c-format msgid "Invalid channel map\n" -msgstr "" +msgstr "Ungültige Kanal-Zuweisung\n" #: ../src/utils/paplay.c:314 #, c-format msgid "Failed to open file '%s'\n" -msgstr "" +msgstr "Öffnen der Datei '%s' fehlgeschlagen\n" #: ../src/utils/paplay.c:350 #, c-format msgid "Channel map doesn't match file.\n" -msgstr "" +msgstr "Kanal-Zuweisung stimmt mit Datei nicht überein.\n" #: ../src/utils/paplay.c:376 #, c-format msgid "Using sample spec '%s'\n" -msgstr "" +msgstr "Sampling-Spezifikation '%s' wird benutzt\n" + +#: ../src/pulsecore/lock-autospawn.c:126 ../src/pulsecore/lock-autospawn.c:207 +msgid "Cannot access autospawn lock." +msgstr "Fehler beim Zugriff auf Autostart -Sperre." +#~ msgid "socketpair(): %s" +#~ msgstr "socketpair(): %s" diff --git a/po/el.po b/po/el.po new file mode 100644 index 00000000..79ccda73 --- /dev/null +++ b/po/el.po @@ -0,0 +1,1824 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Dimitris Glezos <dimitris@glezos.com>, 2008. +msgid "" +msgstr "" +"Project-Id-Version: el\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-07 21:03+0200\n" +"PO-Revision-Date: 2008-08-22 19:40+0300\n" +"Last-Translator: Dimitris Glezos <dimitris@glezos.com>\n" +"Language-Team: Greek <fedora-trans-el@redhat.com>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KAider 0.1\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../src/daemon/ltdl-bind-now.c:177 ../src/daemon/ltdl-bind-now.c:197 +msgid "Failed to add bind-now-loader." +msgstr "" + +#: ../src/daemon/ltdl-bind-now.c:184 +msgid "Failed to find original dlopen loader." +msgstr "" + +#: ../src/daemon/polkit.c:55 +#, c-format +msgid "Cannot connect to system bus: %s" +msgstr "" + +#: ../src/daemon/polkit.c:65 +#, c-format +msgid "Cannot get caller from PID: %s" +msgstr "" + +#: ../src/daemon/polkit.c:77 +msgid "Cannot set UID on caller object." +msgstr "" + +#: ../src/daemon/polkit.c:82 +msgid "Failed to get CK session." +msgstr "" + +#: ../src/daemon/polkit.c:90 +msgid "Cannot set UID on session object." +msgstr "" + +#: ../src/daemon/polkit.c:95 +msgid "Cannot allocate PolKitAction." +msgstr "" + +#: ../src/daemon/polkit.c:100 +msgid "Cannot set action_id" +msgstr "" + +#: ../src/daemon/polkit.c:105 +msgid "Cannot allocate PolKitContext." +msgstr "" + +#: ../src/daemon/polkit.c:110 +#, c-format +msgid "Cannot initialize PolKitContext: %s" +msgstr "" + +#: ../src/daemon/polkit.c:119 +#, c-format +msgid "Could not determine whether caller is authorized: %s" +msgstr "" + +#: ../src/daemon/polkit.c:139 +#, c-format +msgid "Cannot obtain auth: %s" +msgstr "" + +#: ../src/daemon/polkit.c:148 +#, c-format +msgid "PolicyKit responded with '%s'" +msgstr "" + +#: ../src/daemon/main.c:134 +#, c-format +msgid "Got signal %s." +msgstr "" + +#: ../src/daemon/main.c:161 +msgid "Exiting." +msgstr "Έξοδος." + +#: ../src/daemon/main.c:179 +#, c-format +msgid "Failed to find user '%s'." +msgstr "Αποτυχία εύρεσης χρήστη '%s'." + +#: ../src/daemon/main.c:184 +#, c-format +msgid "Failed to find group '%s'." +msgstr "Αποτυχία εύρεσης ομάδας χρηστών '%s'." + +#: ../src/daemon/main.c:188 +#, c-format +msgid "Found user '%s' (UID %lu) and group '%s' (GID %lu)." +msgstr "" + +#: ../src/daemon/main.c:193 +#, c-format +msgid "GID of user '%s' and of group '%s' don't match." +msgstr "" + +#: ../src/daemon/main.c:198 +#, c-format +msgid "Home directory of user '%s' is not '%s', ignoring." +msgstr "" + +#: ../src/daemon/main.c:201 ../src/daemon/main.c:206 +#, c-format +msgid "Failed to create '%s': %s" +msgstr "" + +#: ../src/daemon/main.c:213 +#, c-format +msgid "Failed to change group list: %s" +msgstr "" + +#: ../src/daemon/main.c:229 +#, c-format +msgid "Failed to change GID: %s" +msgstr "" + +#: ../src/daemon/main.c:245 +#, c-format +msgid "Failed to change UID: %s" +msgstr "" + +#: ../src/daemon/main.c:259 +msgid "Successfully dropped root privileges." +msgstr "" + +#: ../src/daemon/main.c:267 +msgid "System wide mode unsupported on this platform." +msgstr "" + +#: ../src/daemon/main.c:285 +#, c-format +msgid "setrlimit(%s, (%u, %u)) failed: %s" +msgstr "" + +#: ../src/daemon/main.c:425 +msgid "Failed to parse command line." +msgstr "" + +#: ../src/daemon/main.c:441 +#, c-format +msgid "We're in the group '%s', allowing high-priority scheduling." +msgstr "" + +#: ../src/daemon/main.c:448 +#, c-format +msgid "We're in the group '%s', allowing real-time scheduling." +msgstr "" + +#: ../src/daemon/main.c:456 +msgid "PolicyKit grants us acquire-high-priority privilege." +msgstr "" + +#: ../src/daemon/main.c:459 +msgid "PolicyKit refuses acquire-high-priority privilege." +msgstr "" + +#: ../src/daemon/main.c:464 +msgid "PolicyKit grants us acquire-real-time privilege." +msgstr "" + +#: ../src/daemon/main.c:467 +msgid "PolicyKit refuses acquire-real-time privilege." +msgstr "" + +#: ../src/daemon/main.c:479 +msgid "" +"Called SUID root and real-time/high-priority scheduling was requested in the " +"configuration. However, we lack the necessary priviliges:\n" +"We are not in group '" +msgstr "" + +#: ../src/daemon/main.c:497 +msgid "" +"High-priority scheduling enabled in configuration but not allowed by policy." +msgstr "" + +#: ../src/daemon/main.c:522 +msgid "Successfully increased RLIMIT_RTPRIO" +msgstr "" + +#: ../src/daemon/main.c:525 +#, c-format +msgid "RLIMIT_RTPRIO failed: %s" +msgstr "" + +#: ../src/daemon/main.c:532 +msgid "Giving up CAP_NICE" +msgstr "" + +#: ../src/daemon/main.c:539 +msgid "" +"Real-time scheduling enabled in configuration but not allowed by policy." +msgstr "" + +#: ../src/daemon/main.c:597 +msgid "Daemon not running" +msgstr "" + +#: ../src/daemon/main.c:599 +#, c-format +msgid "Daemon running as PID %u" +msgstr "" + +#: ../src/daemon/main.c:609 +#, c-format +msgid "Failed to kill daemon: %s" +msgstr "" + +#: ../src/daemon/main.c:627 +msgid "" +"This program is not intended to be run as root (unless --system is " +"specified)." +msgstr "" + +#: ../src/daemon/main.c:629 +msgid "Root priviliges required." +msgstr "" + +#: ../src/daemon/main.c:634 +msgid "--start not supported for system instances." +msgstr "" + +#: ../src/daemon/main.c:639 +msgid "Running in system mode, but --disallow-exit not set!" +msgstr "" + +#: ../src/daemon/main.c:642 +msgid "Running in system mode, but --disallow-module-loading not set!" +msgstr "" + +#: ../src/daemon/main.c:645 +msgid "Running in system mode, forcibly disabling SHM mode!" +msgstr "" + +#: ../src/daemon/main.c:650 +msgid "Running in system mode, forcibly disabling exit idle time!" +msgstr "" + +#: ../src/daemon/main.c:677 +msgid "Failed to acquire stdio." +msgstr "" + +#: ../src/daemon/main.c:683 +#, c-format +msgid "pipe failed: %s" +msgstr "" + +#: ../src/daemon/main.c:688 +#, c-format +msgid "fork() failed: %s" +msgstr "" + +#: ../src/daemon/main.c:702 +#, c-format +msgid "read() failed: %s" +msgstr "" + +#: ../src/daemon/main.c:708 +msgid "Daemon startup failed." +msgstr "" + +#: ../src/daemon/main.c:710 +msgid "Daemon startup successful." +msgstr "" + +#: ../src/daemon/main.c:780 +#, c-format +msgid "This is PulseAudio %s" +msgstr "Αυτό είναι το PulseAudio %s" + +#: ../src/daemon/main.c:781 +#, c-format +msgid "Compilation host: %s" +msgstr "" + +#: ../src/daemon/main.c:782 +#, c-format +msgid "Compilation CFLAGS: %s" +msgstr "" + +#: ../src/daemon/main.c:785 +#, c-format +msgid "Running on host: %s" +msgstr "" + +#: ../src/daemon/main.c:788 +#, c-format +msgid "Page size is %lu bytes" +msgstr "" + +#: ../src/daemon/main.c:791 +msgid "Compiled with Valgrind support: yes" +msgstr "" + +#: ../src/daemon/main.c:793 +msgid "Compiled with Valgrind support: no" +msgstr "" + +#: ../src/daemon/main.c:796 +#, c-format +msgid "Running in valgrind mode: %s" +msgstr "" + +#: ../src/daemon/main.c:799 +msgid "Optimized build: yes" +msgstr "" + +#: ../src/daemon/main.c:801 +msgid "Optimized build: no" +msgstr "" + +#: ../src/daemon/main.c:805 +msgid "Failed to get machine ID" +msgstr "" + +#: ../src/daemon/main.c:808 +#, c-format +msgid "Machine ID is %s." +msgstr "" + +#: ../src/daemon/main.c:813 +#, c-format +msgid "Using runtime directory %s." +msgstr "" + +#: ../src/daemon/main.c:818 +#, c-format +msgid "Using state directory %s." +msgstr "" + +#: ../src/daemon/main.c:821 +#, c-format +msgid "Running in system mode: %s" +msgstr "" + +#: ../src/daemon/main.c:836 +msgid "pa_pid_file_create() failed." +msgstr "" + +#: ../src/daemon/main.c:848 +msgid "Fresh high-resolution timers available! Bon appetit!" +msgstr "" + +#: ../src/daemon/main.c:850 +msgid "" +"Dude, your kernel stinks! The chef's recommendation today is Linux with high-" +"resolution timers enabled!" +msgstr "" +"Δικέ μου, ο πυρήνας σου είναι για τα μπάζα! Η πρόταση του σεφ σήμερα είναι " +"Linux με ενεργοποιημένα τα high-resolution timers!" + +#: ../src/daemon/main.c:860 +msgid "pa_core_new() failed." +msgstr "" + +#: ../src/daemon/main.c:921 +msgid "Failed to initialize daemon." +msgstr "" + +#: ../src/daemon/main.c:926 +msgid "Daemon startup without any loaded modules, refusing to work." +msgstr "" + +#: ../src/daemon/main.c:931 +#, c-format +msgid "Default sink name (%s) does not exist in name register." +msgstr "" + +#: ../src/daemon/main.c:944 +msgid "Daemon startup complete." +msgstr "" + +#: ../src/daemon/main.c:950 +msgid "Daemon shutdown initiated." +msgstr "" + +#: ../src/daemon/main.c:971 +msgid "Daemon terminated." +msgstr "" + +#: ../src/daemon/cmdline.c:117 +#, c-format +msgid "" +"%s [options]\n" +"\n" +"COMMANDS:\n" +" -h, --help Show this help\n" +" --version Show version\n" +" --dump-conf Dump default configuration\n" +" --dump-modules Dump list of available modules\n" +" --dump-resample-methods Dump available resample methods\n" +" --cleanup-shm Cleanup stale shared memory " +"segments\n" +" --start Start the daemon if it is not " +"running\n" +" -k --kill Kill a running daemon\n" +" --check Check for a running daemon\n" +"\n" +"OPTIONS:\n" +" --system[=BOOL] Run as system-wide instance\n" +" -D, --daemonize[=BOOL] Daemonize after startup\n" +" --fail[=BOOL] Quit when startup fails\n" +" --high-priority[=BOOL] Try to set high nice level\n" +" (only available as root, when SUID " +"or\n" +" with elevated RLIMIT_NICE)\n" +" --realtime[=BOOL] Try to enable realtime scheduling\n" +" (only available as root, when SUID " +"or\n" +" with elevated RLIMIT_RTPRIO)\n" +" --disallow-module-loading[=BOOL] Disallow module user requested " +"module\n" +" loading/unloading after startup\n" +" --disallow-exit[=BOOL] Disallow user requested exit\n" +" --exit-idle-time=SECS Terminate the daemon when idle and " +"this\n" +" time passed\n" +" --module-idle-time=SECS Unload autoloaded modules when idle " +"and\n" +" this time passed\n" +" --scache-idle-time=SECS Unload autoloaded samples when idle " +"and\n" +" this time passed\n" +" --log-level[=LEVEL] Increase or set verbosity level\n" +" -v Increase the verbosity level\n" +" --log-target={auto,syslog,stderr} Specify the log target\n" +" -p, --dl-search-path=PATH Set the search path for dynamic " +"shared\n" +" objects (plugins)\n" +" --resample-method=METHOD Use the specified resampling method\n" +" (See --dump-resample-methods for\n" +" possible values)\n" +" --use-pid-file[=BOOL] Create a PID file\n" +" --no-cpu-limit[=BOOL] Do not install CPU load limiter on\n" +" platforms that support it.\n" +" --disable-shm[=BOOL] Disable shared memory support.\n" +"\n" +"STARTUP SCRIPT:\n" +" -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module " +"with\n" +" the specified argument\n" +" -F, --file=FILENAME Run the specified script\n" +" -C Open a command line on the running " +"TTY\n" +" after startup\n" +"\n" +" -n Don't load default script file\n" +msgstr "" + +#: ../src/daemon/cmdline.c:245 +msgid "--daemonize expects boolean argument" +msgstr "" + +#: ../src/daemon/cmdline.c:252 +msgid "--fail expects boolean argument" +msgstr "" + +#: ../src/daemon/cmdline.c:262 +msgid "" +"--log-level expects log level argument (either numeric in range 0..4 or one " +"of debug, info, notice, warn, error)." +msgstr "" + +#: ../src/daemon/cmdline.c:274 +msgid "--high-priority expects boolean argument" +msgstr "" + +#: ../src/daemon/cmdline.c:281 +msgid "--realtime expects boolean argument" +msgstr "" + +#: ../src/daemon/cmdline.c:288 +msgid "--disallow-module-loading expects boolean argument" +msgstr "" + +#: ../src/daemon/cmdline.c:295 +msgid "--disallow-exit boolean argument" +msgstr "" + +#: ../src/daemon/cmdline.c:302 +msgid "--use-pid-file expects boolean argument" +msgstr "" + +#: ../src/daemon/cmdline.c:319 +msgid "Invalid log target: use either 'syslog', 'stderr' or 'auto'." +msgstr "" + +#: ../src/daemon/cmdline.c:338 +#, c-format +msgid "Invalid resample method '%s'." +msgstr "" + +#: ../src/daemon/cmdline.c:345 +msgid "--system expects boolean argument" +msgstr "" + +#: ../src/daemon/cmdline.c:352 +msgid "--no-cpu-limit expects boolean argument" +msgstr "" + +#: ../src/daemon/cmdline.c:359 +msgid "--disable-shm expects boolean argument" +msgstr "" + +#: ../src/daemon/dumpmodules.c:60 +#, c-format +msgid "Name: %s\n" +msgstr "Όνομα: %s\n" + +#: ../src/daemon/dumpmodules.c:63 +#, c-format +msgid "No module information available\n" +msgstr "" + +#: ../src/daemon/dumpmodules.c:66 +#, c-format +msgid "Version: %s\n" +msgstr "" + +#: ../src/daemon/dumpmodules.c:68 +#, c-format +msgid "Description: %s\n" +msgstr "" + +#: ../src/daemon/dumpmodules.c:70 +#, c-format +msgid "Author: %s\n" +msgstr "" + +#: ../src/daemon/dumpmodules.c:72 +#, c-format +msgid "Usage: %s\n" +msgstr "" + +#: ../src/daemon/dumpmodules.c:73 +#, c-format +msgid "Load Once: %s\n" +msgstr "" + +#: ../src/daemon/dumpmodules.c:77 +#, c-format +msgid "Path: %s\n" +msgstr "" + +#: ../src/daemon/daemon-conf.c:205 +#, c-format +msgid "[%s:%u] Invalid log target '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:221 +#, c-format +msgid "[%s:%u] Invalid log level '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:237 +#, c-format +msgid "[%s:%u] Invalid resample method '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:260 +#, c-format +msgid "[%s:%u] Invalid rlimit '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:267 +#, c-format +msgid "[%s:%u] rlimit not supported on this platform." +msgstr "" + +#: ../src/daemon/daemon-conf.c:283 +#, c-format +msgid "[%s:%u] Invalid sample format '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:301 +#, c-format +msgid "[%s:%u] Invalid sample rate '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:319 +#, c-format +msgid "[%s:%u] Invalid sample channels '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:337 +#, c-format +msgid "[%s:%u] Invalid number of fragments '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:355 +#, c-format +msgid "[%s:%u] Invalid fragment size '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:373 +#, c-format +msgid "[%s:%u] Invalid nice level '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:570 +#, c-format +msgid "Failed to open configuration file: %s" +msgstr "" + +#: ../src/daemon/daemon-conf.c:644 +#, c-format +msgid "### Read from configuration file: %s ###\n" +msgstr "" + +#: ../src/daemon/caps.c:63 +msgid "Dropping root priviliges." +msgstr "" + +#: ../src/daemon/caps.c:103 +msgid "Limited capabilities successfully to CAP_SYS_NICE." +msgstr "" + +#: ../src/pulse/channelmap.c:102 +msgid "Mono" +msgstr "" + +#: ../src/pulse/channelmap.c:104 +msgid "Front Center" +msgstr "" + +#: ../src/pulse/channelmap.c:105 +msgid "Front Left" +msgstr "" + +#: ../src/pulse/channelmap.c:106 +msgid "Front Right" +msgstr "" + +#: ../src/pulse/channelmap.c:108 +msgid "Rear Center" +msgstr "" + +#: ../src/pulse/channelmap.c:109 +msgid "Rear Left" +msgstr "" + +#: ../src/pulse/channelmap.c:110 +msgid "Rear Right" +msgstr "" + +#: ../src/pulse/channelmap.c:112 +msgid "Low Frequency Emmiter" +msgstr "" + +#: ../src/pulse/channelmap.c:114 +msgid "Front Left-of-center" +msgstr "" + +#: ../src/pulse/channelmap.c:115 +msgid "Front Right-of-center" +msgstr "" + +#: ../src/pulse/channelmap.c:117 +msgid "Side Left" +msgstr "" + +#: ../src/pulse/channelmap.c:118 +msgid "Side Right" +msgstr "" + +#: ../src/pulse/channelmap.c:120 +msgid "Auxiliary 0" +msgstr "" + +#: ../src/pulse/channelmap.c:121 +msgid "Auxiliary 1" +msgstr "" + +#: ../src/pulse/channelmap.c:122 +msgid "Auxiliary 2" +msgstr "" + +#: ../src/pulse/channelmap.c:123 +msgid "Auxiliary 3" +msgstr "" + +#: ../src/pulse/channelmap.c:124 +msgid "Auxiliary 4" +msgstr "" + +#: ../src/pulse/channelmap.c:125 +msgid "Auxiliary 5" +msgstr "" + +#: ../src/pulse/channelmap.c:126 +msgid "Auxiliary 6" +msgstr "" + +#: ../src/pulse/channelmap.c:127 +msgid "Auxiliary 7" +msgstr "" + +#: ../src/pulse/channelmap.c:128 +msgid "Auxiliary 8" +msgstr "" + +#: ../src/pulse/channelmap.c:129 +msgid "Auxiliary 9" +msgstr "" + +#: ../src/pulse/channelmap.c:130 +msgid "Auxiliary 10" +msgstr "" + +#: ../src/pulse/channelmap.c:131 +msgid "Auxiliary 11" +msgstr "" + +#: ../src/pulse/channelmap.c:132 +msgid "Auxiliary 12" +msgstr "" + +#: ../src/pulse/channelmap.c:133 +msgid "Auxiliary 13" +msgstr "" + +#: ../src/pulse/channelmap.c:134 +msgid "Auxiliary 14" +msgstr "" + +#: ../src/pulse/channelmap.c:135 +msgid "Auxiliary 15" +msgstr "" + +#: ../src/pulse/channelmap.c:136 +msgid "Auxiliary 16" +msgstr "" + +#: ../src/pulse/channelmap.c:137 +msgid "Auxiliary 17" +msgstr "" + +#: ../src/pulse/channelmap.c:138 +msgid "Auxiliary 18" +msgstr "" + +#: ../src/pulse/channelmap.c:139 +msgid "Auxiliary 19" +msgstr "" + +#: ../src/pulse/channelmap.c:140 +msgid "Auxiliary 20" +msgstr "" + +#: ../src/pulse/channelmap.c:141 +msgid "Auxiliary 21" +msgstr "" + +#: ../src/pulse/channelmap.c:142 +msgid "Auxiliary 22" +msgstr "" + +#: ../src/pulse/channelmap.c:143 +msgid "Auxiliary 23" +msgstr "" + +#: ../src/pulse/channelmap.c:144 +msgid "Auxiliary 24" +msgstr "" + +#: ../src/pulse/channelmap.c:145 +msgid "Auxiliary 25" +msgstr "" + +#: ../src/pulse/channelmap.c:146 +msgid "Auxiliary 26" +msgstr "" + +#: ../src/pulse/channelmap.c:147 +msgid "Auxiliary 27" +msgstr "" + +#: ../src/pulse/channelmap.c:148 +msgid "Auxiliary 28" +msgstr "" + +#: ../src/pulse/channelmap.c:149 +msgid "Auxiliary 29" +msgstr "" + +#: ../src/pulse/channelmap.c:150 +msgid "Auxiliary 30" +msgstr "" + +#: ../src/pulse/channelmap.c:151 +msgid "Auxiliary 31" +msgstr "" + +#: ../src/pulse/channelmap.c:153 +msgid "Top Center" +msgstr "" + +#: ../src/pulse/channelmap.c:155 +msgid "Top Front Center" +msgstr "" + +#: ../src/pulse/channelmap.c:156 +msgid "Top Front Left" +msgstr "" + +#: ../src/pulse/channelmap.c:157 +msgid "Top Front Right" +msgstr "" + +#: ../src/pulse/channelmap.c:159 +msgid "Top Rear Center" +msgstr "" + +#: ../src/pulse/channelmap.c:160 +msgid "Top Rear Left" +msgstr "" + +#: ../src/pulse/channelmap.c:161 +msgid "Top Rear Right" +msgstr "" + +#: ../src/pulse/channelmap.c:472 ../src/pulse/sample.c:144 +#: ../src/pulse/volume.c:163 ../src/pulse/volume.c:194 +msgid "(invalid)" +msgstr "" + +#: ../src/pulse/error.c:43 +msgid "OK" +msgstr "" + +#: ../src/pulse/error.c:44 +msgid "Access denied" +msgstr "" + +#: ../src/pulse/error.c:45 +msgid "Unknown command" +msgstr "" + +#: ../src/pulse/error.c:46 +msgid "Invalid argument" +msgstr "" + +#: ../src/pulse/error.c:47 +msgid "Entity exists" +msgstr "" + +#: ../src/pulse/error.c:48 +msgid "No such entity" +msgstr "" + +#: ../src/pulse/error.c:49 +msgid "Connection refused" +msgstr "" + +#: ../src/pulse/error.c:50 +msgid "Protocol error" +msgstr "" + +#: ../src/pulse/error.c:51 +msgid "Timeout" +msgstr "" + +#: ../src/pulse/error.c:52 +msgid "No authorization key" +msgstr "" + +#: ../src/pulse/error.c:53 +msgid "Internal error" +msgstr "" + +#: ../src/pulse/error.c:54 +msgid "Connection terminated" +msgstr "" + +#: ../src/pulse/error.c:55 +msgid "Entity killed" +msgstr "" + +#: ../src/pulse/error.c:56 +msgid "Invalid server" +msgstr "" + +#: ../src/pulse/error.c:57 +msgid "Module initalization failed" +msgstr "" + +#: ../src/pulse/error.c:58 +msgid "Bad state" +msgstr "" + +#: ../src/pulse/error.c:59 +msgid "No data" +msgstr "" + +#: ../src/pulse/error.c:60 +msgid "Incompatible protocol version" +msgstr "" + +#: ../src/pulse/error.c:61 +msgid "Too large" +msgstr "" + +#: ../src/pulse/error.c:62 +msgid "Not supported" +msgstr "" + +#: ../src/pulse/error.c:63 +msgid "Unknown error code" +msgstr "" + +#: ../src/pulse/error.c:64 +msgid "No such extension" +msgstr "" + +#: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100 +msgid "XOpenDisplay() failed" +msgstr "" + +#: ../src/pulse/client-conf-x11.c:78 +msgid "Failed to parse cookie data" +msgstr "" + +#: ../src/pulse/client-conf.c:120 +#, c-format +msgid "Failed to open configuration file '%s': %s" +msgstr "" + +#: ../src/pulse/context.c:516 +msgid "No cookie loaded. Attempting to connect without." +msgstr "" + +#: ../src/pulse/context.c:642 +#, c-format +msgid "fork(): %s" +msgstr "" + +#: ../src/pulse/context.c:695 +#, c-format +msgid "waitpid(): %s" +msgstr "" + +#: ../src/pulse/context.c:1256 +#, c-format +msgid "Received message for unknown extension '%s'" +msgstr "" + +#: ../src/utils/pacat.c:93 +#, c-format +msgid "pa_stream_write() failed: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:132 +#, c-format +msgid "pa_stream_peek() failed: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:141 +#, c-format +msgid "Buffer overrun, dropping incoming data\n" +msgstr "" + +#: ../src/utils/pacat.c:143 +#, c-format +msgid "pa_stream_drop() failed: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:169 +#, c-format +msgid "Stream successfully created.\n" +msgstr "" + +#: ../src/utils/pacat.c:172 +#, c-format +msgid "pa_stream_get_buffer_attr() failed: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:176 +#, c-format +msgid "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n" +msgstr "" + +#: ../src/utils/pacat.c:179 +#, c-format +msgid "Buffer metrics: maxlength=%u, fragsize=%u\n" +msgstr "" + +#: ../src/utils/pacat.c:183 +#, c-format +msgid "Using sample spec '%s', channel map '%s'.\n" +msgstr "" + +#: ../src/utils/pacat.c:187 +#, c-format +msgid "Connected to device %s (%u, %ssuspended).\n" +msgstr "" + +#: ../src/utils/pacat.c:197 +#, c-format +msgid "Stream error: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:207 +#, c-format +msgid "Stream device suspended.%s \n" +msgstr "" + +#: ../src/utils/pacat.c:209 +#, c-format +msgid "Stream device resumed.%s \n" +msgstr "" + +#: ../src/utils/pacat.c:217 +#, c-format +msgid "Stream underrun.%s \n" +msgstr "" + +#: ../src/utils/pacat.c:224 +#, c-format +msgid "Stream overrun.%s \n" +msgstr "" + +#: ../src/utils/pacat.c:231 +#, c-format +msgid "Stream started.%s \n" +msgstr "" + +#: ../src/utils/pacat.c:238 +#, c-format +msgid "Stream moved to device %s (%u, %ssuspended).%s \n" +msgstr "" + +#: ../src/utils/pacat.c:238 +msgid "not " +msgstr "" + +#: ../src/utils/pacat.c:259 +#, c-format +msgid "Connection established.%s \n" +msgstr "" + +#: ../src/utils/pacat.c:262 +#, c-format +msgid "pa_stream_new() failed: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:287 +#, c-format +msgid "pa_stream_connect_playback() failed: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:293 +#, c-format +msgid "pa_stream_connect_record() failed: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:307 ../src/utils/pasuspender.c:159 +#: ../src/utils/pactl.c:666 ../src/utils/paplay.c:183 +#, c-format +msgid "Connection failure: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:328 ../src/utils/paplay.c:75 +#, c-format +msgid "Failed to drain stream: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:333 ../src/utils/paplay.c:80 +#, c-format +msgid "Playback stream drained.\n" +msgstr "" + +#: ../src/utils/pacat.c:343 ../src/utils/paplay.c:92 +#, c-format +msgid "Draining connection to server.\n" +msgstr "" + +#: ../src/utils/pacat.c:369 +#, c-format +msgid "Got EOF.\n" +msgstr "" + +#: ../src/utils/pacat.c:375 +#, c-format +msgid "pa_stream_drain(): %s\n" +msgstr "" + +#: ../src/utils/pacat.c:385 +#, c-format +msgid "read() failed: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:417 +#, c-format +msgid "write() failed: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:438 +#, c-format +msgid "Got signal, exiting.\n" +msgstr "" + +#: ../src/utils/pacat.c:452 +#, c-format +msgid "Failed to get latency: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:457 +#, c-format +msgid "Time: %0.3f sec; Latency: %0.0f usec. \r" +msgstr "" + +#: ../src/utils/pacat.c:477 +#, c-format +msgid "pa_stream_update_timing_info() failed: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:490 +#, c-format +msgid "" +"%s [options]\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -r, --record Create a connection for recording\n" +" -p, --playback Create a connection for playback\n" +"\n" +" -v, --verbose Enable verbose operations\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -d, --device=DEVICE The name of the sink/source to " +"connect to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" +" --rate=SAMPLERATE The sample rate in Hz (defaults to " +"44100)\n" +" --format=SAMPLEFORMAT The sample type, one of s16le, " +"s16be, u8, float32le,\n" +" float32be, ulaw, alaw, s32le, s32be " +"(defaults to s16ne)\n" +" --channels=CHANNELS The number of channels, 1 for mono, " +"2 for stereo\n" +" (defaults to 2)\n" +" --channel-map=CHANNELMAP Channel map to use instead of the " +"default\n" +" --fix-format Take the sample format from the sink " +"the stream is\n" +" being connected to.\n" +" --fix-rate Take the sampling rate from the sink " +"the stream is\n" +" being connected to.\n" +" --fix-channels Take the number of channels and the " +"channel map\n" +" from the sink the stream is being " +"connected to.\n" +" --no-remix Don't upmix or downmix channels.\n" +" --no-remap Map channels by index instead of " +"name.\n" +" --latency=BYTES Request the specified latency in " +"bytes.\n" +" --process-time=BYTES Request the specified process time " +"per request in bytes.\n" +msgstr "" + +#: ../src/utils/pacat.c:591 +#, c-format +msgid "" +"pacat %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" + +#: ../src/utils/pacat.c:647 +#, c-format +msgid "Invalid channel map '%s'\n" +msgstr "" + +#: ../src/utils/pacat.c:676 +#, c-format +msgid "Invalid latency specification '%s'\n" +msgstr "" + +#: ../src/utils/pacat.c:683 +#, c-format +msgid "Invalid process time specification '%s'\n" +msgstr "" + +#: ../src/utils/pacat.c:694 +#, c-format +msgid "Invalid sample specification\n" +msgstr "" + +#: ../src/utils/pacat.c:699 +#, c-format +msgid "Channel map doesn't match sample specification\n" +msgstr "" + +#: ../src/utils/pacat.c:706 +#, c-format +msgid "Opening a %s stream with sample specification '%s'.\n" +msgstr "" + +#: ../src/utils/pacat.c:706 +msgid "recording" +msgstr "" + +#: ../src/utils/pacat.c:706 +msgid "playback" +msgstr "" + +#: ../src/utils/pacat.c:714 +#, c-format +msgid "open(): %s\n" +msgstr "" + +#: ../src/utils/pacat.c:719 +#, c-format +msgid "dup2(): %s\n" +msgstr "" + +#: ../src/utils/pacat.c:729 +#, c-format +msgid "Too many arguments.\n" +msgstr "" + +#: ../src/utils/pacat.c:742 ../src/utils/pasuspender.c:280 +#: ../src/utils/pactl.c:909 ../src/utils/paplay.c:381 +#, c-format +msgid "pa_mainloop_new() failed.\n" +msgstr "" + +#: ../src/utils/pacat.c:763 +#, c-format +msgid "io_new() failed.\n" +msgstr "" + +#: ../src/utils/pacat.c:769 ../src/utils/pasuspender.c:293 +#: ../src/utils/pactl.c:923 ../src/utils/paplay.c:396 +#, c-format +msgid "pa_context_new() failed.\n" +msgstr "" + +#: ../src/utils/pacat.c:777 +#, c-format +msgid "pa_context_connect() failed: %s" +msgstr "" + +#: ../src/utils/pacat.c:788 +#, c-format +msgid "time_new() failed.\n" +msgstr "" + +#: ../src/utils/pacat.c:795 ../src/utils/pasuspender.c:301 +#: ../src/utils/pactl.c:931 ../src/utils/paplay.c:407 +#, c-format +msgid "pa_mainloop_run() failed.\n" +msgstr "" + +#: ../src/utils/pasuspender.c:81 +#, c-format +msgid "fork(): %s\n" +msgstr "" + +#: ../src/utils/pasuspender.c:92 +#, c-format +msgid "execvp(): %s\n" +msgstr "" + +#: ../src/utils/pasuspender.c:109 +#, c-format +msgid "Failure to suspend: %s\n" +msgstr "" + +#: ../src/utils/pasuspender.c:124 +#, c-format +msgid "Failure to resume: %s\n" +msgstr "" + +#: ../src/utils/pasuspender.c:147 +#, c-format +msgid "WARNING: Sound server is not local, not suspending.\n" +msgstr "" + +#: ../src/utils/pasuspender.c:176 ../src/utils/pactl.c:672 +#: ../src/utils/paplay.c:191 +#, c-format +msgid "Got SIGINT, exiting.\n" +msgstr "" + +#: ../src/utils/pasuspender.c:194 +#, c-format +msgid "WARNING: Child process terminated by signal %u\n" +msgstr "" + +#: ../src/utils/pasuspender.c:212 +#, c-format +msgid "" +"%s [options] ... \n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +"\n" +msgstr "" + +#: ../src/utils/pasuspender.c:251 +#, c-format +msgid "" +"pasuspender %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" + +#: ../src/utils/pactl.c:107 +#, c-format +msgid "Failed to get statistics: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:113 +#, c-format +msgid "Currently in use: %u blocks containing %s bytes total.\n" +msgstr "" + +#: ../src/utils/pactl.c:116 +#, c-format +msgid "Allocated during whole lifetime: %u blocks containing %s bytes total.\n" +msgstr "" + +#: ../src/utils/pactl.c:119 +#, c-format +msgid "Sample cache size: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:128 +#, c-format +msgid "Failed to get server information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:135 +#, c-format +msgid "" +"User name: %s\n" +"Host Name: %s\n" +"Server Name: %s\n" +"Server Version: %s\n" +"Default Sample Specification: %s\n" +"Default Sink: %s\n" +"Default Source: %s\n" +"Cookie: %08x\n" +msgstr "" + +#: ../src/utils/pactl.c:160 +#, c-format +msgid "Failed to get sink information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:176 +#, c-format +msgid "" +"*** Sink #%u ***\n" +"Name: %s\n" +"Driver: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Owner Module: %u\n" +"Volume: %s\n" +"Monitor Source: %s\n" +"Latency: %0.0f usec, configured %0.0f usec\n" +"Flags: %s%s%s%s%s%s\n" +"Properties:\n" +"%s" +msgstr "" + +#: ../src/utils/pactl.c:193 ../src/utils/pactl.c:371 +msgid "muted" +msgstr "" + +#: ../src/utils/pactl.c:212 +#, c-format +msgid "Failed to get source information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:228 +#, c-format +msgid "" +"*** Source #%u ***\n" +"Name: %s\n" +"Driver: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Owner Module: %u\n" +"Volume: %s\n" +"Monitor of Sink: %s\n" +"Latency: %0.0f usec, configured %0.0f usec\n" +"Flags: %s%s%s%s%s%s\n" +"Properties:\n" +"%s" +msgstr "" + +#: ../src/utils/pactl.c:246 ../src/utils/pactl.c:289 ../src/utils/pactl.c:322 +#: ../src/utils/pactl.c:366 ../src/utils/pactl.c:367 ../src/utils/pactl.c:374 +#: ../src/utils/pactl.c:418 ../src/utils/pactl.c:419 ../src/utils/pactl.c:425 +#: ../src/utils/pactl.c:468 ../src/utils/pactl.c:469 ../src/utils/pactl.c:473 +msgid "n/a" +msgstr "" + +#: ../src/utils/pactl.c:263 +#, c-format +msgid "Failed to get module information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:281 +#, c-format +msgid "" +"*** Module #%u ***\n" +"Name: %s\n" +"Argument: %s\n" +"Usage counter: %s\n" +"Auto unload: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:298 +#, c-format +msgid "Failed to get client information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:316 +#, c-format +msgid "" +"*** Client #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Properties:\n" +"%s" +msgstr "" + +#: ../src/utils/pactl.c:333 +#, c-format +msgid "Failed to get sink input information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:352 +#, c-format +msgid "" +"*** Sink Input #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Client: %s\n" +"Sink: %u\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Volume: %s\n" +"Buffer Latency: %0.0f usec\n" +"Sink Latency: %0.0f usec\n" +"Resample method: %s\n" +"Properties:\n" +"%s" +msgstr "" + +#: ../src/utils/pactl.c:385 +#, c-format +msgid "Failed to get source output information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:405 +#, c-format +msgid "" +"*** Source Output #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Client: %s\n" +"Source: %u\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Buffer Latency: %0.0f usec\n" +"Source Latency: %0.0f usec\n" +"Resample method: %s\n" +"Properties:\n" +"%s" +msgstr "" + +#: ../src/utils/pactl.c:436 +#, c-format +msgid "Failed to get sample information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:455 +#, c-format +msgid "" +"*** Sample #%u ***\n" +"Name: %s\n" +"Volume: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Duration: %0.1fs\n" +"Size: %s\n" +"Lazy: %s\n" +"Filename: %s\n" +"Properties:\n" +"%s" +msgstr "" + +#: ../src/utils/pactl.c:481 +#, c-format +msgid "Failed to get autoload information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:497 +#, c-format +msgid "" +"*** Autoload Entry #%u ***\n" +"Name: %s\n" +"Type: %s\n" +"Module: %s\n" +"Argument: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:504 +msgid "sink" +msgstr "" + +#: ../src/utils/pactl.c:504 +msgid "source" +msgstr "" + +#: ../src/utils/pactl.c:511 ../src/utils/pactl.c:521 +#, c-format +msgid "Failure: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:545 +#, c-format +msgid "Failed to upload sample: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:562 +#, c-format +msgid "Premature end of file\n" +msgstr "" + +#: ../src/utils/pactl.c:678 +#, c-format +msgid "" +"%s [options] stat\n" +"%s [options] list\n" +"%s [options] exit\n" +"%s [options] upload-sample FILENAME [NAME]\n" +"%s [options] play-sample NAME [SINK]\n" +"%s [options] remove-sample NAME\n" +"%s [options] move-sink-input ID SINK\n" +"%s [options] move-source-output ID SOURCE\n" +"%s [options] load-module NAME [ARGS ...]\n" +"%s [options] unload-module ID\n" +"%s [options] suspend-sink [SINK] 1|0\n" +"%s [options] suspend-source [SOURCE] 1|0\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +msgstr "" + +#: ../src/utils/pactl.c:729 +#, c-format +msgid "" +"pactl %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" + +#: ../src/utils/pactl.c:768 +#, c-format +msgid "Please specify a sample file to load\n" +msgstr "" + +#: ../src/utils/pactl.c:790 +#, c-format +msgid "Failed to open sound file.\n" +msgstr "" + +#: ../src/utils/pactl.c:802 +#, c-format +msgid "You have to specify a sample name to play\n" +msgstr "" + +#: ../src/utils/pactl.c:814 +#, c-format +msgid "You have to specify a sample name to remove\n" +msgstr "" + +#: ../src/utils/pactl.c:822 +#, c-format +msgid "You have to specify a sink input index and a sink\n" +msgstr "" + +#: ../src/utils/pactl.c:831 +#, c-format +msgid "You have to specify a source output index and a source\n" +msgstr "" + +#: ../src/utils/pactl.c:845 +#, c-format +msgid "You have to specify a module name and arguments.\n" +msgstr "" + +#: ../src/utils/pactl.c:865 +#, c-format +msgid "You have to specify a module index\n" +msgstr "" + +#: ../src/utils/pactl.c:875 +#, c-format +msgid "" +"You may not specify more than one sink. You have to specify at least one " +"boolean value.\n" +msgstr "" + +#: ../src/utils/pactl.c:888 +#, c-format +msgid "" +"You may not specify more than one source. You have to specify at least one " +"boolean value.\n" +msgstr "" + +#: ../src/utils/pactl.c:904 +#, c-format +msgid "No valid command specified.\n" +msgstr "" + +#: ../src/utils/pax11publish.c:61 +#, c-format +msgid "" +"%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n" +"\n" +" -d Show current PulseAudio data attached to X11 display (default)\n" +" -e Export local PulseAudio data to X11 display\n" +" -i Import PulseAudio data from X11 display to local environment " +"variables and cookie file.\n" +" -r Remove PulseAudio data from X11 display\n" +msgstr "" + +#: ../src/utils/pax11publish.c:94 +#, c-format +msgid "Failed to parse command line.\n" +msgstr "" + +#: ../src/utils/pax11publish.c:108 +#, c-format +msgid "Server: %s\n" +msgstr "" + +#: ../src/utils/pax11publish.c:110 +#, c-format +msgid "Source: %s\n" +msgstr "" + +#: ../src/utils/pax11publish.c:112 +#, c-format +msgid "Sink: %s\n" +msgstr "" + +#: ../src/utils/pax11publish.c:114 +#, c-format +msgid "Cookie: %s\n" +msgstr "" + +#: ../src/utils/pax11publish.c:132 +#, c-format +msgid "Failed to parse cookie data\n" +msgstr "" + +#: ../src/utils/pax11publish.c:137 +#, c-format +msgid "Failed to save cookie data\n" +msgstr "" + +#: ../src/utils/pax11publish.c:152 +#, c-format +msgid "Failed to load client configuration file.\n" +msgstr "" + +#: ../src/utils/pax11publish.c:157 +#, c-format +msgid "Failed to read environment configuration data.\n" +msgstr "" + +#: ../src/utils/pax11publish.c:174 +#, c-format +msgid "Failed to get FQDN.\n" +msgstr "" + +#: ../src/utils/pax11publish.c:194 +#, c-format +msgid "Failed to load cookie data\n" +msgstr "" + +#: ../src/utils/pax11publish.c:211 +#, c-format +msgid "Not yet implemented.\n" +msgstr "" + +#: ../src/utils/pacmd.c:64 +#, c-format +msgid "socket(PF_UNIX, SOCK_STREAM, 0): %s" +msgstr "" + +#: ../src/utils/pacmd.c:81 +#, c-format +msgid "connect(): %s" +msgstr "" + +#: ../src/utils/pacmd.c:89 +msgid "Failed to kill PulseAudio daemon." +msgstr "" + +#: ../src/utils/pacmd.c:97 +msgid "Daemon not responding." +msgstr "" + +#: ../src/utils/pacmd.c:112 +#, c-format +msgid "select(): %s" +msgstr "" + +#: ../src/utils/pacmd.c:124 ../src/utils/pacmd.c:140 +#, c-format +msgid "read(): %s" +msgstr "" + +#: ../src/utils/pacmd.c:153 ../src/utils/pacmd.c:167 +#, c-format +msgid "write(): %s" +msgstr "" + +#: ../src/utils/paplay.c:139 +#, c-format +msgid "Stream successfully created\n" +msgstr "" + +#: ../src/utils/paplay.c:144 +#, c-format +msgid "Stream errror: %s\n" +msgstr "" + +#: ../src/utils/paplay.c:165 +#, c-format +msgid "Connection established.\n" +msgstr "" + +#: ../src/utils/paplay.c:198 +#, c-format +msgid "" +"%s [options] [FILE]\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -v, --verbose Enable verbose operation\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -d, --device=DEVICE The name of the sink to connect to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" +" --channel-map=CHANNELMAP Set the channel map to the use\n" +msgstr "" + +#: ../src/utils/paplay.c:255 +#, c-format +msgid "" +"paplay %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" + +#: ../src/utils/paplay.c:292 +#, c-format +msgid "Invalid channel map\n" +msgstr "" + +#: ../src/utils/paplay.c:314 +#, c-format +msgid "Failed to open file '%s'\n" +msgstr "" + +#: ../src/utils/paplay.c:350 +#, c-format +msgid "Channel map doesn't match file.\n" +msgstr "" + +#: ../src/utils/paplay.c:376 +#, c-format +msgid "Using sample spec '%s'\n" +msgstr "" + +#: ../src/pulsecore/lock-autospawn.c:126 ../src/pulsecore/lock-autospawn.c:207 +msgid "Cannot access autospawn lock." +msgstr "" diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 00000000..6d35390a --- /dev/null +++ b/po/fr.po @@ -0,0 +1,2178 @@ +# French translation of pulseaudio. +# Copyright (C) 2006-2008 Lennart Poettering +# This file is distributed under the same license as the pulseaudio package. +# +# Robert-André Mauchin <zebob.m@pengzone.org>, 2008. +# Michaël Ughetto <telimektar esraonline com>, 2008. +# +msgid "" +msgstr "" +"Project-Id-Version: pulseaudio trunk\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-07 21:03+0200\n" +"PO-Revision-Date: 2008-09-06 10:49+0200\n" +"Last-Translator: Robert-André Mauchin <zebob.m@pengzone.org>\n" +"Language-Team: Fedora French <fedora-trans-fr@redhat.com>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n>1;\n" + +#: ../src/daemon/ltdl-bind-now.c:177 ../src/daemon/ltdl-bind-now.c:197 +msgid "Failed to add bind-now-loader." +msgstr "Échec lors de l'ajout du chargeur bind-now." + +#: ../src/daemon/ltdl-bind-now.c:184 +msgid "Failed to find original dlopen loader." +msgstr "Échec lors de la recherche du chargeur dlopen original." + +#: ../src/daemon/polkit.c:55 +#, c-format +msgid "Cannot connect to system bus: %s" +msgstr "Impossible de se connecter au bus système : %s" + +#: ../src/daemon/polkit.c:65 +#, c-format +msgid "Cannot get caller from PID: %s" +msgstr "Impossible d'obtenir le programme appelant à partir du PID : %s" + +#: ../src/daemon/polkit.c:77 +msgid "Cannot set UID on caller object." +msgstr "Impossible de définir un UID sur l'objet appelant." + +#: ../src/daemon/polkit.c:82 +msgid "Failed to get CK session." +msgstr "Échec lors de l'obtention de la session CK." + +#: ../src/daemon/polkit.c:90 +msgid "Cannot set UID on session object." +msgstr "Impossible de définir l'UID sur l'objet de session." + +#: ../src/daemon/polkit.c:95 +msgid "Cannot allocate PolKitAction." +msgstr "Impossible d'allouer PolKitAction." + +#: ../src/daemon/polkit.c:100 +msgid "Cannot set action_id" +msgstr "Impossible de définir action_id." + +#: ../src/daemon/polkit.c:105 +msgid "Cannot allocate PolKitContext." +msgstr "Impossible d'allouer PolKitContext." + +#: ../src/daemon/polkit.c:110 +#, c-format +msgid "Cannot initialize PolKitContext: %s" +msgstr "Impossible d'initialiser PolKitContext : %s" + +#: ../src/daemon/polkit.c:119 +#, c-format +msgid "Could not determine whether caller is authorized: %s" +msgstr "Impossible de déterminer si le programme appelant est autorisé : %s" + +#: ../src/daemon/polkit.c:139 +#, c-format +msgid "Cannot obtain auth: %s" +msgstr "Impossible d'obtenir l'authentification : %s" + +#: ../src/daemon/polkit.c:148 +#, c-format +msgid "PolicyKit responded with '%s'" +msgstr "PolicyKit a renvoyé « %s »" + +#: ../src/daemon/main.c:134 +#, c-format +msgid "Got signal %s." +msgstr "Signal %s obtenu." + +#: ../src/daemon/main.c:161 +msgid "Exiting." +msgstr "Fermeture." + +#: ../src/daemon/main.c:179 +#, c-format +msgid "Failed to find user '%s'." +msgstr "Impossible de trouver l'utilisateur « %s »." + +#: ../src/daemon/main.c:184 +#, c-format +msgid "Failed to find group '%s'." +msgstr "Impossible de trouver le groupe « %s »." + +#: ../src/daemon/main.c:188 +#, c-format +msgid "Found user '%s' (UID %lu) and group '%s' (GID %lu)." +msgstr "Utilisateur « %s ” (UID %lu) et groupe « %s » (GID %lu) trouvé." + +#: ../src/daemon/main.c:193 +#, c-format +msgid "GID of user '%s' and of group '%s' don't match." +msgstr "" +"Le GID de l'utilisateur « %s » et du groupe « %s » ne sont pas identiques." + +#: ../src/daemon/main.c:198 +#, c-format +msgid "Home directory of user '%s' is not '%s', ignoring." +msgstr "Le dossier personnel de l'utilisateur « %s » n'est pas « %s », ignoré." + +#: ../src/daemon/main.c:201 ../src/daemon/main.c:206 +#, c-format +msgid "Failed to create '%s': %s" +msgstr "Échec lors de la création de « %s » : %s" + +#: ../src/daemon/main.c:213 +#, c-format +msgid "Failed to change group list: %s" +msgstr "Échec lors du changement de la liste du groupe : %s" + +#: ../src/daemon/main.c:229 +#, c-format +msgid "Failed to change GID: %s" +msgstr "Échec lors du changement de GID : %s" + +#: ../src/daemon/main.c:245 +#, c-format +msgid "Failed to change UID: %s" +msgstr "Échec lors du changement d'UID : %s" + +#: ../src/daemon/main.c:259 +msgid "Successfully dropped root privileges." +msgstr "Les permissions root ont été correctement abandonnées." + +#: ../src/daemon/main.c:267 +msgid "System wide mode unsupported on this platform." +msgstr "Mode système étendu non pris en charge sur cette plateforme." + +#: ../src/daemon/main.c:285 +#, c-format +msgid "setrlimit(%s, (%u, %u)) failed: %s" +msgstr "setrlimit(%s, (%u, %u)) a échoué : %s" + +#: ../src/daemon/main.c:425 +msgid "Failed to parse command line." +msgstr "Échec lors de l'analyse de la ligne de commande" + +#: ../src/daemon/main.c:441 +#, c-format +msgid "We're in the group '%s', allowing high-priority scheduling." +msgstr "" +"Nous sommes dans le groupe « %s », permettant une planification à haute " +"priorité." + +#: ../src/daemon/main.c:448 +#, c-format +msgid "We're in the group '%s', allowing real-time scheduling." +msgstr "" +"Nous sommes dans le groupe « %s », permettant une planification en temps réel." + +#: ../src/daemon/main.c:456 +msgid "PolicyKit grants us acquire-high-priority privilege." +msgstr "PolicyKit a accordé l'acquisition des permissions de haute priorité." + +#: ../src/daemon/main.c:459 +msgid "PolicyKit refuses acquire-high-priority privilege." +msgstr "PolicyKit a refusé l'acquisition des permissions de haute priorité." + +#: ../src/daemon/main.c:464 +msgid "PolicyKit grants us acquire-real-time privilege." +msgstr "PolicyKit a accordé l'acquisition des permissions de temps réel." + +#: ../src/daemon/main.c:467 +msgid "PolicyKit refuses acquire-real-time privilege." +msgstr "PolicyKit a refusé l'acquisition des permissions de temps réel." + +#: ../src/daemon/main.c:479 +msgid "" +"Called SUID root and real-time/high-priority scheduling was requested in the " +"configuration. However, we lack the necessary priviliges:\n" +"We are not in group '" +msgstr "" +"Le SUID root a été appelé et la planification à haute priorité/en temps réel " +"demandée dans la configuration. Néanmoins nous n'avons pas les permissions " +"nécessaires :\n" +"nous ne somme pas dans le groupe " + +#: ../src/daemon/main.c:497 +msgid "" +"High-priority scheduling enabled in configuration but not allowed by policy." +msgstr "" +"La planification à haute priorité est activée dans la configuration mais " +"n'est pas permise par la politique." + +#: ../src/daemon/main.c:522 +msgid "Successfully increased RLIMIT_RTPRIO" +msgstr "Augmentation de RLIMIT_RTPRIO réussie" + +#: ../src/daemon/main.c:525 +#, c-format +msgid "RLIMIT_RTPRIO failed: %s" +msgstr "RLIMIT_RTPRIO a échoué : %s" + +#: ../src/daemon/main.c:532 +msgid "Giving up CAP_NICE" +msgstr "Abandon de CAP_NICE" + +#: ../src/daemon/main.c:539 +msgid "" +"Real-time scheduling enabled in configuration but not allowed by policy." +msgstr "" +"La planification en temps réel est activée mais n'est pas permise par la " +"politique." + +#: ../src/daemon/main.c:597 +msgid "Daemon not running" +msgstr "Lé démon n'est pas lancé" + +#: ../src/daemon/main.c:599 +#, c-format +msgid "Daemon running as PID %u" +msgstr "Le démon est lancé avec le PID %u" + +#: ../src/daemon/main.c:609 +#, c-format +msgid "Failed to kill daemon: %s" +msgstr "Impossible de tuer le démon : %s" + +#: ../src/daemon/main.c:627 +msgid "" +"This program is not intended to be run as root (unless --system is " +"specified)." +msgstr "" +"Le programme n'est pas conçu pour être lancé en tant que root (sauf si --" +"system est renseigné)." + +#: ../src/daemon/main.c:629 +msgid "Root priviliges required." +msgstr "Les permissions root sont nécessaires." + +#: ../src/daemon/main.c:634 +msgid "--start not supported for system instances." +msgstr "--start n'est pas pris en charge pour les instances système." + +#: ../src/daemon/main.c:639 +msgid "Running in system mode, but --disallow-exit not set!" +msgstr "" +"Le démon s'exécute en mode système, mais --disallow-exit n'est pas défini." + +#: ../src/daemon/main.c:642 +msgid "Running in system mode, but --disallow-module-loading not set!" +msgstr "" +"Le démon s'exécute en mode système, mais --disallow-module-loading n'est pas " +"défini." + +#: ../src/daemon/main.c:645 +msgid "Running in system mode, forcibly disabling SHM mode!" +msgstr "Le démon s'exécute en mode système, désactivation forcée du mode SHM." + +#: ../src/daemon/main.c:650 +msgid "Running in system mode, forcibly disabling exit idle time!" +msgstr "" +"Le démon s'exécute en mode système, désactivation forcée de la fermeture " +"après délai d'inactivité." + +#: ../src/daemon/main.c:677 +msgid "Failed to acquire stdio." +msgstr "Échec lors de l'acquisition de stdio." + +#: ../src/daemon/main.c:683 +#, c-format +msgid "pipe failed: %s" +msgstr "Échec du tube : %s" + +#: ../src/daemon/main.c:688 +#, c-format +msgid "fork() failed: %s" +msgstr "Échec de fork() : %s" + +#: ../src/daemon/main.c:702 +#, c-format +msgid "read() failed: %s" +msgstr "Échec de read() : %s" + +#: ../src/daemon/main.c:708 +msgid "Daemon startup failed." +msgstr "Échec lors du démarrage du démon." + +#: ../src/daemon/main.c:710 +msgid "Daemon startup successful." +msgstr "Démarrage du démon réussi." + +#: ../src/daemon/main.c:780 +#, c-format +msgid "This is PulseAudio %s" +msgstr "Pulseaudio %s" + +#: ../src/daemon/main.c:781 +#, fuzzy, c-format +msgid "Compilation host: %s" +msgstr "CFLAGS de compilation : %s" + +#: ../src/daemon/main.c:782 +#, c-format +msgid "Compilation CFLAGS: %s" +msgstr "CFLAGS de compilation : %s" + +#: ../src/daemon/main.c:785 +#, fuzzy, c-format +msgid "Running on host: %s" +msgstr "Exécution en mode système : %s" + +#: ../src/daemon/main.c:788 +#, c-format +msgid "Page size is %lu bytes" +msgstr "La taille de la page est de %lu octets" + +#: ../src/daemon/main.c:791 +msgid "Compiled with Valgrind support: yes" +msgstr "Compilé avec la prise en charge Valgrind : oui" + +#: ../src/daemon/main.c:793 +msgid "Compiled with Valgrind support: no" +msgstr "Compilé avec la prise en charge Valgrind : non" + +#: ../src/daemon/main.c:796 +#, fuzzy, c-format +msgid "Running in valgrind mode: %s" +msgstr "Exécution en mode système : %s" + +#: ../src/daemon/main.c:799 +msgid "Optimized build: yes" +msgstr "Construction optimisée : oui" + +#: ../src/daemon/main.c:801 +msgid "Optimized build: no" +msgstr "Construction optimisée : non" + +#: ../src/daemon/main.c:805 +msgid "Failed to get machine ID" +msgstr "Échec lors de l'obtention de l'ID de la machine" + +#: ../src/daemon/main.c:808 +#, c-format +msgid "Machine ID is %s." +msgstr "L'ID de la machine est %s." + +#: ../src/daemon/main.c:813 +#, c-format +msgid "Using runtime directory %s." +msgstr "Utilisation du répertoire d'exécution %s." + +#: ../src/daemon/main.c:818 +#, c-format +msgid "Using state directory %s." +msgstr "Utilisation du répertoire d'état %s." + +#: ../src/daemon/main.c:821 +#, c-format +msgid "Running in system mode: %s" +msgstr "Exécution en mode système : %s" + +#: ../src/daemon/main.c:836 +msgid "pa_pid_file_create() failed." +msgstr "Échec de pa_pid_file_create()." + +#: ../src/daemon/main.c:848 +msgid "Fresh high-resolution timers available! Bon appetit!" +msgstr "" +"De nouvelles horloges à haute résolution sont disponibles ! Bon appétit !" + +#: ../src/daemon/main.c:850 +msgid "" +"Dude, your kernel stinks! The chef's recommendation today is Linux with high-" +"resolution timers enabled!" +msgstr "" +"Eh mec, ton noyau il pue ! La recommandation d'aujourd'hui du patron est " +"d'activer les horloges à haute résolution sur ton Linux." + +#: ../src/daemon/main.c:860 +msgid "pa_core_new() failed." +msgstr "Échec de pa_core_new()." + +#: ../src/daemon/main.c:921 +msgid "Failed to initialize daemon." +msgstr "Échec lors de l'initialisation du démon" + +#: ../src/daemon/main.c:926 +msgid "Daemon startup without any loaded modules, refusing to work." +msgstr "Démarrage du démon sans aucun module chargé : refus de fonctionner." + +#: ../src/daemon/main.c:931 +#, c-format +msgid "Default sink name (%s) does not exist in name register." +msgstr "" +"Le nom de la destination par défaut (%s) n'existe pas dans le registre des " +"noms." + +#: ../src/daemon/main.c:944 +msgid "Daemon startup complete." +msgstr "Démarrage du démon effectué." + +#: ../src/daemon/main.c:950 +msgid "Daemon shutdown initiated." +msgstr "Fermeture du démon initiée." + +#: ../src/daemon/main.c:971 +msgid "Daemon terminated." +msgstr "Démon terminé." + +#: ../src/daemon/cmdline.c:117 +#, c-format +msgid "" +"%s [options]\n" +"\n" +"COMMANDS:\n" +" -h, --help Show this help\n" +" --version Show version\n" +" --dump-conf Dump default configuration\n" +" --dump-modules Dump list of available modules\n" +" --dump-resample-methods Dump available resample methods\n" +" --cleanup-shm Cleanup stale shared memory " +"segments\n" +" --start Start the daemon if it is not " +"running\n" +" -k --kill Kill a running daemon\n" +" --check Check for a running daemon\n" +"\n" +"OPTIONS:\n" +" --system[=BOOL] Run as system-wide instance\n" +" -D, --daemonize[=BOOL] Daemonize after startup\n" +" --fail[=BOOL] Quit when startup fails\n" +" --high-priority[=BOOL] Try to set high nice level\n" +" (only available as root, when SUID " +"or\n" +" with elevated RLIMIT_NICE)\n" +" --realtime[=BOOL] Try to enable realtime scheduling\n" +" (only available as root, when SUID " +"or\n" +" with elevated RLIMIT_RTPRIO)\n" +" --disallow-module-loading[=BOOL] Disallow module user requested " +"module\n" +" loading/unloading after startup\n" +" --disallow-exit[=BOOL] Disallow user requested exit\n" +" --exit-idle-time=SECS Terminate the daemon when idle and " +"this\n" +" time passed\n" +" --module-idle-time=SECS Unload autoloaded modules when idle " +"and\n" +" this time passed\n" +" --scache-idle-time=SECS Unload autoloaded samples when idle " +"and\n" +" this time passed\n" +" --log-level[=LEVEL] Increase or set verbosity level\n" +" -v Increase the verbosity level\n" +" --log-target={auto,syslog,stderr} Specify the log target\n" +" -p, --dl-search-path=PATH Set the search path for dynamic " +"shared\n" +" objects (plugins)\n" +" --resample-method=METHOD Use the specified resampling method\n" +" (See --dump-resample-methods for\n" +" possible values)\n" +" --use-pid-file[=BOOL] Create a PID file\n" +" --no-cpu-limit[=BOOL] Do not install CPU load limiter on\n" +" platforms that support it.\n" +" --disable-shm[=BOOL] Disable shared memory support.\n" +"\n" +"STARTUP SCRIPT:\n" +" -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module " +"with\n" +" the specified argument\n" +" -F, --file=FILENAME Run the specified script\n" +" -C Open a command line on the running " +"TTY\n" +" after startup\n" +"\n" +" -n Don't load default script file\n" +msgstr "" +"%s [options]\n" +"\n" +"COMMANDES :\n" +" -h, --help Affiche cette aide\n" +" --version Affiche la version\n" +" --dump-conf Affiche la configuration par défaut\n" +" --dump-modules Affiche la liste des modules " +"disponibles\n" +" --dump-resample-methods Affiche la liste des méthodes " +"d'échantillonnage disponibles\n" +" --cleanup-shm Nettoie les segments de mémoire " +"partagée périmés\n" +" --start Démarre le démon s'il n'est pas " +"lancé\n" +" -k --kill Tue un démon en cours d'exécution\n" +" --check Vérifie s'il existe un démon en " +"cours d'exécution\n" +"\n" +"OPTIONS :\n" +" --system[=BOOL] Exécuter en tant qu'instance " +"système\n" +" -D, --daemonize[=BOOL] Définir en tant que démon après le " +"démarrage\n" +" --fail[=BOOL] Quitte quand le démarrage échoue\n" +" --high-priority[=BOOL] Tente de définir un niveau nice plus " +"élevé\n" +" (seulement disponible en tant que " +"root, avec le SUID ou\n" +" avec un RLIMIT_NICE élevé)\n" +" --realtime[=BOOL] Tente d'activer une planification en " +"temps réel\n" +" (seulement disponible en tant que " +"root, avec le SUID ou\n" +" ave un RLIMIT_RTPRIO élevé)\n" +" --disallow-module-loading[=BOOL] Empêche les chargements/" +"déchargements de module\n" +" demandés par l'utilisateur après le " +"démarrage\n" +" --disallow-exit[=BOOL] Empêche les fermetures demandées par " +"l'utilisateur\n" +" --exit-idle-time=SECS Termine le démon quand la durée " +"d'inactivité \n" +" et ce temps se sont écoulés\n" +" --module-idle-time=SECS Décharge les modules chargés " +"automatiquement \n" +" quand la durée d'inactivité et ce " +"temps se sont écoulés\n" +" --scache-idle-time=SECS Décharge les échantillons chargés " +"automatiquement \n" +" quand la durée d'inactivité et ce " +"temps se sont écoulés\n" +" --log-level[=NIVEAU] Augmente ou définit le niveau de " +"verbosité\n" +" -v Augmente le niveau de verbosité\n" +" --log-target={auto,syslog,stderr} Indique la cible du journal\n" +" -p, --dl-search-path=CHEMIN Définit le chemin de recherche pour " +"les objets dynamiques\n" +" partagés (extensions)\n" +" --resample-method=MÉTHODE Utilise la méthode de " +"rééchantillonnage indiquée\n" +" (Voir --dump-resample-methods pour\n" +" les valeurs possibles)\n" +" --use-pid-file[=BOOL] Crée un fichier PID\n" +" --no-cpu-limit[=BOOL] Ne pas installer de limiteur de " +"charge CPU\n" +" sur les plateformes qui le " +"supportent.\n" +" --disable-shm[=BOOL] Désactive la prise en charge de la " +"mémoire partagée.\n" +"\n" +"SCRIPT DE DÉMARRAGE :\n" +" -L, --load=\"PARAMÈTRES DU MODULE\" Charge le module d'extension indiqué " +"avec\n" +" le paramètre indiqué\n" +" -F, --file=NOMDEFICHIER Exécute le script indiqué\n" +" -C Ouvre une ligne de commande sur le " +"TTY en cours \n" +" après le démarrage\n" +"\n" +" -n Ne pas charger les fichiers de " +"scripts par défaut\n" + +#: ../src/daemon/cmdline.c:245 +msgid "--daemonize expects boolean argument" +msgstr "--daemonize requiert un paramètre booléen" + +#: ../src/daemon/cmdline.c:252 +msgid "--fail expects boolean argument" +msgstr "--fail requiert un paramètre booléen" + +#: ../src/daemon/cmdline.c:262 +msgid "" +"--log-level expects log level argument (either numeric in range 0..4 or one " +"of debug, info, notice, warn, error)." +msgstr "" +"--log-level requiert un paramètre de niveau de journal (soit numérique entre " +"0 et 4, soit de débogage : info, notice, warn , error)." + +#: ../src/daemon/cmdline.c:274 +msgid "--high-priority expects boolean argument" +msgstr "--high-priority requiert un paramètre booléen" + +#: ../src/daemon/cmdline.c:281 +msgid "--realtime expects boolean argument" +msgstr "--realtime requiert un paramètre booléen" + +#: ../src/daemon/cmdline.c:288 +msgid "--disallow-module-loading expects boolean argument" +msgstr "--disallow-module-loading requiert un paramètre booléen" + +#: ../src/daemon/cmdline.c:295 +msgid "--disallow-exit boolean argument" +msgstr "--disallow-exit requiert un paramètre booléen" + +#: ../src/daemon/cmdline.c:302 +msgid "--use-pid-file expects boolean argument" +msgstr "--use-pid-file requiert un paramètre booléen" + +#: ../src/daemon/cmdline.c:319 +msgid "Invalid log target: use either 'syslog', 'stderr' or 'auto'." +msgstr "Cible du journal invalide : utilisez « syslog », « stderr » ou « auto »." + +#: ../src/daemon/cmdline.c:338 +#, c-format +msgid "Invalid resample method '%s'." +msgstr "Méthode de rééchantillonnage invalide « %s »." + +#: ../src/daemon/cmdline.c:345 +msgid "--system expects boolean argument" +msgstr "--system requiert un paramètre booléen" + +#: ../src/daemon/cmdline.c:352 +msgid "--no-cpu-limit expects boolean argument" +msgstr "--no-cpu-limit requiert un paramètre booléen" + +#: ../src/daemon/cmdline.c:359 +msgid "--disable-shm expects boolean argument" +msgstr "--disable-shm requiert un paramètre booléen" + +#: ../src/daemon/dumpmodules.c:60 +#, c-format +msgid "Name: %s\n" +msgstr "Nom : %s\n" + +#: ../src/daemon/dumpmodules.c:63 +#, c-format +msgid "No module information available\n" +msgstr "Aucune information de module disponible\n" + +#: ../src/daemon/dumpmodules.c:66 +#, c-format +msgid "Version: %s\n" +msgstr "Version : %s\n" + +#: ../src/daemon/dumpmodules.c:68 +#, c-format +msgid "Description: %s\n" +msgstr "Description : %s\n" + +#: ../src/daemon/dumpmodules.c:70 +#, c-format +msgid "Author: %s\n" +msgstr "Auteur : %s\n" + +#: ../src/daemon/dumpmodules.c:72 +#, c-format +msgid "Usage: %s\n" +msgstr "Utilisation : %s\n" + +#: ../src/daemon/dumpmodules.c:73 +#, c-format +msgid "Load Once: %s\n" +msgstr "Chargement unique : %s\n" + +#: ../src/daemon/dumpmodules.c:77 +#, c-format +msgid "Path: %s\n" +msgstr "Chemin : %s\n" + +# dans les lignes suivantes [%s = nom de fichier: %u = ligne dans celui-ci] +#: ../src/daemon/daemon-conf.c:205 +#, c-format +msgid "[%s:%u] Invalid log target '%s'." +msgstr "[%s:%u] Cible du journal « %s » invalide." + +#: ../src/daemon/daemon-conf.c:221 +#, c-format +msgid "[%s:%u] Invalid log level '%s'." +msgstr "[%s:%u] Niveau du journal « %s » invalide." + +#: ../src/daemon/daemon-conf.c:237 +#, c-format +msgid "[%s:%u] Invalid resample method '%s'." +msgstr "[%s:%u] Méthode de rééchantillonnage « %s » invalide." + +#: ../src/daemon/daemon-conf.c:260 +#, c-format +msgid "[%s:%u] Invalid rlimit '%s'." +msgstr "[%s:%u] rlimit « %s » invalide." + +#: ../src/daemon/daemon-conf.c:267 +#, c-format +msgid "[%s:%u] rlimit not supported on this platform." +msgstr "[%s:%u] rlimit n'est pas pris en charge sur cette plateforme." + +#: ../src/daemon/daemon-conf.c:283 +#, c-format +msgid "[%s:%u] Invalid sample format '%s'." +msgstr "[%s:%u] Format d'échantillon « %s » invalide." + +#: ../src/daemon/daemon-conf.c:301 +#, c-format +msgid "[%s:%u] Invalid sample rate '%s'." +msgstr "[%s:%u] Taux d'échantillonnage « %s » invalide." + +#: ../src/daemon/daemon-conf.c:319 +#, c-format +msgid "[%s:%u] Invalid sample channels '%s'." +msgstr "[%s:%u] Canaux d'échantillonnage « %s » invalide." + +#: ../src/daemon/daemon-conf.c:337 +#, c-format +msgid "[%s:%u] Invalid number of fragments '%s'." +msgstr "[%s:%u] Nombre de fragments « %s » invalide." + +#: ../src/daemon/daemon-conf.c:355 +#, c-format +msgid "[%s:%u] Invalid fragment size '%s'." +msgstr "[%s:%u] Taille du fragment « %s » invalide." + +#: ../src/daemon/daemon-conf.c:373 +#, c-format +msgid "[%s:%u] Invalid nice level '%s'." +msgstr "[%s:%u] Niveau de priorité (nice) « %s » invalide." + +#: ../src/daemon/daemon-conf.c:570 +#, c-format +msgid "Failed to open configuration file: %s" +msgstr "Échec lors de l'ouverture du fichier de configuration : %s" + +#: ../src/daemon/daemon-conf.c:644 +#, c-format +msgid "### Read from configuration file: %s ###\n" +msgstr "### Lecture à partir du fichier de configuration : %s ###\n" + +#: ../src/daemon/caps.c:63 +msgid "Dropping root priviliges." +msgstr "Abandon des permissions root." + +#: ../src/daemon/caps.c:103 +msgid "Limited capabilities successfully to CAP_SYS_NICE." +msgstr "Limitation des capacités à CAP_SYS_NICE réussie." + +#: ../src/pulse/channelmap.c:102 +msgid "Mono" +msgstr "Mono" + +#: ../src/pulse/channelmap.c:104 +msgid "Front Center" +msgstr "Avant centre" + +#: ../src/pulse/channelmap.c:105 +msgid "Front Left" +msgstr "Avant gauche" + +#: ../src/pulse/channelmap.c:106 +msgid "Front Right" +msgstr "Avant droit" + +#: ../src/pulse/channelmap.c:108 +msgid "Rear Center" +msgstr "Arrière centre" + +#: ../src/pulse/channelmap.c:109 +msgid "Rear Left" +msgstr "Arrière gauche" + +#: ../src/pulse/channelmap.c:110 +msgid "Rear Right" +msgstr "Arrière droit" + +#: ../src/pulse/channelmap.c:112 +msgid "Low Frequency Emmiter" +msgstr "Émetteur à basse fréquence" + +#: ../src/pulse/channelmap.c:114 +msgid "Front Left-of-center" +msgstr "Avant à gauche du centre" + +#: ../src/pulse/channelmap.c:115 +msgid "Front Right-of-center" +msgstr "Avant à droite du centre" + +#: ../src/pulse/channelmap.c:117 +msgid "Side Left" +msgstr "Côté gauche" + +#: ../src/pulse/channelmap.c:118 +msgid "Side Right" +msgstr "Côté droit" + +#: ../src/pulse/channelmap.c:120 +msgid "Auxiliary 0" +msgstr "Auxiliaire 0" + +#: ../src/pulse/channelmap.c:121 +msgid "Auxiliary 1" +msgstr "Auxiliaire 1" + +#: ../src/pulse/channelmap.c:122 +msgid "Auxiliary 2" +msgstr "Auxiliaire 2" + +#: ../src/pulse/channelmap.c:123 +msgid "Auxiliary 3" +msgstr "Auxiliaire 3" + +#: ../src/pulse/channelmap.c:124 +msgid "Auxiliary 4" +msgstr "Auxiliaire 4" + +#: ../src/pulse/channelmap.c:125 +msgid "Auxiliary 5" +msgstr "Auxiliaire 5" + +#: ../src/pulse/channelmap.c:126 +msgid "Auxiliary 6" +msgstr "Auxiliaire 6" + +#: ../src/pulse/channelmap.c:127 +msgid "Auxiliary 7" +msgstr "Auxiliaire 7" + +#: ../src/pulse/channelmap.c:128 +msgid "Auxiliary 8" +msgstr "Auxiliaire 8" + +#: ../src/pulse/channelmap.c:129 +msgid "Auxiliary 9" +msgstr "Auxiliaire 9" + +#: ../src/pulse/channelmap.c:130 +msgid "Auxiliary 10" +msgstr "Auxiliaire 10" + +#: ../src/pulse/channelmap.c:131 +msgid "Auxiliary 11" +msgstr "Auxiliaire 11" + +#: ../src/pulse/channelmap.c:132 +msgid "Auxiliary 12" +msgstr "Auxiliaire 12" + +#: ../src/pulse/channelmap.c:133 +msgid "Auxiliary 13" +msgstr "Auxiliaire 13" + +#: ../src/pulse/channelmap.c:134 +msgid "Auxiliary 14" +msgstr "Auxiliaire 14" + +#: ../src/pulse/channelmap.c:135 +msgid "Auxiliary 15" +msgstr "Auxiliaire 15" + +#: ../src/pulse/channelmap.c:136 +msgid "Auxiliary 16" +msgstr "Auxiliaire 16" + +#: ../src/pulse/channelmap.c:137 +msgid "Auxiliary 17" +msgstr "Auxiliaire 17" + +#: ../src/pulse/channelmap.c:138 +msgid "Auxiliary 18" +msgstr "Auxiliaire 18" + +#: ../src/pulse/channelmap.c:139 +msgid "Auxiliary 19" +msgstr "Auxiliaire 19" + +#: ../src/pulse/channelmap.c:140 +msgid "Auxiliary 20" +msgstr "Auxiliaire 20" + +#: ../src/pulse/channelmap.c:141 +msgid "Auxiliary 21" +msgstr "Auxiliaire 21" + +#: ../src/pulse/channelmap.c:142 +msgid "Auxiliary 22" +msgstr "Auxiliaire 22" + +#: ../src/pulse/channelmap.c:143 +msgid "Auxiliary 23" +msgstr "Auxiliaire 23" + +#: ../src/pulse/channelmap.c:144 +msgid "Auxiliary 24" +msgstr "Auxiliaire 24" + +#: ../src/pulse/channelmap.c:145 +msgid "Auxiliary 25" +msgstr "Auxiliaire 25" + +#: ../src/pulse/channelmap.c:146 +msgid "Auxiliary 26" +msgstr "Auxiliaire 26" + +#: ../src/pulse/channelmap.c:147 +msgid "Auxiliary 27" +msgstr "Auxiliaire 27" + +#: ../src/pulse/channelmap.c:148 +msgid "Auxiliary 28" +msgstr "Auxiliaire 28" + +#: ../src/pulse/channelmap.c:149 +msgid "Auxiliary 29" +msgstr "Auxiliaire 29" + +#: ../src/pulse/channelmap.c:150 +msgid "Auxiliary 30" +msgstr "Auxiliaire 30" + +#: ../src/pulse/channelmap.c:151 +msgid "Auxiliary 31" +msgstr "Auxiliaire 31" + +#: ../src/pulse/channelmap.c:153 +msgid "Top Center" +msgstr "Centre haut" + +#: ../src/pulse/channelmap.c:155 +msgid "Top Front Center" +msgstr "Avant centre haut" + +#: ../src/pulse/channelmap.c:156 +msgid "Top Front Left" +msgstr "Avant gauche haut" + +#: ../src/pulse/channelmap.c:157 +msgid "Top Front Right" +msgstr "Avant droit haut" + +#: ../src/pulse/channelmap.c:159 +msgid "Top Rear Center" +msgstr "Arrière centre haut" + +#: ../src/pulse/channelmap.c:160 +msgid "Top Rear Left" +msgstr "Arrière gauche haut" + +#: ../src/pulse/channelmap.c:161 +msgid "Top Rear Right" +msgstr "Arrière droit haut" + +#: ../src/pulse/channelmap.c:472 ../src/pulse/sample.c:144 +#: ../src/pulse/volume.c:163 ../src/pulse/volume.c:194 +#, fuzzy +msgid "(invalid)" +msgstr "Invalide" + +#: ../src/pulse/error.c:43 +msgid "OK" +msgstr "OK" + +#: ../src/pulse/error.c:44 +msgid "Access denied" +msgstr "Accès refusé" + +#: ../src/pulse/error.c:45 +msgid "Unknown command" +msgstr "Commande inconnue" + +#: ../src/pulse/error.c:46 +msgid "Invalid argument" +msgstr "Paramètre invalide" + +#: ../src/pulse/error.c:47 +msgid "Entity exists" +msgstr "L'entité existe" + +#: ../src/pulse/error.c:48 +msgid "No such entity" +msgstr "Aucune entité de ce type" + +#: ../src/pulse/error.c:49 +msgid "Connection refused" +msgstr "Connexion refusée" + +#: ../src/pulse/error.c:50 +msgid "Protocol error" +msgstr "Erreur du protocole" + +#: ../src/pulse/error.c:51 +msgid "Timeout" +msgstr "Délai dépassé" + +#: ../src/pulse/error.c:52 +msgid "No authorization key" +msgstr "Aucune clé d'autorisation" + +#: ../src/pulse/error.c:53 +msgid "Internal error" +msgstr "Erreur interne" + +#: ../src/pulse/error.c:54 +msgid "Connection terminated" +msgstr "Connexion terminée" + +#: ../src/pulse/error.c:55 +msgid "Entity killed" +msgstr "L'entité a été tuée" + +#: ../src/pulse/error.c:56 +msgid "Invalid server" +msgstr "Serveur invalide" + +#: ../src/pulse/error.c:57 +msgid "Module initalization failed" +msgstr "Échec lors de l'initialisation du module" + +#: ../src/pulse/error.c:58 +msgid "Bad state" +msgstr "État incorrect" + +#: ../src/pulse/error.c:59 +msgid "No data" +msgstr "Aucune donnée" + +#: ../src/pulse/error.c:60 +msgid "Incompatible protocol version" +msgstr "Version du protocole invalide" + +#: ../src/pulse/error.c:61 +msgid "Too large" +msgstr "Trop grand" + +#: ../src/pulse/error.c:62 +msgid "Not supported" +msgstr "Non pris en charge" + +#: ../src/pulse/error.c:63 +msgid "Unknown error code" +msgstr "Code d'erreur inconnu" + +#: ../src/pulse/error.c:64 +msgid "No such extension" +msgstr "Aucune extension de ce type" + +#: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100 +msgid "XOpenDisplay() failed" +msgstr "Échec de XOpenDisplay()" + +#: ../src/pulse/client-conf-x11.c:78 +msgid "Failed to parse cookie data" +msgstr "Échec lors de l'analyse des données du cookie" + +#: ../src/pulse/client-conf.c:120 +#, c-format +msgid "Failed to open configuration file '%s': %s" +msgstr "Échec lors de l'ouverture du fichier de configuration « %s » :%s" + +#: ../src/pulse/context.c:516 +msgid "No cookie loaded. Attempting to connect without." +msgstr "Aucun cookie chargé. Tentative de connexion sans celui-ci." + +#: ../src/pulse/context.c:642 +#, c-format +msgid "fork(): %s" +msgstr "fork() : %s" + +#: ../src/pulse/context.c:695 +#, c-format +msgid "waitpid(): %s" +msgstr "waitpid() : %s" + +#: ../src/pulse/context.c:1256 +#, c-format +msgid "Received message for unknown extension '%s'" +msgstr "Message reçu pour une extension inconnue « %s »" + +#: ../src/utils/pacat.c:93 +#, c-format +msgid "pa_stream_write() failed: %s\n" +msgstr "Échec de pa_stream_write() : %s\n" + +#: ../src/utils/pacat.c:132 +#, c-format +msgid "pa_stream_peek() failed: %s\n" +msgstr "Échec de pa_stream_peek() : %s\n" + +#: ../src/utils/pacat.c:141 +#, c-format +msgid "Buffer overrun, dropping incoming data\n" +msgstr "Saturation du tampon, abandon des données entrantes\n" + +#: ../src/utils/pacat.c:143 +#, c-format +msgid "pa_stream_drop() failed: %s\n" +msgstr "Échec de pa_stream_drop() : %s\n" + +#: ../src/utils/pacat.c:169 +#, c-format +msgid "Stream successfully created.\n" +msgstr "Création du flux réussie.\n" + +#: ../src/utils/pacat.c:172 +#, c-format +msgid "pa_stream_get_buffer_attr() failed: %s\n" +msgstr "Échec de pa_stream_get_buffer_attr() : %s\n" + +#: ../src/utils/pacat.c:176 +#, c-format +msgid "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n" +msgstr "Mesures du tampon : maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n" + +#: ../src/utils/pacat.c:179 +#, c-format +msgid "Buffer metrics: maxlength=%u, fragsize=%u\n" +msgstr "Mesures du tampon : maxlength=%u, fragsize=%u\n" + +#: ../src/utils/pacat.c:183 +#, c-format +msgid "Using sample spec '%s', channel map '%s'.\n" +msgstr "" +"Utilisation de la spécification d'échantillon « %s », plan des canaux « %s ».\n" + +# l'espace manquant entre %s et suspended est voulu +#: ../src/utils/pacat.c:187 +#, c-format +msgid "Connected to device %s (%u, %ssuspended).\n" +msgstr "Connecté au périphérique %s (%u, %ssuspendu).\n" + +#: ../src/utils/pacat.c:197 +#, c-format +msgid "Stream error: %s\n" +msgstr "Erreur du flux : %s\n" + +#: ../src/utils/pacat.c:207 +#, c-format +msgid "Stream device suspended.%s \n" +msgstr "Périphérique de flux suspendu %s \n" + +#: ../src/utils/pacat.c:209 +#, c-format +msgid "Stream device resumed.%s \n" +msgstr "Périphérique de flux repris %s \n" + +#: ../src/utils/pacat.c:217 +#, c-format +msgid "Stream underrun.%s \n" +msgstr "Flux vide %s \n" + +#: ../src/utils/pacat.c:224 +#, c-format +msgid "Stream overrun.%s \n" +msgstr "Flux saturé %s \n" + +#: ../src/utils/pacat.c:231 +#, c-format +msgid "Stream started.%s \n" +msgstr "Flux démarré %s \n" + +#: ../src/utils/pacat.c:238 +#, c-format +msgid "Stream moved to device %s (%u, %ssuspended).%s \n" +msgstr "Flux déplacé vers le périphérique %s (%u, %ssuspendu).%s \n" + +# suspendu ou non suspendu +#: ../src/utils/pacat.c:238 +msgid "not " +msgstr "non " + +#: ../src/utils/pacat.c:259 +#, c-format +msgid "Connection established.%s \n" +msgstr "Connection établie.%s \n" + +#: ../src/utils/pacat.c:262 +#, c-format +msgid "pa_stream_new() failed: %s\n" +msgstr "Échec de pa_stream_new() : %s\n" + +#: ../src/utils/pacat.c:287 +#, c-format +msgid "pa_stream_connect_playback() failed: %s\n" +msgstr "Échec de pa_stream_connect_playback() : %s\n" + +#: ../src/utils/pacat.c:293 +#, c-format +msgid "pa_stream_connect_record() failed: %s\n" +msgstr "Échec de pa_stream_connect_record() : %s\n" + +#: ../src/utils/pacat.c:307 ../src/utils/pasuspender.c:159 +#: ../src/utils/pactl.c:666 ../src/utils/paplay.c:183 +#, c-format +msgid "Connection failure: %s\n" +msgstr "Échec lors de la connexion : %s\n" + +#: ../src/utils/pacat.c:328 ../src/utils/paplay.c:75 +#, c-format +msgid "Failed to drain stream: %s\n" +msgstr "Échec lors du vidage du flux : %s\n" + +#: ../src/utils/pacat.c:333 ../src/utils/paplay.c:80 +#, c-format +msgid "Playback stream drained.\n" +msgstr "Flux de lecture vidé.\n" + +#: ../src/utils/pacat.c:343 ../src/utils/paplay.c:92 +#, c-format +msgid "Draining connection to server.\n" +msgstr "Vidage de la connexion au serveur.\n" + +#: ../src/utils/pacat.c:369 +#, c-format +msgid "Got EOF.\n" +msgstr "EOF obtenu.\n" + +#: ../src/utils/pacat.c:375 +#, c-format +msgid "pa_stream_drain(): %s\n" +msgstr "pa_stream_drain() : %s\n" + +#: ../src/utils/pacat.c:385 +#, c-format +msgid "read() failed: %s\n" +msgstr "Échec de read() : %s\n" + +#: ../src/utils/pacat.c:417 +#, c-format +msgid "write() failed: %s\n" +msgstr "Échec de write() : %s\n" + +#: ../src/utils/pacat.c:438 +#, c-format +msgid "Got signal, exiting.\n" +msgstr "Signal obtenu, fermeture.\n" + +#: ../src/utils/pacat.c:452 +#, c-format +msgid "Failed to get latency: %s\n" +msgstr "Échec lors de l'obtention de la latence : %s\n" + +#: ../src/utils/pacat.c:457 +#, c-format +msgid "Time: %0.3f sec; Latency: %0.0f usec. \r" +msgstr "Durée : %0.3f s ; Latency : %0.0f µs. \r" + +#: ../src/utils/pacat.c:477 +#, c-format +msgid "pa_stream_update_timing_info() failed: %s\n" +msgstr "Échec de pa_stream_update_timing_info() : %s\n" + +# downmix = par ex. convertir 5 canaux en 2 canaux +# upmixer = par ex. convertir 2 canaux en 5 canaux +# https://bugzilla.redhat.com/show_bug.cgi?id=460798 +#: ../src/utils/pacat.c:490 +#, fuzzy, c-format +msgid "" +"%s [options]\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -r, --record Create a connection for recording\n" +" -p, --playback Create a connection for playback\n" +"\n" +" -v, --verbose Enable verbose operations\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -d, --device=DEVICE The name of the sink/source to " +"connect to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" +" --rate=SAMPLERATE The sample rate in Hz (defaults to " +"44100)\n" +" --format=SAMPLEFORMAT The sample type, one of s16le, " +"s16be, u8, float32le,\n" +" float32be, ulaw, alaw, s32le, s32be " +"(defaults to s16ne)\n" +" --channels=CHANNELS The number of channels, 1 for mono, " +"2 for stereo\n" +" (defaults to 2)\n" +" --channel-map=CHANNELMAP Channel map to use instead of the " +"default\n" +" --fix-format Take the sample format from the sink " +"the stream is\n" +" being connected to.\n" +" --fix-rate Take the sampling rate from the sink " +"the stream is\n" +" being connected to.\n" +" --fix-channels Take the number of channels and the " +"channel map\n" +" from the sink the stream is being " +"connected to.\n" +" --no-remix Don't upmix or downmix channels.\n" +" --no-remap Map channels by index instead of " +"name.\n" +" --latency=BYTES Request the specified latency in " +"bytes.\n" +" --process-time=BYTES Request the specified process time " +"per request in bytes.\n" +msgstr "" +"%s [options]\n" +"\n" +" -h, --help Affiche cette aide\n" +" --version Affiche la version\n" +"\n" +" -r, --record Crée une connexion pour " +"l'enregistrement\n" +" -p, --playback Crée une connexion pour la lecture\n" +"\n" +" -v, --verbose Active le mode verbeux\n" +"\n" +" -s, --server=SERVEUR Le nom du serveur auquel se " +"connecter\n" +" -d, --device=PÉRIPHÉRIQUE Le nom de la destination/source à " +"laquelle de connecter\n" +" -n, --client-name=NOM Définit le nom de ce client sur le " +"serveur\n" +" --stream-name=NOM Définit le nom de ce flux sur le " +"serveur\n" +" --volume=VOLUME Indique le volume initial (linéaire) " +"entre 0 et 65536\n" +" --rate=TAUXDÉCHANTILLONNAGE Le taux d'échantillonnage en Hz (par " +"défaut 44100)\n" +" --format=FORMATDELÉCHANTILLON Le type de l'échantillon, parmi : " +"s16le, s16be, u8, float32le,\n" +" float32be, ulaw, alaw (par défaut " +"s16ne)\n" +" --channels=CANAUX Le nombre de canaux, 1 pour mono, 2 " +"pour stéréo\n" +" (par défaut 2)\n" +" --channel-map=PLANDESCANAUX Plan des canaux à utiliser au lieu " +"de celui par défaut\n" +" --fix-format Prend le format de l'échantillon de " +"la destination où le flux\n" +" est en train de se connecter.\n" +" --fix-rate Prend le taux d'échantillonnage de " +"la destination où le flux\n" +" est en train de se connecter.\n" +" --fix-channels Prend le nombre et le plan des " +"canaux de la destination \n" +" où le flux est en train de se " +"connecter.\n" +" --no-remix Ne pas augmenter ou diminuer le " +"nombre de canaux par mixage.\n" +" --no-remap Créer le plan des canaux par index " +"et non par nom.\n" +" --latency=OCTETS Demande la latence indiquée en " +"octets.\n" +" --process-time=OCTETS Demande le temps de traitement " +"indiqué par requête en octets.\n" + +#: ../src/utils/pacat.c:591 +#, c-format +msgid "" +"pacat %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"pacat %s\n" +"Compilé avec libpulse %s\n" +"Lié avec libpulse %s\n" + +#: ../src/utils/pacat.c:647 +#, c-format +msgid "Invalid channel map '%s'\n" +msgstr "Plan des canaux invalide « %s »\n" + +#: ../src/utils/pacat.c:676 +#, c-format +msgid "Invalid latency specification '%s'\n" +msgstr "Spécification de latence invalide « %s »\n" + +#: ../src/utils/pacat.c:683 +#, c-format +msgid "Invalid process time specification '%s'\n" +msgstr "Spécification de temps de traitement invalide « %s »\n" + +#: ../src/utils/pacat.c:694 +#, c-format +msgid "Invalid sample specification\n" +msgstr "Spécification d'échantillon invalide\n" + +#: ../src/utils/pacat.c:699 +#, c-format +msgid "Channel map doesn't match sample specification\n" +msgstr "" +"Le plan des canaux ne correspond pas à la spécification d'échantillon\n" + +#: ../src/utils/pacat.c:706 +#, c-format +msgid "Opening a %s stream with sample specification '%s'.\n" +msgstr "Ouverture d'un flux %s avec une spécification d'échantillon « %s ».\n" + +#: ../src/utils/pacat.c:706 +msgid "recording" +msgstr "enregistrement" + +#: ../src/utils/pacat.c:706 +msgid "playback" +msgstr "lecture" + +#: ../src/utils/pacat.c:714 +#, c-format +msgid "open(): %s\n" +msgstr "open() : %s\n" + +#: ../src/utils/pacat.c:719 +#, c-format +msgid "dup2(): %s\n" +msgstr "dup2() : %s\n" + +#: ../src/utils/pacat.c:729 +#, c-format +msgid "Too many arguments.\n" +msgstr "Trop de paramètres.\n" + +#: ../src/utils/pacat.c:742 ../src/utils/pasuspender.c:280 +#: ../src/utils/pactl.c:909 ../src/utils/paplay.c:381 +#, c-format +msgid "pa_mainloop_new() failed.\n" +msgstr "Échec de pa_mainloop_new().\n" + +#: ../src/utils/pacat.c:763 +#, c-format +msgid "io_new() failed.\n" +msgstr "Échec de io_new().\n" + +#: ../src/utils/pacat.c:769 ../src/utils/pasuspender.c:293 +#: ../src/utils/pactl.c:923 ../src/utils/paplay.c:396 +#, c-format +msgid "pa_context_new() failed.\n" +msgstr "Échec de pa_context_new().\n" + +#: ../src/utils/pacat.c:777 +#, fuzzy, c-format +msgid "pa_context_connect() failed: %s" +msgstr "Échec de pa_context_new().\n" + +#: ../src/utils/pacat.c:788 +#, c-format +msgid "time_new() failed.\n" +msgstr "Échec de time_new().\n" + +#: ../src/utils/pacat.c:795 ../src/utils/pasuspender.c:301 +#: ../src/utils/pactl.c:931 ../src/utils/paplay.c:407 +#, c-format +msgid "pa_mainloop_run() failed.\n" +msgstr "Échec de pa_mainloop_run().\n" + +#: ../src/utils/pasuspender.c:81 +#, c-format +msgid "fork(): %s\n" +msgstr "fork() : %s\n" + +#: ../src/utils/pasuspender.c:92 +#, c-format +msgid "execvp(): %s\n" +msgstr "execvp() : %s\n" + +#: ../src/utils/pasuspender.c:109 +#, c-format +msgid "Failure to suspend: %s\n" +msgstr "Échec lors de la suspension : %s\n" + +#: ../src/utils/pasuspender.c:124 +#, c-format +msgid "Failure to resume: %s\n" +msgstr "Échec lors de la reprise : %s\n" + +#: ../src/utils/pasuspender.c:147 +#, c-format +msgid "WARNING: Sound server is not local, not suspending.\n" +msgstr "" +"AVERTISSEMENT : le serveur de son n'est pas local, suspension annulée.\n" + +#: ../src/utils/pasuspender.c:176 ../src/utils/pactl.c:672 +#: ../src/utils/paplay.c:191 +#, c-format +msgid "Got SIGINT, exiting.\n" +msgstr "SIGINT reçu, fermeture.\n" + +#: ../src/utils/pasuspender.c:194 +#, c-format +msgid "WARNING: Child process terminated by signal %u\n" +msgstr "AVERTISSEMENT : le processus fils a été terminé par le signal %u\n" + +#: ../src/utils/pasuspender.c:212 +#, c-format +msgid "" +"%s [options] ... \n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +"\n" +msgstr "" +"%s [options] ... \n" +"\n" +" -h, --help Affiche cette aide\n" +" --version Affiche la version\n" +" -s, --server=SERVEUR Le nom du serveur auquel se " +"connecter\n" +"\n" + +#: ../src/utils/pasuspender.c:251 +#, c-format +msgid "" +"pasuspender %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"pasuspender %s\n" +"Compilé avec libpulse %s\n" +"Lié avec libpulse %s\n" + +#: ../src/utils/pactl.c:107 +#, c-format +msgid "Failed to get statistics: %s\n" +msgstr "Échec lors de l'obtention des statistiques : %s\n" + +#: ../src/utils/pactl.c:113 +#, c-format +msgid "Currently in use: %u blocks containing %s bytes total.\n" +msgstr "En cours d'utilisation : %u blocs contenant au total %s octets.\n" + +#: ../src/utils/pactl.c:116 +#, c-format +msgid "Allocated during whole lifetime: %u blocks containing %s bytes total.\n" +msgstr "" +"Alloué pendant l'ensemble de la durée d'exécution : %u blocs contenant au " +"total %s octets.\n" + +#: ../src/utils/pactl.c:119 +#, c-format +msgid "Sample cache size: %s\n" +msgstr "Taille du cache de l'échantillon : %s\n" + +#: ../src/utils/pactl.c:128 +#, c-format +msgid "Failed to get server information: %s\n" +msgstr "Échec lors de l'obtention des informations du serveur : %s\n" + +#: ../src/utils/pactl.c:135 +#, c-format +msgid "" +"User name: %s\n" +"Host Name: %s\n" +"Server Name: %s\n" +"Server Version: %s\n" +"Default Sample Specification: %s\n" +"Default Sink: %s\n" +"Default Source: %s\n" +"Cookie: %08x\n" +msgstr "" +"Nom d'utilisateur : %s\n" +"Nom d'hôte : %s\n" +"Nom du serveur : %s\n" +"Version du serveur : %s\n" +"Spécification d'échantillon par défaut : %s\n" +"Destination par défaut : %s\n" +"Source par défaut : %s\n" +"Cookie : %08x\n" + +#: ../src/utils/pactl.c:160 +#, c-format +msgid "Failed to get sink information: %s\n" +msgstr "Échec lors de l'obtention des informations sur la destination : %s\n" + +# demander à Lennart s'il s'agit de monitor of source +#: ../src/utils/pactl.c:176 +#, c-format +msgid "" +"*** Sink #%u ***\n" +"Name: %s\n" +"Driver: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Owner Module: %u\n" +"Volume: %s\n" +"Monitor Source: %s\n" +"Latency: %0.0f usec, configured %0.0f usec\n" +"Flags: %s%s%s%s%s%s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Destination #%u ***\n" +"Nom : %s\n" +"Pilote : %s\n" +"Spécification de l'échantillon : %s\n" +"Plan des canaux : %s\n" +"Module propriétaire : %u\n" +"Volume : %s\n" +"Moniteur de la source : %s\n" +"Latence : %0.0f µs, %0.0f µs configurée \n" +"Drapeaux : %s%s%s%s%s%s\n" +"Propriétés :\n" +"%s" + +#: ../src/utils/pactl.c:193 ../src/utils/pactl.c:371 +msgid "muted" +msgstr "en sourdine" + +#: ../src/utils/pactl.c:212 +#, c-format +msgid "Failed to get source information: %s\n" +msgstr "Échec lors de l'obtention des informations sur la source : %s\n" + +#: ../src/utils/pactl.c:228 +#, c-format +msgid "" +"*** Source #%u ***\n" +"Name: %s\n" +"Driver: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Owner Module: %u\n" +"Volume: %s\n" +"Monitor of Sink: %s\n" +"Latency: %0.0f usec, configured %0.0f usec\n" +"Flags: %s%s%s%s%s%s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Source #%u ***\n" +"Nom : %s\n" +"Pilote : %s\n" +"Spécification de l'échantillon : %s\n" +"Plan des canaux : %s\n" +"Module propriétaire : %u\n" +"Volume : %s\n" +"Moniteur de la destination : %s\n" +"Latence : %0.0f µs, %0.0f µs configurée \n" +"Drapeaux : %s%s%s%s%s%s\n" +"Propriétés :\n" +"%s" + +#: ../src/utils/pactl.c:246 ../src/utils/pactl.c:289 ../src/utils/pactl.c:322 +#: ../src/utils/pactl.c:366 ../src/utils/pactl.c:367 ../src/utils/pactl.c:374 +#: ../src/utils/pactl.c:418 ../src/utils/pactl.c:419 ../src/utils/pactl.c:425 +#: ../src/utils/pactl.c:468 ../src/utils/pactl.c:469 ../src/utils/pactl.c:473 +msgid "n/a" +msgstr "n/d" + +#: ../src/utils/pactl.c:263 +#, c-format +msgid "Failed to get module information: %s\n" +msgstr "Échec lors de l'obtention des informations du module : %s\n" + +#: ../src/utils/pactl.c:281 +#, c-format +msgid "" +"*** Module #%u ***\n" +"Name: %s\n" +"Argument: %s\n" +"Usage counter: %s\n" +"Auto unload: %s\n" +msgstr "" +"*** Module #%u ***\n" +"Nom : %s\n" +"Paramètre : %s\n" +"Nombre d'utilisations : %s\n" +"Déchargement automatique : %s\n" + +#: ../src/utils/pactl.c:298 +#, c-format +msgid "Failed to get client information: %s\n" +msgstr "Échec lors de l'obtention des informations du client : %s\n" + +#: ../src/utils/pactl.c:316 +#, c-format +msgid "" +"*** Client #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Client #%u ***\n" +"Pilote : %s\n" +"Module propriétaire : %s\n" +"Propriétés :\n" +"%s" + +#: ../src/utils/pactl.c:333 +#, c-format +msgid "Failed to get sink input information: %s\n" +msgstr "" +"Échec lors de l'obtention des informations de l'entrée de la destination : %" +"s\n" + +#: ../src/utils/pactl.c:352 +#, c-format +msgid "" +"*** Sink Input #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Client: %s\n" +"Sink: %u\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Volume: %s\n" +"Buffer Latency: %0.0f usec\n" +"Sink Latency: %0.0f usec\n" +"Resample method: %s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Entrée de la destination #%u ***\n" +"Pilote : %s\n" +"Module propriétaire : %s\n" +"Client : %s\n" +"Destination : %u\n" +"Spécification de l'échantillon : %s\n" +"Plan des canaux : %s\n" +"Volume : %s\n" +"Latence du tampon : %0.0f µs\n" +"Latence de la destination : %0.0f µs\n" +"Méthode de rééchantillonnage : %s\n" +"Propriétés :\n" +"%s" + +#: ../src/utils/pactl.c:385 +#, c-format +msgid "Failed to get source output information: %s\n" +msgstr "" +"Échec lors de l'obtention des informations de la sortie de la source : %s\n" + +#: ../src/utils/pactl.c:405 +#, c-format +msgid "" +"*** Source Output #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Client: %s\n" +"Source: %u\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Buffer Latency: %0.0f usec\n" +"Source Latency: %0.0f usec\n" +"Resample method: %s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Source Output #%u ***\n" +"Pilote : %s\n" +"Module propriétaire : %s\n" +"Client : %s\n" +"Source : %u\n" +"Spécification de l'échantillon : %s\n" +"Plan des canaux : %s\n" +"Latence du tampon : %0.0f µs\n" +"Latence de la source : %0.0f µs\n" +"Méthode de rééchantillonnage : %s\n" +"Propriétés :\n" +"%s" + +#: ../src/utils/pactl.c:436 +#, c-format +msgid "Failed to get sample information: %s\n" +msgstr "Échec lors de l'obtention des informations de l'échantillon : %s\n" + +# Lazy ? +# load-sample-lazy = Create a new entry in the sample cache, but don't load +# the sample immediately. The sample is loaded only when it is first used +#: ../src/utils/pactl.c:455 +#, c-format +msgid "" +"*** Sample #%u ***\n" +"Name: %s\n" +"Volume: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Duration: %0.1fs\n" +"Size: %s\n" +"Lazy: %s\n" +"Filename: %s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Échantillon #%u ***\n" +"Nom : %s\n" +"Volume : %s\n" +"Spécification de l'échantillon : %s\n" +"Plan des canaux : %s\n" +"Durée : %0.1f s\n" +"Taille : %s\n" +"Cache retardé : %s\n" +"Nom de fichier : %s\n" +"Propriétés :\n" +"%s" + +#: ../src/utils/pactl.c:481 +#, c-format +msgid "Failed to get autoload information: %s\n" +msgstr "" +"Échec lors de l'obtention des informations du chargement automatique : %s\n" + +#: ../src/utils/pactl.c:497 +#, c-format +msgid "" +"*** Autoload Entry #%u ***\n" +"Name: %s\n" +"Type: %s\n" +"Module: %s\n" +"Argument: %s\n" +msgstr "" +"*** Entrée de chargement automatique #%u ***\n" +"Nom : %s\n" +"Type : %s\n" +"Module : %s\n" +"Paramètre : %s\n" + +#: ../src/utils/pactl.c:504 +msgid "sink" +msgstr "destination" + +#: ../src/utils/pactl.c:504 +msgid "source" +msgstr "source" + +#: ../src/utils/pactl.c:511 ../src/utils/pactl.c:521 +#, c-format +msgid "Failure: %s\n" +msgstr "Échec : %s\n" + +#: ../src/utils/pactl.c:545 +#, c-format +msgid "Failed to upload sample: %s\n" +msgstr "Échec lors de l'envoi de l'échantillon : %s\n" + +#: ../src/utils/pactl.c:562 +#, c-format +msgid "Premature end of file\n" +msgstr "Fin prématurée du fichier\n" + +#: ../src/utils/pactl.c:678 +#, c-format +msgid "" +"%s [options] stat\n" +"%s [options] list\n" +"%s [options] exit\n" +"%s [options] upload-sample FILENAME [NAME]\n" +"%s [options] play-sample NAME [SINK]\n" +"%s [options] remove-sample NAME\n" +"%s [options] move-sink-input ID SINK\n" +"%s [options] move-source-output ID SOURCE\n" +"%s [options] load-module NAME [ARGS ...]\n" +"%s [options] unload-module ID\n" +"%s [options] suspend-sink [SINK] 1|0\n" +"%s [options] suspend-source [SOURCE] 1|0\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +msgstr "" +"%s [options] stat\n" +"%s [options] list\n" +"%s [options] exit\n" +"%s [options] upload-sample NOMDEFICHIER [NOM]\n" +"%s [options] play-sample NOM [DEST]\n" +"%s [options] remove-sample NOM\n" +"%s [options] move-sink-input ID DEST\n" +"%s [options] move-source-output ID SOURCE\n" +"%s [options] load-module NOM [PARAMS ...]\n" +"%s [options] unload-module ID\n" +"%s [options] suspend-sink [DEST] 1|0\n" +"%s [options] suspend-source [SOURCE] 1|0\n" +"\n" +" -h, --help Affiche cette aide\n" +" --version Affiche la version\n" +"\n" +" -s, --server=SERVEUR Le nom du serveur auquel se " +"connecter\n" +" -n, --client-name=NOM Définit le nom de ce client sur le " +"serveur\n" + +#: ../src/utils/pactl.c:729 +#, c-format +msgid "" +"pactl %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"pactl %s\n" +"Compilé avec libpulse %s\n" +"Lié avec libpulse %s\n" + +#: ../src/utils/pactl.c:768 +#, c-format +msgid "Please specify a sample file to load\n" +msgstr "Veuillez indiquer un fichier d'échantillon à charger\n" + +#: ../src/utils/pactl.c:790 +#, c-format +msgid "Failed to open sound file.\n" +msgstr "Échec lors de l'ouverture du fichier audio.\n" + +#: ../src/utils/pactl.c:802 +#, c-format +msgid "You have to specify a sample name to play\n" +msgstr "Vous devez indiquer un nom d'échantillon à lire\n" + +#: ../src/utils/pactl.c:814 +#, c-format +msgid "You have to specify a sample name to remove\n" +msgstr "Vous devez indiquer un nom d'échantillon à supprimer\n" + +#: ../src/utils/pactl.c:822 +#, c-format +msgid "You have to specify a sink input index and a sink\n" +msgstr "" +"Vous devez indiquer un index de sortie de destination et une destination\n" + +#: ../src/utils/pactl.c:831 +#, c-format +msgid "You have to specify a source output index and a source\n" +msgstr "Vous devez indiquer un index de sortie de source et une source\n" + +#: ../src/utils/pactl.c:845 +#, c-format +msgid "You have to specify a module name and arguments.\n" +msgstr "Vous devez indiquer un nom de module et des paramètres.\n" + +#: ../src/utils/pactl.c:865 +#, c-format +msgid "You have to specify a module index\n" +msgstr "Vous devez indiquer un index de module\n" + +#: ../src/utils/pactl.c:875 +#, c-format +msgid "" +"You may not specify more than one sink. You have to specify at least one " +"boolean value.\n" +msgstr "" +"Vous ne pouvez pas indiquer plus d'une destination. Vous devez indiquer au " +"moins une valeur booléenne.\n" + +#: ../src/utils/pactl.c:888 +#, c-format +msgid "" +"You may not specify more than one source. You have to specify at least one " +"boolean value.\n" +msgstr "" +"Vous ne pouvez pas indiquer plus d'une source. Vous devez indiquer au moins " +"une valeur booléenne.\n" + +#: ../src/utils/pactl.c:904 +#, c-format +msgid "No valid command specified.\n" +msgstr "Aucune commande valide indiquée.\n" + +#: ../src/utils/pax11publish.c:61 +#, c-format +msgid "" +"%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n" +"\n" +" -d Show current PulseAudio data attached to X11 display (default)\n" +" -e Export local PulseAudio data to X11 display\n" +" -i Import PulseAudio data from X11 display to local environment " +"variables and cookie file.\n" +" -r Remove PulseAudio data from X11 display\n" +msgstr "" +"%s [-D visuel] [-S serveur] [-O destination] [-I source] [-c fichier] [-d|-" +"e|-i|-r]\n" +"\n" +" -d Affiche les données PulseAudio actuelles attachées au visuel X11 (par " +"défaut)\n" +" -e Exporte les données PulseAudio locales vers le visuel X11\n" +" -i Importe les données PulseAudio depuis le visuel X11 vers les " +"variables de l'environnement local et le fichier de cookie.\n" +" -r Enlève les données PulseAudio du visuel X11\n" + +#: ../src/utils/pax11publish.c:94 +#, c-format +msgid "Failed to parse command line.\n" +msgstr "Échec lors de l'analyse de la ligne de commande.\n" + +#: ../src/utils/pax11publish.c:108 +#, c-format +msgid "Server: %s\n" +msgstr "Serveur : %s\n" + +#: ../src/utils/pax11publish.c:110 +#, c-format +msgid "Source: %s\n" +msgstr "Source : %s\n" + +#: ../src/utils/pax11publish.c:112 +#, c-format +msgid "Sink: %s\n" +msgstr "Destination : %s\n" + +#: ../src/utils/pax11publish.c:114 +#, c-format +msgid "Cookie: %s\n" +msgstr "Cookie : %s\n" + +#: ../src/utils/pax11publish.c:132 +#, c-format +msgid "Failed to parse cookie data\n" +msgstr "Échec lors de l'analyse des données du cookie\n" + +#: ../src/utils/pax11publish.c:137 +#, c-format +msgid "Failed to save cookie data\n" +msgstr "Échec lors de l'enregistrement des données du cookie\n" + +#: ../src/utils/pax11publish.c:152 +#, c-format +msgid "Failed to load client configuration file.\n" +msgstr "Échec lors du chargement du fichier de configuration du client.\n" + +#: ../src/utils/pax11publish.c:157 +#, c-format +msgid "Failed to read environment configuration data.\n" +msgstr "" +"Échec lors de la lecture des données de configuration de l'environnement.\n" + +# Fully Qualified Domain Name +#: ../src/utils/pax11publish.c:174 +#, c-format +msgid "Failed to get FQDN.\n" +msgstr "Échec lors de l'obtention du FQDN (« nom de domaine complet »).\n" + +#: ../src/utils/pax11publish.c:194 +#, c-format +msgid "Failed to load cookie data\n" +msgstr "Échec lors du chargement des données du cookie\n" + +#: ../src/utils/pax11publish.c:211 +#, c-format +msgid "Not yet implemented.\n" +msgstr "Pas encore implémenté.\n" + +#: ../src/utils/pacmd.c:64 +#, c-format +msgid "socket(PF_UNIX, SOCK_STREAM, 0): %s" +msgstr "socket(PF_UNIX, SOCK_STREAM, 0) : %s" + +#: ../src/utils/pacmd.c:81 +#, c-format +msgid "connect(): %s" +msgstr "connect() : %s" + +#: ../src/utils/pacmd.c:89 +msgid "Failed to kill PulseAudio daemon." +msgstr "Impossible de tuer le démon PulseAudio." + +#: ../src/utils/pacmd.c:97 +msgid "Daemon not responding." +msgstr "Le démon ne répond pas." + +#: ../src/utils/pacmd.c:112 +#, c-format +msgid "select(): %s" +msgstr "select() : %s" + +#: ../src/utils/pacmd.c:124 ../src/utils/pacmd.c:140 +#, c-format +msgid "read(): %s" +msgstr "read() : %s" + +#: ../src/utils/pacmd.c:153 ../src/utils/pacmd.c:167 +#, c-format +msgid "write(): %s" +msgstr "write() : %s" + +#: ../src/utils/paplay.c:139 +#, c-format +msgid "Stream successfully created\n" +msgstr "Création du flux réussie\n" + +#: ../src/utils/paplay.c:144 +#, c-format +msgid "Stream errror: %s\n" +msgstr "Erreur du flux : %s\n" + +#: ../src/utils/paplay.c:165 +#, c-format +msgid "Connection established.\n" +msgstr "Connexion établie.\n" + +#: ../src/utils/paplay.c:198 +#, c-format +msgid "" +"%s [options] [FILE]\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -v, --verbose Enable verbose operation\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -d, --device=DEVICE The name of the sink to connect to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" +" --channel-map=CHANNELMAP Set the channel map to the use\n" +msgstr "" +"%s [options] [FICHIER]\n" +"\n" +" -h, --help Affiche cette aide\n" +" --version Affiche la version\n" +"\n" +" -v, --verbose Active le mode verbeux\n" +"\n" +" -s, --server=SERVEUR Le nom du serveur auquel se " +"connecter\n" +" -d, --device=PÉRIPHÉRIQUE Le nom de la destination à laquelle " +"se connecter\n" +" -n, --client-name=NOM Définit le nom de ce client sur le " +"serveur\n" +" --stream-name=NOM Définit le nom de ce flux sur le " +"serveur\n" +" --volume=VOLUME Définit le volume initial (linéaire) " +"entre 0 et 65536\n" +" --channel-map=PLANDESCANAUX Définit le plan des canaux à " +"utiliser\n" + +#: ../src/utils/paplay.c:255 +#, c-format +msgid "" +"paplay %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"paplay %s\n" +"Compilé avec libpulse %s\n" +"Lié avec libpulse %s\n" + +#: ../src/utils/paplay.c:292 +#, c-format +msgid "Invalid channel map\n" +msgstr "Plan des canaux invalide\n" + +#: ../src/utils/paplay.c:314 +#, c-format +msgid "Failed to open file '%s'\n" +msgstr "Échec lors de l'ouverture du fichier « %s »\n" + +#: ../src/utils/paplay.c:350 +#, c-format +msgid "Channel map doesn't match file.\n" +msgstr "Le plan des canaux ne correspond pas au fichier.\n" + +#: ../src/utils/paplay.c:376 +#, c-format +msgid "Using sample spec '%s'\n" +msgstr "Utilisation de la spécification de l'échantillon « %s »\n" + +#: ../src/pulsecore/lock-autospawn.c:126 ../src/pulsecore/lock-autospawn.c:207 +msgid "Cannot access autospawn lock." +msgstr "" + +#~ msgid "" +#~ "' and PolicyKit refuse to grant us priviliges. Dropping SUID again.\n" +#~ "For enabling real-time scheduling please acquire the appropriate " +#~ "PolicyKit priviliges, or become a member of '" +#~ msgstr "" +#~ " et PolicyKit refuse de nous accorder les permissions. Abandon du SUID à " +#~ "nouveau.\n" +#~ "Pour activer la planification en temps réel, veuillez aquérir les " +#~ "permissions PolicyKit appropriées, ou devenez membre de " + +#~ msgid "" +#~ "', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this " +#~ "user." +#~ msgstr "" +#~ ", ou augmentez les limites de ressource RLIMIT_NICE/RLIMIT_RTPRIO pour " +#~ "cet utilisateur." + +#~ msgid "socketpair(): %s" +#~ msgstr "socketpair() : %s" diff --git a/po/pl.po b/po/pl.po new file mode 100644 index 00000000..5c5b3b4f --- /dev/null +++ b/po/pl.po @@ -0,0 +1,2113 @@ +# translation of pl.po to Polish +# Piotr Drąg <piotrdrag@gmail.com>, 2008. +# +msgid "" +msgstr "" +"Project-Id-Version: pl\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-07 21:03+0200\n" +"PO-Revision-Date: 2008-09-10 22:41+0200\n" +"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n" +"Language-Team: Polish <pl@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../src/daemon/ltdl-bind-now.c:177 ../src/daemon/ltdl-bind-now.c:197 +msgid "Failed to add bind-now-loader." +msgstr "Dodanie bind-now-loader nie powiodło się." + +#: ../src/daemon/ltdl-bind-now.c:184 +msgid "Failed to find original dlopen loader." +msgstr "" +"Znalezienie oryginalnego programu wczytującego dlopen nie powiodło się." + +#: ../src/daemon/polkit.c:55 +#, c-format +msgid "Cannot connect to system bus: %s" +msgstr "Nie można połączyć się z magistralą systemową: %s" + +#: ../src/daemon/polkit.c:65 +#, c-format +msgid "Cannot get caller from PID: %s" +msgstr "Nie można uzyskać obiektu caller z PID: %s" + +#: ../src/daemon/polkit.c:77 +msgid "Cannot set UID on caller object." +msgstr "Nie można ustawić UID obiektu caller." + +#: ../src/daemon/polkit.c:82 +msgid "Failed to get CK session." +msgstr "Uzyskanie sesji CK nie powiodło się." + +#: ../src/daemon/polkit.c:90 +msgid "Cannot set UID on session object." +msgstr "Nie można ustawić UID obiektowi sesji." + +#: ../src/daemon/polkit.c:95 +msgid "Cannot allocate PolKitAction." +msgstr "Nie można przydzielić PolKitAction." + +#: ../src/daemon/polkit.c:100 +msgid "Cannot set action_id" +msgstr "Nie można ustawić action_id" + +#: ../src/daemon/polkit.c:105 +msgid "Cannot allocate PolKitContext." +msgstr "Nie można przydzielić PolKitContext." + +#: ../src/daemon/polkit.c:110 +#, c-format +msgid "Cannot initialize PolKitContext: %s" +msgstr "Nie można zainicjować PolKitContext: %s" + +#: ../src/daemon/polkit.c:119 +#, c-format +msgid "Could not determine whether caller is authorized: %s" +msgstr "Nie można ustalić, czy obiekt caller jest upoważniony: %s" + +#: ../src/daemon/polkit.c:139 +#, c-format +msgid "Cannot obtain auth: %s" +msgstr "Nie można uzyskać upoważnienia: %s" + +#: ../src/daemon/polkit.c:148 +#, c-format +msgid "PolicyKit responded with '%s'" +msgstr "PolicyKit zwróciło \"%s\"" + +#: ../src/daemon/main.c:134 +#, c-format +msgid "Got signal %s." +msgstr "Otrzymano sygnał %s." + +#: ../src/daemon/main.c:161 +msgid "Exiting." +msgstr "Wyłączanie." + +#: ../src/daemon/main.c:179 +#, c-format +msgid "Failed to find user '%s'." +msgstr "Znalezienie użytkownika \"%s\" nie powiodło się." + +#: ../src/daemon/main.c:184 +#, c-format +msgid "Failed to find group '%s'." +msgstr "Znalezienie grupy \"%s\" nie powiodło się." + +#: ../src/daemon/main.c:188 +#, c-format +msgid "Found user '%s' (UID %lu) and group '%s' (GID %lu)." +msgstr "Znaleziono użytkownika \"%s\" (UID %lu) i grupę \"%s\" (GID %lu)." + +#: ../src/daemon/main.c:193 +#, c-format +msgid "GID of user '%s' and of group '%s' don't match." +msgstr "GID użytkownika \"%s\" i grupy \"%s\" nie zgadzają się." + +#: ../src/daemon/main.c:198 +#, c-format +msgid "Home directory of user '%s' is not '%s', ignoring." +msgstr "Folder domowy użytkownika \"%s\" nie jest \"%s\", ignorowanie." + +#: ../src/daemon/main.c:201 ../src/daemon/main.c:206 +#, c-format +msgid "Failed to create '%s': %s" +msgstr "Utworzenie \"%s\" nie powiodło się: %s" + +#: ../src/daemon/main.c:213 +#, c-format +msgid "Failed to change group list: %s" +msgstr "Zmiana listy grup nie powiodła się: %s" + +#: ../src/daemon/main.c:229 +#, c-format +msgid "Failed to change GID: %s" +msgstr "Zmiana GID nie powiodła się: %s" + +#: ../src/daemon/main.c:245 +#, c-format +msgid "Failed to change UID: %s" +msgstr "Zmiana UID nie powiodła się: %s" + +#: ../src/daemon/main.c:259 +msgid "Successfully dropped root privileges." +msgstr "Pomyślnie porzucono uprawnienia roota." + +#: ../src/daemon/main.c:267 +msgid "System wide mode unsupported on this platform." +msgstr "Tryb systemowy nie jest obsługiwany na tej platformie." + +#: ../src/daemon/main.c:285 +#, c-format +msgid "setrlimit(%s, (%u, %u)) failed: %s" +msgstr "setrlimit(%s, (%u, %u)) nie powiodło się: %s" + +#: ../src/daemon/main.c:425 +msgid "Failed to parse command line." +msgstr "Analiza wiersza poleceń nie powiodła się." + +#: ../src/daemon/main.c:441 +#, c-format +msgid "We're in the group '%s', allowing high-priority scheduling." +msgstr "" +"Jesteśmy w grupie \"%s\", co umożliwia szeregowanie o wysokim priorytecie." + +#: ../src/daemon/main.c:448 +#, c-format +msgid "We're in the group '%s', allowing real-time scheduling." +msgstr "" +"Jesteśmy w grupie \"%s\", co umożliwia szeregowanie w czasie rzeczywistym." + +#: ../src/daemon/main.c:456 +msgid "PolicyKit grants us acquire-high-priority privilege." +msgstr "PolicyKit nadał uprawnienie \"acquire-high-priority\"." + +#: ../src/daemon/main.c:459 +msgid "PolicyKit refuses acquire-high-priority privilege." +msgstr "PolicyKit odmówił nadania uprawnienia \"acquire-high-priority\"." + +#: ../src/daemon/main.c:464 +msgid "PolicyKit grants us acquire-real-time privilege." +msgstr "PolicyKit nadał uprawnienie \"acquire-real-time\"." + +#: ../src/daemon/main.c:467 +msgid "PolicyKit refuses acquire-real-time privilege." +msgstr "PolicyKit odmówił nadania uprawnienia \"acquire-real-time\"." + +#: ../src/daemon/main.c:479 +msgid "" +"Called SUID root and real-time/high-priority scheduling was requested in the " +"configuration. However, we lack the necessary priviliges:\n" +"We are not in group '" +msgstr "" +"Wywołane SUID roota i szeregowanie w czasie rzeczywistym/o wysokim " +"priorytecie zostało zażądane w konfiguracji. Mimo to brak niezbędnych " +"uprawnień:\n" +"Nie jesteśmy w grupie \"" + +#: ../src/daemon/main.c:497 +msgid "" +"High-priority scheduling enabled in configuration but not allowed by policy." +msgstr "" +"Szeregowanie o wysokim priorytecie jest włączone w konfiguracji, ale nie " +"jest zezwolone przez politykę." + +#: ../src/daemon/main.c:522 +msgid "Successfully increased RLIMIT_RTPRIO" +msgstr "Pomyślnie zwiększono RLIMIT_RTPRIO" + +#: ../src/daemon/main.c:525 +#, c-format +msgid "RLIMIT_RTPRIO failed: %s" +msgstr "RLIMIT_RTPRIO nie powiodło się: %s" + +#: ../src/daemon/main.c:532 +msgid "Giving up CAP_NICE" +msgstr "Oddawanie CAP_NICE" + +#: ../src/daemon/main.c:539 +msgid "" +"Real-time scheduling enabled in configuration but not allowed by policy." +msgstr "" +"Szeregowanie w czasie rzeczywistym jest włączone w konfiguracji, ale nie " +"jest zezwolone przez politykę." + +#: ../src/daemon/main.c:597 +msgid "Daemon not running" +msgstr "Demon nie jest uruchomiony" + +#: ../src/daemon/main.c:599 +#, c-format +msgid "Daemon running as PID %u" +msgstr "Demon jest uruchomiony jako PID %u" + +#: ../src/daemon/main.c:609 +#, c-format +msgid "Failed to kill daemon: %s" +msgstr "Zniszczenie demona nie powiodło się: %s" + +#: ../src/daemon/main.c:627 +msgid "" +"This program is not intended to be run as root (unless --system is " +"specified)." +msgstr "" +"Ten program nie powinien być uruchomiany jako root (chyba, że podano --" +"system)" + +#: ../src/daemon/main.c:629 +msgid "Root priviliges required." +msgstr "Wymagane są uprawnienia roota." + +#: ../src/daemon/main.c:634 +msgid "--start not supported for system instances." +msgstr "--start nie jest obsługiwane przy uruchamianiu systemowym." + +#: ../src/daemon/main.c:639 +msgid "Running in system mode, but --disallow-exit not set!" +msgstr "" +"Uruchamianie w trybie systemowym, ale --disallow-exit nie jest ustawione!" + +#: ../src/daemon/main.c:642 +msgid "Running in system mode, but --disallow-module-loading not set!" +msgstr "" +"Uruchamianie w trybie systemowym, ale --disallow-module-loading nie jest " +"ustawione!" + +#: ../src/daemon/main.c:645 +msgid "Running in system mode, forcibly disabling SHM mode!" +msgstr "Uruchamianie w trybie systemowym, wymuszanie wyłączenia trybu SHM!" + +#: ../src/daemon/main.c:650 +msgid "Running in system mode, forcibly disabling exit idle time!" +msgstr "" +"Uruchamianie w trybie systemowym, wymuszanie wyłączenia czasu oczekiwania na " +"zakończenie!" + +#: ../src/daemon/main.c:677 +msgid "Failed to acquire stdio." +msgstr "Uzyskanie standardowego wejścia/wyjścia nie powiodło się" + +#: ../src/daemon/main.c:683 +#, c-format +msgid "pipe failed: %s" +msgstr "potok nie powiódł się: %s" + +#: ../src/daemon/main.c:688 +#, c-format +msgid "fork() failed: %s" +msgstr "fork() nie powiodło się: %s" + +#: ../src/daemon/main.c:702 +#, c-format +msgid "read() failed: %s" +msgstr "read() nie powiodło się: %s" + +#: ../src/daemon/main.c:708 +msgid "Daemon startup failed." +msgstr "Uruchomienie demona nie powiodło się." + +#: ../src/daemon/main.c:710 +msgid "Daemon startup successful." +msgstr "Pomyślnie uruchomiono demona." + +#: ../src/daemon/main.c:780 +#, c-format +msgid "This is PulseAudio %s" +msgstr "To jest PulseAudio %s" + +#: ../src/daemon/main.c:781 +#, c-format +msgid "Compilation host: %s" +msgstr "Komputer kompilacji: %s" + +#: ../src/daemon/main.c:782 +#, c-format +msgid "Compilation CFLAGS: %s" +msgstr "CFLAGS kompilacji: %s" + +#: ../src/daemon/main.c:785 +#, c-format +msgid "Running on host: %s" +msgstr "Uruchamianie na komputerze: %s" + +#: ../src/daemon/main.c:788 +#, c-format +msgid "Page size is %lu bytes" +msgstr "Rozmiar strony to %lu bajtów" + +#: ../src/daemon/main.c:791 +msgid "Compiled with Valgrind support: yes" +msgstr "Skompilowano z obsługą Valgrind: tak" + +#: ../src/daemon/main.c:793 +msgid "Compiled with Valgrind support: no" +msgstr "Skompilowano z obsługą Valgrind: nie" + +#: ../src/daemon/main.c:796 +#, fuzzy, c-format +msgid "Running in valgrind mode: %s" +msgstr "Uruchamianie w trybie systemowym: %s" + +#: ../src/daemon/main.c:799 +msgid "Optimized build: yes" +msgstr "Budowanie optymalizowane: tak" + +#: ../src/daemon/main.c:801 +msgid "Optimized build: no" +msgstr "Budowanie optymalizowane: nie" + +#: ../src/daemon/main.c:805 +msgid "Failed to get machine ID" +msgstr "Uzyskanie identyfikatora komputera nie powiodło się" + +#: ../src/daemon/main.c:808 +#, c-format +msgid "Machine ID is %s." +msgstr "Identyfikator komputera to %s." + +#: ../src/daemon/main.c:813 +#, c-format +msgid "Using runtime directory %s." +msgstr "Używanie folderu wykonywania %s." + +#: ../src/daemon/main.c:818 +#, c-format +msgid "Using state directory %s." +msgstr "Używanie folderu stanu %s." + +#: ../src/daemon/main.c:821 +#, c-format +msgid "Running in system mode: %s" +msgstr "Uruchamianie w trybie systemowym: %s" + +#: ../src/daemon/main.c:836 +msgid "pa_pid_file_create() failed." +msgstr "pa_pid_file_create() nie powiodło się." + +#: ../src/daemon/main.c:848 +msgid "Fresh high-resolution timers available! Bon appetit!" +msgstr "Świeże zegary o wysokiej rozdzielczości! Smacznego!" + +#: ../src/daemon/main.c:850 +msgid "" +"Dude, your kernel stinks! The chef's recommendation today is Linux with high-" +"resolution timers enabled!" +msgstr "" +"Koleś, twoje jądro śmierdzi! Szef kuchni poleca dzisiaj Linuksa w włączonymi " +"zegarami o wysokiej rozdzielczości!" + +#: ../src/daemon/main.c:860 +msgid "pa_core_new() failed." +msgstr "pa_core_new() nie powiodło się." + +#: ../src/daemon/main.c:921 +msgid "Failed to initialize daemon." +msgstr "Zainicjowanie demona nie powiodło się." + +#: ../src/daemon/main.c:926 +msgid "Daemon startup without any loaded modules, refusing to work." +msgstr "Uruchamianie demona bez żadnych wczytanych modułów, odmawianie pracy." + +#: ../src/daemon/main.c:931 +#, c-format +msgid "Default sink name (%s) does not exist in name register." +msgstr "Domyślna nazwa odpływu (%s) nie istnieje w rejestrze nazw." + +#: ../src/daemon/main.c:944 +msgid "Daemon startup complete." +msgstr "Zakończono uruchamianie demona." + +#: ../src/daemon/main.c:950 +msgid "Daemon shutdown initiated." +msgstr "Zainicjowano wyłączenie demona." + +#: ../src/daemon/main.c:971 +msgid "Daemon terminated." +msgstr "Demon został zniszczony." + +#: ../src/daemon/cmdline.c:117 +#, c-format +msgid "" +"%s [options]\n" +"\n" +"COMMANDS:\n" +" -h, --help Show this help\n" +" --version Show version\n" +" --dump-conf Dump default configuration\n" +" --dump-modules Dump list of available modules\n" +" --dump-resample-methods Dump available resample methods\n" +" --cleanup-shm Cleanup stale shared memory " +"segments\n" +" --start Start the daemon if it is not " +"running\n" +" -k --kill Kill a running daemon\n" +" --check Check for a running daemon\n" +"\n" +"OPTIONS:\n" +" --system[=BOOL] Run as system-wide instance\n" +" -D, --daemonize[=BOOL] Daemonize after startup\n" +" --fail[=BOOL] Quit when startup fails\n" +" --high-priority[=BOOL] Try to set high nice level\n" +" (only available as root, when SUID " +"or\n" +" with elevated RLIMIT_NICE)\n" +" --realtime[=BOOL] Try to enable realtime scheduling\n" +" (only available as root, when SUID " +"or\n" +" with elevated RLIMIT_RTPRIO)\n" +" --disallow-module-loading[=BOOL] Disallow module user requested " +"module\n" +" loading/unloading after startup\n" +" --disallow-exit[=BOOL] Disallow user requested exit\n" +" --exit-idle-time=SECS Terminate the daemon when idle and " +"this\n" +" time passed\n" +" --module-idle-time=SECS Unload autoloaded modules when idle " +"and\n" +" this time passed\n" +" --scache-idle-time=SECS Unload autoloaded samples when idle " +"and\n" +" this time passed\n" +" --log-level[=LEVEL] Increase or set verbosity level\n" +" -v Increase the verbosity level\n" +" --log-target={auto,syslog,stderr} Specify the log target\n" +" -p, --dl-search-path=PATH Set the search path for dynamic " +"shared\n" +" objects (plugins)\n" +" --resample-method=METHOD Use the specified resampling method\n" +" (See --dump-resample-methods for\n" +" possible values)\n" +" --use-pid-file[=BOOL] Create a PID file\n" +" --no-cpu-limit[=BOOL] Do not install CPU load limiter on\n" +" platforms that support it.\n" +" --disable-shm[=BOOL] Disable shared memory support.\n" +"\n" +"STARTUP SCRIPT:\n" +" -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module " +"with\n" +" the specified argument\n" +" -F, --file=FILENAME Run the specified script\n" +" -C Open a command line on the running " +"TTY\n" +" after startup\n" +"\n" +" -n Don't load default script file\n" +msgstr "" +"%s [opcje]\n" +"\n" +"POLECENIA:\n" +" -h, --help Wyświetla tę pomoc\n" +" --version Wyświetla wersję\n" +" --dump-conf Zrzuca domyślną konfigurację\n" +" --dump-modules Zrzuca listę dostępnych modułów\n" +" --dump-resample-methods Zrzuca dostępne metody resamplingu\n" +" --cleanup-shm Czyści stare fragmenty pamięci " +"współdzielonej\n" +" --start Uruchamia demona, jeśli nie jest " +"uruchomiony\n" +" -k --kill Niszczy uruchomionego demona\n" +" --check Sprawdza, czy demon jest " +"uruchomiony\n" +"\n" +"OPCJE:\n" +" --system[=ZMIENNALOGICZNA] Uruchamia w trybie systemowym\n" +" -D, --daemonize[=ZMIENNALOGICZNA] Tworzy demona po uruchomieniu\n" +" --fail[=ZMIENNALOGICZNA] Wyłącza, kiedy uruchomienie nie " +"powiedzie się\n" +" --high-priority[=ZMIENNALOGICZNA] Próbuje ustawić wysoki poziom nice\n" +" (dostępne tylko jako root, na SUID " +"lub\n" +" z podniesionym RLIMIT_NICE)\n" +" --realtime[=ZMIENNALOGICZNA] Próbuje ustawić szeregowanie w " +"czasie rzeczywistym\n" +" (dostępne tylko jako root, na SUID " +"lub\n" +" z podniesionym RLIMIT_RTPRIO)\n" +" --disallow-module-loading[=ZMIENNALOGICZNA] Nie zezwala użytkownikowi " +"modułu na\n" +" żądanie wczytania/usunięcia modułu " +"po uruchomieniu\n" +" --disallow-exit[=ZMIENNALOGICZNA] Nie zezwala użytkownikowi na żądanie " +"wyłączenia\n" +" --exit-idle-time=SEKUNDY Niszczy demona, kiedy jest zajęty i " +"upłynął\n" +" ten czas\n" +" --module-idle-time=SEKUNDY Usuwa automatycznie wczytane moduły, " +"kiedy jest\n" +" zajęty i upłynął ten czas\n" +" --scache-idle-time=SEKUNDY Usuwa automatycznie wczytane próbki, " +"kiedy jest\n" +" zajęty i upłynął ten czas\n" +" --log-level[=POZIOM] Zwiększa lub ustaw poziom " +"wyświetlanych informacji\n" +" -v Zwiększa poziom wyświetlanych " +"informacji\n" +" --log-target={auto,syslog,stderr} Określa dziennik docelowy\n" +" -p, --dl-search-path=ŚCIEŻKA Ustawia ścieżkę wyszukiwania dla " +"dynamicznie\n" +" współdzielonych obiektów (wtyczek)\n" +" --resample-method=METODA Używa podanej metody resamplingu\n" +" (zobacz --dump-resample-methods,\n" +" aby poznać możliwe wartości)\n" +" --use-pid-file[=ZMIENNALOGICZNA] Tworzy plik PID\n" +" --no-cpu-limit[=ZMIENNALOGICZNA] Nie instaluje ograniczenia zasobów\n" +" procesora na obsługujących je " +"platformach.\n" +" --disable-shm[=ZMIENNALOGICZNA] Wyłącza obsługę pamięci " +"współdzielonej.\n" +"\n" +"SKRYPT STARTOWY:\n" +" -L, --load=\"PARAMETRY MODUŁU\" Wczytuje podany moduł wtyczki z\n" +" podanym parametrem\n" +" -F, --file=NAZWAPLIKU Wykonuje podany skrypt\n" +" -C Otwiera wiersz poleceń na " +"uruchomionym TTY\n" +" po uruchomieniu\n" +"\n" +" -n Nie wczytuje domyślnego pliku " +"skryptu\n" + +#: ../src/daemon/cmdline.c:245 +msgid "--daemonize expects boolean argument" +msgstr "--daemonize oczekuje parametru w postaci zmiennej logicznej" + +#: ../src/daemon/cmdline.c:252 +msgid "--fail expects boolean argument" +msgstr "--fail oczekuje parametru w postaci zmiennej logicznej" + +#: ../src/daemon/cmdline.c:262 +msgid "" +"--log-level expects log level argument (either numeric in range 0..4 or one " +"of debug, info, notice, warn, error)." +msgstr "" +"--log-level oczekuje parametru poziomu dziennika (numeryczny w zakresie 0..4 " +"lub jeden z debug, info, notice, warn, error)." + +#: ../src/daemon/cmdline.c:274 +msgid "--high-priority expects boolean argument" +msgstr "--high-priority oczekuje parametru zmiennej logicznej" + +#: ../src/daemon/cmdline.c:281 +msgid "--realtime expects boolean argument" +msgstr "-realtime oczekuje parametru zmiennej logicznej" + +#: ../src/daemon/cmdline.c:288 +msgid "--disallow-module-loading expects boolean argument" +msgstr "--disallow-module-loading oczekuje parametru zmiennej logicznej" + +#: ../src/daemon/cmdline.c:295 +msgid "--disallow-exit boolean argument" +msgstr "--disallow-exit zmienna logiczna" + +#: ../src/daemon/cmdline.c:302 +msgid "--use-pid-file expects boolean argument" +msgstr "--use-pid-file oczekuje parametru zmiennej logicznej" + +#: ../src/daemon/cmdline.c:319 +msgid "Invalid log target: use either 'syslog', 'stderr' or 'auto'." +msgstr "" +"Nieprawidłowy dziennik docelowy: należy użyć \"syslog\", \"stderr\" lub " +"\"auto\"." + +#: ../src/daemon/cmdline.c:338 +#, c-format +msgid "Invalid resample method '%s'." +msgstr "Nieprawidłowa metoda resamplingu \"%s\"." + +#: ../src/daemon/cmdline.c:345 +msgid "--system expects boolean argument" +msgstr "--system oczekuje parametru zmiennej logicznej" + +#: ../src/daemon/cmdline.c:352 +msgid "--no-cpu-limit expects boolean argument" +msgstr "--no-cpu-limit oczekuje parametru zmiennej logicznej" + +#: ../src/daemon/cmdline.c:359 +msgid "--disable-shm expects boolean argument" +msgstr "--disable-shm oczekuje parametru zmiennej logicznej" + +#: ../src/daemon/dumpmodules.c:60 +#, c-format +msgid "Name: %s\n" +msgstr "Nazwa: %s\n" + +#: ../src/daemon/dumpmodules.c:63 +#, c-format +msgid "No module information available\n" +msgstr "Brak informacji o module\n" + +#: ../src/daemon/dumpmodules.c:66 +#, c-format +msgid "Version: %s\n" +msgstr "Wersja: %s\n" + +#: ../src/daemon/dumpmodules.c:68 +#, c-format +msgid "Description: %s\n" +msgstr "Opis: %s\n" + +#: ../src/daemon/dumpmodules.c:70 +#, c-format +msgid "Author: %s\n" +msgstr "Autor: %s\n" + +#: ../src/daemon/dumpmodules.c:72 +#, c-format +msgid "Usage: %s\n" +msgstr "Użycie: %s\n" + +#: ../src/daemon/dumpmodules.c:73 +#, c-format +msgid "Load Once: %s\n" +msgstr "Wczytanie jednorazowe: %s\n" + +#: ../src/daemon/dumpmodules.c:77 +#, c-format +msgid "Path: %s\n" +msgstr "Ścieżka: %s\n" + +#: ../src/daemon/daemon-conf.c:205 +#, c-format +msgid "[%s:%u] Invalid log target '%s'." +msgstr "[%s:%u] Nieprawidłowy dziennik docelowy \"%s\"." + +#: ../src/daemon/daemon-conf.c:221 +#, c-format +msgid "[%s:%u] Invalid log level '%s'." +msgstr "[%s:%u] Nieprawidłowy poziom dziennika \"%s\"." + +#: ../src/daemon/daemon-conf.c:237 +#, c-format +msgid "[%s:%u] Invalid resample method '%s'." +msgstr "[%s:%u] Nieprawidłowa metoda resamplingu \"%s\"." + +#: ../src/daemon/daemon-conf.c:260 +#, c-format +msgid "[%s:%u] Invalid rlimit '%s'." +msgstr "[%s:%u] Nieprawidłowy rlimit \"%s\"." + +#: ../src/daemon/daemon-conf.c:267 +#, c-format +msgid "[%s:%u] rlimit not supported on this platform." +msgstr "[%s:%u] rlimit nie jest obsługiwany na tej platformie." + +#: ../src/daemon/daemon-conf.c:283 +#, c-format +msgid "[%s:%u] Invalid sample format '%s'." +msgstr "[%s:%u] Nieprawidłowy format próbki \"%s\"." + +#: ../src/daemon/daemon-conf.c:301 +#, c-format +msgid "[%s:%u] Invalid sample rate '%s'." +msgstr "[%s:%u] Nieprawidłowa częstotliwość próbki \"%s\"." + +#: ../src/daemon/daemon-conf.c:319 +#, c-format +msgid "[%s:%u] Invalid sample channels '%s'." +msgstr "[%s:%u] Nieprawidłowe kanały próbki \"%s\"." + +#: ../src/daemon/daemon-conf.c:337 +#, c-format +msgid "[%s:%u] Invalid number of fragments '%s'." +msgstr "[%s:%u] Nieprawidłowa liczba fragmentów \"%s\"." + +#: ../src/daemon/daemon-conf.c:355 +#, c-format +msgid "[%s:%u] Invalid fragment size '%s'." +msgstr "[%s:%u] Nieprawidłowy rozmiar fragmentu \"%s\"." + +#: ../src/daemon/daemon-conf.c:373 +#, c-format +msgid "[%s:%u] Invalid nice level '%s'." +msgstr "[%s:%u] Nieprawidłowy poziom nice \"%s\"." + +#: ../src/daemon/daemon-conf.c:570 +#, c-format +msgid "Failed to open configuration file: %s" +msgstr "Otwarcie pliku konfiguracji nie powiodło się: %s" + +#: ../src/daemon/daemon-conf.c:644 +#, c-format +msgid "### Read from configuration file: %s ###\n" +msgstr "### Odczytano z pliku konfiguracji: %s ###\n" + +#: ../src/daemon/caps.c:63 +msgid "Dropping root priviliges." +msgstr "Porzucanie uprawnień roota." + +#: ../src/daemon/caps.c:103 +msgid "Limited capabilities successfully to CAP_SYS_NICE." +msgstr "Pomyślnie ograniczono możliwości do CAP_SYS_NICE." + +#: ../src/pulse/channelmap.c:102 +msgid "Mono" +msgstr "Mono" + +#: ../src/pulse/channelmap.c:104 +msgid "Front Center" +msgstr "Przedni środkowy" + +#: ../src/pulse/channelmap.c:105 +msgid "Front Left" +msgstr "Przedni lewy" + +#: ../src/pulse/channelmap.c:106 +msgid "Front Right" +msgstr "Przedni prawy" + +#: ../src/pulse/channelmap.c:108 +msgid "Rear Center" +msgstr "Tylny środkowy" + +#: ../src/pulse/channelmap.c:109 +msgid "Rear Left" +msgstr "Tylny lewy" + +#: ../src/pulse/channelmap.c:110 +msgid "Rear Right" +msgstr "Tylny prawy" + +#: ../src/pulse/channelmap.c:112 +msgid "Low Frequency Emmiter" +msgstr "Subwoofer" + +#: ../src/pulse/channelmap.c:114 +msgid "Front Left-of-center" +msgstr "Przedni lewy po środku" + +#: ../src/pulse/channelmap.c:115 +msgid "Front Right-of-center" +msgstr "Przedni prawy po środku" + +#: ../src/pulse/channelmap.c:117 +msgid "Side Left" +msgstr "Boczny lewy" + +#: ../src/pulse/channelmap.c:118 +msgid "Side Right" +msgstr "Boczny prawy" + +#: ../src/pulse/channelmap.c:120 +msgid "Auxiliary 0" +msgstr "Pomocnicze 0" + +#: ../src/pulse/channelmap.c:121 +msgid "Auxiliary 1" +msgstr "Pomocnicze 1" + +#: ../src/pulse/channelmap.c:122 +msgid "Auxiliary 2" +msgstr "Pomocnicze 2" + +#: ../src/pulse/channelmap.c:123 +msgid "Auxiliary 3" +msgstr "Pomocnicze 3" + +#: ../src/pulse/channelmap.c:124 +msgid "Auxiliary 4" +msgstr "Pomocnicze 4" + +#: ../src/pulse/channelmap.c:125 +msgid "Auxiliary 5" +msgstr "Pomocnicze 5" + +#: ../src/pulse/channelmap.c:126 +msgid "Auxiliary 6" +msgstr "Pomocnicze 6" + +#: ../src/pulse/channelmap.c:127 +msgid "Auxiliary 7" +msgstr "Pomocnicze 7" + +#: ../src/pulse/channelmap.c:128 +msgid "Auxiliary 8" +msgstr "Pomocnicze 8" + +#: ../src/pulse/channelmap.c:129 +msgid "Auxiliary 9" +msgstr "Pomocnicze 9" + +#: ../src/pulse/channelmap.c:130 +msgid "Auxiliary 10" +msgstr "Pomocnicze 10" + +#: ../src/pulse/channelmap.c:131 +msgid "Auxiliary 11" +msgstr "Pomocnicze 11" + +#: ../src/pulse/channelmap.c:132 +msgid "Auxiliary 12" +msgstr "Pomocnicze 12" + +#: ../src/pulse/channelmap.c:133 +msgid "Auxiliary 13" +msgstr "Pomocnicze 13" + +#: ../src/pulse/channelmap.c:134 +msgid "Auxiliary 14" +msgstr "Pomocnicze 14" + +#: ../src/pulse/channelmap.c:135 +msgid "Auxiliary 15" +msgstr "Pomocnicze 15" + +#: ../src/pulse/channelmap.c:136 +msgid "Auxiliary 16" +msgstr "Pomocnicze 16" + +#: ../src/pulse/channelmap.c:137 +msgid "Auxiliary 17" +msgstr "Pomocnicze 17" + +#: ../src/pulse/channelmap.c:138 +msgid "Auxiliary 18" +msgstr "Pomocnicze 18" + +#: ../src/pulse/channelmap.c:139 +msgid "Auxiliary 19" +msgstr "Pomocnicze 19" + +#: ../src/pulse/channelmap.c:140 +msgid "Auxiliary 20" +msgstr "Pomocnicze 20" + +#: ../src/pulse/channelmap.c:141 +msgid "Auxiliary 21" +msgstr "Pomocnicze 21" + +#: ../src/pulse/channelmap.c:142 +msgid "Auxiliary 22" +msgstr "Pomocnicze 22" + +#: ../src/pulse/channelmap.c:143 +msgid "Auxiliary 23" +msgstr "Pomocnicze 23" + +#: ../src/pulse/channelmap.c:144 +msgid "Auxiliary 24" +msgstr "Pomocnicze 24" + +#: ../src/pulse/channelmap.c:145 +msgid "Auxiliary 25" +msgstr "Pomocnicze 25" + +#: ../src/pulse/channelmap.c:146 +msgid "Auxiliary 26" +msgstr "Pomocnicze 26" + +#: ../src/pulse/channelmap.c:147 +msgid "Auxiliary 27" +msgstr "Pomocnicze 27" + +#: ../src/pulse/channelmap.c:148 +msgid "Auxiliary 28" +msgstr "Pomocnicze 28" + +#: ../src/pulse/channelmap.c:149 +msgid "Auxiliary 29" +msgstr "Pomocnicze 29" + +#: ../src/pulse/channelmap.c:150 +msgid "Auxiliary 30" +msgstr "Pomocnicze 30" + +#: ../src/pulse/channelmap.c:151 +msgid "Auxiliary 31" +msgstr "Pomocnicze 31" + +#: ../src/pulse/channelmap.c:153 +msgid "Top Center" +msgstr "Górny środkowy" + +#: ../src/pulse/channelmap.c:155 +msgid "Top Front Center" +msgstr "Górny przedni środkowy" + +#: ../src/pulse/channelmap.c:156 +msgid "Top Front Left" +msgstr "Górny przedni lewy" + +#: ../src/pulse/channelmap.c:157 +msgid "Top Front Right" +msgstr "Górny przedni prawy" + +#: ../src/pulse/channelmap.c:159 +msgid "Top Rear Center" +msgstr "Górny tylny środkowy" + +#: ../src/pulse/channelmap.c:160 +msgid "Top Rear Left" +msgstr "Górny tylny lewy" + +#: ../src/pulse/channelmap.c:161 +msgid "Top Rear Right" +msgstr "Górny tylny prawy" + +#: ../src/pulse/channelmap.c:472 ../src/pulse/sample.c:144 +#: ../src/pulse/volume.c:163 ../src/pulse/volume.c:194 +#, fuzzy +msgid "(invalid)" +msgstr "Nieprawidłowe" + +#: ../src/pulse/error.c:43 +msgid "OK" +msgstr "OK" + +#: ../src/pulse/error.c:44 +msgid "Access denied" +msgstr "Odmówiono dostępu" + +#: ../src/pulse/error.c:45 +msgid "Unknown command" +msgstr "Nieznane polecenie" + +#: ../src/pulse/error.c:46 +msgid "Invalid argument" +msgstr "Nieprawidłowy parametr" + +#: ../src/pulse/error.c:47 +msgid "Entity exists" +msgstr "Jednostka istnieje" + +#: ../src/pulse/error.c:48 +msgid "No such entity" +msgstr "Brak jednostki" + +#: ../src/pulse/error.c:49 +msgid "Connection refused" +msgstr "Odrzucono połączenie" + +#: ../src/pulse/error.c:50 +msgid "Protocol error" +msgstr "Błąd protokołu" + +#: ../src/pulse/error.c:51 +msgid "Timeout" +msgstr "Przekroczono czas oczekiwania" + +#: ../src/pulse/error.c:52 +msgid "No authorization key" +msgstr "Brak klucza upoważnienia" + +#: ../src/pulse/error.c:53 +msgid "Internal error" +msgstr "Wewnętrzny błąd" + +#: ../src/pulse/error.c:54 +msgid "Connection terminated" +msgstr "Zniszczono połączenie" + +#: ../src/pulse/error.c:55 +msgid "Entity killed" +msgstr "Zniszczono jednostkę" + +#: ../src/pulse/error.c:56 +msgid "Invalid server" +msgstr "Nieprawidłowy serwer" + +#: ../src/pulse/error.c:57 +msgid "Module initalization failed" +msgstr "Zainicjowanie modułu nie powiodło się" + +#: ../src/pulse/error.c:58 +msgid "Bad state" +msgstr "Błędny stan" + +#: ../src/pulse/error.c:59 +msgid "No data" +msgstr "Brak danych" + +#: ../src/pulse/error.c:60 +msgid "Incompatible protocol version" +msgstr "Niezgodna wersja protokołu" + +#: ../src/pulse/error.c:61 +msgid "Too large" +msgstr "Za duże" + +#: ../src/pulse/error.c:62 +msgid "Not supported" +msgstr "Nieobsługiwane" + +#: ../src/pulse/error.c:63 +msgid "Unknown error code" +msgstr "Nieznany kod błędu" + +#: ../src/pulse/error.c:64 +msgid "No such extension" +msgstr "Nie ma takiego rozszerzenia" + +#: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100 +msgid "XOpenDisplay() failed" +msgstr "XOpenDisplay() nie powiodło się" + +#: ../src/pulse/client-conf-x11.c:78 +msgid "Failed to parse cookie data" +msgstr "Analiza danych ciasteczka nie powiodło się" + +#: ../src/pulse/client-conf.c:120 +#, c-format +msgid "Failed to open configuration file '%s': %s" +msgstr "Otwarcie pliku konfiguracji \"%s\" nie powiodło się: %s" + +#: ../src/pulse/context.c:516 +msgid "No cookie loaded. Attempting to connect without." +msgstr "Nie wczytano ciasteczka. Próbowanie połączenia się bez niego." + +#: ../src/pulse/context.c:642 +#, c-format +msgid "fork(): %s" +msgstr "fork(): %s" + +#: ../src/pulse/context.c:695 +#, c-format +msgid "waitpid(): %s" +msgstr "waitpid(): %s" + +#: ../src/pulse/context.c:1256 +#, c-format +msgid "Received message for unknown extension '%s'" +msgstr "Otrzymano komunikat z nieznanego powodu \"%s\"" + +#: ../src/utils/pacat.c:93 +#, c-format +msgid "pa_stream_write() failed: %s\n" +msgstr "pa_stream_write() nie powiodło się: %s\n" + +#: ../src/utils/pacat.c:132 +#, c-format +msgid "pa_stream_peek() failed: %s\n" +msgstr "pa_stream_peek() nie powiodło się: %s\n" + +#: ../src/utils/pacat.c:141 +#, c-format +msgid "Buffer overrun, dropping incoming data\n" +msgstr "Przepełniono bufor, porzucanie danych przychodzących\n" + +#: ../src/utils/pacat.c:143 +#, c-format +msgid "pa_stream_drop() failed: %s\n" +msgstr "pa_stream_drop() nie powiodło się: %s\n" + +#: ../src/utils/pacat.c:169 +#, c-format +msgid "Stream successfully created.\n" +msgstr "Pomyślnie utworzono strumień.\n" + +#: ../src/utils/pacat.c:172 +#, c-format +msgid "pa_stream_get_buffer_attr() failed: %s\n" +msgstr "pa_stream_get_buffer_attr() nie powiodło się: %s\n" + +#: ../src/utils/pacat.c:176 +#, c-format +msgid "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n" +msgstr "Metryka bufora: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n" + +#: ../src/utils/pacat.c:179 +#, c-format +msgid "Buffer metrics: maxlength=%u, fragsize=%u\n" +msgstr "Metryka bufora: maxlength=%u, fragsize=%u\n" + +#: ../src/utils/pacat.c:183 +#, c-format +msgid "Using sample spec '%s', channel map '%s'.\n" +msgstr "Używanie przykładowej specyfikacji \"%s\", mapa kanałów \"%s\".\n" + +#: ../src/utils/pacat.c:187 +#, c-format +msgid "Connected to device %s (%u, %ssuspended).\n" +msgstr "Połączono się z urządzeniem %s (%u, %swstrzymane).\n" + +#: ../src/utils/pacat.c:197 +#, c-format +msgid "Stream error: %s\n" +msgstr "Błąd strumienia: %s\n" + +#: ../src/utils/pacat.c:207 +#, c-format +msgid "Stream device suspended.%s \n" +msgstr "Wstrzymano urządzenie strumienia.%s \n" + +#: ../src/utils/pacat.c:209 +#, c-format +msgid "Stream device resumed.%s \n" +msgstr "Wznowiono urządzenie strumienia.%s \n" + +#: ../src/utils/pacat.c:217 +#, c-format +msgid "Stream underrun.%s \n" +msgstr "Niedopełniono strumień.%s \n" + +#: ../src/utils/pacat.c:224 +#, c-format +msgid "Stream overrun.%s \n" +msgstr "Przepełniono strumień.%s \n" + +#: ../src/utils/pacat.c:231 +#, c-format +msgid "Stream started.%s \n" +msgstr "Utworzono strumień.%s \n" + +#: ../src/utils/pacat.c:238 +#, c-format +msgid "Stream moved to device %s (%u, %ssuspended).%s \n" +msgstr "Strumień został przeniesiony do urządzenia %s (%u, %swstrzymane).%s \n" + +#: ../src/utils/pacat.c:238 +msgid "not " +msgstr "nie " + +#: ../src/utils/pacat.c:259 +#, c-format +msgid "Connection established.%s \n" +msgstr "Ustanowiono połączenie.%s \n" + +#: ../src/utils/pacat.c:262 +#, c-format +msgid "pa_stream_new() failed: %s\n" +msgstr "pa_stream_new() nie powiodło się: %s\n" + +#: ../src/utils/pacat.c:287 +#, c-format +msgid "pa_stream_connect_playback() failed: %s\n" +msgstr "pa_stream_connect_playback() nie powiodło się: %s\n" + +#: ../src/utils/pacat.c:293 +#, c-format +msgid "pa_stream_connect_record() failed: %s\n" +msgstr "pa_stream_connect_record() nie powiodło się: %s\n" + +#: ../src/utils/pacat.c:307 ../src/utils/pasuspender.c:159 +#: ../src/utils/pactl.c:666 ../src/utils/paplay.c:183 +#, c-format +msgid "Connection failure: %s\n" +msgstr "Połączenie nie powiodło się: %s\n" + +#: ../src/utils/pacat.c:328 ../src/utils/paplay.c:75 +#, c-format +msgid "Failed to drain stream: %s\n" +msgstr "Opróżnienie strumienia nie powiodło się: %s\n" + +#: ../src/utils/pacat.c:333 ../src/utils/paplay.c:80 +#, c-format +msgid "Playback stream drained.\n" +msgstr "Opróżniono strumień odtwarzania.\n" + +#: ../src/utils/pacat.c:343 ../src/utils/paplay.c:92 +#, c-format +msgid "Draining connection to server.\n" +msgstr "Opróżnianie połączenia z serwerem.\n" + +#: ../src/utils/pacat.c:369 +#, c-format +msgid "Got EOF.\n" +msgstr "Otrzymano EOF.\n" + +#: ../src/utils/pacat.c:375 +#, c-format +msgid "pa_stream_drain(): %s\n" +msgstr "pa_stream_drain(): %s\n" + +#: ../src/utils/pacat.c:385 +#, c-format +msgid "read() failed: %s\n" +msgstr "read() nie powiodło się: %s\n" + +#: ../src/utils/pacat.c:417 +#, c-format +msgid "write() failed: %s\n" +msgstr "write() nie powiodło się: %s\n" + +#: ../src/utils/pacat.c:438 +#, c-format +msgid "Got signal, exiting.\n" +msgstr "Otrzymano sygnał, wyłączanie.\n" + +#: ../src/utils/pacat.c:452 +#, c-format +msgid "Failed to get latency: %s\n" +msgstr "Uzyskanie opóźnienia nie powiodło się: %s\n" + +#: ../src/utils/pacat.c:457 +#, c-format +msgid "Time: %0.3f sec; Latency: %0.0f usec. \r" +msgstr "Czas: %0.3f sekundy; opóźnienie: %0.0f usekundy. \r" + +#: ../src/utils/pacat.c:477 +#, c-format +msgid "pa_stream_update_timing_info() failed: %s\n" +msgstr "pa_stream_update_timing_info() nie powiodło się: %s\n" + +#: ../src/utils/pacat.c:490 +#, c-format +msgid "" +"%s [options]\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -r, --record Create a connection for recording\n" +" -p, --playback Create a connection for playback\n" +"\n" +" -v, --verbose Enable verbose operations\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -d, --device=DEVICE The name of the sink/source to " +"connect to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" +" --rate=SAMPLERATE The sample rate in Hz (defaults to " +"44100)\n" +" --format=SAMPLEFORMAT The sample type, one of s16le, " +"s16be, u8, float32le,\n" +" float32be, ulaw, alaw, s32le, s32be " +"(defaults to s16ne)\n" +" --channels=CHANNELS The number of channels, 1 for mono, " +"2 for stereo\n" +" (defaults to 2)\n" +" --channel-map=CHANNELMAP Channel map to use instead of the " +"default\n" +" --fix-format Take the sample format from the sink " +"the stream is\n" +" being connected to.\n" +" --fix-rate Take the sampling rate from the sink " +"the stream is\n" +" being connected to.\n" +" --fix-channels Take the number of channels and the " +"channel map\n" +" from the sink the stream is being " +"connected to.\n" +" --no-remix Don't upmix or downmix channels.\n" +" --no-remap Map channels by index instead of " +"name.\n" +" --latency=BYTES Request the specified latency in " +"bytes.\n" +" --process-time=BYTES Request the specified process time " +"per request in bytes.\n" +msgstr "" +"%s [opcje]\n" +"\n" +" -h, --help Wyświetla tę pomoc\n" +" --version Wyświetla wersję\n" +"\n" +" -r, --record Tworzy połączenie do nagrywania\n" +" -p, --playback Tworzy połączenie do odtwarzania\n" +"\n" +" -v, --verbose Wyświetla więcej informacji o " +"działaniu\n" +"\n" +" -s, --server=SERWER Nazwa serwera do połączenia się z\n" +" -d, --device=URZĄDZENIE Nazwa odpływu/źródła do połączenia " +"się z\n" +" -n, --client-name=NAZWA Jak nazywać tego klienta na " +"serwerze\n" +" --stream-name=NAZWA Jak nazwać ten strumień na serwerze\n" +" --volume=POZIOMGŁOŚNOŚCI Określa początkowy (liniowy) poziom " +"głośności z zakresie 0...65536\n" +" --rate=CZĘSTOTLIWOŚĆPRÓBKI Częstotliwość próbki w Hz (domyślnie " +"44100)\n" +" --format=FORMATPRÓBKI Typ próbki, jeden z s16le, s16be, " +"u8, float32le,\n" +" float32be, ulaw, alaw, s32le, s32be " +"(domyślnie s16ne)\n" +" --channels=KANAŁY Liczba kanałów, 1 dla mono, 2 dla " +"stereo\n" +" (domyślnie 2)\n" +" --channel-map=MAPAKANAŁÓW Mapa kanałów używa zamiast " +"domyślnej\n" +" --fix-format Pobiera format próbki z odpływu, z " +"jakim\n" +" połączony jest strumień.\n" +" --fix-rate Pobiera częstotliwość sampli z " +"odpływu, z\n" +" jakim połączony jest strumień.\n" +" --fix-channels Pobiera liczbę kanałów i mapę " +"kanałów z odpływu,\n" +" z jakim połączony jest strumień.\n" +" --no-remix Nie miesza kanałów w górę lub w " +"dół.\n" +" --no-remap Mapuje kanały przez indeks zamiast " +"przez nazwę.\n" +" --latency=BAJTY Żąda określonego opóźnienia w " +"bajtach.\n" +" --process-time=BAJTY Żąda określonego czasu procesu na " +"żądanie w bajtach.\n" + +#: ../src/utils/pacat.c:591 +#, c-format +msgid "" +"pacat %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"pacat %s\n" +"Skompilowane za pomocą libpulse %s\n" +"Skonsolidowane za pomocą libpulse %s\n" + +#: ../src/utils/pacat.c:647 +#, c-format +msgid "Invalid channel map '%s'\n" +msgstr "Nieprawidłowa mapa kanałów \"%s\"\n" + +#: ../src/utils/pacat.c:676 +#, c-format +msgid "Invalid latency specification '%s'\n" +msgstr "Nieprawidłowe określenie opóźnienia \"%s\"\n" + +#: ../src/utils/pacat.c:683 +#, c-format +msgid "Invalid process time specification '%s'\n" +msgstr "Nieprawidłowe określenie czasu procesu \"%s\"\n" + +#: ../src/utils/pacat.c:694 +#, c-format +msgid "Invalid sample specification\n" +msgstr "Nieprawidłowe określenie próbki\n" + +#: ../src/utils/pacat.c:699 +#, c-format +msgid "Channel map doesn't match sample specification\n" +msgstr "Mapa kanałów nie zgadza się z określeniem próbki\n" + +#: ../src/utils/pacat.c:706 +#, c-format +msgid "Opening a %s stream with sample specification '%s'.\n" +msgstr "Otwieranie strumienia %s za pomocą określenie próbki \"%s\".\n" + +#: ../src/utils/pacat.c:706 +msgid "recording" +msgstr "nagrywanie" + +#: ../src/utils/pacat.c:706 +msgid "playback" +msgstr "odtwarzanie" + +#: ../src/utils/pacat.c:714 +#, c-format +msgid "open(): %s\n" +msgstr "open(): %s\n" + +#: ../src/utils/pacat.c:719 +#, c-format +msgid "dup2(): %s\n" +msgstr "dup2(): %s\n" + +#: ../src/utils/pacat.c:729 +#, c-format +msgid "Too many arguments.\n" +msgstr "Za dużo parametrów.\n" + +#: ../src/utils/pacat.c:742 ../src/utils/pasuspender.c:280 +#: ../src/utils/pactl.c:909 ../src/utils/paplay.c:381 +#, c-format +msgid "pa_mainloop_new() failed.\n" +msgstr "pa_mainloop_new() nie powiodło się.\n" + +#: ../src/utils/pacat.c:763 +#, c-format +msgid "io_new() failed.\n" +msgstr "io_new() nie powiodło się.\n" + +#: ../src/utils/pacat.c:769 ../src/utils/pasuspender.c:293 +#: ../src/utils/pactl.c:923 ../src/utils/paplay.c:396 +#, c-format +msgid "pa_context_new() failed.\n" +msgstr "pa_context_new() nie powiodło się.\n" + +#: ../src/utils/pacat.c:777 +#, c-format +msgid "pa_context_connect() failed: %s" +msgstr "pa_context_connect() nie powiodło się: %s" + +#: ../src/utils/pacat.c:788 +#, c-format +msgid "time_new() failed.\n" +msgstr "time_new() nie powiodło się.\n" + +#: ../src/utils/pacat.c:795 ../src/utils/pasuspender.c:301 +#: ../src/utils/pactl.c:931 ../src/utils/paplay.c:407 +#, c-format +msgid "pa_mainloop_run() failed.\n" +msgstr "pa_mainloop_run() nie powiodło się.\n" + +#: ../src/utils/pasuspender.c:81 +#, c-format +msgid "fork(): %s\n" +msgstr "fork(): %s\n" + +#: ../src/utils/pasuspender.c:92 +#, c-format +msgid "execvp(): %s\n" +msgstr "execvp(): %s\n" + +#: ../src/utils/pasuspender.c:109 +#, c-format +msgid "Failure to suspend: %s\n" +msgstr "Wstrzymanie nie powiodło się: %s\n" + +#: ../src/utils/pasuspender.c:124 +#, c-format +msgid "Failure to resume: %s\n" +msgstr "Wznowienie nie powiodło się: %s\n" + +#: ../src/utils/pasuspender.c:147 +#, c-format +msgid "WARNING: Sound server is not local, not suspending.\n" +msgstr "" +"OSTRZEŻENIE: serwer dźwięku nie jest lokalny, nie zostanie wstrzymany.\n" + +#: ../src/utils/pasuspender.c:176 ../src/utils/pactl.c:672 +#: ../src/utils/paplay.c:191 +#, c-format +msgid "Got SIGINT, exiting.\n" +msgstr "Otrzymano SIGINT, wyłączanie.\n" + +#: ../src/utils/pasuspender.c:194 +#, c-format +msgid "WARNING: Child process terminated by signal %u\n" +msgstr "OSTRZEŻENIE: proces potomny został zniszczony przez sygnał %u\n" + +#: ../src/utils/pasuspender.c:212 +#, c-format +msgid "" +"%s [options] ... \n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +"\n" +msgstr "" +"%s [opcje] ... \n" +"\n" +" -h, --help Wyświetla tę pomoc\n" +" --version Wyświetla wersję\n" +" -s, --server=SERWER Nazwa serwera do połączenia się z\n" +"\n" + +#: ../src/utils/pasuspender.c:251 +#, c-format +msgid "" +"pasuspender %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"pasuspender %s\n" +"Skompilowane za pomocą libpulse %s\n" +"Skonsolidowane za pomocą libpulse %s\n" + +#: ../src/utils/pactl.c:107 +#, c-format +msgid "Failed to get statistics: %s\n" +msgstr "Uzyskanie statystyk nie powiodło się: %s\n" + +#: ../src/utils/pactl.c:113 +#, c-format +msgid "Currently in use: %u blocks containing %s bytes total.\n" +msgstr "Obecnie używane: %u bloków zawierających razem %s bajtów.\n" + +#: ../src/utils/pactl.c:116 +#, c-format +msgid "Allocated during whole lifetime: %u blocks containing %s bytes total.\n" +msgstr "" +"Przydzielono podczas całego czasu uruchomienia: %u bloków zawierających " +"razem %s bajtów.\n" + +#: ../src/utils/pactl.c:119 +#, c-format +msgid "Sample cache size: %s\n" +msgstr "Rozmiar pamięci podręcznej próbek: %s\n" + +#: ../src/utils/pactl.c:128 +#, c-format +msgid "Failed to get server information: %s\n" +msgstr "Uzyskanie informacji o serwerze nie powiodło się: %s\n" + +#: ../src/utils/pactl.c:135 +#, c-format +msgid "" +"User name: %s\n" +"Host Name: %s\n" +"Server Name: %s\n" +"Server Version: %s\n" +"Default Sample Specification: %s\n" +"Default Sink: %s\n" +"Default Source: %s\n" +"Cookie: %08x\n" +msgstr "" +"Nazwa użytkownika: %s\n" +"Nazwa komputera: %s\n" +"Nazwa serwera: %s\n" +"Wersja serwera: %s\n" +"Domyślne określenie próbki: %s\n" +"Domyślny odpływ: %s\n" +"Domyślne źródło: %s\n" +"Ciasteczko: %08x\n" + +#: ../src/utils/pactl.c:160 +#, c-format +msgid "Failed to get sink information: %s\n" +msgstr "Uzyskanie informacji o odpływie nie powiodło się: %s\n" + +#: ../src/utils/pactl.c:176 +#, c-format +msgid "" +"*** Sink #%u ***\n" +"Name: %s\n" +"Driver: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Owner Module: %u\n" +"Volume: %s\n" +"Monitor Source: %s\n" +"Latency: %0.0f usec, configured %0.0f usec\n" +"Flags: %s%s%s%s%s%s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Odpływ #%u ***\n" +"Nazwa: %s\n" +"Sterownik: %s\n" +"Określenie próbki: %s\n" +"Mapa kanałów: %s\n" +"Właściciel modułu: %u\n" +"Poziom głośności: %s\n" +"Źródło monitora: %s\n" +"Opóźnienie: %0.0f usekundy, skonfigurowano %0.0f usekundy\n" +"Flagi: %s%s%s%s%s%s\n" +"Właściwości:\n" +"%s" + +#: ../src/utils/pactl.c:193 ../src/utils/pactl.c:371 +msgid "muted" +msgstr "wyciszone" + +#: ../src/utils/pactl.c:212 +#, c-format +msgid "Failed to get source information: %s\n" +msgstr "Uzyskanie informacji o źródle nie powiodło się: %s\n" + +#: ../src/utils/pactl.c:228 +#, c-format +msgid "" +"*** Source #%u ***\n" +"Name: %s\n" +"Driver: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Owner Module: %u\n" +"Volume: %s\n" +"Monitor of Sink: %s\n" +"Latency: %0.0f usec, configured %0.0f usec\n" +"Flags: %s%s%s%s%s%s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Źródło #%u ***\n" +"Nazwa: %s\n" +"Sterownik: %s\n" +"Określenie próbki: %s\n" +"Mapa kanałów: %s\n" +"Właściciel modułu: %u\n" +"Poziom głośności: %s\n" +"Monitor odpływu: %s\n" +"Opóźnienie: %0.0f usekundy, skonfigurowano %0.0f usekundy\n" +"Flagi: %s%s%s%s%s%s\n" +"Właściwości:\n" +"%s" + +#: ../src/utils/pactl.c:246 ../src/utils/pactl.c:289 ../src/utils/pactl.c:322 +#: ../src/utils/pactl.c:366 ../src/utils/pactl.c:367 ../src/utils/pactl.c:374 +#: ../src/utils/pactl.c:418 ../src/utils/pactl.c:419 ../src/utils/pactl.c:425 +#: ../src/utils/pactl.c:468 ../src/utils/pactl.c:469 ../src/utils/pactl.c:473 +msgid "n/a" +msgstr "nie dotyczy" + +#: ../src/utils/pactl.c:263 +#, c-format +msgid "Failed to get module information: %s\n" +msgstr "Uzyskanie informacji o module nie powiodło się: %s\n" + +#: ../src/utils/pactl.c:281 +#, c-format +msgid "" +"*** Module #%u ***\n" +"Name: %s\n" +"Argument: %s\n" +"Usage counter: %s\n" +"Auto unload: %s\n" +msgstr "" +"*** Moduł #%u ***\n" +"Nazwa: %s\n" +"Parametr: %s\n" +"Liczniki użycia: %s\n" +"Automatyczne usuwanie: %s\n" + +#: ../src/utils/pactl.c:298 +#, c-format +msgid "Failed to get client information: %s\n" +msgstr "Uzyskanie informacji o kliencie nie powiodło się: %s\n" + +#: ../src/utils/pactl.c:316 +#, c-format +msgid "" +"*** Client #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Klient #%u ***\n" +"Sterownik: %s\n" +"Właściciel modułu: %s\n" +"Właściwości:\n" +"%s" + +#: ../src/utils/pactl.c:333 +#, c-format +msgid "Failed to get sink input information: %s\n" +msgstr "Uzyskanie informacji o wejściu odpływu nie powiodło się: %s\n" + +#: ../src/utils/pactl.c:352 +#, c-format +msgid "" +"*** Sink Input #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Client: %s\n" +"Sink: %u\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Volume: %s\n" +"Buffer Latency: %0.0f usec\n" +"Sink Latency: %0.0f usec\n" +"Resample method: %s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Odpływ wejścia #%u ***\n" +"Sterownik: %s\n" +"Właściciel modułu: %s\n" +"Klient: %s\n" +"Odpływ: %u\n" +"Określenie próbki: %s\n" +"Mapa kanałów: %s\n" +"Poziom głośności: %s\n" +"Opóźnienie bufora: %0.0f usekundy\n" +"Opóźnienie odpływu: %0.0f usekundy\n" +"Metoda resamplingu: %s\n" +"Właściwości:\n" +"%s" + +#: ../src/utils/pactl.c:385 +#, c-format +msgid "Failed to get source output information: %s\n" +msgstr "Uzyskanie informacji o wyjściu źródła nie powiodło się: %s\n" + +#: ../src/utils/pactl.c:405 +#, c-format +msgid "" +"*** Source Output #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Client: %s\n" +"Source: %u\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Buffer Latency: %0.0f usec\n" +"Source Latency: %0.0f usec\n" +"Resample method: %s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Źródło wyjścia #%u ***\n" +"Sterownik: %s\n" +"Właściciel modułu: %s\n" +"Klient: %s\n" +"Źródło: %u\n" +"Określenie próbki: %s\n" +"Mapa kanałów: %s\n" +"Opóźnienie bufora: %0.0f usekundy\n" +"Opóźnienie źródła: %0.0f usekundy\n" +"Metoda resamplingu: %s\n" +"Właściwości:\n" +"%s" + +#: ../src/utils/pactl.c:436 +#, c-format +msgid "Failed to get sample information: %s\n" +msgstr "Uzyskanie informacji o przykładzie nie powiodło się: %s\n" + +#: ../src/utils/pactl.c:455 +#, c-format +msgid "" +"*** Sample #%u ***\n" +"Name: %s\n" +"Volume: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Duration: %0.1fs\n" +"Size: %s\n" +"Lazy: %s\n" +"Filename: %s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Próbka #%u ***\n" +"Nazwa: %s\n" +"Poziom głośności: %s\n" +"Określenie próbki: %s\n" +"Mapa kanałów: %s\n" +"Czas trwania: %0.1fs\n" +"Rozmiar: %s\n" +"Lazy: %s\n" +"Nazwa pliku: %s\n" +"Właściwości:\n" +"%s" + +#: ../src/utils/pactl.c:481 +#, c-format +msgid "Failed to get autoload information: %s\n" +msgstr "" +"Uzyskanie informacji o automatycznym wczytywaniu nie powiodło się: %s\n" + +#: ../src/utils/pactl.c:497 +#, c-format +msgid "" +"*** Autoload Entry #%u ***\n" +"Name: %s\n" +"Type: %s\n" +"Module: %s\n" +"Argument: %s\n" +msgstr "" +"*** Wpis automatycznego wczytywania #%u ***\n" +"Nazwa: %s\n" +"Typ: %s\n" +"Moduł: %s\n" +"Parametr: %s\n" + +#: ../src/utils/pactl.c:504 +msgid "sink" +msgstr "odpływ" + +#: ../src/utils/pactl.c:504 +msgid "source" +msgstr "źródło" + +#: ../src/utils/pactl.c:511 ../src/utils/pactl.c:521 +#, c-format +msgid "Failure: %s\n" +msgstr "Niepowodzenie: %s\n" + +#: ../src/utils/pactl.c:545 +#, c-format +msgid "Failed to upload sample: %s\n" +msgstr "Usunięcie próbki nie powiodło się: %s\n" + +#: ../src/utils/pactl.c:562 +#, c-format +msgid "Premature end of file\n" +msgstr "Przedwczesny koniec pliku\n" + +#: ../src/utils/pactl.c:678 +#, c-format +msgid "" +"%s [options] stat\n" +"%s [options] list\n" +"%s [options] exit\n" +"%s [options] upload-sample FILENAME [NAME]\n" +"%s [options] play-sample NAME [SINK]\n" +"%s [options] remove-sample NAME\n" +"%s [options] move-sink-input ID SINK\n" +"%s [options] move-source-output ID SOURCE\n" +"%s [options] load-module NAME [ARGS ...]\n" +"%s [options] unload-module ID\n" +"%s [options] suspend-sink [SINK] 1|0\n" +"%s [options] suspend-source [SOURCE] 1|0\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +msgstr "" +"%s [opcje] stat\n" +"%s [opcje] list\n" +"%s [opcje] exit\n" +"%s [opcje] upload-sample NAZWAPLIKU [NAZWA]\n" +"%s [opcje] play-sample NAZWA [ODPŁYW]\n" +"%s [opcje] remove-sample NAZWA\n" +"%s [opcje] move-sink-input IDENTYFIKATOR ODPŁYW\n" +"%s [opcje] move-source-output IDENTYFIKATOR ŹRÓDŁO\n" +"%s [opcje] load-module NAZWA [PARAMETRY...]\n" +"%s [opcje] unload-module IDENTYFIKATOR\n" +"%s [opcje] suspend-sink [ODPŁYW] 1|0\n" +"%s [opcje] suspend-source [ŹRÓDŁO] 1|0\n" +"\n" +" -h, --help Wyświetla tę pomoc\n" +" --version Wyświetla wersję\n" +"\n" +" -s, --server=SERWER Nazwa serwera do połączenia się z\n" +" -n, --client-name=NAZWA Jak nazwać tego klienta na serwerze\n" + +#: ../src/utils/pactl.c:729 +#, c-format +msgid "" +"pactl %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"pactl %s\n" +"Skompilowane za pomocą libpulse %s\n" +"Skonsolidowane za pomocą libpulse %s\n" + +#: ../src/utils/pactl.c:768 +#, c-format +msgid "Please specify a sample file to load\n" +msgstr "Proszę podać plik próbki do wczytania\n" + +#: ../src/utils/pactl.c:790 +#, c-format +msgid "Failed to open sound file.\n" +msgstr "Otwarcie pliku dźwiękowego nie powiodło się.\n" + +#: ../src/utils/pactl.c:802 +#, c-format +msgid "You have to specify a sample name to play\n" +msgstr "Należy podać nazwę próbki do odtworzenia\n" + +#: ../src/utils/pactl.c:814 +#, c-format +msgid "You have to specify a sample name to remove\n" +msgstr "Należy podać nazwę próbki do usunięcia\n" + +#: ../src/utils/pactl.c:822 +#, c-format +msgid "You have to specify a sink input index and a sink\n" +msgstr "Należy podać indeks odpływu wejścia i odpływ\n" + +#: ../src/utils/pactl.c:831 +#, c-format +msgid "You have to specify a source output index and a source\n" +msgstr "Należy podać indeks źródła wyjścia i źródło\n" + +#: ../src/utils/pactl.c:845 +#, c-format +msgid "You have to specify a module name and arguments.\n" +msgstr "Należy podać nazwę modułu i parametry.\n" + +#: ../src/utils/pactl.c:865 +#, c-format +msgid "You have to specify a module index\n" +msgstr "Należy podać indeks modułu\n" + +#: ../src/utils/pactl.c:875 +#, c-format +msgid "" +"You may not specify more than one sink. You have to specify at least one " +"boolean value.\n" +msgstr "" +"Nie można podać więcej niż jednego odpływu. Należy podać co najmniej jedną " +"wartość logiczną.\n" + +#: ../src/utils/pactl.c:888 +#, c-format +msgid "" +"You may not specify more than one source. You have to specify at least one " +"boolean value.\n" +msgstr "" +"Nie można podać więcej niż jednego źródła. Należy podać co najmniej jedną " +"wartość logiczną.\n" + +#: ../src/utils/pactl.c:904 +#, c-format +msgid "No valid command specified.\n" +msgstr "Nie podano prawidłowego polecenia.\n" + +#: ../src/utils/pax11publish.c:61 +#, c-format +msgid "" +"%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n" +"\n" +" -d Show current PulseAudio data attached to X11 display (default)\n" +" -e Export local PulseAudio data to X11 display\n" +" -i Import PulseAudio data from X11 display to local environment " +"variables and cookie file.\n" +" -r Remove PulseAudio data from X11 display\n" +msgstr "" +"%s [-D ekran] [-S serwer] [-O odpływ] [-I źródło] [-c plik] [-d|-e|-i|-r]\n" +"\n" +" -d Wyświetla dane PulseAudio dołączone do ekranu X11 (domyślne)\n" +" -e Eksportuje lokalne dane PulseAudio na ekran X11\n" +" -i Importuje dane PulseAudio z ekranu X11 do lokalnych zmiennych " +"środowiskowych i pliku ciasteczka.\n" +" -r Usuwa dane PulseAudio z ekranu X11\n" + +#: ../src/utils/pax11publish.c:94 +#, c-format +msgid "Failed to parse command line.\n" +msgstr "Analiza wiersza poleceń nie powiodła się.\n" + +#: ../src/utils/pax11publish.c:108 +#, c-format +msgid "Server: %s\n" +msgstr "Serwer: %s\n" + +#: ../src/utils/pax11publish.c:110 +#, c-format +msgid "Source: %s\n" +msgstr "Źródło: %s\n" + +#: ../src/utils/pax11publish.c:112 +#, c-format +msgid "Sink: %s\n" +msgstr "Odpływ: %s\n" + +#: ../src/utils/pax11publish.c:114 +#, c-format +msgid "Cookie: %s\n" +msgstr "Ciasteczko: %s\n" + +#: ../src/utils/pax11publish.c:132 +#, c-format +msgid "Failed to parse cookie data\n" +msgstr "Analiza danych ciasteczka nie powiodła się\n" + +#: ../src/utils/pax11publish.c:137 +#, c-format +msgid "Failed to save cookie data\n" +msgstr "Zapisanie danych ciasteczka nie powiodło się\n" + +#: ../src/utils/pax11publish.c:152 +#, c-format +msgid "Failed to load client configuration file.\n" +msgstr "Wczytanie pliku konfiguracji klienta nie powiodło się.\n" + +#: ../src/utils/pax11publish.c:157 +#, c-format +msgid "Failed to read environment configuration data.\n" +msgstr "Odczytanie danych konfiguracji środowiska nie powiodło się.\n" + +#: ../src/utils/pax11publish.c:174 +#, c-format +msgid "Failed to get FQDN.\n" +msgstr "Uzyskanie FQDN nie powiodło się.\n" + +#: ../src/utils/pax11publish.c:194 +#, c-format +msgid "Failed to load cookie data\n" +msgstr "Wczytanie danych ciasteczka nie powiodło się\n" + +#: ../src/utils/pax11publish.c:211 +#, c-format +msgid "Not yet implemented.\n" +msgstr "Niezaimplementowane.\n" + +#: ../src/utils/pacmd.c:64 +#, c-format +msgid "socket(PF_UNIX, SOCK_STREAM, 0): %s" +msgstr "gniazdo(PF_UNIX, SOCK_STREAM, 0): %s" + +#: ../src/utils/pacmd.c:81 +#, c-format +msgid "connect(): %s" +msgstr "connect(): %s" + +#: ../src/utils/pacmd.c:89 +msgid "Failed to kill PulseAudio daemon." +msgstr "Zniszczenie demona PulseAudio nie powiodło się." + +#: ../src/utils/pacmd.c:97 +msgid "Daemon not responding." +msgstr "Demon nie odpowiada." + +#: ../src/utils/pacmd.c:112 +#, c-format +msgid "select(): %s" +msgstr "select(): %s" + +#: ../src/utils/pacmd.c:124 ../src/utils/pacmd.c:140 +#, c-format +msgid "read(): %s" +msgstr "read(): %s" + +#: ../src/utils/pacmd.c:153 ../src/utils/pacmd.c:167 +#, c-format +msgid "write(): %s" +msgstr "write(): %s" + +#: ../src/utils/paplay.c:139 +#, c-format +msgid "Stream successfully created\n" +msgstr "Pomyślnie utworzono strumień\n" + +#: ../src/utils/paplay.c:144 +#, c-format +msgid "Stream errror: %s\n" +msgstr "Błąd strumienia: %s\n" + +#: ../src/utils/paplay.c:165 +#, c-format +msgid "Connection established.\n" +msgstr "Ustanowiono połączenie.\n" + +#: ../src/utils/paplay.c:198 +#, c-format +msgid "" +"%s [options] [FILE]\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -v, --verbose Enable verbose operation\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -d, --device=DEVICE The name of the sink to connect to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" +" --channel-map=CHANNELMAP Set the channel map to the use\n" +msgstr "" +"%s [opcje] [PLIK]\n" +"\n" +" -h, --help Wyświetla tę pomoc\n" +" --version Wyświetla wersję\n" +"\n" +" -v, --verbose Wyświetla więcej informacji o " +"działaniach\n" +"\n" +" -s, --server=SERWER Nazwa serwera do połączenia się z\n" +" -d, --device=URZĄDZENIE Nazwa odpływu do połączenia się z\n" +" -n, --client-name=NAZWA Jak nazwać tego klienta na serwerze\n" +" --stream-name=NAZWA Jak nazwać ten strumień na serwerze\n" +" --volume=POZIOMGŁOŚNOŚCI Określa początkowy (liniowy) poziom " +"głośności w zakresie 0...65536\n" +" --channel-map=MAPAKANAŁÓW Ustawia używaną mapę kanałów\n" + +#: ../src/utils/paplay.c:255 +#, c-format +msgid "" +"paplay %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"paplay %s\n" +"Skompilowane za pomocą libpulse %s\n" +"Skonsolidowane za pomocą libpulse %s\n" + +#: ../src/utils/paplay.c:292 +#, c-format +msgid "Invalid channel map\n" +msgstr "Nieprawidłowa mapa kanałów\n" + +#: ../src/utils/paplay.c:314 +#, c-format +msgid "Failed to open file '%s'\n" +msgstr "Otwarcie pliku \"%s\" nie powiodło się\n" + +#: ../src/utils/paplay.c:350 +#, c-format +msgid "Channel map doesn't match file.\n" +msgstr "Mapa kanałów nie zgadza się z plikiem.\n" + +#: ../src/utils/paplay.c:376 +#, c-format +msgid "Using sample spec '%s'\n" +msgstr "Używanie przykładowej specyfikacji \"%s\"\n" + +#: ../src/pulsecore/lock-autospawn.c:126 ../src/pulsecore/lock-autospawn.c:207 +msgid "Cannot access autospawn lock." +msgstr "Nie można uzyskać dostępu do blokady automatycznego wznawiania." diff --git a/po/pt_BR.po b/po/pt_BR.po new file mode 100644 index 00000000..94494f7f --- /dev/null +++ b/po/pt_BR.po @@ -0,0 +1,2130 @@ +# Brazilian Translation of PulseAudio +# Copyright (C) 2008 pulseaudio +# This file is distributed under the same license as the pulseaudio package. +# Fabian Affolter <fab@fedoraproject.org>, 2008. +# +msgid "" +msgstr "" +"Project-Id-Version: pulseaudio\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-07 21:03+0200\n" +"PO-Revision-Date: 2008-09-21 17:05-0300\n" +"Last-Translator: Herli Menezes <herlimenezes@gmail.com>\n" +"Language-Team: Brazilian-Portuguese <fedora-trans-pt_br@redhat.com>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Poedit-Language: Brazilian Portuguese\n" +"X-Poedit-Country: Brazil\n" + +#: ../src/daemon/ltdl-bind-now.c:177 ../src/daemon/ltdl-bind-now.c:197 +msgid "Failed to add bind-now-loader." +msgstr "Falha em adicionar o bind-now-loader." + +#: ../src/daemon/ltdl-bind-now.c:184 +msgid "Failed to find original dlopen loader." +msgstr "Falha em encontrar o carregador original dlopen" + +#: ../src/daemon/polkit.c:55 +#, c-format +msgid "Cannot connect to system bus: %s" +msgstr "Não foi possível conectar com o barramento do sistema: %s" + +#: ../src/daemon/polkit.c:65 +#, c-format +msgid "Cannot get caller from PID: %s" +msgstr "Não foi possível obter quem chamou pelo PID: %s" + +#: ../src/daemon/polkit.c:77 +msgid "Cannot set UID on caller object." +msgstr "Não foi possível definir o UID sobre o objeto que chamou." + +#: ../src/daemon/polkit.c:82 +msgid "Failed to get CK session." +msgstr "Falha em obter a sessão CK." + +#: ../src/daemon/polkit.c:90 +msgid "Cannot set UID on session object." +msgstr "Não foi possível definir o UID do objeto da sessão." + +#: ../src/daemon/polkit.c:95 +msgid "Cannot allocate PolKitAction." +msgstr "Não foi possível alocar o PolKitAction." + +#: ../src/daemon/polkit.c:100 +msgid "Cannot set action_id" +msgstr "Não foi possível definir a action_id" + +#: ../src/daemon/polkit.c:105 +msgid "Cannot allocate PolKitContext." +msgstr "Não foi possível alocar o PolKitContext." + +#: ../src/daemon/polkit.c:110 +#, c-format +msgid "Cannot initialize PolKitContext: %s" +msgstr "Não foi possível iniciar o PolKitContext: %s" + +#: ../src/daemon/polkit.c:119 +#, c-format +msgid "Could not determine whether caller is authorized: %s" +msgstr "Não foi possível determinar se o solicitante está autorizado: %s" + +#: ../src/daemon/polkit.c:139 +#, c-format +msgid "Cannot obtain auth: %s" +msgstr "Não foi possível obter auth: %s" + +#: ../src/daemon/polkit.c:148 +#, c-format +msgid "PolicyKit responded with '%s'" +msgstr "PolicyKit respondeu com '%s'" + +#: ../src/daemon/main.c:134 +#, c-format +msgid "Got signal %s." +msgstr "Sinal %s recebido." + +#: ../src/daemon/main.c:161 +msgid "Exiting." +msgstr "Saindo." + +#: ../src/daemon/main.c:179 +#, c-format +msgid "Failed to find user '%s'." +msgstr "Falha em encontrar o usuário '%s'." + +#: ../src/daemon/main.c:184 +#, c-format +msgid "Failed to find group '%s'." +msgstr "Falha em encontrar o grupo '%s'." + +#: ../src/daemon/main.c:188 +#, c-format +msgid "Found user '%s' (UID %lu) and group '%s' (GID %lu)." +msgstr "Usuário '%s' (UID %lu) e grupo '%s' (GID %lu) encontrados." + +#: ../src/daemon/main.c:193 +#, c-format +msgid "GID of user '%s' and of group '%s' don't match." +msgstr "O GID do usuário'%s' e do grupo '%s' não combinam." + +#: ../src/daemon/main.c:198 +#, c-format +msgid "Home directory of user '%s' is not '%s', ignoring." +msgstr "O diretório Home do usuário '%s' não é '%s', ignorando." + +#: ../src/daemon/main.c:201 ../src/daemon/main.c:206 +#, c-format +msgid "Failed to create '%s': %s" +msgstr "Falha em criar '%s': %s" + +#: ../src/daemon/main.c:213 +#, c-format +msgid "Failed to change group list: %s" +msgstr "Falha em alterar a lista de grupos: %s" + +#: ../src/daemon/main.c:229 +#, c-format +msgid "Failed to change GID: %s" +msgstr "Falha em mudar o GID: %s" + +#: ../src/daemon/main.c:245 +#, c-format +msgid "Failed to change UID: %s" +msgstr "Falha em mudar o UID: %s" + +#: ../src/daemon/main.c:259 +msgid "Successfully dropped root privileges." +msgstr "Os privilégios do root foram retirados com sucesso." + +#: ../src/daemon/main.c:267 +msgid "System wide mode unsupported on this platform." +msgstr "O modo ampliado do sistema não tem suporte nessa plataforma." + +#: ../src/daemon/main.c:285 +#, c-format +msgid "setrlimit(%s, (%u, %u)) failed: %s" +msgstr "setrlimit(%s, (%u, %u)) falhou: %s" + +#: ../src/daemon/main.c:425 +msgid "Failed to parse command line." +msgstr "Falha em interpretar a linha de comando." + +#: ../src/daemon/main.c:441 +#, c-format +msgid "We're in the group '%s', allowing high-priority scheduling." +msgstr "Estamos no grupo '%s', permitindo escalonamento de alta prioridade." + +#: ../src/daemon/main.c:448 +#, c-format +msgid "We're in the group '%s', allowing real-time scheduling." +msgstr "Estamos no grupo '%s', permitindo escalonamento em tempo real." + +#: ../src/daemon/main.c:456 +msgid "PolicyKit grants us acquire-high-priority privilege." +msgstr "O PolicyKit assegura-nos a aquisição de privilégio de alta prioridade." + +#: ../src/daemon/main.c:459 +msgid "PolicyKit refuses acquire-high-priority privilege." +msgstr "O PolicyKit recusa a aquisição de privilégios de alta prioridade." + +#: ../src/daemon/main.c:464 +msgid "PolicyKit grants us acquire-real-time privilege." +msgstr "O PolicyKit assegura-nos a aquisição de privilégios de tempo-real." + +#: ../src/daemon/main.c:467 +msgid "PolicyKit refuses acquire-real-time privilege." +msgstr "O PolicyKit recusa a aquisição de privilégios de tempo real." + +#: ../src/daemon/main.c:479 +msgid "" +"Called SUID root and real-time/high-priority scheduling was requested in the " +"configuration. However, we lack the necessary priviliges:\n" +"We are not in group '" +msgstr "" +"A chamada de SUID root e tempo real/alta prioridade no escalonamento foi " +"requisitada pela configuração. Todavia, falta-nos os privilégios " +"necessários:\n" +"Não estamos no grupo'" + +#: ../src/daemon/main.c:497 +msgid "" +"High-priority scheduling enabled in configuration but not allowed by policy." +msgstr "" +"O escalonamento de alta prioridade foi habilitado para esta configuração, " +"mas não é permitida pela política." + +#: ../src/daemon/main.c:522 +msgid "Successfully increased RLIMIT_RTPRIO" +msgstr "RLIMIT_RTPRIO aumentado com sucesso" + +#: ../src/daemon/main.c:525 +#, c-format +msgid "RLIMIT_RTPRIO failed: %s" +msgstr "RLIMIT_RTPRIO falhou: %s" + +#: ../src/daemon/main.c:532 +msgid "Giving up CAP_NICE" +msgstr "Abandonando CAP_NICE" + +#: ../src/daemon/main.c:539 +msgid "" +"Real-time scheduling enabled in configuration but not allowed by policy." +msgstr "" +"O escalonamento de tempo real foi habilitado pela configuração, mas não é " +"permitido pela política." + +#: ../src/daemon/main.c:597 +msgid "Daemon not running" +msgstr "O daemon não está em execução" + +#: ../src/daemon/main.c:599 +#, c-format +msgid "Daemon running as PID %u" +msgstr "Daemon executando como PID %u" + +#: ../src/daemon/main.c:609 +#, c-format +msgid "Failed to kill daemon: %s" +msgstr "Falha em encerrar o daemon: %s" + +#: ../src/daemon/main.c:627 +msgid "" +"This program is not intended to be run as root (unless --system is " +"specified)." +msgstr "" +"Este programa não é para ser executado como root (a não ser que --system " +"seja especificado)." + +#: ../src/daemon/main.c:629 +msgid "Root priviliges required." +msgstr "Privilégios de rot são requeridos." + +#: ../src/daemon/main.c:634 +msgid "--start not supported for system instances." +msgstr "--start não tem suporte para instâncias de sistemas." + +#: ../src/daemon/main.c:639 +msgid "Running in system mode, but --disallow-exit not set!" +msgstr "Executando em no modo system, mas --disallow-exit não foi configurado!" + +#: ../src/daemon/main.c:642 +msgid "Running in system mode, but --disallow-module-loading not set!" +msgstr "" +"Executando no modo system, mas --disallow-module-loading não foi configurado!" + +#: ../src/daemon/main.c:645 +msgid "Running in system mode, forcibly disabling SHM mode!" +msgstr "Executando no modo system, desabilitando forçadamente o modo SHM!" + +#: ../src/daemon/main.c:650 +msgid "Running in system mode, forcibly disabling exit idle time!" +msgstr "" +"Executando no modo system, desabilitando forçadamente o exit idle time!" + +#: ../src/daemon/main.c:677 +msgid "Failed to acquire stdio." +msgstr "Falha em adquirir o stdio." + +#: ../src/daemon/main.c:683 +#, c-format +msgid "pipe failed: %s" +msgstr "O pipe falhou: %s" + +#: ../src/daemon/main.c:688 +#, c-format +msgid "fork() failed: %s" +msgstr "O fork() falhou: %s" + +#: ../src/daemon/main.c:702 +#, c-format +msgid "read() failed: %s" +msgstr "A operação read() falhou: %s" + +#: ../src/daemon/main.c:708 +msgid "Daemon startup failed." +msgstr "Falha na partida do daemon." + +#: ../src/daemon/main.c:710 +msgid "Daemon startup successful." +msgstr "Os daemons foram iniciados com sucesso." + +#: ../src/daemon/main.c:780 +#, c-format +msgid "This is PulseAudio %s" +msgstr "Este é o PulseAudio %s" + +#: ../src/daemon/main.c:781 +#, c-format +msgid "Compilation host: %s" +msgstr "Host de compilação: %s" + +#: ../src/daemon/main.c:782 +#, c-format +msgid "Compilation CFLAGS: %s" +msgstr "Compilação CFLAGS: %s" + +#: ../src/daemon/main.c:785 +#, c-format +msgid "Running on host: %s" +msgstr "Executando no host: %s" + +#: ../src/daemon/main.c:788 +#, c-format +msgid "Page size is %lu bytes" +msgstr "O tamanho da página é %lu bytes" + +#: ../src/daemon/main.c:791 +msgid "Compiled with Valgrind support: yes" +msgstr "Compilado com suporte do Valgrind: sim" + +#: ../src/daemon/main.c:793 +msgid "Compiled with Valgrind support: no" +msgstr "Compilado com suporte do Valgrind: não" + +#: ../src/daemon/main.c:796 +#, fuzzy, c-format +msgid "Running in valgrind mode: %s" +msgstr "Executando em modo do sistema: %s" + +#: ../src/daemon/main.c:799 +msgid "Optimized build: yes" +msgstr "Build otimizado: sim" + +#: ../src/daemon/main.c:801 +msgid "Optimized build: no" +msgstr "Build otimizado: não" + +#: ../src/daemon/main.c:805 +msgid "Failed to get machine ID" +msgstr "Falha em obter o ID da máquina" + +#: ../src/daemon/main.c:808 +#, c-format +msgid "Machine ID is %s." +msgstr "A ID da máquina é %s." + +#: ../src/daemon/main.c:813 +#, c-format +msgid "Using runtime directory %s." +msgstr "Usando o diretório de runtime %s." + +#: ../src/daemon/main.c:818 +#, c-format +msgid "Using state directory %s." +msgstr "Usando o diretório de estado %s." + +#: ../src/daemon/main.c:821 +#, c-format +msgid "Running in system mode: %s" +msgstr "Executando em modo do sistema: %s" + +#: ../src/daemon/main.c:836 +msgid "pa_pid_file_create() failed." +msgstr "pa_pid_file_create() falhou." + +#: ../src/daemon/main.c:848 +msgid "Fresh high-resolution timers available! Bon appetit!" +msgstr "Timers de alta resolução frequinhos disponíveis! Bon appetit!" + +#: ../src/daemon/main.c:850 +msgid "" +"Dude, your kernel stinks! The chef's recommendation today is Linux with high-" +"resolution timers enabled!" +msgstr "" +"Cara, teu kernel fede! A recomendação do chef hoje é Linux com timers de " +"alta resolução habilitados!" + +#: ../src/daemon/main.c:860 +msgid "pa_core_new() failed." +msgstr "pa_core_new() falhou." + +#: ../src/daemon/main.c:921 +msgid "Failed to initialize daemon." +msgstr "Falha em iniciar o daemon." + +#: ../src/daemon/main.c:926 +msgid "Daemon startup without any loaded modules, refusing to work." +msgstr "" +"O Daemon iniciou sem qualquer módulo carregado, recusando-se a trabalhar." + +#: ../src/daemon/main.c:931 +#, c-format +msgid "Default sink name (%s) does not exist in name register." +msgstr "O nome padrão do destino (%s) não existe no registro de nomes." + +#: ../src/daemon/main.c:944 +msgid "Daemon startup complete." +msgstr "A partida dos Daemon está completa." + +#: ../src/daemon/main.c:950 +msgid "Daemon shutdown initiated." +msgstr "O encerramento do Daemon foi iniciado." + +#: ../src/daemon/main.c:971 +msgid "Daemon terminated." +msgstr "Daemon terminado." + +#: ../src/daemon/cmdline.c:117 +#, c-format +msgid "" +"%s [options]\n" +"\n" +"COMMANDS:\n" +" -h, --help Show this help\n" +" --version Show version\n" +" --dump-conf Dump default configuration\n" +" --dump-modules Dump list of available modules\n" +" --dump-resample-methods Dump available resample methods\n" +" --cleanup-shm Cleanup stale shared memory " +"segments\n" +" --start Start the daemon if it is not " +"running\n" +" -k --kill Kill a running daemon\n" +" --check Check for a running daemon\n" +"\n" +"OPTIONS:\n" +" --system[=BOOL] Run as system-wide instance\n" +" -D, --daemonize[=BOOL] Daemonize after startup\n" +" --fail[=BOOL] Quit when startup fails\n" +" --high-priority[=BOOL] Try to set high nice level\n" +" (only available as root, when SUID " +"or\n" +" with elevated RLIMIT_NICE)\n" +" --realtime[=BOOL] Try to enable realtime scheduling\n" +" (only available as root, when SUID " +"or\n" +" with elevated RLIMIT_RTPRIO)\n" +" --disallow-module-loading[=BOOL] Disallow module user requested " +"module\n" +" loading/unloading after startup\n" +" --disallow-exit[=BOOL] Disallow user requested exit\n" +" --exit-idle-time=SECS Terminate the daemon when idle and " +"this\n" +" time passed\n" +" --module-idle-time=SECS Unload autoloaded modules when idle " +"and\n" +" this time passed\n" +" --scache-idle-time=SECS Unload autoloaded samples when idle " +"and\n" +" this time passed\n" +" --log-level[=LEVEL] Increase or set verbosity level\n" +" -v Increase the verbosity level\n" +" --log-target={auto,syslog,stderr} Specify the log target\n" +" -p, --dl-search-path=PATH Set the search path for dynamic " +"shared\n" +" objects (plugins)\n" +" --resample-method=METHOD Use the specified resampling method\n" +" (See --dump-resample-methods for\n" +" possible values)\n" +" --use-pid-file[=BOOL] Create a PID file\n" +" --no-cpu-limit[=BOOL] Do not install CPU load limiter on\n" +" platforms that support it.\n" +" --disable-shm[=BOOL] Disable shared memory support.\n" +"\n" +"STARTUP SCRIPT:\n" +" -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module " +"with\n" +" the specified argument\n" +" -F, --file=FILENAME Run the specified script\n" +" -C Open a command line on the running " +"TTY\n" +" after startup\n" +"\n" +" -n Don't load default script file\n" +msgstr "" +"%s [opções]\n" +"\n" +"COMANDOS:\n" +" -h, --help Mostra esta ajuda\n" +" --version Mostra a versão\n" +" --dump-conf Descarrega a configuração padrão\n" +" --dump-modules Descarrega a lista de módulos " +"disponíveis\n" +" --dump-resample-methods Descarrega os métodos de " +"reamostragem (resample)\n" +" --cleanup-shm Limpa os segmentos de memória " +"compartilhados\n" +" --start Inicia o daemon se ele não estiver " +"em execução\n" +" -k --kill Encerra um daemon em execução\n" +" --check Verifica um daemon em execução\n" +"\n" +"OPÇÕES:\n" +" --system[=BOOL] Executa como uma instância do " +"sistema em escala ampla \n" +" -D, --daemonize[=BOOL] Torna um daemom (daemonize) depois " +"da partida\n" +" --fail[=BOOL] Sai quando a partida falha\n" +" --high-priority[=BOOL] Tenta definir um nível alto de nice\n" +" (disponível apenas, quando SUID ou\n" +" com RLIMIT_NICE) elevado\n" +" --realtime[=BOOL] Tenta habilidar o escalonamento em " +"tempo real\n" +" (disponível apenas como root, quando " +"SUID ou\n" +" com RLIMIT_RTPRIO) elevado\n" +" --disallow-module-loading[=BOOL] Não permite carga/descarga de módulo " +"requerido pelo usuário\n" +" depois da partida\n" +" --disallow-exit[=BOOL] Não permite saída requisitada pelo " +"usuário\n" +" --exit-idle-time=SECS Termina um daemon quando ocioso e " +"este\n" +" tempo foi decorrido\n" +" --module-idle-time=SECS Descarrega os modulos " +"autocarregáveis quando ociosos e\n" +" tempo foi decorrido\n" +" --scache-idle-time=SECS Descarrega amostras quando ociosas " +"e\n" +" este tempo tenha passado\n" +" --log-level[=LEVEL] Aumenta ou define o grau de " +"verbosidade\n" +" -v Aumenta o nível de verbosidade\n" +" --log-target={auto,syslog,stderr} Especifica o alvo do log\n" +" -p, --dl-search-path=PATH Define o caminho de busca (search " +"paht)para objetos (plugins)\n" +" dinamicamente commpartilhados\n" +" --resample-method=METHOD Usa o método de reamostragem " +"especificado\n" +" (Veja --dump-resample-methods para\n" +" valores possíveis)\n" +" --use-pid-file[=BOOL] Cria um arquivo PID file\n" +" --no-cpu-limit[=BOOL] Não instala um limitador de carga de " +"CPU load em\n" +" plataformas que o suportem.\n" +" --disable-shm[=BOOL] Desabilita o suporte a memória " +"compartilhada.\n" +"\n" +"STARTUP SCRIPT:\n" +" -L, --load=\"MODULE ARGUMENTS\" Carrega um plugin especificado " +"com\n" +" o argumento especificado\n" +" -F, --file=FILENAME Executa o script especificado\n" +" -C Abre uma linha de comando no TTY em " +"execução\n" +" depois da partida\n" +"\n" +" -n Não carrega o arquivo de script " +"padrão\n" + +#: ../src/daemon/cmdline.c:245 +msgid "--daemonize expects boolean argument" +msgstr "--daemonize espera argumento booleano" + +#: ../src/daemon/cmdline.c:252 +msgid "--fail expects boolean argument" +msgstr "--fail espera argumento booleano" + +#: ../src/daemon/cmdline.c:262 +msgid "" +"--log-level expects log level argument (either numeric in range 0..4 or one " +"of debug, info, notice, warn, error)." +msgstr "" +"--log-level espera um argumento em nível de log (seja numérico na faixa de " +"0..4 seja algum entre debug, info, notice, warn, error)." + +#: ../src/daemon/cmdline.c:274 +msgid "--high-priority expects boolean argument" +msgstr "--high-priority espera um argumento booleano" + +#: ../src/daemon/cmdline.c:281 +msgid "--realtime expects boolean argument" +msgstr "--realtime espera um argumento booleano" + +#: ../src/daemon/cmdline.c:288 +msgid "--disallow-module-loading expects boolean argument" +msgstr "--disallow-module-loading espera um argumento booleano" + +#: ../src/daemon/cmdline.c:295 +msgid "--disallow-exit boolean argument" +msgstr "--disallow-exit argumento booleano" + +#: ../src/daemon/cmdline.c:302 +msgid "--use-pid-file expects boolean argument" +msgstr "--use-pid-file espera argumento booleano" + +#: ../src/daemon/cmdline.c:319 +msgid "Invalid log target: use either 'syslog', 'stderr' or 'auto'." +msgstr "Log target inválido: use 'syslog', 'stderr' ou 'auto'." + +#: ../src/daemon/cmdline.c:338 +#, c-format +msgid "Invalid resample method '%s'." +msgstr "Método de reamostragem inválido '%s'." + +#: ../src/daemon/cmdline.c:345 +msgid "--system expects boolean argument" +msgstr "--system espera argumento booleano" + +#: ../src/daemon/cmdline.c:352 +msgid "--no-cpu-limit expects boolean argument" +msgstr "--no-cpu-limit espera argumento booleano" + +#: ../src/daemon/cmdline.c:359 +msgid "--disable-shm expects boolean argument" +msgstr "--disable-shm espera argumento booleano" + +#: ../src/daemon/dumpmodules.c:60 +#, c-format +msgid "Name: %s\n" +msgstr "Nome: %s\n" + +#: ../src/daemon/dumpmodules.c:63 +#, c-format +msgid "No module information available\n" +msgstr "Não há informação do módulo disponível\n" + +#: ../src/daemon/dumpmodules.c:66 +#, c-format +msgid "Version: %s\n" +msgstr "Versão: %s\n" + +#: ../src/daemon/dumpmodules.c:68 +#, c-format +msgid "Description: %s\n" +msgstr "Descrição: %s\n" + +#: ../src/daemon/dumpmodules.c:70 +#, c-format +msgid "Author: %s\n" +msgstr "Autor: %s\n" + +#: ../src/daemon/dumpmodules.c:72 +#, c-format +msgid "Usage: %s\n" +msgstr "Uso: %s\n" + +#: ../src/daemon/dumpmodules.c:73 +#, c-format +msgid "Load Once: %s\n" +msgstr "Carrega uma vez: %s\n" + +#: ../src/daemon/dumpmodules.c:77 +#, c-format +msgid "Path: %s\n" +msgstr "Caminho: %s\n" + +#: ../src/daemon/daemon-conf.c:205 +#, c-format +msgid "[%s:%u] Invalid log target '%s'." +msgstr "[%s:%u] Alvo do log inválido '%s'." + +#: ../src/daemon/daemon-conf.c:221 +#, c-format +msgid "[%s:%u] Invalid log level '%s'." +msgstr "[%s:%u] Nível de log inválido '%s'." + +#: ../src/daemon/daemon-conf.c:237 +#, c-format +msgid "[%s:%u] Invalid resample method '%s'." +msgstr "[%s:%u] Método de reamostragem inválido '%s'." + +#: ../src/daemon/daemon-conf.c:260 +#, c-format +msgid "[%s:%u] Invalid rlimit '%s'." +msgstr "[%s:%u] rlimit inválido '%s'." + +#: ../src/daemon/daemon-conf.c:267 +#, c-format +msgid "[%s:%u] rlimit not supported on this platform." +msgstr "[%s:%u] rlimit não tem suporte nessa plataforma." + +#: ../src/daemon/daemon-conf.c:283 +#, c-format +msgid "[%s:%u] Invalid sample format '%s'." +msgstr "[%s:%u] Formato de amostragem inválido '%s'." + +#: ../src/daemon/daemon-conf.c:301 +#, c-format +msgid "[%s:%u] Invalid sample rate '%s'." +msgstr "[%s:%u] Taxa de amostragem inválida '%s'." + +#: ../src/daemon/daemon-conf.c:319 +#, c-format +msgid "[%s:%u] Invalid sample channels '%s'." +msgstr "[%s:%u] Canais de amostragem inválidos'%s'." + +#: ../src/daemon/daemon-conf.c:337 +#, c-format +msgid "[%s:%u] Invalid number of fragments '%s'." +msgstr "[%s:%u] Números de fragmentos inválidos '%s'." + +#: ../src/daemon/daemon-conf.c:355 +#, c-format +msgid "[%s:%u] Invalid fragment size '%s'." +msgstr "[%s:%u] Tamanho de fragmentos inválido '%s'." + +#: ../src/daemon/daemon-conf.c:373 +#, c-format +msgid "[%s:%u] Invalid nice level '%s'." +msgstr "[%s:%u] Número de nice inválido'%s'." + +#: ../src/daemon/daemon-conf.c:570 +#, c-format +msgid "Failed to open configuration file: %s" +msgstr "Falha em abrir o arquivo de configuração: %s" + +#: ../src/daemon/daemon-conf.c:644 +#, c-format +msgid "### Read from configuration file: %s ###\n" +msgstr "### Lido do arquivo de configuração: %s ###\n" + +#: ../src/daemon/caps.c:63 +msgid "Dropping root priviliges." +msgstr "Descartando os privilégios de root." + +#: ../src/daemon/caps.c:103 +msgid "Limited capabilities successfully to CAP_SYS_NICE." +msgstr "As capacidades foram limitadas com sucesso para CAP_SYS_NICE." + +#: ../src/pulse/channelmap.c:102 +msgid "Mono" +msgstr "Mono" + +#: ../src/pulse/channelmap.c:104 +msgid "Front Center" +msgstr "Fronto-cental" + +#: ../src/pulse/channelmap.c:105 +msgid "Front Left" +msgstr "Frontal esquerdo" + +#: ../src/pulse/channelmap.c:106 +msgid "Front Right" +msgstr "Frontal direito" + +#: ../src/pulse/channelmap.c:108 +msgid "Rear Center" +msgstr "Posterior central" + +#: ../src/pulse/channelmap.c:109 +msgid "Rear Left" +msgstr "Posterior esquerdo" + +#: ../src/pulse/channelmap.c:110 +msgid "Rear Right" +msgstr "Posterior direito" + +#: ../src/pulse/channelmap.c:112 +msgid "Low Frequency Emmiter" +msgstr "Emissor de baixa freqüência" + +#: ../src/pulse/channelmap.c:114 +msgid "Front Left-of-center" +msgstr "Frontal Esquerdo do centro" + +#: ../src/pulse/channelmap.c:115 +msgid "Front Right-of-center" +msgstr "Frontal Direito do centro" + +#: ../src/pulse/channelmap.c:117 +msgid "Side Left" +msgstr "Lateral esquedo" + +#: ../src/pulse/channelmap.c:118 +msgid "Side Right" +msgstr "Lateral direito" + +#: ../src/pulse/channelmap.c:120 +msgid "Auxiliary 0" +msgstr "Auxiliar 0" + +#: ../src/pulse/channelmap.c:121 +msgid "Auxiliary 1" +msgstr "Auxiliar 1" + +#: ../src/pulse/channelmap.c:122 +msgid "Auxiliary 2" +msgstr "Auxiliar 2" + +#: ../src/pulse/channelmap.c:123 +msgid "Auxiliary 3" +msgstr "Auxiliar 3" + +#: ../src/pulse/channelmap.c:124 +msgid "Auxiliary 4" +msgstr "Auxiliar 4" + +#: ../src/pulse/channelmap.c:125 +msgid "Auxiliary 5" +msgstr "Auxiliar 5" + +#: ../src/pulse/channelmap.c:126 +msgid "Auxiliary 6" +msgstr "Auxiliar 6" + +#: ../src/pulse/channelmap.c:127 +msgid "Auxiliary 7" +msgstr "Auxiliar 7" + +#: ../src/pulse/channelmap.c:128 +msgid "Auxiliary 8" +msgstr "Auxiliar 8" + +#: ../src/pulse/channelmap.c:129 +msgid "Auxiliary 9" +msgstr "Auxiliar 9" + +#: ../src/pulse/channelmap.c:130 +msgid "Auxiliary 10" +msgstr "Auxiliar 10" + +#: ../src/pulse/channelmap.c:131 +msgid "Auxiliary 11" +msgstr "Auxiliar 11" + +#: ../src/pulse/channelmap.c:132 +msgid "Auxiliary 12" +msgstr "Auxiliar 12" + +#: ../src/pulse/channelmap.c:133 +msgid "Auxiliary 13" +msgstr "Auxiliar13" + +#: ../src/pulse/channelmap.c:134 +msgid "Auxiliary 14" +msgstr "Auxiliar 14" + +#: ../src/pulse/channelmap.c:135 +msgid "Auxiliary 15" +msgstr "Auxiliar 15" + +#: ../src/pulse/channelmap.c:136 +msgid "Auxiliary 16" +msgstr "Auxiliar 16" + +#: ../src/pulse/channelmap.c:137 +msgid "Auxiliary 17" +msgstr "Auxiliar 17" + +#: ../src/pulse/channelmap.c:138 +msgid "Auxiliary 18" +msgstr "Auxiliar 18" + +#: ../src/pulse/channelmap.c:139 +msgid "Auxiliary 19" +msgstr "Auxiliar 19" + +#: ../src/pulse/channelmap.c:140 +msgid "Auxiliary 20" +msgstr "Auxiliar 20" + +#: ../src/pulse/channelmap.c:141 +msgid "Auxiliary 21" +msgstr "Auxiliar 21" + +#: ../src/pulse/channelmap.c:142 +msgid "Auxiliary 22" +msgstr "Auxiliar 22" + +#: ../src/pulse/channelmap.c:143 +msgid "Auxiliary 23" +msgstr "Auxiliar 23" + +#: ../src/pulse/channelmap.c:144 +msgid "Auxiliary 24" +msgstr "Auxiliar 24" + +#: ../src/pulse/channelmap.c:145 +msgid "Auxiliary 25" +msgstr "Auxiliar 25" + +#: ../src/pulse/channelmap.c:146 +msgid "Auxiliary 26" +msgstr "Auxiliar 26" + +#: ../src/pulse/channelmap.c:147 +msgid "Auxiliary 27" +msgstr "Auxiliar 26" + +#: ../src/pulse/channelmap.c:148 +msgid "Auxiliary 28" +msgstr "Auxiliar 28" + +#: ../src/pulse/channelmap.c:149 +msgid "Auxiliary 29" +msgstr "Auxiliar 29" + +#: ../src/pulse/channelmap.c:150 +msgid "Auxiliary 30" +msgstr "Auxiliar 30" + +#: ../src/pulse/channelmap.c:151 +msgid "Auxiliary 31" +msgstr "Auxiliar 31" + +#: ../src/pulse/channelmap.c:153 +msgid "Top Center" +msgstr "Central Superior" + +#: ../src/pulse/channelmap.c:155 +msgid "Top Front Center" +msgstr "Central Frontal Superior" + +#: ../src/pulse/channelmap.c:156 +msgid "Top Front Left" +msgstr "Frontal Superior Esquerdo" + +#: ../src/pulse/channelmap.c:157 +msgid "Top Front Right" +msgstr "Fontal Superior Direito" + +#: ../src/pulse/channelmap.c:159 +msgid "Top Rear Center" +msgstr "Central Superior Posterior" + +#: ../src/pulse/channelmap.c:160 +msgid "Top Rear Left" +msgstr "Posterior Superior Esquerdo" + +#: ../src/pulse/channelmap.c:161 +msgid "Top Rear Right" +msgstr "Posterior Superior Direito" + +#: ../src/pulse/channelmap.c:472 ../src/pulse/sample.c:144 +#: ../src/pulse/volume.c:163 ../src/pulse/volume.c:194 +#, fuzzy +msgid "(invalid)" +msgstr "Inválido" + +#: ../src/pulse/error.c:43 +msgid "OK" +msgstr "OK" + +#: ../src/pulse/error.c:44 +msgid "Access denied" +msgstr "Acesso Negado" + +#: ../src/pulse/error.c:45 +msgid "Unknown command" +msgstr "Comando desconhecido" + +#: ../src/pulse/error.c:46 +msgid "Invalid argument" +msgstr "Argumento inválido" + +#: ../src/pulse/error.c:47 +msgid "Entity exists" +msgstr "Entidade existente" + +#: ../src/pulse/error.c:48 +msgid "No such entity" +msgstr "Não existe tal entidade" + +#: ../src/pulse/error.c:49 +msgid "Connection refused" +msgstr "Conexão recusada" + +#: ../src/pulse/error.c:50 +msgid "Protocol error" +msgstr "Erro de protocolo" + +#: ../src/pulse/error.c:51 +msgid "Timeout" +msgstr "Timeout" + +#: ../src/pulse/error.c:52 +msgid "No authorization key" +msgstr "Não há chave para autorização" + +#: ../src/pulse/error.c:53 +msgid "Internal error" +msgstr "Erro interno" + +#: ../src/pulse/error.c:54 +msgid "Connection terminated" +msgstr "Conexão terminada" + +#: ../src/pulse/error.c:55 +msgid "Entity killed" +msgstr "Entidade terminada" + +#: ../src/pulse/error.c:56 +msgid "Invalid server" +msgstr "Servidor inválido" + +#: ../src/pulse/error.c:57 +msgid "Module initalization failed" +msgstr "A inicialização do módulo falhou" + +#: ../src/pulse/error.c:58 +msgid "Bad state" +msgstr "Mau estado" + +#: ../src/pulse/error.c:59 +msgid "No data" +msgstr "Não há dados" + +#: ../src/pulse/error.c:60 +msgid "Incompatible protocol version" +msgstr "Versão de protocolo incompatível" + +#: ../src/pulse/error.c:61 +msgid "Too large" +msgstr "Muito grande" + +#: ../src/pulse/error.c:62 +msgid "Not supported" +msgstr "Não há suporte" + +#: ../src/pulse/error.c:63 +msgid "Unknown error code" +msgstr "Código de erro desconhecido" + +#: ../src/pulse/error.c:64 +msgid "No such extension" +msgstr "Não existe tal extensão" + +#: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100 +msgid "XOpenDisplay() failed" +msgstr "XOpenDisplay() falhou" + +#: ../src/pulse/client-conf-x11.c:78 +msgid "Failed to parse cookie data" +msgstr "Falhou ao analisar os dados do cookie" + +#: ../src/pulse/client-conf.c:120 +#, c-format +msgid "Failed to open configuration file '%s': %s" +msgstr "Falha em abrir o arquivo de configuração '%s': %s" + +#: ../src/pulse/context.c:516 +msgid "No cookie loaded. Attempting to connect without." +msgstr "Nenhum cookie foi carregado. Tentativa de conexão sem eles." + +#: ../src/pulse/context.c:642 +#, c-format +msgid "fork(): %s" +msgstr "fork(): %s" + +#: ../src/pulse/context.c:695 +#, c-format +msgid "waitpid(): %s" +msgstr "waitpid(): %s" + +#: ../src/pulse/context.c:1256 +#, c-format +msgid "Received message for unknown extension '%s'" +msgstr "Foi recebida uma mensagem para uma extensão desconhecida '%s'" + +#: ../src/utils/pacat.c:93 +#, c-format +msgid "pa_stream_write() failed: %s\n" +msgstr "pa_stream_write() falhou: %s\n" + +#: ../src/utils/pacat.c:132 +#, c-format +msgid "pa_stream_peek() failed: %s\n" +msgstr "pa_stream_peek() falhou: %s\n" + +#: ../src/utils/pacat.c:141 +#, c-format +msgid "Buffer overrun, dropping incoming data\n" +msgstr "Houve estouro de buffer, os dados que chegaram foram descartados\n" + +#: ../src/utils/pacat.c:143 +#, c-format +msgid "pa_stream_drop() failed: %s\n" +msgstr "pa_stream_drop() falhou: %s\n" + +#: ../src/utils/pacat.c:169 +#, c-format +msgid "Stream successfully created.\n" +msgstr "O fluxo (stream) foi criado com sucesso.\n" + +#: ../src/utils/pacat.c:172 +#, c-format +msgid "pa_stream_get_buffer_attr() failed: %s\n" +msgstr "pa_stream_get_buffer_attr() falhou: %s\n" + +#: ../src/utils/pacat.c:176 +#, c-format +msgid "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n" +msgstr "Metrica do buffer: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n" + +#: ../src/utils/pacat.c:179 +#, c-format +msgid "Buffer metrics: maxlength=%u, fragsize=%u\n" +msgstr "Métrica do buffer: maxlength=%u, fragsize=%u\n" + +#: ../src/utils/pacat.c:183 +#, c-format +msgid "Using sample spec '%s', channel map '%s'.\n" +msgstr "Usando a espeficifação de amostragem '%s', mapa do canal '%s'.\n" + +#: ../src/utils/pacat.c:187 +#, c-format +msgid "Connected to device %s (%u, %ssuspended).\n" +msgstr "Conectado ao dispositivo %s (%u, %ssuspended).\n" + +#: ../src/utils/pacat.c:197 +#, c-format +msgid "Stream error: %s\n" +msgstr "Erro de fluxo: %s\n" + +#: ../src/utils/pacat.c:207 +#, c-format +msgid "Stream device suspended.%s \n" +msgstr "Dispositivo de fluxo suspenso.%s \n" + +#: ../src/utils/pacat.c:209 +#, c-format +msgid "Stream device resumed.%s \n" +msgstr "Dispositivo de fluxo prosseguiu.%s \n" + +#: ../src/utils/pacat.c:217 +#, c-format +msgid "Stream underrun.%s \n" +msgstr "Extravazamento do fluxo. %s\n" + +#: ../src/utils/pacat.c:224 +#, c-format +msgid "Stream overrun.%s \n" +msgstr "O fluxo extravazou.%s \n" + +#: ../src/utils/pacat.c:231 +#, c-format +msgid "Stream started.%s \n" +msgstr "O fluxo iniciou: %s\n" + +#: ../src/utils/pacat.c:238 +#, c-format +msgid "Stream moved to device %s (%u, %ssuspended).%s \n" +msgstr "O fluxo foi movido para o dispositivo %s (%u, %ssuspended).%s \n" + +#: ../src/utils/pacat.c:238 +msgid "not " +msgstr "não" + +#: ../src/utils/pacat.c:259 +#, c-format +msgid "Connection established.%s \n" +msgstr "Conexão estabelecida.%s \n" + +#: ../src/utils/pacat.c:262 +#, c-format +msgid "pa_stream_new() failed: %s\n" +msgstr "pa_stream_new() falhou: %s\n" + +#: ../src/utils/pacat.c:287 +#, c-format +msgid "pa_stream_connect_playback() failed: %s\n" +msgstr "pa_stream_connect_playback() falhou: %s\n" + +#: ../src/utils/pacat.c:293 +#, c-format +msgid "pa_stream_connect_record() failed: %s\n" +msgstr "pa_stream_connect_record() falhou: %s\n" + +#: ../src/utils/pacat.c:307 ../src/utils/pasuspender.c:159 +#: ../src/utils/pactl.c:666 ../src/utils/paplay.c:183 +#, c-format +msgid "Connection failure: %s\n" +msgstr "Falha na conexão: %s\n" + +#: ../src/utils/pacat.c:328 ../src/utils/paplay.c:75 +#, c-format +msgid "Failed to drain stream: %s\n" +msgstr "Falha em drenar o fluxo: %s\n" + +#: ../src/utils/pacat.c:333 ../src/utils/paplay.c:80 +#, c-format +msgid "Playback stream drained.\n" +msgstr "Drenado o fluxo de playback.\n" + +#: ../src/utils/pacat.c:343 ../src/utils/paplay.c:92 +#, c-format +msgid "Draining connection to server.\n" +msgstr "Drenando a conexão par ao servidor.\n" + +#: ../src/utils/pacat.c:369 +#, c-format +msgid "Got EOF.\n" +msgstr "Atingiu EOF.\n" + +#: ../src/utils/pacat.c:375 +#, c-format +msgid "pa_stream_drain(): %s\n" +msgstr "pa_stream_drain(): %s\n" + +#: ../src/utils/pacat.c:385 +#, c-format +msgid "read() failed: %s\n" +msgstr "read() falhou: %s\n" + +#: ../src/utils/pacat.c:417 +#, c-format +msgid "write() failed: %s\n" +msgstr "write() falhou: %s\n" + +#: ../src/utils/pacat.c:438 +#, c-format +msgid "Got signal, exiting.\n" +msgstr "Sinal recebido, saindo (exiting).\n" + +#: ../src/utils/pacat.c:452 +#, c-format +msgid "Failed to get latency: %s\n" +msgstr "Falhou em obter a latência: %s\n" + +#: ../src/utils/pacat.c:457 +#, c-format +msgid "Time: %0.3f sec; Latency: %0.0f usec. \r" +msgstr "Tempo: %0.3f s; Latência: %0.0f us. \r" + +#: ../src/utils/pacat.c:477 +#, c-format +msgid "pa_stream_update_timing_info() failed: %s\n" +msgstr "Falha em pa_stream_update_timing_info(): %s\n" + +#: ../src/utils/pacat.c:490 +#, c-format +msgid "" +"%s [options]\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -r, --record Create a connection for recording\n" +" -p, --playback Create a connection for playback\n" +"\n" +" -v, --verbose Enable verbose operations\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -d, --device=DEVICE The name of the sink/source to " +"connect to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" +" --rate=SAMPLERATE The sample rate in Hz (defaults to " +"44100)\n" +" --format=SAMPLEFORMAT The sample type, one of s16le, " +"s16be, u8, float32le,\n" +" float32be, ulaw, alaw, s32le, s32be " +"(defaults to s16ne)\n" +" --channels=CHANNELS The number of channels, 1 for mono, " +"2 for stereo\n" +" (defaults to 2)\n" +" --channel-map=CHANNELMAP Channel map to use instead of the " +"default\n" +" --fix-format Take the sample format from the sink " +"the stream is\n" +" being connected to.\n" +" --fix-rate Take the sampling rate from the sink " +"the stream is\n" +" being connected to.\n" +" --fix-channels Take the number of channels and the " +"channel map\n" +" from the sink the stream is being " +"connected to.\n" +" --no-remix Don't upmix or downmix channels.\n" +" --no-remap Map channels by index instead of " +"name.\n" +" --latency=BYTES Request the specified latency in " +"bytes.\n" +" --process-time=BYTES Request the specified process time " +"per request in bytes.\n" +msgstr "" +"%s [opções]\n" +"\n" +" -h, --help Mostra essa ajuda\n" +" --version Mostra a versão\n" +"\n" +" -r, --record Cria uma conexão para gravação\n" +" -p, --playback Cria uma conexão para playback\n" +"\n" +" -v, --verbose Habilita operações no modo verboso\n" +"\n" +" -s, --server=SERVER Nome do servidor a ser conectado\n" +" -d, --device=DEVICE O nome do destino/fonte a conectar\n" +" -n, --client-name=NAME Como chamar o cliente no servidor\n" +" --stream-name=NAME Como chamar este fluxo no " +"servidorn --volume=VOLUME Especifica a faixa (linear) " +"inicial de volume no intervalo 0...65536\n" +" --rate=SAMPLERATE Taxa de amostragem em Hz (o padrão é " +"44100)\n" +" --format=SAMPLEFORMAT Tipo de amostragem, um de s16le, " +"s16be, u8, float32le,\n" +" float32be, ulaw, alaw, s32le, s32be " +"(o padrão é s16ne)\n" +" --channels=CHANNELS O número de canais, 1 para mono, 2 " +"para estéreo\n" +" (o padrão é 2)\n" +" --channel-map=CHANNELMAP Mapeamento de canais a ser usando em " +"lugar do padrão\n" +" --fix-format Obtém o formato da amostragem do " +"destino onde o fluxo\n" +" está sendo conectado.\n" +" --fix-rate Obtém o taxa de amostragem do " +"destino onde o fluxo está\n" +" sendo conectado.\n" +" --fix-channels Obtém o número de canais e o mapa de " +"canais\n" +" do destino onde o fluxo está sendo " +"conectado.\n" +" --no-remix Don't upmix or downmix channels.\n" +" --no-remap Map channels by index instead of " +"name.\n" +" --latency=BYTES Request the specified latency in " +"bytes.\n" +" --process-time=BYTES Request the specified process time " +"per request in bytes.\n" + +#: ../src/utils/pacat.c:591 +#, c-format +msgid "" +"pacat %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"pacat %s\n" +"Compilado com libpulse %s\n" +"Linkado com libpulse %s\n" + +#: ../src/utils/pacat.c:647 +#, c-format +msgid "Invalid channel map '%s'\n" +msgstr "Mapa de canal inválido '%s'\n" + +#: ../src/utils/pacat.c:676 +#, c-format +msgid "Invalid latency specification '%s'\n" +msgstr "Especificação de latência inválida '%s'\n" + +#: ../src/utils/pacat.c:683 +#, c-format +msgid "Invalid process time specification '%s'\n" +msgstr "Especificação do tempo do processo inválida '%s'\n" + +#: ../src/utils/pacat.c:694 +#, c-format +msgid "Invalid sample specification\n" +msgstr "Especificação de amostragem inválida\n" + +#: ../src/utils/pacat.c:699 +#, c-format +msgid "Channel map doesn't match sample specification\n" +msgstr "O mapeamento do canal não casa com a especificação da amostragem\n" + +#: ../src/utils/pacat.c:706 +#, c-format +msgid "Opening a %s stream with sample specification '%s'.\n" +msgstr "Abrindo um %s fluxo com a especificação de amostragem '%s'.\n" + +#: ../src/utils/pacat.c:706 +msgid "recording" +msgstr "gravando" + +#: ../src/utils/pacat.c:706 +msgid "playback" +msgstr "playback" + +#: ../src/utils/pacat.c:714 +#, c-format +msgid "open(): %s\n" +msgstr "open(): %s\n" + +#: ../src/utils/pacat.c:719 +#, c-format +msgid "dup2(): %s\n" +msgstr "dup2(): %s\n" + +#: ../src/utils/pacat.c:729 +#, c-format +msgid "Too many arguments.\n" +msgstr "Argumentos em excesso.\n" + +#: ../src/utils/pacat.c:742 ../src/utils/pasuspender.c:280 +#: ../src/utils/pactl.c:909 ../src/utils/paplay.c:381 +#, c-format +msgid "pa_mainloop_new() failed.\n" +msgstr "pa_mainloop_new() falhou.\n" + +#: ../src/utils/pacat.c:763 +#, c-format +msgid "io_new() failed.\n" +msgstr "io_new() falhou.\n" + +#: ../src/utils/pacat.c:769 ../src/utils/pasuspender.c:293 +#: ../src/utils/pactl.c:923 ../src/utils/paplay.c:396 +#, c-format +msgid "pa_context_new() failed.\n" +msgstr "pa_context_new() falhou.\n" + +#: ../src/utils/pacat.c:777 +#, c-format +msgid "pa_context_connect() failed: %s" +msgstr "pa_context_new() falhou: %s" + +#: ../src/utils/pacat.c:788 +#, c-format +msgid "time_new() failed.\n" +msgstr "time_new() falhou.\n" + +#: ../src/utils/pacat.c:795 ../src/utils/pasuspender.c:301 +#: ../src/utils/pactl.c:931 ../src/utils/paplay.c:407 +#, c-format +msgid "pa_mainloop_run() failed.\n" +msgstr "pa_mainloop_run() falhou.\n" + +#: ../src/utils/pasuspender.c:81 +#, c-format +msgid "fork(): %s\n" +msgstr "fork(): %s\n" + +#: ../src/utils/pasuspender.c:92 +#, c-format +msgid "execvp(): %s\n" +msgstr "execvp(): %s\n" + +#: ../src/utils/pasuspender.c:109 +#, c-format +msgid "Failure to suspend: %s\n" +msgstr "Falha em suspender: %s\n" + +#: ../src/utils/pasuspender.c:124 +#, c-format +msgid "Failure to resume: %s\n" +msgstr "Falha ao prosseguir: %s\n" + +#: ../src/utils/pasuspender.c:147 +#, c-format +msgid "WARNING: Sound server is not local, not suspending.\n" +msgstr "" +"AVISO: O servidor de som não é local, Sound server is not local, não está em " +"suspenso.\n" + +#: ../src/utils/pasuspender.c:176 ../src/utils/pactl.c:672 +#: ../src/utils/paplay.c:191 +#, c-format +msgid "Got SIGINT, exiting.\n" +msgstr "Recebido o SIGINT, saindo.\n" + +#: ../src/utils/pasuspender.c:194 +#, c-format +msgid "WARNING: Child process terminated by signal %u\n" +msgstr "AVISO: O processo filho terminou pelo sinal %u \n" + +#: ../src/utils/pasuspender.c:212 +#, c-format +msgid "" +"%s [options] ... \n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +"\n" +msgstr "" +"%s [options] ... \n" +"\n" +" -h, --help Mostra esta ajuda\n" +" --version Mostra a versão\n" +" -s, --server=SERVER Nome do servidor a ser conectado\n" +"\n" + +#: ../src/utils/pasuspender.c:251 +#, c-format +msgid "" +"pasuspender %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"pasuspender %s\n" +"Compilado com libpulse %s\n" +"Linkado com libpulse %s\n" + +#: ../src/utils/pactl.c:107 +#, c-format +msgid "Failed to get statistics: %s\n" +msgstr "Falha em obter as estatísticas: %s\n" + +#: ../src/utils/pactl.c:113 +#, c-format +msgid "Currently in use: %u blocks containing %s bytes total.\n" +msgstr "Em uso no momento: %u blocos contendo %s bytes no total.\n" + +#: ../src/utils/pactl.c:116 +#, c-format +msgid "Allocated during whole lifetime: %u blocks containing %s bytes total.\n" +msgstr "Alocado por todo o tempo: %u blocos contendo %s bytes no total.\n" + +#: ../src/utils/pactl.c:119 +#, c-format +msgid "Sample cache size: %s\n" +msgstr "Tamanho do cache para amostragem: %s\n" + +#: ../src/utils/pactl.c:128 +#, c-format +msgid "Failed to get server information: %s\n" +msgstr "Falha em obter a informação do servidor: %s\n" + +#: ../src/utils/pactl.c:135 +#, c-format +msgid "" +"User name: %s\n" +"Host Name: %s\n" +"Server Name: %s\n" +"Server Version: %s\n" +"Default Sample Specification: %s\n" +"Default Sink: %s\n" +"Default Source: %s\n" +"Cookie: %08x\n" +msgstr "" +"Nome do Usuário: %s\n" +"Nome do Host: %s\n" +"Nome do Servidor: %s\n" +"Versão do Servidor: %s\n" +"Especificação padrão de amostragem: %s\n" +"Destino padrão: %s\n" +"Fonte padrão %s\n" +"Cookie: %08x\n" + +#: ../src/utils/pactl.c:160 +#, c-format +msgid "Failed to get sink information: %s\n" +msgstr "Falha em obter a informação do destino: %s\n" + +#: ../src/utils/pactl.c:176 +#, c-format +msgid "" +"*** Sink #%u ***\n" +"Name: %s\n" +"Driver: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Owner Module: %u\n" +"Volume: %s\n" +"Monitor Source: %s\n" +"Latency: %0.0f usec, configured %0.0f usec\n" +"Flags: %s%s%s%s%s%s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Destino #%u ***\n" +"Nome: %s\n" +"Driver: %s\n" +"Especificação de amostragem: %s\n" +"Mapa de canais: %s\n" +"Propretário do módulo: %u\n" +"Volume: %s\n" +"Fonte do monitor: %s\n" +"Latência: %0.0f us, configurado %0.0f us\n" +"Flags: %s%s%s%s%s%s\n" +"Propriedades:\n" +"%s" + +#: ../src/utils/pactl.c:193 ../src/utils/pactl.c:371 +msgid "muted" +msgstr "mudo" + +#: ../src/utils/pactl.c:212 +#, c-format +msgid "Failed to get source information: %s\n" +msgstr "Falha em obter a informação da fonte: %s\n" + +#: ../src/utils/pactl.c:228 +#, c-format +msgid "" +"*** Source #%u ***\n" +"Name: %s\n" +"Driver: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Owner Module: %u\n" +"Volume: %s\n" +"Monitor of Sink: %s\n" +"Latency: %0.0f usec, configured %0.0f usec\n" +"Flags: %s%s%s%s%s%s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Fonte #%u ***\n" +"Nome: %s\n" +"Driver: %s\n" +"Especificação de amostragem: %s\n" +"Mapa do canal: %s\n" +"Proprietário do módulo: %u\n" +"Volume: %s\n" +"Monitor do destino: %s\n" +"Latência: %0.0f us, configurado %0.0f us:\n" +"Flags: %s%s%s%s%s%s\n" +"Propriedades:\n" +"%s" + +#: ../src/utils/pactl.c:246 ../src/utils/pactl.c:289 ../src/utils/pactl.c:322 +#: ../src/utils/pactl.c:366 ../src/utils/pactl.c:367 ../src/utils/pactl.c:374 +#: ../src/utils/pactl.c:418 ../src/utils/pactl.c:419 ../src/utils/pactl.c:425 +#: ../src/utils/pactl.c:468 ../src/utils/pactl.c:469 ../src/utils/pactl.c:473 +msgid "n/a" +msgstr "n/a" + +#: ../src/utils/pactl.c:263 +#, c-format +msgid "Failed to get module information: %s\n" +msgstr "Falha em obter a informação do módulo: %s\n" + +#: ../src/utils/pactl.c:281 +#, c-format +msgid "" +"*** Module #%u ***\n" +"Name: %s\n" +"Argument: %s\n" +"Usage counter: %s\n" +"Auto unload: %s\n" +msgstr "" +"*** Módulo #%u ***\n" +"Nome: %s\n" +"Argumento: %s\n" +"Contador de uso: %s\n" +"Auto descarregar: %s\n" + +#: ../src/utils/pactl.c:298 +#, c-format +msgid "Failed to get client information: %s\n" +msgstr "Falhou ao obter a informação do cliente: %s\n" + +#: ../src/utils/pactl.c:316 +#, c-format +msgid "" +"*** Client #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Cliente #%u ***\n" +"Driver: %s\n" +"Poprietário do módulo: %s\n" +"Propriedades:\n" +"%s" + +#: ../src/utils/pactl.c:333 +#, c-format +msgid "Failed to get sink input information: %s\n" +msgstr "Falha na obtenção da informação de entrada do destino: %s\n" + +#: ../src/utils/pactl.c:352 +#, c-format +msgid "" +"*** Sink Input #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Client: %s\n" +"Sink: %u\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Volume: %s\n" +"Buffer Latency: %0.0f usec\n" +"Sink Latency: %0.0f usec\n" +"Resample method: %s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Entrada do destino #%u ***\n" +"Driver: %s\n" +"Proprietário do módulo: %s\n" +"Cliente: %s\n" +"Destino: %u\n" +"Especificação da amostragem: %s\n" +"Mapa de canais: %s\n" +"Volume: %s\n" +"Latência do buffer: %0.0f us\n" +"Latência do destino %0.0f usec\n" +"Método de reamostragem (resample): %s\n" +"Propriedades:\n" +"%s" + +#: ../src/utils/pactl.c:385 +#, c-format +msgid "Failed to get source output information: %s\n" +msgstr "Falha em obter informações sobre a saída da fonte: %s\n" + +#: ../src/utils/pactl.c:405 +#, c-format +msgid "" +"*** Source Output #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Client: %s\n" +"Source: %u\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Buffer Latency: %0.0f usec\n" +"Source Latency: %0.0f usec\n" +"Resample method: %s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Saída da Fonte #%u ***\n" +"Driver: %s\n" +"Proprietário do Módulo: %s\n" +"Cliente: %s\n" +"Fonte: %u\n" +"Especificação de Amostragem: %s\n" +"Mapa do Canal: %s\n" +"Latência do Buffer: %0.0f usec\n" +"Latência da Fonte: %0.0f usec\n" +"Método de Reamostragem (resample): %s\n" +"Propriedades:\n" +"%s" + +#: ../src/utils/pactl.c:436 +#, c-format +msgid "Failed to get sample information: %s\n" +msgstr "Falha em obter informações sobre a amostragem: %s\n" + +#: ../src/utils/pactl.c:455 +#, c-format +msgid "" +"*** Sample #%u ***\n" +"Name: %s\n" +"Volume: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Duration: %0.1fs\n" +"Size: %s\n" +"Lazy: %s\n" +"Filename: %s\n" +"Properties:\n" +"%s" +msgstr "" +"*** Amostragem #%u ***\n" +"Nome: %s\n" +"Volume: %s\n" +"Especificação da Amostragem: %s\n" +"Mapa de Canais: %s\n" +"Duração: %0.1fs\n" +"Tamanho: %s\n" +"Lazy: %s\n" +"Nome do Arquivo: %s\n" +"Propriedades:\n" +"%s" + +#: ../src/utils/pactl.c:481 +#, c-format +msgid "Failed to get autoload information: %s\n" +msgstr "Falha em obter a informação do autoload: %s\n" + +#: ../src/utils/pactl.c:497 +#, c-format +msgid "" +"*** Autoload Entry #%u ***\n" +"Name: %s\n" +"Type: %s\n" +"Module: %s\n" +"Argument: %s\n" +msgstr "" +"*** Entrada do Autoload #%u ***\n" +"Nome: %s\n" +"Tipo: %s\n" +"Módulo: %s\n" +"Argumento: %s\n" + +#: ../src/utils/pactl.c:504 +msgid "sink" +msgstr "destino" + +#: ../src/utils/pactl.c:504 +msgid "source" +msgstr "fonte" + +#: ../src/utils/pactl.c:511 ../src/utils/pactl.c:521 +#, c-format +msgid "Failure: %s\n" +msgstr "Falha: %s\n" + +#: ../src/utils/pactl.c:545 +#, c-format +msgid "Failed to upload sample: %s\n" +msgstr "Falha em carregar a amostra: %s\n" + +#: ../src/utils/pactl.c:562 +#, c-format +msgid "Premature end of file\n" +msgstr "Fim prematuro do arquivo\n" + +#: ../src/utils/pactl.c:678 +#, c-format +msgid "" +"%s [options] stat\n" +"%s [options] list\n" +"%s [options] exit\n" +"%s [options] upload-sample FILENAME [NAME]\n" +"%s [options] play-sample NAME [SINK]\n" +"%s [options] remove-sample NAME\n" +"%s [options] move-sink-input ID SINK\n" +"%s [options] move-source-output ID SOURCE\n" +"%s [options] load-module NAME [ARGS ...]\n" +"%s [options] unload-module ID\n" +"%s [options] suspend-sink [SINK] 1|0\n" +"%s [options] suspend-source [SOURCE] 1|0\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +msgstr "" +"%s [options] stat\n" +"%s [options] list\n" +"%s [options] exit\n" +"%s [options] upload-sample FILENAME [NAME]\n" +"%s [options] play-sample NAME [SINK]\n" +"%s [options] remove-sample NAME\n" +"%s [options] move-sink-input ID SINK\n" +"%s [options] move-source-output ID SOURCE\n" +"%s [options] load-module NAME [ARGS ...]\n" +"%s [options] unload-module ID\n" +"%s [options] suspend-sink [SINK] 1|0\n" +"%s [options] suspend-source [SOURCE] 1|0\n" +"\n" +" -h, --help Mostra essa ajuda\n" +" --version Mostra a versão\n" +"\n" +" -s, --server=SERVER O nome do servidor a ser conectado\n" +" -n, --client-name=NAME Como chamar este cliente no " +"servidor \n" + +#: ../src/utils/pactl.c:729 +#, c-format +msgid "" +"pactl %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"pactl %s\n" +"Compilado com libpulse %s\n" +"Linkado com libpulse %s\n" + +#: ../src/utils/pactl.c:768 +#, c-format +msgid "Please specify a sample file to load\n" +msgstr "Por favor, especifique o arquivo de amostra a ser carregado\n" + +#: ../src/utils/pactl.c:790 +#, c-format +msgid "Failed to open sound file.\n" +msgstr "Falha em abrir o arquivo de som.\n" + +#: ../src/utils/pactl.c:802 +#, c-format +msgid "You have to specify a sample name to play\n" +msgstr "Você deve especificar um nome da amostra para ser executada\n" + +#: ../src/utils/pactl.c:814 +#, c-format +msgid "You have to specify a sample name to remove\n" +msgstr "Você deve especificar um nome da amostra para ser removida\n" + +#: ../src/utils/pactl.c:822 +#, c-format +msgid "You have to specify a sink input index and a sink\n" +msgstr "" +"Você tem que especificar a entrada para o destino (sink) e um destino(sink)\n" + +#: ../src/utils/pactl.c:831 +#, c-format +msgid "You have to specify a source output index and a source\n" +msgstr "Você tem que especificar um índice de saída da fonte e uma fonte\n" + +#: ../src/utils/pactl.c:845 +#, c-format +msgid "You have to specify a module name and arguments.\n" +msgstr "Você deve especificar um nome do módulo e seus argumentos\n" + +#: ../src/utils/pactl.c:865 +#, c-format +msgid "You have to specify a module index\n" +msgstr "Você deve especificar um índice de um módulo\n" + +#: ../src/utils/pactl.c:875 +#, c-format +msgid "" +"You may not specify more than one sink. You have to specify at least one " +"boolean value.\n" +msgstr "" +"Você não pode especificar mais de um destino. Pelo menos um valor booleano " +"deve ser especificado.\n" + +#: ../src/utils/pactl.c:888 +#, c-format +msgid "" +"You may not specify more than one source. You have to specify at least one " +"boolean value.\n" +msgstr "" +"Você não pode especificar mais de uma fonte. Pelo menos um valor booleano " +"deve ser especificado.\n" + +#: ../src/utils/pactl.c:904 +#, c-format +msgid "No valid command specified.\n" +msgstr "Nenhum comando válido especificado.\n" + +#: ../src/utils/pax11publish.c:61 +#, c-format +msgid "" +"%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n" +"\n" +" -d Show current PulseAudio data attached to X11 display (default)\n" +" -e Export local PulseAudio data to X11 display\n" +" -i Import PulseAudio data from X11 display to local environment " +"variables and cookie file.\n" +" -r Remove PulseAudio data from X11 display\n" +msgstr "" +"%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n" +"\n" +" -d Mostra os dados atuais do PulseAudio associados ao display X11 " +"(padrão)\n" +" -e Exporta os dados locais do PulseAudio para um display X11 \n" +" -i Importa os dados do PulseAudio de um display X11 para as variáveis " +"de ambiente locais e para o arquivo de cookie.\n" +" -r Remove os dados do PulseAudio do display X11\n" + +#: ../src/utils/pax11publish.c:94 +#, c-format +msgid "Failed to parse command line.\n" +msgstr "Falha em interpretar a linha de comando.\n" + +#: ../src/utils/pax11publish.c:108 +#, c-format +msgid "Server: %s\n" +msgstr "Servidor: %s\n" + +#: ../src/utils/pax11publish.c:110 +#, c-format +msgid "Source: %s\n" +msgstr "Fonte: %s\n" + +#: ../src/utils/pax11publish.c:112 +#, c-format +msgid "Sink: %s\n" +msgstr "Destino: %s\n" + +#: ../src/utils/pax11publish.c:114 +#, c-format +msgid "Cookie: %s\n" +msgstr "Cookie: %s\n" + +#: ../src/utils/pax11publish.c:132 +#, c-format +msgid "Failed to parse cookie data\n" +msgstr "Falha ao analisar os dados do cookie\n" + +#: ../src/utils/pax11publish.c:137 +#, c-format +msgid "Failed to save cookie data\n" +msgstr "Falha em salvar os dados do cookie\n" + +#: ../src/utils/pax11publish.c:152 +#, c-format +msgid "Failed to load client configuration file.\n" +msgstr "Falha em carregar o arquivo de configuração do cliente.\n" + +#: ../src/utils/pax11publish.c:157 +#, c-format +msgid "Failed to read environment configuration data.\n" +msgstr "Falha em ler os dados de configuração do ambiente\n" + +#: ../src/utils/pax11publish.c:174 +#, c-format +msgid "Failed to get FQDN.\n" +msgstr "Falha na obtenção do FQDN.\n" + +#: ../src/utils/pax11publish.c:194 +#, c-format +msgid "Failed to load cookie data\n" +msgstr "Falha em carregar os dados do cookie\n" + +#: ../src/utils/pax11publish.c:211 +#, c-format +msgid "Not yet implemented.\n" +msgstr "Ainda não implementado.\n" + +#: ../src/utils/pacmd.c:64 +#, c-format +msgid "socket(PF_UNIX, SOCK_STREAM, 0): %s" +msgstr "socket(PF_UNIX, SOCK_STREAM, 0): %s" + +#: ../src/utils/pacmd.c:81 +#, c-format +msgid "connect(): %s" +msgstr "connect(): %s" + +#: ../src/utils/pacmd.c:89 +msgid "Failed to kill PulseAudio daemon." +msgstr "Falha em cancelar o daemon do PulseAudio." + +#: ../src/utils/pacmd.c:97 +msgid "Daemon not responding." +msgstr "Daemon não responde." + +#: ../src/utils/pacmd.c:112 +#, c-format +msgid "select(): %s" +msgstr "select(): %s" + +#: ../src/utils/pacmd.c:124 ../src/utils/pacmd.c:140 +#, c-format +msgid "read(): %s" +msgstr "read(): %s" + +#: ../src/utils/pacmd.c:153 ../src/utils/pacmd.c:167 +#, c-format +msgid "write(): %s" +msgstr "write(): %s" + +#: ../src/utils/paplay.c:139 +#, c-format +msgid "Stream successfully created\n" +msgstr "Fluxo criado com sucesso\n" + +#: ../src/utils/paplay.c:144 +#, c-format +msgid "Stream errror: %s\n" +msgstr "Erro de fluxo: %s\n" + +#: ../src/utils/paplay.c:165 +#, c-format +msgid "Connection established.\n" +msgstr "Conexão estabelecida.\n" + +#: ../src/utils/paplay.c:198 +#, c-format +msgid "" +"%s [options] [FILE]\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -v, --verbose Enable verbose operation\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -d, --device=DEVICE The name of the sink to connect to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" +" --channel-map=CHANNELMAP Set the channel map to the use\n" +msgstr "" +"%s [options] [FILE]\n" +"\n" +" -h, --help Mostra essa ajuda\n" +" --version Mostra a versão\n" +"\n" +" -v, --verbose Habilida a operação detalhada\n" +"\n" +" -s, --server=SERVER O nome do servidor a ser conectado\n" +" -d, --device=DEVICE O nome do destino a ser conectado\n" +" -n, --client-name=NAME Como chamar este cliente no " +"servidor\n" +" --stream-name=NAME Como chamar este fluxo no servidor\n" +" --volume=VOLUME Especifica o volume inicial (linear) " +"no intervalo 0...65536\n" +" --channel-map=CHANNELMAP Define o mapa do canal para uso\n" + +#: ../src/utils/paplay.c:255 +#, c-format +msgid "" +"paplay %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"paplay %s\n" +"Compilado com libpulse %s\n" +"Linkado com libpulse %s\n" + +#: ../src/utils/paplay.c:292 +#, c-format +msgid "Invalid channel map\n" +msgstr "Mapa de canais inválido\n" + +#: ../src/utils/paplay.c:314 +#, c-format +msgid "Failed to open file '%s'\n" +msgstr "Falha ao abrir o arquivo '%s'\n" + +#: ../src/utils/paplay.c:350 +#, c-format +msgid "Channel map doesn't match file.\n" +msgstr "O mapa dos canais não coincide com o arquivo.\n" + +#: ../src/utils/paplay.c:376 +#, c-format +msgid "Using sample spec '%s'\n" +msgstr "Usando a especificação da amostragem '%s'\n" + +#: ../src/pulsecore/lock-autospawn.c:126 ../src/pulsecore/lock-autospawn.c:207 +msgid "Cannot access autospawn lock." +msgstr "Não foi possível acessar a trava de autogeração." + +#~ msgid "" +#~ "' and PolicyKit refuse to grant us priviliges. Dropping SUID again.\n" +#~ "For enabling real-time scheduling please acquire the appropriate " +#~ "PolicyKit priviliges, or become a member of '" +#~ msgstr "" +#~ "' e o PolicyKit recusa-nos a garantia de privilégios. Retirando o SUID " +#~ "outra vez.\n" +#~ " Para habilitar o escalonamento em tempo real, por favo, adquira os " +#~ "privilégios adequados pelo PolicyKit, ou torne-se membro do'" + +#~ msgid "" +#~ "', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this " +#~ "user." +#~ msgstr "" +#~ "', ou eleve o RLIMIT_NICE/RLIMIT_RTPRIO dos limites do recurso para este " +#~ "usuário." + +#~ msgid "socketpair(): %s" +#~ msgstr "socketpair(): %s" diff --git a/po/sv.po b/po/sv.po new file mode 100644 index 00000000..772e1552 --- /dev/null +++ b/po/sv.po @@ -0,0 +1,1836 @@ +# Swedish translation for pulseaudio. +# Copyright (C) 2008 Free Software Foundation, Inc. +# This file is distributed under the same license as the pulseaudio package. +# Daniel Nylander <po@danielnylander.se>, 2008. +# +msgid "" +msgstr "" +"Project-Id-Version: pulseaudio\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-10-07 21:03+0200\n" +"PO-Revision-Date: 2008-09-05 18:24+0100\n" +"Last-Translator: Daniel Nylander <po@danielnylander.se>\n" +"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../src/daemon/ltdl-bind-now.c:177 ../src/daemon/ltdl-bind-now.c:197 +msgid "Failed to add bind-now-loader." +msgstr "" + +#: ../src/daemon/ltdl-bind-now.c:184 +msgid "Failed to find original dlopen loader." +msgstr "" + +#: ../src/daemon/polkit.c:55 +#, c-format +msgid "Cannot connect to system bus: %s" +msgstr "" + +#: ../src/daemon/polkit.c:65 +#, c-format +msgid "Cannot get caller from PID: %s" +msgstr "" + +#: ../src/daemon/polkit.c:77 +msgid "Cannot set UID on caller object." +msgstr "" + +#: ../src/daemon/polkit.c:82 +msgid "Failed to get CK session." +msgstr "" + +#: ../src/daemon/polkit.c:90 +msgid "Cannot set UID on session object." +msgstr "" + +#: ../src/daemon/polkit.c:95 +msgid "Cannot allocate PolKitAction." +msgstr "" + +#: ../src/daemon/polkit.c:100 +msgid "Cannot set action_id" +msgstr "" + +#: ../src/daemon/polkit.c:105 +msgid "Cannot allocate PolKitContext." +msgstr "" + +#: ../src/daemon/polkit.c:110 +#, c-format +msgid "Cannot initialize PolKitContext: %s" +msgstr "" + +#: ../src/daemon/polkit.c:119 +#, c-format +msgid "Could not determine whether caller is authorized: %s" +msgstr "" + +#: ../src/daemon/polkit.c:139 +#, c-format +msgid "Cannot obtain auth: %s" +msgstr "" + +#: ../src/daemon/polkit.c:148 +#, c-format +msgid "PolicyKit responded with '%s'" +msgstr "PolicyKit svarade med \"%s\"" + +#: ../src/daemon/main.c:134 +#, c-format +msgid "Got signal %s." +msgstr "Fick signal %s." + +#: ../src/daemon/main.c:161 +msgid "Exiting." +msgstr "Avslutar." + +#: ../src/daemon/main.c:179 +#, c-format +msgid "Failed to find user '%s'." +msgstr "Misslyckades med att hitta användaren \"%s\"." + +#: ../src/daemon/main.c:184 +#, c-format +msgid "Failed to find group '%s'." +msgstr "Misslyckades med att hitta gruppen \"%s\"." + +#: ../src/daemon/main.c:188 +#, c-format +msgid "Found user '%s' (UID %lu) and group '%s' (GID %lu)." +msgstr "" + +#: ../src/daemon/main.c:193 +#, c-format +msgid "GID of user '%s' and of group '%s' don't match." +msgstr "" + +#: ../src/daemon/main.c:198 +#, c-format +msgid "Home directory of user '%s' is not '%s', ignoring." +msgstr "Hemkatalogen för användaren \"%s\" är inte \"%s\", ignorerar." + +#: ../src/daemon/main.c:201 ../src/daemon/main.c:206 +#, c-format +msgid "Failed to create '%s': %s" +msgstr "Misslyckades med att skapa \"%s\": %s" + +#: ../src/daemon/main.c:213 +#, c-format +msgid "Failed to change group list: %s" +msgstr "" + +#: ../src/daemon/main.c:229 +#, c-format +msgid "Failed to change GID: %s" +msgstr "" + +#: ../src/daemon/main.c:245 +#, c-format +msgid "Failed to change UID: %s" +msgstr "" + +#: ../src/daemon/main.c:259 +msgid "Successfully dropped root privileges." +msgstr "" + +#: ../src/daemon/main.c:267 +msgid "System wide mode unsupported on this platform." +msgstr "" + +#: ../src/daemon/main.c:285 +#, c-format +msgid "setrlimit(%s, (%u, %u)) failed: %s" +msgstr "setrlimit(%s, (%u, %u)) misslyckades: %s" + +#: ../src/daemon/main.c:425 +msgid "Failed to parse command line." +msgstr "" + +#: ../src/daemon/main.c:441 +#, c-format +msgid "We're in the group '%s', allowing high-priority scheduling." +msgstr "" + +#: ../src/daemon/main.c:448 +#, c-format +msgid "We're in the group '%s', allowing real-time scheduling." +msgstr "" + +#: ../src/daemon/main.c:456 +msgid "PolicyKit grants us acquire-high-priority privilege." +msgstr "" + +#: ../src/daemon/main.c:459 +msgid "PolicyKit refuses acquire-high-priority privilege." +msgstr "" + +#: ../src/daemon/main.c:464 +msgid "PolicyKit grants us acquire-real-time privilege." +msgstr "" + +#: ../src/daemon/main.c:467 +msgid "PolicyKit refuses acquire-real-time privilege." +msgstr "" + +#: ../src/daemon/main.c:479 +msgid "" +"Called SUID root and real-time/high-priority scheduling was requested in the " +"configuration. However, we lack the necessary priviliges:\n" +"We are not in group '" +msgstr "" + +#: ../src/daemon/main.c:497 +msgid "" +"High-priority scheduling enabled in configuration but not allowed by policy." +msgstr "" + +#: ../src/daemon/main.c:522 +msgid "Successfully increased RLIMIT_RTPRIO" +msgstr "" + +#: ../src/daemon/main.c:525 +#, c-format +msgid "RLIMIT_RTPRIO failed: %s" +msgstr "RLIMIT_RTPRIO misslyckades: %s" + +#: ../src/daemon/main.c:532 +msgid "Giving up CAP_NICE" +msgstr "" + +#: ../src/daemon/main.c:539 +msgid "" +"Real-time scheduling enabled in configuration but not allowed by policy." +msgstr "" + +#: ../src/daemon/main.c:597 +msgid "Daemon not running" +msgstr "" + +#: ../src/daemon/main.c:599 +#, c-format +msgid "Daemon running as PID %u" +msgstr "" + +#: ../src/daemon/main.c:609 +#, c-format +msgid "Failed to kill daemon: %s" +msgstr "" + +#: ../src/daemon/main.c:627 +msgid "" +"This program is not intended to be run as root (unless --system is " +"specified)." +msgstr "" +"Detta program är inte tänkt att köras som root (såvida inte --system har " +"angivits)." + +#: ../src/daemon/main.c:629 +msgid "Root priviliges required." +msgstr "Root-behörighet krävs." + +#: ../src/daemon/main.c:634 +msgid "--start not supported for system instances." +msgstr "--start stöds inte för systeminstanser." + +#: ../src/daemon/main.c:639 +msgid "Running in system mode, but --disallow-exit not set!" +msgstr "" + +#: ../src/daemon/main.c:642 +msgid "Running in system mode, but --disallow-module-loading not set!" +msgstr "" + +#: ../src/daemon/main.c:645 +msgid "Running in system mode, forcibly disabling SHM mode!" +msgstr "" + +#: ../src/daemon/main.c:650 +msgid "Running in system mode, forcibly disabling exit idle time!" +msgstr "" + +#: ../src/daemon/main.c:677 +msgid "Failed to acquire stdio." +msgstr "" + +#: ../src/daemon/main.c:683 +#, c-format +msgid "pipe failed: %s" +msgstr "pipe misslyckades: %s" + +#: ../src/daemon/main.c:688 +#, c-format +msgid "fork() failed: %s" +msgstr "fork() misslyckades: %s" + +#: ../src/daemon/main.c:702 +#, c-format +msgid "read() failed: %s" +msgstr "read() misslyckades: %s" + +#: ../src/daemon/main.c:708 +msgid "Daemon startup failed." +msgstr "" + +#: ../src/daemon/main.c:710 +msgid "Daemon startup successful." +msgstr "" + +#: ../src/daemon/main.c:780 +#, c-format +msgid "This is PulseAudio %s" +msgstr "Detta är PulseAudio %s" + +#: ../src/daemon/main.c:781 +#, c-format +msgid "Compilation host: %s" +msgstr "" + +#: ../src/daemon/main.c:782 +#, c-format +msgid "Compilation CFLAGS: %s" +msgstr "" + +#: ../src/daemon/main.c:785 +#, c-format +msgid "Running on host: %s" +msgstr "" + +#: ../src/daemon/main.c:788 +#, c-format +msgid "Page size is %lu bytes" +msgstr "" + +#: ../src/daemon/main.c:791 +msgid "Compiled with Valgrind support: yes" +msgstr "" + +#: ../src/daemon/main.c:793 +msgid "Compiled with Valgrind support: no" +msgstr "" + +#: ../src/daemon/main.c:796 +#, c-format +msgid "Running in valgrind mode: %s" +msgstr "" + +#: ../src/daemon/main.c:799 +msgid "Optimized build: yes" +msgstr "" + +#: ../src/daemon/main.c:801 +msgid "Optimized build: no" +msgstr "" + +#: ../src/daemon/main.c:805 +msgid "Failed to get machine ID" +msgstr "" + +#: ../src/daemon/main.c:808 +#, c-format +msgid "Machine ID is %s." +msgstr "" + +#: ../src/daemon/main.c:813 +#, c-format +msgid "Using runtime directory %s." +msgstr "" + +#: ../src/daemon/main.c:818 +#, c-format +msgid "Using state directory %s." +msgstr "" + +#: ../src/daemon/main.c:821 +#, c-format +msgid "Running in system mode: %s" +msgstr "" + +#: ../src/daemon/main.c:836 +msgid "pa_pid_file_create() failed." +msgstr "pa_pid_file_create() misslyckades." + +#: ../src/daemon/main.c:848 +msgid "Fresh high-resolution timers available! Bon appetit!" +msgstr "" + +#: ../src/daemon/main.c:850 +msgid "" +"Dude, your kernel stinks! The chef's recommendation today is Linux with high-" +"resolution timers enabled!" +msgstr "" + +#: ../src/daemon/main.c:860 +msgid "pa_core_new() failed." +msgstr "pa_core_new() misslyckades." + +#: ../src/daemon/main.c:921 +msgid "Failed to initialize daemon." +msgstr "" + +#: ../src/daemon/main.c:926 +msgid "Daemon startup without any loaded modules, refusing to work." +msgstr "" + +#: ../src/daemon/main.c:931 +#, c-format +msgid "Default sink name (%s) does not exist in name register." +msgstr "" + +#: ../src/daemon/main.c:944 +msgid "Daemon startup complete." +msgstr "" + +#: ../src/daemon/main.c:950 +msgid "Daemon shutdown initiated." +msgstr "" + +#: ../src/daemon/main.c:971 +msgid "Daemon terminated." +msgstr "" + +#: ../src/daemon/cmdline.c:117 +#, c-format +msgid "" +"%s [options]\n" +"\n" +"COMMANDS:\n" +" -h, --help Show this help\n" +" --version Show version\n" +" --dump-conf Dump default configuration\n" +" --dump-modules Dump list of available modules\n" +" --dump-resample-methods Dump available resample methods\n" +" --cleanup-shm Cleanup stale shared memory " +"segments\n" +" --start Start the daemon if it is not " +"running\n" +" -k --kill Kill a running daemon\n" +" --check Check for a running daemon\n" +"\n" +"OPTIONS:\n" +" --system[=BOOL] Run as system-wide instance\n" +" -D, --daemonize[=BOOL] Daemonize after startup\n" +" --fail[=BOOL] Quit when startup fails\n" +" --high-priority[=BOOL] Try to set high nice level\n" +" (only available as root, when SUID " +"or\n" +" with elevated RLIMIT_NICE)\n" +" --realtime[=BOOL] Try to enable realtime scheduling\n" +" (only available as root, when SUID " +"or\n" +" with elevated RLIMIT_RTPRIO)\n" +" --disallow-module-loading[=BOOL] Disallow module user requested " +"module\n" +" loading/unloading after startup\n" +" --disallow-exit[=BOOL] Disallow user requested exit\n" +" --exit-idle-time=SECS Terminate the daemon when idle and " +"this\n" +" time passed\n" +" --module-idle-time=SECS Unload autoloaded modules when idle " +"and\n" +" this time passed\n" +" --scache-idle-time=SECS Unload autoloaded samples when idle " +"and\n" +" this time passed\n" +" --log-level[=LEVEL] Increase or set verbosity level\n" +" -v Increase the verbosity level\n" +" --log-target={auto,syslog,stderr} Specify the log target\n" +" -p, --dl-search-path=PATH Set the search path for dynamic " +"shared\n" +" objects (plugins)\n" +" --resample-method=METHOD Use the specified resampling method\n" +" (See --dump-resample-methods for\n" +" possible values)\n" +" --use-pid-file[=BOOL] Create a PID file\n" +" --no-cpu-limit[=BOOL] Do not install CPU load limiter on\n" +" platforms that support it.\n" +" --disable-shm[=BOOL] Disable shared memory support.\n" +"\n" +"STARTUP SCRIPT:\n" +" -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module " +"with\n" +" the specified argument\n" +" -F, --file=FILENAME Run the specified script\n" +" -C Open a command line on the running " +"TTY\n" +" after startup\n" +"\n" +" -n Don't load default script file\n" +msgstr "" + +#: ../src/daemon/cmdline.c:245 +msgid "--daemonize expects boolean argument" +msgstr "--daemonize förväntar sig ett booleskt argument" + +#: ../src/daemon/cmdline.c:252 +msgid "--fail expects boolean argument" +msgstr "--fail förväntar sig ett booleskt argument" + +#: ../src/daemon/cmdline.c:262 +msgid "" +"--log-level expects log level argument (either numeric in range 0..4 or one " +"of debug, info, notice, warn, error)." +msgstr "" + +#: ../src/daemon/cmdline.c:274 +msgid "--high-priority expects boolean argument" +msgstr "--high-priority förväntar sig ett booleskt argument" + +#: ../src/daemon/cmdline.c:281 +msgid "--realtime expects boolean argument" +msgstr "--realtime förväntar sig ett booleskt argument" + +#: ../src/daemon/cmdline.c:288 +msgid "--disallow-module-loading expects boolean argument" +msgstr "--disallow-module-loading förväntar sig ett booleskt argument" + +#: ../src/daemon/cmdline.c:295 +msgid "--disallow-exit boolean argument" +msgstr "--disallow-exit booleskt argument" + +#: ../src/daemon/cmdline.c:302 +msgid "--use-pid-file expects boolean argument" +msgstr "--use-pid-file förväntar sig ett booleskt argument" + +#: ../src/daemon/cmdline.c:319 +msgid "Invalid log target: use either 'syslog', 'stderr' or 'auto'." +msgstr "" + +#: ../src/daemon/cmdline.c:338 +#, c-format +msgid "Invalid resample method '%s'." +msgstr "" + +#: ../src/daemon/cmdline.c:345 +msgid "--system expects boolean argument" +msgstr "--system förväntar sig ett booleskt argument" + +#: ../src/daemon/cmdline.c:352 +msgid "--no-cpu-limit expects boolean argument" +msgstr "--no-cpu-limit förväntar sig ett booleskt argument" + +#: ../src/daemon/cmdline.c:359 +msgid "--disable-shm expects boolean argument" +msgstr "--disable-shm förväntar sig ett booleskt argument" + +#: ../src/daemon/dumpmodules.c:60 +#, c-format +msgid "Name: %s\n" +msgstr "Namn: %s\n" + +#: ../src/daemon/dumpmodules.c:63 +#, c-format +msgid "No module information available\n" +msgstr "" + +#: ../src/daemon/dumpmodules.c:66 +#, c-format +msgid "Version: %s\n" +msgstr "Version: %s\n" + +#: ../src/daemon/dumpmodules.c:68 +#, c-format +msgid "Description: %s\n" +msgstr "Beskrivning: %s\n" + +#: ../src/daemon/dumpmodules.c:70 +#, c-format +msgid "Author: %s\n" +msgstr "Upphovsman: %s\n" + +#: ../src/daemon/dumpmodules.c:72 +#, c-format +msgid "Usage: %s\n" +msgstr "Användning: %s\n" + +#: ../src/daemon/dumpmodules.c:73 +#, c-format +msgid "Load Once: %s\n" +msgstr "" + +#: ../src/daemon/dumpmodules.c:77 +#, c-format +msgid "Path: %s\n" +msgstr "Sökväg: %s\n" + +#: ../src/daemon/daemon-conf.c:205 +#, c-format +msgid "[%s:%u] Invalid log target '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:221 +#, c-format +msgid "[%s:%u] Invalid log level '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:237 +#, c-format +msgid "[%s:%u] Invalid resample method '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:260 +#, c-format +msgid "[%s:%u] Invalid rlimit '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:267 +#, c-format +msgid "[%s:%u] rlimit not supported on this platform." +msgstr "" + +#: ../src/daemon/daemon-conf.c:283 +#, c-format +msgid "[%s:%u] Invalid sample format '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:301 +#, c-format +msgid "[%s:%u] Invalid sample rate '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:319 +#, c-format +msgid "[%s:%u] Invalid sample channels '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:337 +#, c-format +msgid "[%s:%u] Invalid number of fragments '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:355 +#, c-format +msgid "[%s:%u] Invalid fragment size '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:373 +#, c-format +msgid "[%s:%u] Invalid nice level '%s'." +msgstr "" + +#: ../src/daemon/daemon-conf.c:570 +#, c-format +msgid "Failed to open configuration file: %s" +msgstr "Misslyckades med att öppna konfigurationsfil: %s" + +#: ../src/daemon/daemon-conf.c:644 +#, c-format +msgid "### Read from configuration file: %s ###\n" +msgstr "" + +#: ../src/daemon/caps.c:63 +msgid "Dropping root priviliges." +msgstr "Släpper root-behörighet." + +#: ../src/daemon/caps.c:103 +msgid "Limited capabilities successfully to CAP_SYS_NICE." +msgstr "" + +#: ../src/pulse/channelmap.c:102 +msgid "Mono" +msgstr "Mono" + +#: ../src/pulse/channelmap.c:104 +msgid "Front Center" +msgstr "Center fram" + +#: ../src/pulse/channelmap.c:105 +msgid "Front Left" +msgstr "Vänster fram" + +#: ../src/pulse/channelmap.c:106 +msgid "Front Right" +msgstr "Höger fram" + +#: ../src/pulse/channelmap.c:108 +msgid "Rear Center" +msgstr "Center bak" + +#: ../src/pulse/channelmap.c:109 +msgid "Rear Left" +msgstr "Vänster bak" + +#: ../src/pulse/channelmap.c:110 +msgid "Rear Right" +msgstr "Höger bak" + +#: ../src/pulse/channelmap.c:112 +msgid "Low Frequency Emmiter" +msgstr "" + +#: ../src/pulse/channelmap.c:114 +msgid "Front Left-of-center" +msgstr "Vänster-om-center fram" + +#: ../src/pulse/channelmap.c:115 +msgid "Front Right-of-center" +msgstr "Höger-om-center fram" + +#: ../src/pulse/channelmap.c:117 +msgid "Side Left" +msgstr "Vänster sida" + +#: ../src/pulse/channelmap.c:118 +msgid "Side Right" +msgstr "Höger sida" + +#: ../src/pulse/channelmap.c:120 +msgid "Auxiliary 0" +msgstr "" + +#: ../src/pulse/channelmap.c:121 +msgid "Auxiliary 1" +msgstr "" + +#: ../src/pulse/channelmap.c:122 +msgid "Auxiliary 2" +msgstr "" + +#: ../src/pulse/channelmap.c:123 +msgid "Auxiliary 3" +msgstr "" + +#: ../src/pulse/channelmap.c:124 +msgid "Auxiliary 4" +msgstr "" + +#: ../src/pulse/channelmap.c:125 +msgid "Auxiliary 5" +msgstr "" + +#: ../src/pulse/channelmap.c:126 +msgid "Auxiliary 6" +msgstr "" + +#: ../src/pulse/channelmap.c:127 +msgid "Auxiliary 7" +msgstr "" + +#: ../src/pulse/channelmap.c:128 +msgid "Auxiliary 8" +msgstr "" + +#: ../src/pulse/channelmap.c:129 +msgid "Auxiliary 9" +msgstr "" + +#: ../src/pulse/channelmap.c:130 +msgid "Auxiliary 10" +msgstr "" + +#: ../src/pulse/channelmap.c:131 +msgid "Auxiliary 11" +msgstr "" + +#: ../src/pulse/channelmap.c:132 +msgid "Auxiliary 12" +msgstr "" + +#: ../src/pulse/channelmap.c:133 +msgid "Auxiliary 13" +msgstr "" + +#: ../src/pulse/channelmap.c:134 +msgid "Auxiliary 14" +msgstr "" + +#: ../src/pulse/channelmap.c:135 +msgid "Auxiliary 15" +msgstr "" + +#: ../src/pulse/channelmap.c:136 +msgid "Auxiliary 16" +msgstr "" + +#: ../src/pulse/channelmap.c:137 +msgid "Auxiliary 17" +msgstr "" + +#: ../src/pulse/channelmap.c:138 +msgid "Auxiliary 18" +msgstr "" + +#: ../src/pulse/channelmap.c:139 +msgid "Auxiliary 19" +msgstr "" + +#: ../src/pulse/channelmap.c:140 +msgid "Auxiliary 20" +msgstr "" + +#: ../src/pulse/channelmap.c:141 +msgid "Auxiliary 21" +msgstr "" + +#: ../src/pulse/channelmap.c:142 +msgid "Auxiliary 22" +msgstr "" + +#: ../src/pulse/channelmap.c:143 +msgid "Auxiliary 23" +msgstr "" + +#: ../src/pulse/channelmap.c:144 +msgid "Auxiliary 24" +msgstr "" + +#: ../src/pulse/channelmap.c:145 +msgid "Auxiliary 25" +msgstr "" + +#: ../src/pulse/channelmap.c:146 +msgid "Auxiliary 26" +msgstr "" + +#: ../src/pulse/channelmap.c:147 +msgid "Auxiliary 27" +msgstr "" + +#: ../src/pulse/channelmap.c:148 +msgid "Auxiliary 28" +msgstr "" + +#: ../src/pulse/channelmap.c:149 +msgid "Auxiliary 29" +msgstr "" + +#: ../src/pulse/channelmap.c:150 +msgid "Auxiliary 30" +msgstr "" + +#: ../src/pulse/channelmap.c:151 +msgid "Auxiliary 31" +msgstr "" + +#: ../src/pulse/channelmap.c:153 +msgid "Top Center" +msgstr "" + +#: ../src/pulse/channelmap.c:155 +msgid "Top Front Center" +msgstr "" + +#: ../src/pulse/channelmap.c:156 +msgid "Top Front Left" +msgstr "" + +#: ../src/pulse/channelmap.c:157 +msgid "Top Front Right" +msgstr "" + +#: ../src/pulse/channelmap.c:159 +msgid "Top Rear Center" +msgstr "" + +#: ../src/pulse/channelmap.c:160 +msgid "Top Rear Left" +msgstr "" + +#: ../src/pulse/channelmap.c:161 +msgid "Top Rear Right" +msgstr "" + +#: ../src/pulse/channelmap.c:472 ../src/pulse/sample.c:144 +#: ../src/pulse/volume.c:163 ../src/pulse/volume.c:194 +#, fuzzy +msgid "(invalid)" +msgstr "Ogiltig" + +#: ../src/pulse/error.c:43 +msgid "OK" +msgstr "OK" + +#: ../src/pulse/error.c:44 +msgid "Access denied" +msgstr "Åtkomst nekad" + +#: ../src/pulse/error.c:45 +msgid "Unknown command" +msgstr "Okänt kommando" + +#: ../src/pulse/error.c:46 +msgid "Invalid argument" +msgstr "Ogiltigt argument" + +#: ../src/pulse/error.c:47 +msgid "Entity exists" +msgstr "Entiteten finns" + +#: ../src/pulse/error.c:48 +msgid "No such entity" +msgstr "Ingen sådan entitet" + +#: ../src/pulse/error.c:49 +msgid "Connection refused" +msgstr "Anslutning nekades" + +#: ../src/pulse/error.c:50 +msgid "Protocol error" +msgstr "Protokollfel" + +#: ../src/pulse/error.c:51 +msgid "Timeout" +msgstr "Tidsgräns nåddes" + +#: ../src/pulse/error.c:52 +msgid "No authorization key" +msgstr "" + +#: ../src/pulse/error.c:53 +msgid "Internal error" +msgstr "Internt fel" + +#: ../src/pulse/error.c:54 +msgid "Connection terminated" +msgstr "Anslutningen terminerad" + +#: ../src/pulse/error.c:55 +msgid "Entity killed" +msgstr "" + +#: ../src/pulse/error.c:56 +msgid "Invalid server" +msgstr "Ogiltig server" + +#: ../src/pulse/error.c:57 +msgid "Module initalization failed" +msgstr "" + +#: ../src/pulse/error.c:58 +msgid "Bad state" +msgstr "Felaktigt tillstånd" + +#: ../src/pulse/error.c:59 +msgid "No data" +msgstr "Inget data" + +#: ../src/pulse/error.c:60 +msgid "Incompatible protocol version" +msgstr "" + +#: ../src/pulse/error.c:61 +msgid "Too large" +msgstr "För stor" + +#: ../src/pulse/error.c:62 +msgid "Not supported" +msgstr "Stöds inte" + +#: ../src/pulse/error.c:63 +msgid "Unknown error code" +msgstr "Okänd felkod" + +#: ../src/pulse/error.c:64 +msgid "No such extension" +msgstr "" + +#: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100 +msgid "XOpenDisplay() failed" +msgstr "XOpenDisplay() misslyckades" + +#: ../src/pulse/client-conf-x11.c:78 +msgid "Failed to parse cookie data" +msgstr "" + +#: ../src/pulse/client-conf.c:120 +#, c-format +msgid "Failed to open configuration file '%s': %s" +msgstr "Misslyckades med att öppna konfigurationsfilen \"%s\": %s" + +#: ../src/pulse/context.c:516 +msgid "No cookie loaded. Attempting to connect without." +msgstr "" + +#: ../src/pulse/context.c:642 +#, c-format +msgid "fork(): %s" +msgstr "fork(): %s" + +#: ../src/pulse/context.c:695 +#, c-format +msgid "waitpid(): %s" +msgstr "waitpid(): %s" + +#: ../src/pulse/context.c:1256 +#, c-format +msgid "Received message for unknown extension '%s'" +msgstr "" + +#: ../src/utils/pacat.c:93 +#, c-format +msgid "pa_stream_write() failed: %s\n" +msgstr "pa_stream_write() misslyckades: %s\n" + +#: ../src/utils/pacat.c:132 +#, c-format +msgid "pa_stream_peek() failed: %s\n" +msgstr "pa_stream_peek() misslyckades: %s\n" + +#: ../src/utils/pacat.c:141 +#, c-format +msgid "Buffer overrun, dropping incoming data\n" +msgstr "" + +#: ../src/utils/pacat.c:143 +#, c-format +msgid "pa_stream_drop() failed: %s\n" +msgstr "pa_stream_drop() misslyckades: %s\n" + +#: ../src/utils/pacat.c:169 +#, c-format +msgid "Stream successfully created.\n" +msgstr "" + +#: ../src/utils/pacat.c:172 +#, c-format +msgid "pa_stream_get_buffer_attr() failed: %s\n" +msgstr "pa_stream_get_buffer_attr() misslyckades: %s\n" + +#: ../src/utils/pacat.c:176 +#, c-format +msgid "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n" +msgstr "" + +#: ../src/utils/pacat.c:179 +#, c-format +msgid "Buffer metrics: maxlength=%u, fragsize=%u\n" +msgstr "" + +#: ../src/utils/pacat.c:183 +#, c-format +msgid "Using sample spec '%s', channel map '%s'.\n" +msgstr "" + +#: ../src/utils/pacat.c:187 +#, c-format +msgid "Connected to device %s (%u, %ssuspended).\n" +msgstr "" + +#: ../src/utils/pacat.c:197 +#, c-format +msgid "Stream error: %s\n" +msgstr "Strömfel: %s\n" + +#: ../src/utils/pacat.c:207 +#, c-format +msgid "Stream device suspended.%s \n" +msgstr "" + +#: ../src/utils/pacat.c:209 +#, c-format +msgid "Stream device resumed.%s \n" +msgstr "" + +#: ../src/utils/pacat.c:217 +#, c-format +msgid "Stream underrun.%s \n" +msgstr "" + +#: ../src/utils/pacat.c:224 +#, c-format +msgid "Stream overrun.%s \n" +msgstr "" + +#: ../src/utils/pacat.c:231 +#, c-format +msgid "Stream started.%s \n" +msgstr "" + +#: ../src/utils/pacat.c:238 +#, c-format +msgid "Stream moved to device %s (%u, %ssuspended).%s \n" +msgstr "" + +#: ../src/utils/pacat.c:238 +msgid "not " +msgstr "inte " + +#: ../src/utils/pacat.c:259 +#, c-format +msgid "Connection established.%s \n" +msgstr "" + +#: ../src/utils/pacat.c:262 +#, c-format +msgid "pa_stream_new() failed: %s\n" +msgstr "pa_stream_new() misslyckades: %s\n" + +#: ../src/utils/pacat.c:287 +#, c-format +msgid "pa_stream_connect_playback() failed: %s\n" +msgstr "pa_stream_connect_playback() misslyckades: %s\n" + +#: ../src/utils/pacat.c:293 +#, c-format +msgid "pa_stream_connect_record() failed: %s\n" +msgstr "pa_stream_connect_record() misslyckades: %s\n" + +#: ../src/utils/pacat.c:307 ../src/utils/pasuspender.c:159 +#: ../src/utils/pactl.c:666 ../src/utils/paplay.c:183 +#, c-format +msgid "Connection failure: %s\n" +msgstr "Anslutningsfel: %s\n" + +#: ../src/utils/pacat.c:328 ../src/utils/paplay.c:75 +#, c-format +msgid "Failed to drain stream: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:333 ../src/utils/paplay.c:80 +#, c-format +msgid "Playback stream drained.\n" +msgstr "" + +#: ../src/utils/pacat.c:343 ../src/utils/paplay.c:92 +#, c-format +msgid "Draining connection to server.\n" +msgstr "" + +#: ../src/utils/pacat.c:369 +#, c-format +msgid "Got EOF.\n" +msgstr "Fick filslut.\n" + +#: ../src/utils/pacat.c:375 +#, c-format +msgid "pa_stream_drain(): %s\n" +msgstr "pa_stream_drain(): %s\n" + +#: ../src/utils/pacat.c:385 +#, c-format +msgid "read() failed: %s\n" +msgstr "read() misslyckades: %s\n" + +#: ../src/utils/pacat.c:417 +#, c-format +msgid "write() failed: %s\n" +msgstr "write() misslyckades: %s\n" + +#: ../src/utils/pacat.c:438 +#, c-format +msgid "Got signal, exiting.\n" +msgstr "" + +#: ../src/utils/pacat.c:452 +#, c-format +msgid "Failed to get latency: %s\n" +msgstr "" + +#: ../src/utils/pacat.c:457 +#, c-format +msgid "Time: %0.3f sec; Latency: %0.0f usec. \r" +msgstr "Tid: %0.3f sec; Latens: %0.0f ms \r" + +#: ../src/utils/pacat.c:477 +#, c-format +msgid "pa_stream_update_timing_info() failed: %s\n" +msgstr "pa_stream_update_timing_info() misslyckades: %s\n" + +#: ../src/utils/pacat.c:490 +#, c-format +msgid "" +"%s [options]\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -r, --record Create a connection for recording\n" +" -p, --playback Create a connection for playback\n" +"\n" +" -v, --verbose Enable verbose operations\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -d, --device=DEVICE The name of the sink/source to " +"connect to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" +" --rate=SAMPLERATE The sample rate in Hz (defaults to " +"44100)\n" +" --format=SAMPLEFORMAT The sample type, one of s16le, " +"s16be, u8, float32le,\n" +" float32be, ulaw, alaw, s32le, s32be " +"(defaults to s16ne)\n" +" --channels=CHANNELS The number of channels, 1 for mono, " +"2 for stereo\n" +" (defaults to 2)\n" +" --channel-map=CHANNELMAP Channel map to use instead of the " +"default\n" +" --fix-format Take the sample format from the sink " +"the stream is\n" +" being connected to.\n" +" --fix-rate Take the sampling rate from the sink " +"the stream is\n" +" being connected to.\n" +" --fix-channels Take the number of channels and the " +"channel map\n" +" from the sink the stream is being " +"connected to.\n" +" --no-remix Don't upmix or downmix channels.\n" +" --no-remap Map channels by index instead of " +"name.\n" +" --latency=BYTES Request the specified latency in " +"bytes.\n" +" --process-time=BYTES Request the specified process time " +"per request in bytes.\n" +msgstr "" + +#: ../src/utils/pacat.c:591 +#, c-format +msgid "" +"pacat %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" + +#: ../src/utils/pacat.c:647 +#, c-format +msgid "Invalid channel map '%s'\n" +msgstr "" + +#: ../src/utils/pacat.c:676 +#, c-format +msgid "Invalid latency specification '%s'\n" +msgstr "" + +#: ../src/utils/pacat.c:683 +#, c-format +msgid "Invalid process time specification '%s'\n" +msgstr "" + +#: ../src/utils/pacat.c:694 +#, c-format +msgid "Invalid sample specification\n" +msgstr "" + +#: ../src/utils/pacat.c:699 +#, c-format +msgid "Channel map doesn't match sample specification\n" +msgstr "" + +#: ../src/utils/pacat.c:706 +#, c-format +msgid "Opening a %s stream with sample specification '%s'.\n" +msgstr "" + +#: ../src/utils/pacat.c:706 +msgid "recording" +msgstr "" + +#: ../src/utils/pacat.c:706 +msgid "playback" +msgstr "" + +#: ../src/utils/pacat.c:714 +#, c-format +msgid "open(): %s\n" +msgstr "open(): %s\n" + +#: ../src/utils/pacat.c:719 +#, c-format +msgid "dup2(): %s\n" +msgstr "dup2(): %s\n" + +#: ../src/utils/pacat.c:729 +#, c-format +msgid "Too many arguments.\n" +msgstr "För många argument.\n" + +#: ../src/utils/pacat.c:742 ../src/utils/pasuspender.c:280 +#: ../src/utils/pactl.c:909 ../src/utils/paplay.c:381 +#, c-format +msgid "pa_mainloop_new() failed.\n" +msgstr "pa_mainloop_new() misslyckades.\n" + +#: ../src/utils/pacat.c:763 +#, c-format +msgid "io_new() failed.\n" +msgstr "io_new() misslyckades.\n" + +#: ../src/utils/pacat.c:769 ../src/utils/pasuspender.c:293 +#: ../src/utils/pactl.c:923 ../src/utils/paplay.c:396 +#, c-format +msgid "pa_context_new() failed.\n" +msgstr "pa_context_new() misslyckades.\n" + +#: ../src/utils/pacat.c:777 +#, fuzzy, c-format +msgid "pa_context_connect() failed: %s" +msgstr "pa_context_new() misslyckades.\n" + +#: ../src/utils/pacat.c:788 +#, c-format +msgid "time_new() failed.\n" +msgstr "time_new() misslyckades.\n" + +#: ../src/utils/pacat.c:795 ../src/utils/pasuspender.c:301 +#: ../src/utils/pactl.c:931 ../src/utils/paplay.c:407 +#, c-format +msgid "pa_mainloop_run() failed.\n" +msgstr "pa_mainloop_run() misslyckades.\n" + +#: ../src/utils/pasuspender.c:81 +#, c-format +msgid "fork(): %s\n" +msgstr "fork(): %s\n" + +#: ../src/utils/pasuspender.c:92 +#, c-format +msgid "execvp(): %s\n" +msgstr "execvp(): %s\n" + +#: ../src/utils/pasuspender.c:109 +#, c-format +msgid "Failure to suspend: %s\n" +msgstr "" + +#: ../src/utils/pasuspender.c:124 +#, c-format +msgid "Failure to resume: %s\n" +msgstr "" + +#: ../src/utils/pasuspender.c:147 +#, c-format +msgid "WARNING: Sound server is not local, not suspending.\n" +msgstr "" + +#: ../src/utils/pasuspender.c:176 ../src/utils/pactl.c:672 +#: ../src/utils/paplay.c:191 +#, c-format +msgid "Got SIGINT, exiting.\n" +msgstr "" + +#: ../src/utils/pasuspender.c:194 +#, c-format +msgid "WARNING: Child process terminated by signal %u\n" +msgstr "" + +#: ../src/utils/pasuspender.c:212 +#, c-format +msgid "" +"%s [options] ... \n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +"\n" +msgstr "" + +#: ../src/utils/pasuspender.c:251 +#, c-format +msgid "" +"pasuspender %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"pasuspender %s\n" +"Kompilerad med libpulse %s\n" +"Länkad med libpulse %s\n" + +#: ../src/utils/pactl.c:107 +#, c-format +msgid "Failed to get statistics: %s\n" +msgstr "Misslyckades med att få statistik: %s\n" + +#: ../src/utils/pactl.c:113 +#, c-format +msgid "Currently in use: %u blocks containing %s bytes total.\n" +msgstr "" + +#: ../src/utils/pactl.c:116 +#, c-format +msgid "Allocated during whole lifetime: %u blocks containing %s bytes total.\n" +msgstr "" + +#: ../src/utils/pactl.c:119 +#, c-format +msgid "Sample cache size: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:128 +#, c-format +msgid "Failed to get server information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:135 +#, c-format +msgid "" +"User name: %s\n" +"Host Name: %s\n" +"Server Name: %s\n" +"Server Version: %s\n" +"Default Sample Specification: %s\n" +"Default Sink: %s\n" +"Default Source: %s\n" +"Cookie: %08x\n" +msgstr "" + +#: ../src/utils/pactl.c:160 +#, c-format +msgid "Failed to get sink information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:176 +#, c-format +msgid "" +"*** Sink #%u ***\n" +"Name: %s\n" +"Driver: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Owner Module: %u\n" +"Volume: %s\n" +"Monitor Source: %s\n" +"Latency: %0.0f usec, configured %0.0f usec\n" +"Flags: %s%s%s%s%s%s\n" +"Properties:\n" +"%s" +msgstr "" + +#: ../src/utils/pactl.c:193 ../src/utils/pactl.c:371 +msgid "muted" +msgstr "tystad" + +#: ../src/utils/pactl.c:212 +#, c-format +msgid "Failed to get source information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:228 +#, c-format +msgid "" +"*** Source #%u ***\n" +"Name: %s\n" +"Driver: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Owner Module: %u\n" +"Volume: %s\n" +"Monitor of Sink: %s\n" +"Latency: %0.0f usec, configured %0.0f usec\n" +"Flags: %s%s%s%s%s%s\n" +"Properties:\n" +"%s" +msgstr "" + +#: ../src/utils/pactl.c:246 ../src/utils/pactl.c:289 ../src/utils/pactl.c:322 +#: ../src/utils/pactl.c:366 ../src/utils/pactl.c:367 ../src/utils/pactl.c:374 +#: ../src/utils/pactl.c:418 ../src/utils/pactl.c:419 ../src/utils/pactl.c:425 +#: ../src/utils/pactl.c:468 ../src/utils/pactl.c:469 ../src/utils/pactl.c:473 +msgid "n/a" +msgstr "" + +#: ../src/utils/pactl.c:263 +#, c-format +msgid "Failed to get module information: %s\n" +msgstr "Misslyckades med att få modulinformation: %s\n" + +#: ../src/utils/pactl.c:281 +#, c-format +msgid "" +"*** Module #%u ***\n" +"Name: %s\n" +"Argument: %s\n" +"Usage counter: %s\n" +"Auto unload: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:298 +#, c-format +msgid "Failed to get client information: %s\n" +msgstr "Misslyckades med att få klientinformation: %s\n" + +#: ../src/utils/pactl.c:316 +#, c-format +msgid "" +"*** Client #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Properties:\n" +"%s" +msgstr "" + +#: ../src/utils/pactl.c:333 +#, c-format +msgid "Failed to get sink input information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:352 +#, c-format +msgid "" +"*** Sink Input #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Client: %s\n" +"Sink: %u\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Volume: %s\n" +"Buffer Latency: %0.0f usec\n" +"Sink Latency: %0.0f usec\n" +"Resample method: %s\n" +"Properties:\n" +"%s" +msgstr "" + +#: ../src/utils/pactl.c:385 +#, c-format +msgid "Failed to get source output information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:405 +#, c-format +msgid "" +"*** Source Output #%u ***\n" +"Driver: %s\n" +"Owner Module: %s\n" +"Client: %s\n" +"Source: %u\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Buffer Latency: %0.0f usec\n" +"Source Latency: %0.0f usec\n" +"Resample method: %s\n" +"Properties:\n" +"%s" +msgstr "" + +#: ../src/utils/pactl.c:436 +#, c-format +msgid "Failed to get sample information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:455 +#, c-format +msgid "" +"*** Sample #%u ***\n" +"Name: %s\n" +"Volume: %s\n" +"Sample Specification: %s\n" +"Channel Map: %s\n" +"Duration: %0.1fs\n" +"Size: %s\n" +"Lazy: %s\n" +"Filename: %s\n" +"Properties:\n" +"%s" +msgstr "" + +#: ../src/utils/pactl.c:481 +#, c-format +msgid "Failed to get autoload information: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:497 +#, c-format +msgid "" +"*** Autoload Entry #%u ***\n" +"Name: %s\n" +"Type: %s\n" +"Module: %s\n" +"Argument: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:504 +msgid "sink" +msgstr "sink" + +#: ../src/utils/pactl.c:504 +msgid "source" +msgstr "källa" + +#: ../src/utils/pactl.c:511 ../src/utils/pactl.c:521 +#, c-format +msgid "Failure: %s\n" +msgstr "Fel: %s\n" + +#: ../src/utils/pactl.c:545 +#, c-format +msgid "Failed to upload sample: %s\n" +msgstr "" + +#: ../src/utils/pactl.c:562 +#, c-format +msgid "Premature end of file\n" +msgstr "" + +#: ../src/utils/pactl.c:678 +#, c-format +msgid "" +"%s [options] stat\n" +"%s [options] list\n" +"%s [options] exit\n" +"%s [options] upload-sample FILENAME [NAME]\n" +"%s [options] play-sample NAME [SINK]\n" +"%s [options] remove-sample NAME\n" +"%s [options] move-sink-input ID SINK\n" +"%s [options] move-source-output ID SOURCE\n" +"%s [options] load-module NAME [ARGS ...]\n" +"%s [options] unload-module ID\n" +"%s [options] suspend-sink [SINK] 1|0\n" +"%s [options] suspend-source [SOURCE] 1|0\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +msgstr "" + +#: ../src/utils/pactl.c:729 +#, c-format +msgid "" +"pactl %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"pactl %s\n" +"Kompilerad med libpulse %s\n" +"Länkad med libpulse %s\n" + +#: ../src/utils/pactl.c:768 +#, c-format +msgid "Please specify a sample file to load\n" +msgstr "" + +#: ../src/utils/pactl.c:790 +#, c-format +msgid "Failed to open sound file.\n" +msgstr "Misslyckades med att öppna ljudfil.\n" + +#: ../src/utils/pactl.c:802 +#, c-format +msgid "You have to specify a sample name to play\n" +msgstr "" + +#: ../src/utils/pactl.c:814 +#, c-format +msgid "You have to specify a sample name to remove\n" +msgstr "" + +#: ../src/utils/pactl.c:822 +#, c-format +msgid "You have to specify a sink input index and a sink\n" +msgstr "" + +#: ../src/utils/pactl.c:831 +#, c-format +msgid "You have to specify a source output index and a source\n" +msgstr "" + +#: ../src/utils/pactl.c:845 +#, c-format +msgid "You have to specify a module name and arguments.\n" +msgstr "" + +#: ../src/utils/pactl.c:865 +#, c-format +msgid "You have to specify a module index\n" +msgstr "" + +#: ../src/utils/pactl.c:875 +#, c-format +msgid "" +"You may not specify more than one sink. You have to specify at least one " +"boolean value.\n" +msgstr "" + +#: ../src/utils/pactl.c:888 +#, c-format +msgid "" +"You may not specify more than one source. You have to specify at least one " +"boolean value.\n" +msgstr "" + +#: ../src/utils/pactl.c:904 +#, c-format +msgid "No valid command specified.\n" +msgstr "" + +#: ../src/utils/pax11publish.c:61 +#, c-format +msgid "" +"%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n" +"\n" +" -d Show current PulseAudio data attached to X11 display (default)\n" +" -e Export local PulseAudio data to X11 display\n" +" -i Import PulseAudio data from X11 display to local environment " +"variables and cookie file.\n" +" -r Remove PulseAudio data from X11 display\n" +msgstr "" + +#: ../src/utils/pax11publish.c:94 +#, c-format +msgid "Failed to parse command line.\n" +msgstr "Misslyckades med att tolka kommandorad.\n" + +#: ../src/utils/pax11publish.c:108 +#, c-format +msgid "Server: %s\n" +msgstr "Server: %s\n" + +#: ../src/utils/pax11publish.c:110 +#, c-format +msgid "Source: %s\n" +msgstr "Källa: %s\n" + +#: ../src/utils/pax11publish.c:112 +#, c-format +msgid "Sink: %s\n" +msgstr "Sink: %s\n" + +#: ../src/utils/pax11publish.c:114 +#, c-format +msgid "Cookie: %s\n" +msgstr "Kaka: %s\n" + +#: ../src/utils/pax11publish.c:132 +#, c-format +msgid "Failed to parse cookie data\n" +msgstr "" + +#: ../src/utils/pax11publish.c:137 +#, c-format +msgid "Failed to save cookie data\n" +msgstr "" + +#: ../src/utils/pax11publish.c:152 +#, c-format +msgid "Failed to load client configuration file.\n" +msgstr "" + +#: ../src/utils/pax11publish.c:157 +#, c-format +msgid "Failed to read environment configuration data.\n" +msgstr "" + +#: ../src/utils/pax11publish.c:174 +#, c-format +msgid "Failed to get FQDN.\n" +msgstr "" + +#: ../src/utils/pax11publish.c:194 +#, c-format +msgid "Failed to load cookie data\n" +msgstr "" + +#: ../src/utils/pax11publish.c:211 +#, c-format +msgid "Not yet implemented.\n" +msgstr "Ännu inte implementerad.\n" + +#: ../src/utils/pacmd.c:64 +#, c-format +msgid "socket(PF_UNIX, SOCK_STREAM, 0): %s" +msgstr "" + +#: ../src/utils/pacmd.c:81 +#, c-format +msgid "connect(): %s" +msgstr "connect(): %s" + +#: ../src/utils/pacmd.c:89 +msgid "Failed to kill PulseAudio daemon." +msgstr "" + +#: ../src/utils/pacmd.c:97 +msgid "Daemon not responding." +msgstr "" + +#: ../src/utils/pacmd.c:112 +#, c-format +msgid "select(): %s" +msgstr "select(): %s" + +#: ../src/utils/pacmd.c:124 ../src/utils/pacmd.c:140 +#, c-format +msgid "read(): %s" +msgstr "read(): %s" + +#: ../src/utils/pacmd.c:153 ../src/utils/pacmd.c:167 +#, c-format +msgid "write(): %s" +msgstr "write(): %s" + +#: ../src/utils/paplay.c:139 +#, c-format +msgid "Stream successfully created\n" +msgstr "" + +#: ../src/utils/paplay.c:144 +#, c-format +msgid "Stream errror: %s\n" +msgstr "" + +#: ../src/utils/paplay.c:165 +#, c-format +msgid "Connection established.\n" +msgstr "Anslutning etablerad.\n" + +#: ../src/utils/paplay.c:198 +#, c-format +msgid "" +"%s [options] [FILE]\n" +"\n" +" -h, --help Show this help\n" +" --version Show version\n" +"\n" +" -v, --verbose Enable verbose operation\n" +"\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -d, --device=DEVICE The name of the sink to connect to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" +" --channel-map=CHANNELMAP Set the channel map to the use\n" +msgstr "" + +#: ../src/utils/paplay.c:255 +#, c-format +msgid "" +"paplay %s\n" +"Compiled with libpulse %s\n" +"Linked with libpulse %s\n" +msgstr "" +"paplay %s\n" +"Kompilerad med libpulse %s\n" +"Länkad med libpulse %s\n" + +#: ../src/utils/paplay.c:292 +#, c-format +msgid "Invalid channel map\n" +msgstr "" + +#: ../src/utils/paplay.c:314 +#, c-format +msgid "Failed to open file '%s'\n" +msgstr "Misslyckades med att öppna filen \"%s\"\n" + +#: ../src/utils/paplay.c:350 +#, c-format +msgid "Channel map doesn't match file.\n" +msgstr "" + +#: ../src/utils/paplay.c:376 +#, c-format +msgid "Using sample spec '%s'\n" +msgstr "" + +#: ../src/pulsecore/lock-autospawn.c:126 ../src/pulsecore/lock-autospawn.c:207 +msgid "Cannot access autospawn lock." +msgstr "" + +#~ msgid "socketpair(): %s" +#~ msgstr "socketpair(): %s" diff --git a/src/.gitignore b/src/.gitignore index 6902eb9f..72c38cc6 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,3 +1,5 @@ +prioq-test +lock-autospawn-test *.lo *.o *.la @@ -7,7 +9,7 @@ Makefile Makefile.in asyncmsgq-test asyncq-test -bt-proximity-helper +proximity-helper channelmap-test client.conf close-test diff --git a/src/Makefile.am b/src/Makefile.am index 29a6ef47..b9d00831 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -45,28 +45,31 @@ endif # Compiler/linker flags # ################################### -AM_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src/modules -I$(top_builddir)/src/modules/rtp -I$(top_builddir)/src/modules/gconf -AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS -AM_CFLAGS += $(LTDLINCL) -AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) $(LIBSPEEX_CFLAGS) -AM_CFLAGS += -DPA_DLSEARCHPATH=\"$(modlibexecdir)\" -AM_CFLAGS += -DPA_DEFAULT_CONFIG_DIR=\"$(PA_DEFAULT_CONFIG_DIR)\" -AM_CFLAGS += -DPA_BINARY=\"$(PA_BINARY)\" -AM_CFLAGS += -DPA_SYSTEM_RUNTIME_PATH=\"$(PA_SYSTEM_RUNTIME_PATH)\" -AM_CFLAGS += -DPA_SYSTEM_CONFIG_PATH=\"$(PA_SYSTEM_CONFIG_PATH)\" -AM_CFLAGS += -DPA_SYSTEM_STATE_PATH=\"$(PA_SYSTEM_STATE_PATH)\" -AM_CFLAGS += -DAO_REQUIRE_CAS -AM_CFLAGS += -DPULSE_LOCALEDIR=\"$(pulselocaledir)\" -AM_CFLAGS += -DPA_MACHINE_ID=\"$(localstatedir)/lib/dbus/machine-id\" - -# This cool debug trap works on i386/gcc only -AM_CFLAGS += '-DDEBUG_TRAP=__asm__("int $$3")' - -AM_LIBADD = $(PTHREAD_LIBS) -AM_LDADD = $(PTHREAD_LIBS) - -# Only required on some platforms but defined for all to avoid errors -AM_LDFLAGS = -Wl,-no-undefined -Wl,--gc-sections +AM_CFLAGS = \ + -I$(top_srcdir)/src \ + -I$(top_builddir)/src/modules \ + -I$(top_builddir)/src/modules/rtp \ + -I$(top_builddir)/src/modules/gconf \ + -I$(top_builddir)/src/modules/bluetooth \ + -I$(top_builddir)/src/modules/raop \ + $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS \ + $(LTDLINCL) \ + $(LIBSAMPLERATE_CFLAGS) \ + $(LIBSNDFILE_CFLAGS) \ + $(LIBSPEEX_CFLAGS) \ + -DPA_DLSEARCHPATH=\"$(modlibexecdir)\" \ + -DPA_DEFAULT_CONFIG_DIR=\"$(PA_DEFAULT_CONFIG_DIR)\" \ + -DPA_BINARY=\"$(PA_BINARY)\" \ + -DPA_SYSTEM_RUNTIME_PATH=\"$(PA_SYSTEM_RUNTIME_PATH)\" \ + -DPA_SYSTEM_CONFIG_PATH=\"$(PA_SYSTEM_CONFIG_PATH)\" \ + -DPA_SYSTEM_STATE_PATH=\"$(PA_SYSTEM_STATE_PATH)\" \ + -DAO_REQUIRE_CAS \ + -DPULSE_LOCALEDIR=\"$(pulselocaledir)\" \ + -DPA_MACHINE_ID=\"$(localstatedir)/lib/dbus/machine-id\" + +AM_LIBADD = $(PTHREAD_LIBS) $(INTLLIBS) +AM_LDADD = $(PTHREAD_LIBS) $(INTLLIBS) +AM_LDFLAGS = -Wl,-z,nodelete if STATIC_BINS BINLDFLAGS = -static @@ -77,18 +80,6 @@ AM_LDFLAGS+=-Wl,--export-all-symbols WINSOCK_LIBS=-lwsock32 -lws2_32 -lwininet endif -if OS_IS_WIN32 -PA_THREAD_OBJS = \ - pulsecore/mutex-win32.c pulsecore/mutex.h \ - pulsecore/thread-win32.c pulsecore/thread.h \ - pulsecore/semaphore-win32.c pulsecore/semaphore.h -else -PA_THREAD_OBJS = \ - pulsecore/mutex-posix.c pulsecore/mutex.h \ - pulsecore/thread-posix.c pulsecore/thread.h \ - pulsecore/semaphore-posix.c pulsecore/semaphore.h -endif - ################################### # Extra files # ################################### @@ -139,10 +130,9 @@ pulseaudio_SOURCES = \ daemon/main.c pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSPEEX_CFLAGS) $(LIBSNDFILE_CFLAGS) $(CAP_CFLAGS) $(LIBOIL_CFLAGS) $(DBUS_CFLAGS) -pulseaudio_CPPFLAGS = $(AM_CPPFLAGS) -pulseaudio_LDADD = $(AM_LDADD) libpulsecore.la $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSPEEX_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS) $(DBUS_LIBS) +pulseaudio_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSPEEX_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS) $(DBUS_LIBS) # This is needed because automake doesn't properly expand the foreach below -pulseaudio_DEPENDENCIES = libpulsecore.la $(PREOPEN_LIBS) +pulseaudio_DEPENDENCIES = libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la $(PREOPEN_LIBS) if PREOPEN_MODS PREOPEN_LIBS = $(PREOPEN_MODS) @@ -157,14 +147,11 @@ pulseaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PRE endif if HAVE_POLKIT - policy_DATA = daemon/org.pulseaudio.policy pulseaudio_SOURCES += daemon/polkit.c daemon/polkit.h pulseaudio_CFLAGS += $(POLKIT_CFLAGS) pulseaudio_LDADD += $(POLKIT_LIBS) - - endif ################################### @@ -201,24 +188,24 @@ paplay_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS) paplay_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) paplay_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -pactl_SOURCES = utils/pactl.c pulsecore/core-util.c pulsecore/core-util.h pulsecore/core-error.c pulsecore/core-error.h pulsecore/log.c pulsecore/log.h pulsecore/once.c pulsecore/once.h $(PA_THREAD_OBJS) -pactl_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS) +pactl_SOURCES = utils/pactl.c +pactl_LDADD = $(AM_LDADD) libpulse.la libpulsecommon-@PA_MAJORMINORMICRO@.la $(LIBSNDFILE_LIBS) pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) pactl_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -pasuspender_SOURCES = utils/pasuspender.c pulsecore/core-util.c pulsecore/core-util.h pulsecore/core-error.c pulsecore/core-error.h pulsecore/log.c pulsecore/log.h pulsecore/once.c pulsecore/once.h $(PA_THREAD_OBJS) -pasuspender_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS) +pasuspender_SOURCES = utils/pasuspender.c +pasuspender_LDADD = $(AM_LDADD) libpulse.la libpulsecommon-@PA_MAJORMINORMICRO@.la $(LIBSNDFILE_LIBS) pasuspender_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) pasuspender_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -pacmd_SOURCES = utils/pacmd.c pulsecore/pid.c pulsecore/pid.h pulsecore/core-util.c pulsecore/core-util.h pulsecore/core-error.c pulsecore/core-error.h pulsecore/log.c pulsecore/log.h pulsecore/once.c pulsecore/once.h $(PA_THREAD_OBJS) +pacmd_SOURCES = utils/pacmd.c pacmd_CFLAGS = $(AM_CFLAGS) -pacmd_LDADD = $(AM_LDADD) libpulse.la +pacmd_LDADD = $(AM_LDADD) libpulse.la libpulsecommon-@PA_MAJORMINORMICRO@.la pacmd_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -pax11publish_SOURCES = utils/pax11publish.c pulsecore/x11prop.c pulsecore/x11prop.h pulse/client-conf.c pulse/client-conf.h pulsecore/authkey.h pulsecore/authkey.c pulsecore/random.h pulsecore/random.c pulsecore/conf-parser.c pulsecore/conf-parser.h pulsecore/core-util.c pulsecore/core-util.h pulsecore/core-error.c pulsecore/core-error.h pulsecore/log.c pulsecore/log.h pulsecore/once.c pulsecore/once.h $(PA_THREAD_OBJS) +pax11publish_SOURCES = utils/pax11publish.c pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -pax11publish_LDADD = $(AM_LDADD) libpulse.la $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) +pax11publish_LDADD = $(AM_LDADD) libpulse.la libpulsecommon-@PA_MAJORMINORMICRO@.la $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) pax11publish_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pabrowse_SOURCES = utils/pabrowse.c @@ -262,7 +249,9 @@ noinst_PROGRAMS = \ envelope-test \ proplist-test \ rtstutter \ - stripnul + stripnul \ + lock-autospawn-test \ + prioq-test if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -282,12 +271,12 @@ mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) thread_mainloop_test_SOURCES = tests/thread-mainloop-test.c thread_mainloop_test_CFLAGS = $(AM_CFLAGS) -thread_mainloop_test_LDADD = $(AM_LDADD) libpulsecore.la libpulse.la +thread_mainloop_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulse.la libpulsecommon-@PA_MAJORMINORMICRO@.la thread_mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) utf8_test_SOURCES = tests/utf8-test.c utf8_test_CFLAGS = $(AM_CFLAGS) -utf8_test_LDADD = $(AM_LDADD) libpulsecore.la +utf8_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la utf8_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) get_binary_name_test_SOURCES = tests/get-binary-name-test.c @@ -295,56 +284,54 @@ get_binary_name_test_CFLAGS = $(AM_CFLAGS) get_binary_name_test_LDADD = $(AM_LDADD) libpulse.la get_binary_name_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -ipacl_test_SOURCES = tests/ipacl-test.c \ - pulsecore/ipacl.c pulsecore/ipacl.h \ - pulsecore/inet_pton.c pulsecore/inet_pton.h +ipacl_test_SOURCES = tests/ipacl-test.c ipacl_test_CFLAGS = $(AM_CFLAGS) -ipacl_test_LDADD = $(AM_LDADD) libpulsecore.la +ipacl_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la ipacl_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) hook_list_test_SOURCES = tests/hook-list-test.c hook_list_test_CFLAGS = $(AM_CFLAGS) -hook_list_test_LDADD = $(AM_LDADD) libpulsecore.la +hook_list_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la hook_list_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) memblock_test_SOURCES = tests/memblock-test.c memblock_test_CFLAGS = $(AM_CFLAGS) -memblock_test_LDADD = $(AM_LDADD) libpulsecore.la +memblock_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la memblock_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) thread_test_SOURCES = tests/thread-test.c thread_test_CFLAGS = $(AM_CFLAGS) -thread_test_LDADD = $(AM_LDADD) libpulsecore.la +thread_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la thread_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) flist_test_SOURCES = tests/flist-test.c flist_test_CFLAGS = $(AM_CFLAGS) -flist_test_LDADD = $(AM_LDADD) libpulsecore.la +flist_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la flist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) asyncq_test_SOURCES = tests/asyncq-test.c asyncq_test_CFLAGS = $(AM_CFLAGS) -asyncq_test_LDADD = $(AM_LDADD) libpulsecore.la +asyncq_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la asyncq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) asyncmsgq_test_SOURCES = tests/asyncmsgq-test.c asyncmsgq_test_CFLAGS = $(AM_CFLAGS) -asyncmsgq_test_LDADD = $(AM_LDADD) libpulsecore.la +asyncmsgq_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la asyncmsgq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) queue_test_SOURCES = tests/queue-test.c queue_test_CFLAGS = $(AM_CFLAGS) -queue_test_LDADD = $(AM_LDADD) libpulsecore.la +queue_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la queue_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) rtpoll_test_SOURCES = tests/rtpoll-test.c rtpoll_test_CFLAGS = $(AM_CFLAGS) -rtpoll_test_LDADD = $(AM_LDADD) libpulsecore.la +rtpoll_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la rtpoll_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) mcalign_test_SOURCES = tests/mcalign-test.c mcalign_test_CFLAGS = $(AM_CFLAGS) -mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la +mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la mcalign_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pacat_simple_SOURCES = tests/pacat-simple.c @@ -359,12 +346,12 @@ parec_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) strlist_test_SOURCES = tests/strlist-test.c strlist_test_CFLAGS = $(AM_CFLAGS) -strlist_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la libstrlist.la +strlist_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la strlist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) close_test_SOURCES = tests/close-test.c close_test_CFLAGS = $(AM_CFLAGS) -close_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la libstrlist.la +close_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la close_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) voltest_SOURCES = tests/voltest.c @@ -379,12 +366,12 @@ channelmap_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) cpulimit_test_SOURCES = tests/cpulimit-test.c daemon/cpulimit.c daemon/cpulimit.h cpulimit_test_CFLAGS = $(AM_CFLAGS) -cpulimit_test_LDADD = $(AM_LDADD) libpulsecore.la +cpulimit_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la cpulimit_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) cpulimit_test2_SOURCES = tests/cpulimit-test.c daemon/cpulimit.c daemon/cpulimit.h cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2 -cpulimit_test2_LDADD = $(AM_LDADD) libpulsecore.la +cpulimit_test2_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la cpulimit_test2_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES) @@ -394,7 +381,7 @@ mainloop_test_glib_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) memblockq_test_SOURCES = tests/memblockq-test.c memblockq_test_CFLAGS = $(AM_CFLAGS) -memblockq_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la +memblockq_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la memblockq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) sync_playback_SOURCES = tests/sync-playback.c @@ -403,55 +390,160 @@ sync_playback_CFLAGS = $(AM_CFLAGS) sync_playback_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) interpol_test_SOURCES = tests/interpol-test.c -interpol_test_LDADD = $(AM_LDADD) libpulse.la libpulsecore.la +interpol_test_LDADD = $(AM_LDADD) libpulse.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la interpol_test_CFLAGS = $(AM_CFLAGS) interpol_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) sig2str_test_SOURCES = tests/sig2str-test.c -sig2str_test_LDADD = $(AM_LDADD) libpulsecore.la +sig2str_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la sig2str_test_CFLAGS = $(AM_CFLAGS) sig2str_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) resampler_test_SOURCES = tests/resampler-test.c -resampler_test_LDADD = $(AM_LDADD) libpulsecore.la +resampler_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la resampler_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) resampler_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) mix_test_SOURCES = tests/mix-test.c -mix_test_LDADD = $(AM_LDADD) libpulsecore.la +mix_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la mix_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) mix_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) remix_test_SOURCES = tests/remix-test.c -remix_test_LDADD = $(AM_LDADD) libpulsecore.la +remix_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la remix_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) remix_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) smoother_test_SOURCES = tests/smoother-test.c -smoother_test_LDADD = $(AM_LDADD) libpulsecore.la +smoother_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la smoother_test_CFLAGS = $(AM_CFLAGS) smoother_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) envelope_test_SOURCES = tests/envelope-test.c -envelope_test_LDADD = $(AM_LDADD) libpulsecore.la +envelope_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la envelope_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) envelope_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) proplist_test_SOURCES = tests/proplist-test.c -proplist_test_LDADD = $(AM_LDADD) libpulsecore.la +proplist_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la proplist_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) proplist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) rtstutter_SOURCES = tests/rtstutter.c -rtstutter_LDADD = $(AM_LDADD) libpulsecore.la +rtstutter_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la rtstutter_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) rtstutter_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) stripnul_SOURCES = tests/stripnul.c -stripnul_LDADD = $(AM_LDADD) libpulsecore.la +stripnul_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la stripnul_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) stripnul_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) +lock_autospawn_test_SOURCES = tests/lock-autospawn-test.c +lock_autospawn_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la +lock_autospawn_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) +lock_autospawn_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) + +prioq_test_SOURCES = tests/prioq-test.c +prioq_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la +prioq_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) +prioq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) + +################################### +# Common library # +################################### + +lib_LTLIBRARIES = \ + libpulsecommon-@PA_MAJORMINORMICRO@.la + +libpulsecommon_@PA_MAJORMINORMICRO@_la_SOURCES = \ + pulse/client-conf.c pulse/client-conf.h \ + pulse/i18n.c pulse/i18n.h \ + pulsecore/authkey.c pulsecore/authkey.h \ + pulsecore/conf-parser.c pulsecore/conf-parser.h \ + pulsecore/core-error.c pulsecore/core-error.h \ + pulsecore/core-util.c pulsecore/core-util.h \ + pulsecore/creds.h \ + pulsecore/dynarray.c pulsecore/dynarray.h \ + pulsecore/endianmacros.h \ + pulsecore/flist.c pulsecore/flist.h \ + pulsecore/hashmap.c pulsecore/hashmap.h \ + pulsecore/idxset.c pulsecore/idxset.h \ + pulsecore/inet_ntop.c pulsecore/inet_ntop.h \ + pulsecore/inet_pton.c pulsecore/inet_pton.h \ + pulsecore/iochannel.c pulsecore/iochannel.h \ + pulsecore/ioline.c pulsecore/ioline.h \ + pulsecore/ipacl.h pulsecore/ipacl.c \ + pulsecore/llist.h \ + pulsecore/lock-autospawn.c pulsecore/lock-autospawn.h \ + pulsecore/log.c pulsecore/log.h \ + pulsecore/macro.h \ + pulsecore/mcalign.c pulsecore/mcalign.h \ + pulsecore/memblock.c pulsecore/memblock.h \ + pulsecore/memblockq.c pulsecore/memblockq.h \ + pulsecore/memchunk.c pulsecore/memchunk.h \ + pulsecore/native-common.h \ + pulsecore/once.c pulsecore/once.h \ + pulsecore/packet.c pulsecore/packet.h \ + pulsecore/parseaddr.c pulsecore/parseaddr.h \ + pulsecore/pdispatch.c pulsecore/pdispatch.h \ + pulsecore/pid.c pulsecore/pid.h \ + pulsecore/pipe.c pulsecore/pipe.h \ + pulsecore/poll.c pulsecore/poll.h \ + pulsecore/prioq.c pulsecore/prioq.h \ + pulsecore/proplist-util.c pulsecore/proplist-util.h \ + pulsecore/pstream-util.c pulsecore/pstream-util.h \ + pulsecore/pstream.c pulsecore/pstream.h \ + pulsecore/queue.c pulsecore/queue.h \ + pulsecore/random.c pulsecore/random.h \ + pulsecore/rtclock.c pulsecore/rtclock.h \ + pulsecore/shm.c pulsecore/shm.h \ + pulsecore/socket-client.c pulsecore/socket-client.h \ + pulsecore/socket-server.c pulsecore/socket-server.h \ + pulsecore/socket-util.c pulsecore/socket-util.h \ + pulsecore/strbuf.c pulsecore/strbuf.h \ + pulsecore/strlist.c pulsecore/strlist.h \ + pulsecore/tagstruct.c pulsecore/tagstruct.h \ + pulsecore/time-smoother.c pulsecore/time-smoother.h \ + pulsecore/tokenizer.c pulsecore/tokenizer.h \ + pulsecore/winsock.h + +libpulsecommon_@PA_MAJORMINORMICRO@_la_CFLAGS = $(AM_CFLAGS) +libpulsecommon_@PA_MAJORMINORMICRO@_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version +libpulsecommon_@PA_MAJORMINORMICRO@_la_LIBADD = $(AM_LIBADD) $(LIBWRAP_LIBS) $(WINSOCK_LIBS) $(LTLIBICONV) + +## Please note that libpulsecommon implicitly also depends on< +## libpulse! i.e. we have a cyclic dependancy here. Which is intended +## since libpulse only includes stable, official APIs, while +## libpulsecommon only includes unofficial APIs. + +if OS_IS_WIN32 +libpulsecommon_@PA_MAJORMINORMICRO@_la_SOURCES += \ + pulsecore/mutex-win32.c pulsecore/mutex.h \ + pulsecore/thread-win32.c pulsecore/thread.h \ + pulsecore/semaphore-win32.c pulsecore/semaphore.h +else +libpulsecommon_@PA_MAJORMINORMICRO@_la_SOURCES += \ + pulsecore/mutex-posix.c pulsecore/mutex.h \ + pulsecore/thread-posix.c pulsecore/thread.h \ + pulsecore/semaphore-posix.c pulsecore/semaphore.h +endif + +if HAVE_X11 +libpulsecommon_@PA_MAJORMINORMICRO@_la_SOURCES += pulsecore/x11prop.c pulsecore/x11prop.h +libpulsecommon_@PA_MAJORMINORMICRO@_la_CFLAGS += $(X_CFLAGS) +libpulsecommon_@PA_MAJORMINORMICRO@_la_LDFLAGS += $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) +endif + +if HAVE_LIBASYNCNS +libpulsecommon_@PA_MAJORMINORMICRO@_la_CFLAGS += $(LIBASYNCNS_CFLAGS) +libpulsecommon_@PA_MAJORMINORMICRO@_la_LIBADD += $(LIBASYNCNS_LIBS) +endif + +if OS_IS_WIN32 +libpulsecommon_@PA_MAJORMINORMICRO@_la_SOURCES += pulsecore/dllmain.c +endif + ################################### # Client library # ################################### @@ -462,11 +554,14 @@ pulseinclude_HEADERS = \ pulse/context.h \ pulse/def.h \ pulse/error.h \ + pulse/ext-stream-restore.h \ + pulse/gccmacro.h \ pulse/introspect.h \ - pulse/mainloop.h \ pulse/mainloop-api.h \ pulse/mainloop-signal.h \ + pulse/mainloop.h \ pulse/operation.h \ + pulse/proplist.h \ pulse/pulseaudio.h \ pulse/sample.h \ pulse/scache.h \ @@ -479,31 +574,24 @@ pulseinclude_HEADERS = \ pulse/util.h \ pulse/version.h \ pulse/volume.h \ - pulse/xmalloc.h \ - pulse/proplist.h \ - pulse/gccmacro.h \ - pulse/ext-stream-restore.h - -if HAVE_AVAHI -pulseinclude_HEADERS += \ - pulse/browser.h -endif - -if HAVE_GLIB20 -pulseinclude_HEADERS += \ - pulse/glib-mainloop.h -endif + pulse/xmalloc.h -lib_LTLIBRARIES = \ +lib_LTLIBRARIES += \ libpulse.la \ libpulse-simple.la if HAVE_AVAHI +pulseinclude_HEADERS += \ + pulse/browser.h + lib_LTLIBRARIES += \ libpulse-browse.la endif if HAVE_GLIB20 +pulseinclude_HEADERS += \ + pulse/glib-mainloop.h + lib_LTLIBRARIES += \ libpulse-mainloop-glib.la endif @@ -512,16 +600,18 @@ endif libpulse_la_SOURCES = \ pulse/cdecl.h \ pulse/channelmap.c pulse/channelmap.h \ - pulse/client-conf.c pulse/client-conf.h \ pulse/context.c pulse/context.h \ pulse/def.h \ pulse/error.c pulse/error.h \ + pulse/ext-stream-restore.c pulse/ext-stream-restore.h \ + pulse/gccmacro.h \ pulse/internal.h \ pulse/introspect.c pulse/introspect.h \ - pulse/mainloop.c pulse/mainloop.h \ pulse/mainloop-api.c pulse/mainloop-api.h \ pulse/mainloop-signal.c pulse/mainloop-signal.h \ + pulse/mainloop.c pulse/mainloop.h \ pulse/operation.c pulse/operation.h \ + pulse/proplist.c pulse/proplist.h \ pulse/pulseaudio.h \ pulse/sample.c pulse/sample.h \ pulse/scache.c pulse/scache.h \ @@ -532,339 +622,121 @@ libpulse_la_SOURCES = \ pulse/utf8.c pulse/utf8.h \ pulse/util.c pulse/util.h \ pulse/volume.c pulse/volume.h \ - pulse/xmalloc.c pulse/xmalloc.h \ - pulse/proplist.c pulse/proplist.h \ - pulse/ext-stream-restore.c pulse/ext-stream-restore.h \ - pulse/i18n.c pulse/i18n.h - -# Internal stuff that is shared with libpulsecore -libpulse_la_SOURCES += \ - pulsecore/authkey.c pulsecore/authkey.h \ - pulsecore/conf-parser.c pulsecore/conf-parser.h \ - pulsecore/core-util.c pulsecore/core-util.h \ - pulsecore/dynarray.c pulsecore/dynarray.h \ - pulsecore/hashmap.c pulsecore/hashmap.h \ - pulsecore/idxset.c pulsecore/idxset.h \ - pulsecore/inet_ntop.c pulsecore/inet_ntop.h \ - pulsecore/iochannel.c pulsecore/iochannel.h \ - pulsecore/llist.h \ - pulsecore/log.c pulsecore/log.h \ - pulsecore/mcalign.c pulsecore/mcalign.h \ - pulsecore/memblock.c pulsecore/memblock.h \ - pulsecore/memblockq.c pulsecore/memblockq.h \ - pulsecore/memchunk.c pulsecore/memchunk.h \ - pulsecore/native-common.h \ - pulsecore/packet.c pulsecore/packet.h \ - pulsecore/parseaddr.c pulsecore/parseaddr.h \ - pulsecore/pdispatch.c pulsecore/pdispatch.h \ - pulsecore/pipe.c pulsecore/pipe.h \ - pulsecore/poll.c pulsecore/poll.h \ - pulsecore/pstream.c pulsecore/pstream.h \ - pulsecore/pstream-util.c pulsecore/pstream-util.h \ - pulsecore/queue.c pulsecore/queue.h \ - pulsecore/random.c pulsecore/random.h \ - pulsecore/socket-client.c pulsecore/socket-client.h \ - pulsecore/socket-util.c pulsecore/socket-util.h \ - pulsecore/strbuf.c pulsecore/strbuf.h \ - pulsecore/strlist.c pulsecore/strlist.h \ - pulsecore/tagstruct.c pulsecore/tagstruct.h \ - pulsecore/core-error.c pulsecore/core-error.h \ - pulsecore/winsock.h pulsecore/creds.h \ - pulsecore/shm.c pulsecore/shm.h \ - pulsecore/flist.c pulsecore/flist.h \ - pulsecore/object.c pulsecore/object.h \ - pulsecore/msgobject.c pulsecore/msgobject.h \ - pulsecore/once.c pulsecore/once.h \ - pulsecore/rtclock.c pulsecore/rtclock.h \ - pulsecore/time-smoother.c pulsecore/time-smoother.h \ - pulsecore/proplist-util.c pulsecore/proplist-util.h \ - $(PA_THREAD_OBJS) - -if OS_IS_WIN32 -libpulse_la_SOURCES += \ - pulsecore/dllmain.c -endif - -if HAVE_X11 -libpulse_la_SOURCES += \ - pulse/client-conf-x11.c pulse/client-conf-x11.h \ - pulsecore/x11prop.c pulsecore/x11prop.h -endif + pulse/xmalloc.c pulse/xmalloc.h libpulse_la_CFLAGS = $(AM_CFLAGS) -libpulse_la_LDFLAGS = -version-info $(LIBPULSE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file -libpulse_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) $(LTLIBICONV) +libpulse_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBPULSE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file +libpulse_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) $(LTLIBICONV) libpulsecommon-@PA_MAJORMINORMICRO@.la if HAVE_X11 +libpulse_la_SOURCES += pulse/client-conf-x11.c pulse/client-conf-x11.h libpulse_la_CFLAGS += $(X_CFLAGS) libpulse_la_LDFLAGS += $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) endif -if HAVE_LIBASYNCNS -libpulse_la_CFLAGS += $(LIBASYNCNS_CFLAGS) -libpulse_la_LIBADD += $(LIBASYNCNS_LIBS) -endif - -libpulse_simple_la_SOURCES = \ - pulse/simple.c pulse/simple.h \ - pulsecore/log.c pulsecore/log.h \ - pulsecore/core-util.c pulsecore/core-util.h \ - pulsecore/core-error.c pulsecore/core-error.h \ - pulsecore/once.c pulsecore/once.h \ - $(PA_THREAD_OBJS) - +libpulse_simple_la_SOURCES = pulse/simple.c pulse/simple.h libpulse_simple_la_CFLAGS = $(AM_CFLAGS) -libpulse_simple_la_LIBADD = $(AM_LIBADD) libpulse.la -libpulse_simple_la_LDFLAGS = -version-info $(LIBPULSE_SIMPLE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file +libpulse_simple_la_LIBADD = $(AM_LIBADD) libpulse.la libpulsecommon-@PA_MAJORMINORMICRO@.la +libpulse_simple_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBPULSE_SIMPLE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file -libpulse_browse_la_SOURCES = pulse/browser.c pulse/browser.h pulsecore/avahi-wrap.c pulsecore/avahi-wrap.h pulsecore/core-util.c pulsecore/core-util.h pulsecore/core-error.c pulsecore/core-error.h pulsecore/log.c pulsecore/log.h pulsecore/once.c pulsecore/once.h $(PA_THREAD_OBJS) +libpulse_browse_la_SOURCES = pulse/browser.c pulse/browser.h pulsecore/avahi-wrap.c pulsecore/avahi-wrap.h libpulse_browse_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS) -libpulse_browse_la_LIBADD = $(AM_LIBADD) libpulse.la $(AVAHI_LIBS) -libpulse_browse_la_LDFLAGS = -version-info $(LIBPULSE_BROWSE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file +libpulse_browse_la_LIBADD = $(AM_LIBADD) libpulse.la libpulsecommon-@PA_MAJORMINORMICRO@.la $(AVAHI_LIBS) +libpulse_browse_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBPULSE_BROWSE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file -libpulse_mainloop_glib_la_SOURCES = \ - pulse/glib-mainloop.h pulse/glib-mainloop.c \ - pulsecore/log.c pulsecore/log.h \ - pulsecore/core-util.c pulsecore/core-util.h \ - pulsecore/core-error.c pulsecore/core-error.h \ - pulsecore/once.c pulsecore/once.h \ - $(PA_THREAD_OBJS) +libpulse_mainloop_glib_la_SOURCES = pulse/glib-mainloop.h pulse/glib-mainloop.c libpulse_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) -libpulse_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpulse.la $(GLIB20_LIBS) -libpulse_mainloop_glib_la_LDFLAGS = -version-info $(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file +libpulse_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpulse.la libpulsecommon-@PA_MAJORMINORMICRO@.la $(GLIB20_LIBS) +libpulse_mainloop_glib_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file ################################### # OSS emulation # ################################### if HAVE_OSS - lib_LTLIBRARIES += libpulsedsp.la - bin_SCRIPTS += utils/padsp - endif -libpulsedsp_la_SOURCES = utils/padsp.c pulsecore/core-util.c pulsecore/core-util.h pulsecore/core-error.c pulsecore/core-error.h pulsecore/log.c pulsecore/log.h pulsecore/once.c pulsecore/once.h $(PA_THREAD_OBJS) +libpulsedsp_la_SOURCES = utils/padsp.c libpulsedsp_la_CFLAGS = $(AM_CFLAGS) -libpulsedsp_la_LIBADD = $(AM_LIBADD) libpulse.la -libpulsedsp_la_LDFLAGS = -avoid-version - -################################### -# ffmpeg resampler # -################################### - -noinst_LTLIBRARIES = libffmpeg-resampler.la - -libffmpeg_resampler_la_CPPFLAGS = $(AM_CPPFLAGS) -libffmpeg_resampler_la_SOURCES = pulsecore/ffmpeg/resample2.c pulsecore/ffmpeg/avcodec.h pulsecore/ffmpeg/dsputil.h +libpulsedsp_la_LIBADD = $(AM_LIBADD) libpulse.la libpulsecommon-@PA_MAJORMINORMICRO@.la +libpulsedsp_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version ################################### # Daemon core library # ################################### -#pulsecoreinclude_HEADERS = -noinst_HEADERS = \ - pulsecore/autoload.h \ - pulsecore/atomic.h \ - pulsecore/cli-command.h \ - pulsecore/cli-text.h \ - pulsecore/client.h \ - pulsecore/core.h \ - pulsecore/core-scache.h \ - pulsecore/core-subscribe.h \ - pulsecore/conf-parser.h \ - pulsecore/core-util.h \ - pulsecore/dynarray.h \ - pulsecore/g711.h \ - pulsecore/hashmap.h \ - pulsecore/idxset.h \ - pulsecore/log.h \ - pulsecore/mcalign.h \ - pulsecore/memblock.h \ - pulsecore/memblockq.h \ - pulsecore/memchunk.h \ - pulsecore/modargs.h \ - pulsecore/modinfo.h \ - pulsecore/module.h \ - pulsecore/namereg.h \ - pulsecore/pid.h \ - pulsecore/play-memchunk.h \ - pulsecore/play-memblockq.h \ - pulsecore/shared.h \ - pulsecore/queue.h \ - pulsecore/random.h \ - pulsecore/resampler.h \ - pulsecore/sample-util.h \ - pulsecore/sconv.h \ - pulsecore/sink.h \ - pulsecore/sink-input.h \ - pulsecore/sioman.h \ - pulsecore/sound-file.h \ - pulsecore/sound-file-stream.h \ - pulsecore/source.h \ - pulsecore/source-output.h \ - pulsecore/strbuf.h \ - pulsecore/tokenizer.h \ - pulsecore/creds.h \ - pulsecore/shm.h \ - pulsecore/llist.h \ - pulsecore/refcnt.h \ - pulsecore/mutex.h \ - pulsecore/thread.h \ - pulsecore/semaphore.h \ - pulsecore/once.h - -lib_LTLIBRARIES += libpulsecore.la - -# Some public stuff is used even in the core -libpulsecore_la_SOURCES = \ - pulse/channelmap.c pulse/channelmap.h \ - pulse/error.c pulse/error.h \ - pulse/mainloop.c pulse/mainloop.h \ - pulse/mainloop-api.c pulse/mainloop-api.h \ - pulse/mainloop-signal.c pulse/mainloop-signal.h \ - pulse/sample.c pulse/sample.h \ - pulse/timeval.c pulse/timeval.h \ - pulse/utf8.c pulse/utf8.h \ - pulse/util.c pulse/util.h \ - pulse/volume.c pulse/volume.h \ - pulse/xmalloc.c pulse/xmalloc.h \ - pulse/proplist.c pulse/proplist.h \ - pulse/i18n.c pulse/i18n.h +lib_LTLIBRARIES += libpulsecore-@PA_MAJORMINORMICRO@.la -# Pure core stuff (some are shared in libpulse though). -libpulsecore_la_SOURCES += \ +# Pure core stuff +libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES = \ + pulsecore/asyncmsgq.c pulsecore/asyncmsgq.h \ + pulsecore/asyncq.c pulsecore/asyncq.h \ + pulsecore/auth-cookie.c pulsecore/auth-cookie.h \ pulsecore/autoload.c pulsecore/autoload.h \ pulsecore/cli-command.c pulsecore/cli-command.h \ pulsecore/cli-text.c pulsecore/cli-text.h \ pulsecore/client.c pulsecore/client.h \ - pulsecore/conf-parser.c pulsecore/conf-parser.h \ - pulsecore/core.c pulsecore/core.h \ pulsecore/core-scache.c pulsecore/core-scache.h \ pulsecore/core-subscribe.c pulsecore/core-subscribe.h \ - pulsecore/core-util.c pulsecore/core-util.h \ - pulsecore/dynarray.c pulsecore/dynarray.h \ - pulsecore/endianmacros.h \ + pulsecore/core.c pulsecore/core.h \ + pulsecore/envelope.c pulsecore/envelope.h \ + pulsecore/fdsem.c pulsecore/fdsem.h \ + pulsecore/ffmpeg/resample2.c pulsecore/ffmpeg/avcodec.h pulsecore/ffmpeg/dsputil.h \ pulsecore/g711.c pulsecore/g711.h \ - pulsecore/hashmap.c pulsecore/hashmap.h \ - pulsecore/idxset.c pulsecore/idxset.h \ - pulsecore/log.c pulsecore/log.h \ - pulsecore/mcalign.c pulsecore/mcalign.h \ - pulsecore/memblock.c pulsecore/memblock.h \ - pulsecore/memblockq.c pulsecore/memblockq.h \ - pulsecore/memchunk.c pulsecore/memchunk.h \ + pulsecore/hook-list.c pulsecore/hook-list.h \ + pulsecore/ltdl-helper.c pulsecore/ltdl-helper.h \ pulsecore/modargs.c pulsecore/modargs.h \ pulsecore/modinfo.c pulsecore/modinfo.h \ - pulsecore/ltdl-helper.c pulsecore/ltdl-helper.h \ pulsecore/module.c pulsecore/module.h \ + pulsecore/msgobject.c pulsecore/msgobject.h \ pulsecore/namereg.c pulsecore/namereg.h \ - pulsecore/pid.c pulsecore/pid.h \ - pulsecore/pipe.c pulsecore/pipe.h \ - pulsecore/play-memchunk.c pulsecore/play-memchunk.h \ + pulsecore/object.c pulsecore/object.h \ pulsecore/play-memblockq.c pulsecore/play-memblockq.h \ - pulsecore/poll.c pulsecore/poll.h \ - pulsecore/shared.c pulsecore/shared.h \ - pulsecore/queue.c pulsecore/queue.h \ - pulsecore/random.c pulsecore/random.h \ + pulsecore/play-memchunk.c pulsecore/play-memchunk.h \ pulsecore/resampler.c pulsecore/resampler.h \ + pulsecore/rtpoll.c pulsecore/rtpoll.h \ + pulsecore/rtsig.c pulsecore/rtsig.h \ pulsecore/sample-util.c pulsecore/sample-util.h \ - pulsecore/sconv.c pulsecore/sconv.h \ pulsecore/sconv-s16be.c pulsecore/sconv-s16be.h \ pulsecore/sconv-s16le.c pulsecore/sconv-s16le.h \ - pulsecore/sink.c pulsecore/sink.h \ + pulsecore/sconv.c pulsecore/sconv.h \ + pulsecore/shared.c pulsecore/shared.h \ + pulsecore/shm.c pulsecore/shm.h \ pulsecore/sink-input.c pulsecore/sink-input.h \ + pulsecore/sink.c pulsecore/sink.h \ pulsecore/sioman.c pulsecore/sioman.h \ - pulsecore/sound-file.c pulsecore/sound-file.h \ pulsecore/sound-file-stream.c pulsecore/sound-file-stream.h \ - pulsecore/source.c pulsecore/source.h \ + pulsecore/sound-file.c pulsecore/sound-file.h \ pulsecore/source-output.c pulsecore/source-output.h \ - pulsecore/strbuf.c pulsecore/strbuf.h \ - pulsecore/tokenizer.c pulsecore/tokenizer.h \ - pulsecore/winsock.h \ - pulsecore/core-error.c pulsecore/core-error.h \ - pulsecore/hook-list.c pulsecore/hook-list.h \ - pulsecore/shm.c pulsecore/shm.h \ - pulsecore/flist.c pulsecore/flist.h \ - pulsecore/asyncmsgq.c pulsecore/asyncmsgq.h \ - pulsecore/asyncq.c pulsecore/asyncq.h \ - pulsecore/thread-mq.c pulsecore/thread-mq.h \ - pulsecore/fdsem.c pulsecore/fdsem.h \ - pulsecore/object.c pulsecore/object.h \ - pulsecore/msgobject.c pulsecore/msgobject.h \ - pulsecore/rtsig.c pulsecore/rtsig.h \ - pulsecore/rtpoll.c pulsecore/rtpoll.h \ - pulsecore/rtclock.c pulsecore/rtclock.h \ - pulsecore/macro.h \ - pulsecore/once.c pulsecore/once.h \ - pulsecore/time-smoother.c pulsecore/time-smoother.h \ + pulsecore/source.c pulsecore/source.h \ pulsecore/start-child.c pulsecore/start-child.h \ - pulsecore/envelope.c pulsecore/envelope.h \ - pulsecore/proplist-util.c pulsecore/proplist-util.h \ - $(PA_THREAD_OBJS) + pulsecore/thread-mq.c pulsecore/thread-mq.h \ + pulsecore/time-smoother.c pulsecore/time-smoother.h -if OS_IS_WIN32 -libpulsecore_la_SOURCES += \ - pulsecore/dllmain.c -endif +libpulsecore_@PA_MAJORMINORMICRO@_la_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) +libpulsecore_@PA_MAJORMINORMICRO@_la_LDFLAGS = -avoid-version +libpulsecore_@PA_MAJORMINORMICRO@_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(LIBSPEEX_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LTLIBICONV) libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la -libpulsecore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) -libpulsecore_la_LDFLAGS = -version-info $(LIBPULSECORE_VERSION_INFO) -libpulsecore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(LIBSPEEX_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LTLIBICONV) libffmpeg-resampler.la +if HAVE_X11 +libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES += pulsecore/x11wrap.c pulsecore/x11wrap.h +libpulsecore_@PA_MAJORMINORMICRO@_la_CFLAGS += $(X_CFLAGS) +libpulsecore_@PA_MAJORMINORMICRO@_la_LDFLAGS += $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) +endif ################################### # Plug-in support libraries # ################################### -#pulsecoreinclude_HEADERS += -noinst_HEADERS += \ - pulsecore/socket-util.h \ - pulsecore/iochannel.h \ - pulsecore/socket-server.h \ - pulsecore/ipacl.h \ - pulsecore/socket-client.h \ - pulsecore/parseaddr.h \ - pulsecore/packet.h \ - pulsecore/pstream.h \ - pulsecore/ioline.h \ - pulsecore/cli.h \ - pulsecore/protocol-cli.h \ - pulsecore/tagstruct.h \ - pulsecore/pstream-util.h \ - pulsecore/pdispatch.h \ - pulsecore/authkey.h \ - pulsecore/auth-cookie.h \ - pulsecore/strlist.h \ - pulsecore/protocol-simple.h \ - pulsecore/esound.h \ - pulsecore/protocol-esound.h \ - pulsecore/native-common.h \ - pulsecore/protocol-native.h \ - pulsecore/protocol-http.h - ### Warning! Due to an obscure bug in libtool/automake it is required ### that the libraries in modlibexec_LTLIBRARIES are specified in-order, ### i.e. libraries near the end of the list depend on libraries near ### the head, and not the other way! modlibexec_LTLIBRARIES = \ - libsocket-util.la \ - libiochannel.la \ - libsocket-server.la \ - libipacl.la \ - libparseaddr.la \ - libsocket-client.la \ - libpacket.la \ - libpstream.la \ - libioline.la \ libcli.la \ libprotocol-cli.la \ - libtagstruct.la \ - libpstream-util.la \ - libpdispatch.la \ - libauthkey.la \ - libauth-cookie.la \ - libstrlist.la \ libprotocol-simple.la \ libprotocol-http.la \ libprotocol-native.la \ @@ -876,146 +748,63 @@ modlibexec_LTLIBRARIES += \ librtp.la endif -if HAVE_X11 -#pulsecoreinclude_HEADERS += -noinst_HEADERS += \ - pulsecore/x11wrap.h \ - pulsecore/x11prop.h - -modlibexec_LTLIBRARIES += \ - libx11wrap.la \ - libx11prop.la -endif - if HAVE_AVAHI -#pulsecoreinclude_HEADERS += -noinst_HEADERS += \ - pulsecore/avahi-wrap.h - modlibexec_LTLIBRARIES += \ libavahi-wrap.la endif libprotocol_simple_la_SOURCES = pulsecore/protocol-simple.c pulsecore/protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version -libprotocol_simple_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-server.la libiochannel.la - -libsocket_server_la_SOURCES = \ - pulsecore/inet_ntop.c pulsecore/inet_ntop.h \ - pulsecore/inet_pton.c pulsecore/inet_pton.h \ - pulsecore/socket-server.c pulsecore/socket-server.h -libsocket_server_la_LDFLAGS = -avoid-version -libsocket_server_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-util.la $(LIBWRAP_LIBS) $(WINSOCK_LIBS) - -libipacl_la_SOURCES = pulsecore/ipacl.h pulsecore/ipacl.c \ - pulsecore/inet_pton.c pulsecore/inet_pton.h -libipacl_la_LDFLAGS = -avoid-version -libipacl_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(WINSOCK_LIBS) - -libsocket_client_la_SOURCES = pulsecore/socket-client.c pulsecore/socket-client.h -libsocket_client_la_LDFLAGS = -avoid-version -libsocket_client_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-util.la libparseaddr.la $(LIBASYNCNS_LIBS) $(WINSOCK_LIBS) -libsocket_client_la_CFLAGS = $(AM_CFLAGS) $(LIBASYNCNS_CFLAGS) - -libparseaddr_la_SOURCES = pulsecore/parseaddr.c pulsecore/parseaddr.h -libparseaddr_la_LDFLAGS = -avoid-version -libparseaddr_la_LIBADD = $(AM_LIBADD) libpulsecore.la - -libpstream_la_SOURCES = pulsecore/pstream.c pulsecore/pstream.h -libpstream_la_LDFLAGS = -avoid-version -libpstream_la_LIBADD = $(AM_LIBADD) libpulsecore.la libpacket.la libiochannel.la $(WINSOCK_LIBS) - -libpstream_util_la_SOURCES = pulsecore/pstream-util.c pulsecore/pstream-util.h -libpstream_util_la_LDFLAGS = -avoid-version -libpstream_util_la_LIBADD = $(AM_LIBADD) libpacket.la libpstream.la libtagstruct.la libpulsecore.la - -libpdispatch_la_SOURCES = pulsecore/pdispatch.c pulsecore/pdispatch.h -libpdispatch_la_LDFLAGS = -avoid-version -libpdispatch_la_LIBADD = $(AM_LIBADD) libtagstruct.la libpulsecore.la - -libiochannel_la_SOURCES = pulsecore/iochannel.c pulsecore/iochannel.h -libiochannel_la_LDFLAGS = -avoid-version -libiochannel_la_LIBADD = $(AM_LIBADD) libsocket-util.la libpulsecore.la $(WINSOCK_LIBS) - -libpacket_la_SOURCES = pulsecore/packet.c pulsecore/packet.h -libpacket_la_LDFLAGS = -avoid-version -libpacket_la_LIBADD = $(AM_LIBADD) libpulsecore.la - -libioline_la_SOURCES = pulsecore/ioline.c pulsecore/ioline.h -libioline_la_LDFLAGS = -avoid-version -libioline_la_LIBADD = $(AM_LIBADD) libiochannel.la libpulsecore.la +libprotocol_simple_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la libcli_la_SOURCES = pulsecore/cli.c pulsecore/cli.h -libcli_la_CPPFLAGS = $(AM_CPPFLAGS) libcli_la_LDFLAGS = -avoid-version -libcli_la_LIBADD = $(AM_LIBADD) libiochannel.la libioline.la libpulsecore.la - -libstrlist_la_SOURCES = pulsecore/strlist.c pulsecore/strlist.h -libstrlist_la_LDFLAGS = -avoid-version -libstrlist_la_LIBADD = $(AM_LIBADD) libpulsecore.la +libcli_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la libprotocol_cli_la_SOURCES = pulsecore/protocol-cli.c pulsecore/protocol-cli.h libprotocol_cli_la_LDFLAGS = -avoid-version -libprotocol_cli_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libcli.la libpulsecore.la +libprotocol_cli_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la libprotocol_http_la_SOURCES = pulsecore/protocol-http.c pulsecore/protocol-http.h libprotocol_http_la_LDFLAGS = -avoid-version -libprotocol_http_la_LIBADD = $(AM_LIBADD) libsocket-server.la libioline.la libpulsecore.la libiochannel.la +libprotocol_http_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la libprotocol_native_la_SOURCES = pulsecore/protocol-native.c pulsecore/protocol-native.h pulsecore/native-common.h libprotocol_native_la_LDFLAGS = -avoid-version -libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauth-cookie.la libstrlist.la libpulsecore.la libiochannel.la libipacl.la - -libtagstruct_la_SOURCES = pulsecore/tagstruct.c pulsecore/tagstruct.h -libtagstruct_la_LDFLAGS = -avoid-version -libtagstruct_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(WINSOCK_LIBS) +libprotocol_native_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la libprotocol_esound_la_SOURCES = pulsecore/protocol-esound.c pulsecore/protocol-esound.h pulsecore/esound.h libprotocol_esound_la_LDFLAGS = -avoid-version -libprotocol_esound_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libauthkey.la libauth-cookie.la libpulsecore.la libipacl.la - -libauthkey_la_SOURCES = pulsecore/authkey.c pulsecore/authkey.h -libauthkey_la_LDFLAGS = -avoid-version -libauthkey_la_LIBADD = $(AM_LIBADD) libpulsecore.la - -libauth_cookie_la_SOURCES = pulsecore/auth-cookie.c pulsecore/auth-cookie.h -libauth_cookie_la_LDFLAGS = -avoid-version -libauth_cookie_la_LIBADD = $(AM_LIBADD) libauthkey.la libpulsecore.la - -libsocket_util_la_SOURCES = \ - pulsecore/inet_ntop.c pulsecore/inet_ntop.h \ - pulsecore/socket-util.c pulsecore/socket-util.h -libsocket_util_la_LDFLAGS = -avoid-version -libsocket_util_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) libpulsecore.la - -librtp_la_SOURCES = modules/rtp/rtp.c modules/rtp/rtp.h modules/rtp/sdp.c modules/rtp/sdp.h modules/rtp/sap.c modules/rtp/sap.h +libprotocol_esound_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la + +librtp_la_SOURCES = \ + modules/rtp/rtp.c modules/rtp/rtp.h \ + modules/rtp/sdp.c modules/rtp/sdp.h \ + modules/rtp/sap.c modules/rtp/sap.h \ + modules/rtp/rtsp_client.c modules/rtp/rtsp_client.h \ + modules/rtp/headerlist.c modules/rtp/headerlist.h librtp_la_LDFLAGS = -avoid-version -librtp_la_LIBADD = $(AM_LIBADD) libpulsecore.la +librtp_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la -# X11 - -libx11wrap_la_SOURCES = pulsecore/x11wrap.c pulsecore/x11wrap.h -libx11wrap_la_LDFLAGS = -avoid-version -libx11wrap_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -libx11wrap_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libpulsecore.la - -libx11prop_la_SOURCES = pulsecore/x11prop.c pulsecore/x11prop.h -libx11prop_la_LDFLAGS = -avoid-version -libx11prop_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -libx11prop_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) +libraop_la_SOURCES = \ + modules/raop/raop_client.c modules/raop/raop_client.h \ + modules/raop/base64.c modules/raop/base64.h +libraop_la_CFLAGS = $(AM_CFLAGS) $(OPENSSL_CFLAGS) +libraop_la_LDFLAGS = -avoid-version +libraop_la_LIBADD = $(AM_LIBADD) $(OPENSSL_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la librtp.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la # Avahi - libavahi_wrap_la_SOURCES = pulsecore/avahi-wrap.c pulsecore/avahi-wrap.h libavahi_wrap_la_LDFLAGS = -avoid-version libavahi_wrap_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS) -libavahi_wrap_la_LIBADD = $(AM_LIBADD) $(AVAHI_CFLAGS) libpulsecore.la +libavahi_wrap_la_LIBADD = $(AM_LIBADD) $(AVAHI_CFLAGS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la ################################### # Plug-in libraries # ################################### modlibexec_LTLIBRARIES += \ + module-flat-volume.la \ module-cli.la \ module-cli-protocol-tcp.la \ module-simple-protocol-tcp.la \ @@ -1151,12 +940,27 @@ endif if HAVE_BLUEZ modlibexec_LTLIBRARIES += \ - module-bt-proximity.la + module-bluetooth-proximity.la \ + module-bluetooth-discover.la \ + libbluetooth-ipc.la \ + libbluetooth-sbc.la \ + module-bluetooth-device.la pulselibexec_PROGRAMS += \ - bt-proximity-helper + proximity-helper endif +if HAVE_OPENSSL +modlibexec_LTLIBRARIES += \ + libraop.la \ + module-raop-sink.la +if HAVE_AVAHI +modlibexec_LTLIBRARIES += \ + module-raop-discover.la +endif +endif + + # These are generated by a M4 script SYMDEF_FILES = \ @@ -1210,10 +1014,15 @@ SYMDEF_FILES = \ modules/module-rescue-streams-symdef.h \ modules/module-suspend-on-idle-symdef.h \ modules/module-hal-detect-symdef.h \ - modules/module-bt-proximity-symdef.h \ + modules/bluetooth/module-bluetooth-proximity-symdef.h \ + modules/bluetooth/module-bluetooth-discover-symdef.h \ + modules/bluetooth/module-bluetooth-device-symdef.h \ + modules/module-raop-sink-symdef.h \ + modules/module-raop-discover-symdef.h \ modules/gconf/module-gconf-symdef.h \ modules/module-position-event-sounds-symdef.h \ - modules/module-console-kit-symdef.h + modules/module-console-kit-symdef.h \ + modules/module-flat-volume-symdef.h EXTRA_DIST += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES) @@ -1222,334 +1031,373 @@ $(SYMDEF_FILES): modules/module-defs.h.m4 $(MKDIR_P) modules $(MKDIR_P) modules/gconf $(MKDIR_P) modules/rtp + $(MKDIR_P) modules/bluetooth $(M4) -Dfname="$@" $< > $@ +# Flat volume + +module_flat_volume_la_SOURCES = modules/module-flat-volume.c +module_flat_volume_la_LDFLAGS = -module -avoid-version +module_flat_volume_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la + # Simple protocol module_simple_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_simple_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-simple.la libsocket-server.la +module_simple_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libprotocol-simple.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_simple_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_unix_la_LDFLAGS = -module -avoid-version -module_simple_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-simple.la libsocket-server.la libsocket-util.la +module_simple_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libprotocol-simple.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la # CLI protocol module_cli_la_SOURCES = modules/module-cli.c module_cli_la_LDFLAGS = -module -avoid-version -module_cli_la_LIBADD = $(AM_LIBADD) libcli.la libiochannel.la libpulsecore.la +module_cli_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libcli.la module_cli_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_cli_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-cli.la libsocket-server.la +module_cli_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libprotocol-cli.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_cli_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_unix_la_LDFLAGS = -module -avoid-version -module_cli_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-cli.la libsocket-server.la libsocket-util.la +module_cli_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libprotocol-cli.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la # HTTP protocol module_http_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_http_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) module_http_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_http_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-http.la libsocket-server.la +module_http_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libprotocol-http.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_http_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_http_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) module_http_protocol_unix_la_LDFLAGS = -module -avoid-version -module_http_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-http.la libsocket-server.la libsocket-util.la +module_http_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libprotocol-http.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la # Native protocol module_native_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la +module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libprotocol-native.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_native_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_unix_la_LDFLAGS = -module -avoid-version -module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la libsocket-util.la +module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libprotocol-native.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_native_protocol_fd_la_SOURCES = modules/module-native-protocol-fd.c module_native_protocol_fd_la_CFLAGS = $(AM_CFLAGS) module_native_protocol_fd_la_LDFLAGS = -module -avoid-version -module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la libsocket-util.la libiochannel.la +module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libprotocol-native.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la # EsounD protocol module_esound_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-esound.la libsocket-server.la +module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libprotocol-esound.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_esound_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version -module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-esound.la libsocket-server.la libsocket-util.la +module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libprotocol-esound.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_esound_compat_spawnfd_la_SOURCES = modules/module-esound-compat-spawnfd.c module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version -module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_esound_compat_spawnpid_la_SOURCES = modules/module-esound-compat-spawnpid.c module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version -module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_esound_sink_la_SOURCES = modules/module-esound-sink.c module_esound_sink_la_LDFLAGS = -module -avoid-version -module_esound_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-client.la libauthkey.la libsocket-util.la +module_esound_sink_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la # Pipes module_pipe_sink_la_SOURCES = modules/module-pipe-sink.c module_pipe_sink_la_LDFLAGS = -module -avoid-version -module_pipe_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la +module_pipe_sink_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_pipe_source_la_SOURCES = modules/module-pipe-source.c module_pipe_source_la_LDFLAGS = -module -avoid-version -module_pipe_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la +module_pipe_source_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la # Fake sources/sinks module_sine_la_SOURCES = modules/module-sine.c module_sine_la_LDFLAGS = -module -avoid-version -module_sine_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_sine_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_null_sink_la_SOURCES = modules/module-null-sink.c module_null_sink_la_LDFLAGS = -module -avoid-version -module_null_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_null_sink_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la # Couplings module_combine_la_SOURCES = modules/module-combine.c module_combine_la_LDFLAGS = -module -avoid-version -module_combine_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_combine_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_remap_sink_la_SOURCES = modules/module-remap-sink.c module_remap_sink_la_LDFLAGS = -module -avoid-version -module_remap_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_remap_sink_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_ladspa_sink_la_SOURCES = modules/module-ladspa-sink.c modules/ladspa.h module_ladspa_sink_la_CFLAGS = -DLADSPA_PATH=\"$(libdir)/ladspa:/usr/local/lib/ladspa:/usr/lib/ladspa:/usr/local/lib64/ladspa:/usr/lib64/ladspa\" $(AM_CFLAGS) module_ladspa_sink_la_LDFLAGS = -module -avoid-version -module_ladspa_sink_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) libpulsecore.la +module_ladspa_sink_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_match_la_SOURCES = modules/module-match.c module_match_la_LDFLAGS = -module -avoid-version -module_match_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_match_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_tunnel_sink_la_SOURCES = modules/module-tunnel.c module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS) module_tunnel_sink_la_LDFLAGS = -module -avoid-version -module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauth-cookie.la libsocket-util.la libiochannel.la +module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_tunnel_source_la_SOURCES = modules/module-tunnel.c module_tunnel_source_la_LDFLAGS = -module -avoid-version -module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauth-cookie.la libsocket-util.la libiochannel.la +module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la # X11 module_x11_bell_la_SOURCES = modules/module-x11-bell.c module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_bell_la_LDFLAGS = -module -avoid-version -module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libpulsecore.la +module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_x11_publish_la_SOURCES = modules/module-x11-publish.c module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_publish_la_LDFLAGS = -module -avoid-version -module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libauthkey.la libauth-cookie.la libx11prop.la libstrlist.la libpulsecore.la +module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libprotocol-native.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_x11_xsmp_la_SOURCES = modules/module-x11-xsmp.c module_x11_xsmp_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_xsmp_la_LDFLAGS = -module -avoid-version -module_x11_xsmp_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libpulsecore.la +module_x11_xsmp_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la # OSS liboss_util_la_SOURCES = modules/oss-util.c modules/oss-util.h liboss_util_la_LDFLAGS = -avoid-version -liboss_util_la_LIBADD = libpulsecore.la +liboss_util_la_LIBADD = libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_oss_la_SOURCES = modules/module-oss.c module_oss_la_LDFLAGS = -module -avoid-version -module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la libpulsecore.la +module_oss_la_LIBADD = $(AM_LIBADD) liboss-util.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la # ALSA libalsa_util_la_SOURCES = modules/alsa-util.c modules/alsa-util.h libalsa_util_la_LDFLAGS = -avoid-version -libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libpulsecore.la +libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) module_alsa_sink_la_SOURCES = modules/module-alsa-sink.c module_alsa_sink_la_LDFLAGS = -module -avoid-version -module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore.la +module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) module_alsa_source_la_SOURCES = modules/module-alsa-source.c module_alsa_source_la_LDFLAGS = -module -avoid-version -module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore.la +module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) # Solaris module_solaris_la_SOURCES = modules/module-solaris.c module_solaris_la_LDFLAGS = -module -avoid-version -module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la libpulsecore.la +module_solaris_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la # Avahi module_zeroconf_publish_la_SOURCES = modules/module-zeroconf-publish.c module_zeroconf_publish_la_LDFLAGS = -module -avoid-version -module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(AVAHI_LIBS) libavahi-wrap.la libpulsecore.la +module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(AVAHI_LIBS) libavahi-wrap.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS) module_zeroconf_discover_la_SOURCES = modules/module-zeroconf-discover.c module_zeroconf_discover_la_LDFLAGS = -module -avoid-version -module_zeroconf_discover_la_LIBADD = $(AM_LIBADD) $(AVAHI_LIBS) libavahi-wrap.la libpulsecore.la +module_zeroconf_discover_la_LIBADD = $(AM_LIBADD) $(AVAHI_LIBS) libavahi-wrap.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_zeroconf_discover_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS) # LIRC module_lirc_la_SOURCES = modules/module-lirc.c module_lirc_la_LDFLAGS = -module -avoid-version -module_lirc_la_LIBADD = $(AM_LIBADD) $(LIRC_LIBS) libpulsecore.la +module_lirc_la_LIBADD = $(AM_LIBADD) $(LIRC_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_lirc_la_CFLAGS = $(AM_CFLAGS) $(LIRC_CFLAGS) # Linux evdev module_mmkbd_evdev_la_SOURCES = modules/module-mmkbd-evdev.c module_mmkbd_evdev_la_LDFLAGS = -module -avoid-version -module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS) # Windows waveout #module_waveout_la_SOURCES = modules/module-waveout.c #module_waveout_la_LDFLAGS = -module -avoid-version -#module_waveout_la_LIBADD = $(AM_LIBADD) libpulsecore.la -lwinmm +#module_waveout_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la -lwinmm libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la #module_waveout_la_CFLAGS = $(AM_CFLAGS) # Hardware autodetection module module_detect_la_SOURCES = modules/module-detect.c module_detect_la_LDFLAGS = -module -avoid-version -module_detect_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_detect_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_detect_la_CFLAGS = $(AM_CFLAGS) # Volume restore module module_volume_restore_la_SOURCES = modules/module-volume-restore.c module_volume_restore_la_LDFLAGS = -module -avoid-version -module_volume_restore_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_volume_restore_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_volume_restore_la_CFLAGS = $(AM_CFLAGS) # Position event sounds in space module_position_event_sounds_la_SOURCES = modules/module-position-event-sounds.c module_position_event_sounds_la_LDFLAGS = -module -avoid-version -module_position_event_sounds_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_position_event_sounds_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_position_event_sounds_CFLAGS = $(AM_CFLAGS) # Device volume/muted restore module module_device_restore_la_SOURCES = modules/module-device-restore.c module_device_restore_la_LDFLAGS = -module -avoid-version -module_device_restore_la_LIBADD = $(AM_LIBADD) libpulsecore.la -lgdbm +module_device_restore_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la -lgdbm libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_device_restore_la_CFLAGS = $(AM_CFLAGS) # Stream volume/muted/device restore module module_stream_restore_la_SOURCES = modules/module-stream-restore.c module_stream_restore_la_LDFLAGS = -module -avoid-version -module_stream_restore_la_LIBADD = $(AM_LIBADD) libpulsecore.la -lgdbm +module_stream_restore_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libpulsecore-@PA_MAJORMINORMICRO@.la -lgdbm libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_stream_restore_la_CFLAGS = $(AM_CFLAGS) # Default sink/source restore module module_default_device_restore_la_SOURCES = modules/module-default-device-restore.c module_default_device_restore_la_LDFLAGS = -module -avoid-version -module_default_device_restore_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_default_device_restore_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_default_device_restore_la_CFLAGS = $(AM_CFLAGS) # Always Sink module module_always_sink_la_SOURCES = modules/module-always-sink.c module_always_sink_la_LDFLAGS = -module -avoid-version -module_always_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_always_sink_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_always_sink_la_CFLAGS = $(AM_CFLAGS) # Rescue streams module module_rescue_streams_la_SOURCES = modules/module-rescue-streams.c module_rescue_streams_la_LDFLAGS = -module -avoid-version -module_rescue_streams_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_rescue_streams_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_rescue_streams_la_CFLAGS = $(AM_CFLAGS) # Suspend-on-idle module module_suspend_on_idle_la_SOURCES = modules/module-suspend-on-idle.c module_suspend_on_idle_la_LDFLAGS = -module -avoid-version -module_suspend_on_idle_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_suspend_on_idle_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_suspend_on_idle_la_CFLAGS = $(AM_CFLAGS) # RTP modules module_rtp_send_la_SOURCES = modules/rtp/module-rtp-send.c module_rtp_send_la_LDFLAGS = -module -avoid-version -module_rtp_send_la_LIBADD = $(AM_LIBADD) libpulsecore.la librtp.la libsocket-util.la +module_rtp_send_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la librtp.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_rtp_send_la_CFLAGS = $(AM_CFLAGS) module_rtp_recv_la_SOURCES = modules/rtp/module-rtp-recv.c module_rtp_recv_la_LDFLAGS = -module -avoid-version -module_rtp_recv_la_LIBADD = $(AM_LIBADD) libpulsecore.la librtp.la +module_rtp_recv_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la librtp.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_rtp_recv_la_CFLAGS = $(AM_CFLAGS) # JACK module_jack_sink_la_SOURCES = modules/module-jack-sink.c module_jack_sink_la_LDFLAGS = -module -avoid-version -module_jack_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS) +module_jack_sink_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la $(JACK_LIBS) libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_jack_sink_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) module_jack_source_la_SOURCES = modules/module-jack-source.c module_jack_source_la_LDFLAGS = -module -avoid-version -module_jack_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS) +module_jack_source_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la $(JACK_LIBS) libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_jack_source_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) # HAL/D-Bus libdbus_util_la_SOURCES = modules/dbus-util.c modules/dbus-util.h libdbus_util_la_LDFLAGS = -avoid-version -libdbus_util_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la +libdbus_util_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la libdbus_util_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) module_hal_detect_la_SOURCES = modules/module-hal-detect.c module_hal_detect_la_LDFLAGS = -module -avoid-version -module_hal_detect_la_LIBADD = $(AM_LIBADD) $(HAL_LIBS) libpulsecore.la libdbus-util.la +module_hal_detect_la_LIBADD = $(AM_LIBADD) $(HAL_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libdbus-util.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_hal_detect_la_CFLAGS = $(AM_CFLAGS) $(HAL_CFLAGS) module_console_kit_la_SOURCES = modules/module-console-kit.c module_console_kit_la_LDFLAGS = -module -avoid-version -module_console_kit_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la +module_console_kit_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libdbus-util.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_console_kit_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) # GConf support module_gconf_la_SOURCES = modules/gconf/module-gconf.c module_gconf_la_LDFLAGS = -module -avoid-version -module_gconf_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_gconf_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_gconf_la_CFLAGS = $(AM_CFLAGS) -DPA_GCONF_HELPER=\"$(pulselibexecdir)/gconf-helper\" gconf_helper_SOURCES = modules/gconf/gconf-helper.c -gconf_helper_LDADD = $(AM_LDADD) $(GCONF_LIBS) libpulsecore.la +gconf_helper_LDADD = $(AM_LDADD) $(GCONF_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la gconf_helper_CFLAGS = $(AM_CFLAGS) $(GCONF_CFLAGS) gconf_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) # Bluetooth proximity -module_bt_proximity_la_SOURCES = modules/module-bt-proximity.c -module_bt_proximity_la_LDFLAGS = -module -avoid-version -module_bt_proximity_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la -module_bt_proximity_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) -DPA_BT_PROXIMITY_HELPER=\"$(pulselibexecdir)/bt-proximity-helper\" +module_bluetooth_proximity_la_SOURCES = modules/bluetooth/module-bluetooth-proximity.c +module_bluetooth_proximity_la_LDFLAGS = -module -avoid-version +module_bluetooth_proximity_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libdbus-util.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +module_bluetooth_proximity_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) -DPA_BT_PROXIMITY_HELPER=\"$(pulselibexecdir)/proximity-helper\" + +proximity_helper_SOURCES = modules/bluetooth/proximity-helper.c +proximity_helper_LDADD = $(AM_LDADD) $(BLUEZ_LIBS) +proximity_helper_CFLAGS = $(AM_CFLAGS) $(BLUEZ_CFLAGS) +proximity_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +# Bluetooth sink / source +module_bluetooth_discover_la_SOURCES = modules/bluetooth/module-bluetooth-discover.c +module_bluetooth_discover_la_LDFLAGS = -module -avoid-version +module_bluetooth_discover_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libdbus-util.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +module_bluetooth_discover_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) + +libbluetooth_sbc_la_SOURCES = modules/bluetooth/sbc.c modules/bluetooth/sbc.h modules/bluetooth/sbc_tables.h modules/bluetooth/sbc_math.h +libbluetooth_sbc_la_LDFLAGS = -avoid-version +libbluetooth_sbc_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +libbluetooth_sbc_la_CFLAGS = $(AM_CFLAGS) + +libbluetooth_ipc_la_SOURCES = modules/bluetooth/ipc.c modules/bluetooth/ipc.h +libbluetooth_ipc_la_LDFLAGS = -avoid-version +libbluetooth_ipc_la_LIBADD = $(AM_LIBADD)libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +libbluetooth_ipc_la_CFLAGS = $(AM_CFLAGS) + +module_bluetooth_device_la_SOURCES = modules/bluetooth/module-bluetooth-device.c modules/bluetooth/rtp.h +module_bluetooth_device_la_LDFLAGS = -module -avoid-version +module_bluetooth_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libdbus-util.la libbluetooth-ipc.la libbluetooth-sbc.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +module_bluetooth_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) + +# Apple Airtunes/RAOP +module_raop_sink_la_SOURCES = modules/module-raop-sink.c +module_raop_sink_la_LDFLAGS = -module -avoid-version +module_raop_sink_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la librtp.la libraop.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la + +module_raop_discover_la_SOURCES = modules/module-raop-discover.c +module_raop_discover_la_LDFLAGS = -module -avoid-version +module_raop_discover_la_LIBADD = $(AM_LIBADD) $(AVAHI_LIBS) libavahi-wrap.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +module_raop_discover_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS) -bt_proximity_helper_SOURCES = modules/bt-proximity-helper.c -bt_proximity_helper_LDADD = $(AM_LDADD) $(BLUEZ_LIBS) -bt_proximity_helper_CFLAGS = $(AM_CFLAGS) $(BLUEZ_CFLAGS) -bt_proximity_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) ################################### # Some minor stuff # @@ -1598,7 +1446,7 @@ daemon.conf: daemon/daemon.conf.in Makefile install-exec-hook: chown root $(DESTDIR)$(bindir)/pulseaudio ; true chmod u+s $(DESTDIR)$(bindir)/pulseaudio - -chmod u+s $(DESTDIR)$(pulselibexecdir)/bt-proximity-helper + -chmod u+s $(DESTDIR)$(pulselibexecdir)/proximity-helper ln -sf pacat $(DESTDIR)$(bindir)/parec rm -f $(DESTDIR)$(modlibexecdir)/*.a rm -f $(DESTDIR)$(libdir)/libpulsedsp.a @@ -1615,7 +1463,7 @@ update-ffmpeg: update-map-file: ( echo "PULSE_0 {" ; \ echo "global:" ; \ - ctags -I PA_GCC_PURE,PA_GCC_CONST,PA_GCC_DEPRECATED,PA_GCC_PRINTF_ATTR -f - --c-kinds=p $(pulseinclude_HEADERS) | awk '/^pa_/ { print $$1 ";" }' | sort ; \ + ctags -I PA_GCC_MALLOC,PA_GCC_ALLOC_SIZE2,PA_GCC_ALLOC_SIZE,PA_GCC_PURE,PA_GCC_CONST,PA_GCC_DEPRECATED,PA_GCC_PRINTF_ATTR -f - --c-kinds=p $(pulseinclude_HEADERS) | awk '/^pa_/ { print $$1 ";" }' | sort ; \ echo "local:" ; \ echo "*;" ; \ echo "};" ) > $(srcdir)/map-file diff --git a/src/daemon/caps.c b/src/daemon/caps.c index f7b6658b..b5cbbc63 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -34,6 +34,7 @@ #include <pulsecore/macro.h> #include <pulsecore/core-error.h> #include <pulsecore/log.h> +#include <pulsecore/core-util.h> #ifdef HAVE_SYS_CAPABILITY_H #include <sys/capability.h> @@ -59,7 +60,7 @@ void pa_drop_root(void) { if (uid == 0 || geteuid() != 0) return; - pa_log_info(_("Dropping root priviliges.")); + pa_log_info(_("Dropping root privileges.")); #if defined(HAVE_SETRESUID) pa_assert_se(setresuid(uid, uid, uid) >= 0); @@ -112,9 +113,9 @@ void pa_drop_caps(void) { #ifndef __OPTIMIZE__ /* Valgrind doesn't not know set_caps, so we bypass it here -- but - * only in development builts.*/ + * only in development builds.*/ - if (getenv("VALGRIND") && !pa_have_caps()) + if (pa_in_valgrind() && !pa_have_caps()) return; #endif diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index fbd6dc32..0bfc8a92 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -55,6 +55,9 @@ enum { ARG_MODULE_IDLE_TIME, ARG_SCACHE_IDLE_TIME, ARG_LOG_TARGET, + ARG_LOG_META, + ARG_LOG_TIME, + ARG_LOG_BACKTRACE, ARG_LOAD, ARG_FILE, ARG_DL_SEARCH_PATH, @@ -88,6 +91,9 @@ static const struct option long_options[] = { {"module-idle-time", 2, 0, ARG_MODULE_IDLE_TIME}, {"scache-idle-time", 2, 0, ARG_SCACHE_IDLE_TIME}, {"log-target", 1, 0, ARG_LOG_TARGET}, + {"log-meta", 2, 0, ARG_LOG_META}, + {"log-time", 2, 0, ARG_LOG_TIME}, + {"log-backtrace", 1, 0, ARG_LOG_BACKTRACE}, {"load", 1, 0, ARG_LOAD}, {"file", 1, 0, ARG_FILE}, {"dl-search-path", 1, 0, ARG_DL_SEARCH_PATH}, @@ -148,6 +154,9 @@ void pa_cmdline_help(const char *argv0) { " --log-level[=LEVEL] Increase or set verbosity level\n" " -v Increase the verbosity level\n" " --log-target={auto,syslog,stderr} Specify the log target\n" + " --log-meta[=BOOL] Include code location in log messages\n" + " --log-time[=BOOL] Include timestamps in log messages\n" + " --log-backtrace=FRAMES Include a backtrace in log messages\n" " -p, --dl-search-path=PATH Set the search path for dynamic shared\n" " objects (plugins)\n" " --resample-method=METHOD Use the specified resampling method\n" @@ -321,6 +330,24 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d } break; + case ARG_LOG_TIME: + if ((conf->log_time = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { + pa_log(_("--log-time boolean argument")); + goto fail; + } + break; + + case ARG_LOG_META: + if ((conf->log_meta = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { + pa_log(_("--log-meta boolean argument")); + goto fail; + } + break; + + case ARG_LOG_BACKTRACE: + conf->log_backtrace = (unsigned) atoi(optarg); + break; + case ARG_EXIT_IDLE_TIME: conf->exit_idle_time = atoi(optarg); break; diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index 42a71f7e..a909600e 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -24,11 +24,13 @@ #endif #include <pulse/error.h> +#include <pulse/timeval.h> #include <pulsecore/core-util.h> #include <pulsecore/core-error.h> #include <pulsecore/log.h> #include <pulsecore/macro.h> +#include <pulsecore/rtclock.h> #include "cpulimit.h" @@ -67,7 +69,7 @@ #define CPUTIME_INTERVAL_HARD (5) /* Time of the last CPU load check */ -static time_t last_time = 0; +static pa_usec_t last_time = 0; /* Pipe for communicating with the main loop */ static int the_pipe[2] = {-1, -1}; @@ -100,7 +102,7 @@ static void reset_cpu_time(int t) { n = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec + t; pa_assert_se(getrlimit(RLIMIT_CPU, &rl) >= 0); - rl.rlim_cur = n; + rl.rlim_cur = (rlim_t) n; pa_assert_se(setrlimit(RLIMIT_CPU, &rl) >= 0); } @@ -117,20 +119,21 @@ static void signal_handler(int sig) { pa_assert(sig == SIGXCPU); if (phase == PHASE_IDLE) { - time_t now; + pa_usec_t now, elapsed; #ifdef PRINT_CPU_LOAD char t[256]; #endif - time(&now); + now = pa_rtclock_usec(); + elapsed = now - last_time; #ifdef PRINT_CPU_LOAD - pa_snprintf(t, sizeof(t), "Using %0.1f%% CPU\n", (double)CPUTIME_INTERVAL_SOFT/(now-last_time)*100); + pa_snprintf(t, sizeof(t), "Using %0.1f%% CPU\n", ((double) CPUTIME_INTERVAL_SOFT * (double) PA_USEC_PER_SEC) / (double) elapsed * 100.0); write_err(t); #endif - if (CPUTIME_INTERVAL_SOFT >= ((now-last_time)*(double)CPUTIME_PERCENT/100)) { + if (((double) CPUTIME_INTERVAL_SOFT * (double) PA_USEC_PER_SEC) >= ((double) elapsed * (double) CPUTIME_PERCENT / 100.0)) { static const char c = 'X'; write_err("Soft CPU time limit exhausted, terminating.\n"); @@ -164,6 +167,8 @@ static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags pa_assert(e == io_event); pa_assert(fd == the_pipe[0]); + pa_log("Recevied request to terminate due to CPU overload."); + pa_read(the_pipe[0], &c, sizeof(c), NULL); m->quit(m, 1); /* Quit the main loop */ } @@ -179,7 +184,7 @@ int pa_cpu_limit_init(pa_mainloop_api *m) { pa_assert(the_pipe[1] == -1); pa_assert(!installed); - time(&last_time); + last_time = pa_rtclock_usec(); /* Prepare the main loop pipe */ if (pipe(the_pipe) < 0) { @@ -235,7 +240,7 @@ void pa_cpu_limit_done(void) { #else /* HAVE_SIGXCPU */ -int pa_cpu_limit_init(PA_GCC_UNUSED pa_mainloop_api *m) { +int pa_cpu_limit_init(pa_mainloop_api *m) { return 0; } diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 05c86c87..d7ffc105 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -74,8 +74,12 @@ static const pa_daemon_conf default_conf = { .default_script_file = NULL, .log_target = PA_LOG_SYSLOG, .log_level = PA_LOG_NOTICE, + .log_backtrace = 0, + .log_meta = FALSE, + .log_time = FALSE, .resample_method = PA_RESAMPLER_AUTO, .disable_remixing = FALSE, + .disable_lfe_remixing = TRUE, .config_file = NULL, .use_pid_file = TRUE, .system_instance = FALSE, @@ -83,7 +87,8 @@ static const pa_daemon_conf default_conf = { .disable_shm = FALSE, .default_n_fragments = 4, .default_fragment_size_msec = 25, - .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 } + .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 }, + .shm_size = 0 #ifdef HAVE_SYS_RESOURCE_H ,.rlimit_fsize = { .value = 0, .is_set = FALSE }, .rlimit_data = { .value = 0, .is_set = FALSE }, @@ -191,7 +196,7 @@ int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) { return 0; } -static int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +static int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; pa_assert(filename); @@ -207,7 +212,7 @@ static int parse_log_target(const char *filename, unsigned line, const char *lva return 0; } -static int parse_log_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +static int parse_log_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; pa_assert(filename); @@ -223,7 +228,7 @@ static int parse_log_level(const char *filename, unsigned line, const char *lval return 0; } -static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; pa_assert(filename); @@ -239,7 +244,7 @@ static int parse_resample_method(const char *filename, unsigned line, const char return 0; } -static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { #ifdef HAVE_SYS_RESOURCE_H struct pa_rlimit *r = data; @@ -268,7 +273,7 @@ static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, return 0; } -static int parse_sample_format(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +static int parse_sample_format(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; pa_sample_format_t f; @@ -286,16 +291,16 @@ static int parse_sample_format(const char *filename, unsigned line, const char * return 0; } -static int parse_sample_rate(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +static int parse_sample_rate(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; - int32_t r; + uint32_t r; pa_assert(filename); pa_assert(lvalue); pa_assert(rvalue); pa_assert(data); - if (pa_atoi(rvalue, &r) < 0 || r > (int32_t) PA_RATE_MAX || r <= 0) { + if (pa_atou(rvalue, &r) < 0 || r > (uint32_t) PA_RATE_MAX || r <= 0) { pa_log(_("[%s:%u] Invalid sample rate '%s'."), filename, line, rvalue); return -1; } @@ -304,7 +309,7 @@ static int parse_sample_rate(const char *filename, unsigned line, const char *lv return 0; } -static int parse_sample_channels(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +static int parse_sample_channels(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; int32_t n; @@ -322,7 +327,7 @@ static int parse_sample_channels(const char *filename, unsigned line, const char return 0; } -static int parse_fragments(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +static int parse_fragments(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; int32_t n; @@ -340,7 +345,7 @@ static int parse_fragments(const char *filename, unsigned line, const char *lval return 0; } -static int parse_fragment_size_msec(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +static int parse_fragment_size_msec(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; int32_t n; @@ -358,7 +363,7 @@ static int parse_fragment_size_msec(const char *filename, unsigned line, const c return 0; } -static int parse_nice_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +static int parse_nice_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; int32_t level; @@ -376,7 +381,7 @@ static int parse_nice_level(const char *filename, unsigned line, const char *lva return 0; } -static int parse_rtprio(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +static int parse_rtprio(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; int32_t rtprio; @@ -397,6 +402,7 @@ static int parse_rtprio(const char *filename, unsigned line, const char *lvalue, int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { int r = -1; FILE *f = NULL; + unsigned i = 0; pa_config_item table[] = { { "daemonize", pa_config_parse_bool, NULL }, @@ -426,7 +432,12 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "default-fragment-size-msec", parse_fragment_size_msec, NULL }, { "nice-level", parse_nice_level, NULL }, { "disable-remixing", pa_config_parse_bool, NULL }, + { "disable-lfe-remixing", pa_config_parse_bool, NULL }, { "load-default-script-file", pa_config_parse_bool, NULL }, + { "shm-size-bytes", pa_config_parse_size, NULL }, + { "log-meta", pa_config_parse_bool, NULL }, + { "log-time", pa_config_parse_bool, NULL }, + { "log-backtrace", pa_config_parse_unsigned, NULL }, #ifdef HAVE_SYS_RESOURCE_H { "rlimit-fsize", parse_rlimit, NULL }, { "rlimit-data", parse_rlimit, NULL }, @@ -463,96 +474,75 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { NULL, NULL, NULL }, }; - table[0].data = &c->daemonize; - table[1].data = &c->fail; - table[2].data = &c->high_priority; - table[3].data = &c->realtime_scheduling; - table[4].data = &c->disallow_module_loading; - table[5].data = &c->disallow_exit; - table[6].data = &c->use_pid_file; - table[7].data = &c->system_instance; - table[8].data = &c->no_cpu_limit; - table[9].data = &c->disable_shm; - table[10].data = &c->exit_idle_time; - table[11].data = &c->module_idle_time; - table[12].data = &c->scache_idle_time; - table[13].data = c; - table[14].data = &c->dl_search_path; - table[15].data = &c->default_script_file; - table[16].data = c; - table[17].data = c; - table[18].data = c; - table[19].data = c; - table[20].data = c; - table[21].data = c; - table[22].data = c; - table[23].data = c; - table[24].data = c; - table[25].data = c; - table[26].data = &c->disable_remixing; - table[27].data = &c->load_default_script_file; + table[i++].data = &c->daemonize; + table[i++].data = &c->fail; + table[i++].data = &c->high_priority; + table[i++].data = &c->realtime_scheduling; + table[i++].data = &c->disallow_module_loading; + table[i++].data = &c->disallow_exit; + table[i++].data = &c->use_pid_file; + table[i++].data = &c->system_instance; + table[i++].data = &c->no_cpu_limit; + table[i++].data = &c->disable_shm; + table[i++].data = &c->exit_idle_time; + table[i++].data = &c->module_idle_time; + table[i++].data = &c->scache_idle_time; + table[i++].data = c; + table[i++].data = &c->dl_search_path; + table[i++].data = &c->default_script_file; + table[i++].data = c; + table[i++].data = c; + table[i++].data = c; + table[i++].data = c; + table[i++].data = c; + table[i++].data = c; + table[i++].data = c; + table[i++].data = c; + table[i++].data = c; + table[i++].data = c; + table[i++].data = &c->disable_remixing; + table[i++].data = &c->disable_lfe_remixing; + table[i++].data = &c->load_default_script_file; + table[i++].data = &c->shm_size; + table[i++].data = &c->log_meta; + table[i++].data = &c->log_time; + table[i++].data = &c->log_backtrace; #ifdef HAVE_SYS_RESOURCE_H - table[28].data = &c->rlimit_fsize; - table[29].data = &c->rlimit_data; - table[30].data = &c->rlimit_stack; - table[31].data = &c->rlimit_as; - table[32].data = &c->rlimit_core; - table[33].data = &c->rlimit_nofile; - table[34].data = &c->rlimit_as; + table[i++].data = &c->rlimit_fsize; + table[i++].data = &c->rlimit_data; + table[i++].data = &c->rlimit_stack; + table[i++].data = &c->rlimit_as; + table[i++].data = &c->rlimit_core; + table[i++].data = &c->rlimit_nofile; + table[i++].data = &c->rlimit_as; #ifdef RLIMIT_NPROC - table[35].data = &c->rlimit_nproc; + table[i++].data = &c->rlimit_nproc; #endif - #ifdef RLIMIT_MEMLOCK -#ifndef RLIMIT_NPROC -#error "Houston, we have a numbering problem!" -#endif - table[36].data = &c->rlimit_memlock; + table[i++].data = &c->rlimit_memlock; #endif - #ifdef RLIMIT_LOCKS -#ifndef RLIMIT_MEMLOCK -#error "Houston, we have a numbering problem!" -#endif - table[37].data = &c->rlimit_locks; + table[i++].data = &c->rlimit_locks; #endif - #ifdef RLIMIT_SIGPENDING -#ifndef RLIMIT_LOCKS -#error "Houston, we have a numbering problem!" -#endif - table[38].data = &c->rlimit_sigpending; + table[i++].data = &c->rlimit_sigpending; #endif - #ifdef RLIMIT_MSGQUEUE -#ifndef RLIMIT_SIGPENDING -#error "Houston, we have a numbering problem!" -#endif - table[39].data = &c->rlimit_msgqueue; + table[i++].data = &c->rlimit_msgqueue; #endif - #ifdef RLIMIT_NICE -#ifndef RLIMIT_MSGQUEUE -#error "Houston, we have a numbering problem!" -#endif - table[40].data = &c->rlimit_nice; + table[i++].data = &c->rlimit_nice; #endif - #ifdef RLIMIT_RTPRIO -#ifndef RLIMIT_NICE -#error "Houston, we have a numbering problem!" -#endif - table[41].data = &c->rlimit_rtprio; + table[i++].data = &c->rlimit_rtprio; #endif - #ifdef RLIMIT_RTTIME -#ifndef RLIMIT_RTTIME -#error "Houston, we have a numbering problem!" -#endif - table[42].data = &c->rlimit_rttime; + table[i++].data = &c->rlimit_rttime; #endif #endif + pa_assert(i == PA_ELEMENTSOF(table)-1); + pa_xfree(c->config_file); c->config_file = NULL; @@ -661,11 +651,16 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]); pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); pa_strbuf_printf(s, "disable-remixing = %s\n", pa_yes_no(c->disable_remixing)); + pa_strbuf_printf(s, "disable-lfe-remixing = %s\n", pa_yes_no(c->disable_lfe_remixing)); pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format)); pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate); pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels); pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments); pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec); + pa_strbuf_printf(s, "shm-size-bytes = %lu\n", (unsigned long) c->shm_size); + pa_strbuf_printf(s, "log-meta = %s\n", pa_yes_no(c->log_meta)); + pa_strbuf_printf(s, "log-time = %s\n", pa_yes_no(c->log_time)); + pa_strbuf_printf(s, "log-backtrace = %u\n", c->log_backtrace); #ifdef HAVE_SYS_RESOURCE_H pa_strbuf_printf(s, "rlimit-fsize = %li\n", c->rlimit_fsize.is_set ? (long int) c->rlimit_fsize.value : -1); pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index c42984f9..04a4ebe7 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -66,8 +66,11 @@ typedef struct pa_daemon_conf { no_cpu_limit, disable_shm, disable_remixing, + disable_lfe_remixing, load_default_script_file, - disallow_exit; + disallow_exit, + log_meta, + log_time; int exit_idle_time, module_idle_time, scache_idle_time, @@ -78,6 +81,7 @@ typedef struct pa_daemon_conf { char *script_commands, *dl_search_path, *default_script_file; pa_log_target_t log_target; pa_log_level_t log_level; + unsigned log_backtrace; char *config_file; #ifdef HAVE_SYS_RESOURCE_H @@ -110,6 +114,7 @@ typedef struct pa_daemon_conf { unsigned default_n_fragments, default_fragment_size_msec; pa_sample_spec default_sample_spec; + size_t shm_size; } pa_daemon_conf; /* Allocate a new structure and fill it with sane defaults */ diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 33b1d61d..00a95932 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -26,6 +26,7 @@ ; use-pid-file = yes ; system-instance = no ; disable-shm = no +; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB ; high-priority = yes ; nice-level = -11 @@ -39,14 +40,18 @@ ; dl-search-path = (depends on architecture) -; load-defaul-script-file = yes +; load-default-script-file = yes ; default-script-file = @PA_DEFAULT_CONFIG_FILE@ ; log-target = auto ; log-level = notice +; log-meta = no +; log-time = no +; log-backtrace = 0 ; resample-method = speex-float-3 ; disable-remixing = no +; disable-lfe-remixing = yes ; no-cpu-limit = no diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index cdaa8bbd..a8318766 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -23,7 +23,7 @@ ### Load something into the sample cache #load-sample-lazy x11-bell /usr/share/sounds/gtk-events/activate.wav -load-sample-lazy pulse-hotplug /usr/share/sounds/startup3.wav +#load-sample-lazy pulse-hotplug /usr/share/sounds/startup3.wav #load-sample-lazy pulse-coldplug /usr/share/sounds/startup3.wav #load-sample-lazy pulse-access /usr/share/sounds/generic.wav @@ -48,6 +48,11 @@ load-module module-hal-detect load-module module-detect .endif +### Automatically load driver modules for Bluetooth hardware +#.ifexists module-bluetooth-discover@PA_SOEXT@ +#load-module module-bluetooth-discover +#.endif + ### Load several protocols .ifexists module-esound-protocol-unix@PA_SOEXT@ load-module module-esound-protocol-unix @@ -67,9 +72,12 @@ load-module module-native-protocol-unix #load-module module-null-sink sink_name=rtp format=s16be channels=2 rate=44100 description="RTP Multicast Sink" #load-module module-rtp-send source=rtp.monitor +### Enable flat volumes where possible +load-module module-flat-volume + ### Automatically restore the volume of streams and devices -load-module module-stream-restore load-module module-device-restore +load-module module-stream-restore ### Automatically restore the default sink/source when changed by the user during runtime load-module module-default-device-restore diff --git a/src/daemon/dumpmodules.c b/src/daemon/dumpmodules.c index 26fb8eef..9c9f1c81 100644 --- a/src/daemon/dumpmodules.c +++ b/src/daemon/dumpmodules.c @@ -40,7 +40,7 @@ #define PREFIX "module-" -static void short_info(const char *name, PA_GCC_UNUSED const char *path, pa_modinfo *i) { +static void short_info(const char *name, const char *path, pa_modinfo *i) { pa_assert(name); pa_assert(i); diff --git a/src/daemon/ltdl-bind-now.c b/src/daemon/ltdl-bind-now.c index 6821aac4..2d80fc7a 100644 --- a/src/daemon/ltdl-bind-now.c +++ b/src/daemon/ltdl-bind-now.c @@ -24,11 +24,11 @@ #include <config.h> #endif -#if HAVE_DLFCN_H +#ifdef HAVE_DLFCN_H #include <dlfcn.h> #endif -#if HAVE_SYS_DL_H +#ifdef HAVE_SYS_DL_H #include <sys/dl.h> #endif @@ -74,7 +74,9 @@ static lt_module bind_now_open(lt_user_data d, const char *fname, lt_dladvise ad pa_assert(fname); if (!(m = dlopen(fname, PA_BIND_NOW))) { +#ifdef HAVE_LT_DLMUTEX_REGISTER libtool_set_error(dlerror()); +#endif return NULL; } @@ -86,7 +88,9 @@ static int bind_now_close(lt_user_data d, lt_module m) { pa_assert(m); if (dlclose(m) != 0){ +#ifdef HAVE_LT_DLMUTEX_REGISTER libtool_set_error(dlerror()); +#endif return 1; } @@ -100,7 +104,9 @@ static lt_ptr bind_now_find_sym(lt_user_data d, lt_module m, const char *symbol) pa_assert(symbol); if (!(ptr = dlsym(m, symbol))) { +#ifdef HAVE_LT_DLMUTEX_REGISTER libtool_set_error(dlerror()); +#endif return NULL; } diff --git a/src/daemon/main.c b/src/daemon/main.c index ab438320..f6d2512c 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -66,6 +66,7 @@ #include <pulse/xmalloc.h> #include <pulse/i18n.h> +#include <pulsecore/lock-autospawn.h> #include <pulsecore/winsock.h> #include <pulsecore/core-error.h> #include <pulsecore/core.h> @@ -95,8 +96,6 @@ #include "ltdl-bind-now.h" #include "polkit.h" -#define AUTOSPAWN_LOCK "autospawn.lock" - #ifdef HAVE_LIBWRAP /* Only one instance of these variables */ int allow_severity = LOG_INFO; @@ -112,7 +111,7 @@ int __padsp_disabled__ = 7; #ifdef OS_IS_WIN32 -static void message_cb(pa_mainloop_api*a, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { +static void message_cb(pa_mainloop_api*a, pa_time_event*e, const struct timeval *tv, void *userdata) { MSG msg; struct timeval tvnext; @@ -131,7 +130,7 @@ static void message_cb(pa_mainloop_api*a, pa_time_event*e, PA_GCC_UNUSED const s #endif -static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e, int sig, void *userdata) { +static void signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { pa_log_info(_("Got signal %s."), pa_sig2str(sig)); switch (sig) { @@ -223,7 +222,7 @@ static int change_user(void) { #elif defined(HAVE_SETREGID) r = setregid(gr->gr_gid, gr->gr_gid); #else -#error "No API to drop priviliges" +#error "No API to drop privileges" #endif if (r < 0) { @@ -239,7 +238,7 @@ static int change_user(void) { #elif defined(HAVE_SETREUID) r = setreuid(pw->pw_uid, pw->pw_uid); #else -#error "No API to drop priviliges" +#error "No API to drop privileges" #endif if (r < 0) { @@ -346,7 +345,11 @@ int main(int argc, char *argv[]) { struct timeval win32_tv; #endif char *lf = NULL; - int autospawn_lock_fd = -1; + int autospawn_fd = -1; + pa_bool_t autospawn_locked = FALSE; + + pa_log_set_maximal_level(PA_LOG_INFO); + pa_log_set_ident("pulseaudio"); #if defined(__linux__) && defined(__OPTIMIZE__) /* @@ -379,7 +382,7 @@ int main(int argc, char *argv[]) { /* Drop all capabilities except CAP_SYS_NICE */ pa_limit_caps(); - /* Drop priviliges, but keep CAP_SYS_NICE */ + /* Drop privileges, but keep CAP_SYS_NICE */ pa_drop_root(); /* After dropping root, the effective set is reset, hence, @@ -410,9 +413,6 @@ int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); pa_init_i18n(); - pa_log_set_maximal_level(PA_LOG_INFO); - pa_log_set_ident("pulseaudio"); - conf = pa_daemon_conf_new(); if (pa_daemon_conf_load(conf, NULL) < 0) @@ -428,6 +428,9 @@ int main(int argc, char *argv[]) { pa_log_set_maximal_level(conf->log_level); pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target, NULL); + pa_log_set_show_meta(conf->log_meta); + pa_log_set_show_backtrace(conf->log_backtrace); + pa_log_set_show_time(conf->log_time); pa_log_debug("Started as real root: %s, suid root: %s", pa_yes_no(real_root), pa_yes_no(suid_root)); @@ -476,9 +479,9 @@ int main(int argc, char *argv[]) { pa_drop_caps(); if (conf->high_priority || conf->realtime_scheduling) - pa_log_notice(_("Called SUID root and real-time/high-priority scheduling was requested in the configuration. However, we lack the necessary priviliges:\n" - "We are not in group '"PA_REALTIME_GROUP"' and PolicyKit refuse to grant us priviliges. Dropping SUID again.\n" - "For enabling real-time scheduling please acquire the appropriate PolicyKit priviliges, or become a member of '"PA_REALTIME_GROUP"', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user.")); + pa_log_notice(_("Called SUID root and real-time/high-priority scheduling was requested in the configuration. However, we lack the necessary privileges:\n" + "We are not in group '"PA_REALTIME_GROUP"' and PolicyKit refuse to grant us privileges. Dropping SUID again.\n" + "For enabling real-time scheduling please acquire the appropriate PolicyKit privileges, or become a member of '"PA_REALTIME_GROUP"', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user.")); } } @@ -606,7 +609,7 @@ int main(int argc, char *argv[]) { case PA_CMD_KILL: if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0) - pa_log(_("Failed to kill daemon.")); + pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno)); else retval = 0; @@ -626,7 +629,7 @@ int main(int argc, char *argv[]) { if (real_root && !conf->system_instance) pa_log_warn(_("This program is not intended to be run as root (unless --system is specified).")); else if (!real_root && conf->system_instance) { - pa_log(_("Root priviliges required.")); + pa_log(_("Root privileges required.")); goto finish; } @@ -646,9 +649,9 @@ int main(int argc, char *argv[]) { conf->disable_shm = TRUE; } - if (conf->system_instance && conf->exit_idle_time > 0) { + if (conf->system_instance && conf->exit_idle_time >= 0) { pa_log_notice(_("Running in system mode, forcibly disabling exit idle time!")); - conf->exit_idle_time = 0; + conf->exit_idle_time = -1; } if (conf->cmd == PA_CMD_START) { @@ -656,8 +659,17 @@ int main(int argc, char *argv[]) { * first take the autospawn lock to make things * synchronous. */ - lf = pa_runtime_path(AUTOSPAWN_LOCK); - autospawn_lock_fd = pa_lock_lockfile(lf); + if ((autospawn_fd = pa_autospawn_lock_init()) < 0) { + pa_log("Failed to initialize autospawn lock"); + goto finish; + } + + if ((pa_autospawn_lock_acquire(TRUE) < 0)) { + pa_log("Failed to acquire autospawn lock"); + goto finish; + } + + autospawn_locked = TRUE; } if (conf->daemonize) { @@ -703,12 +715,15 @@ int main(int argc, char *argv[]) { goto finish; } - if (autospawn_lock_fd >= 0) { + if (autospawn_fd >= 0) { /* The lock file is unlocked from the parent, so we need * to close it in the child */ - pa_close(autospawn_lock_fd); - autospawn_lock_fd = -1; + pa_autospawn_lock_release(); + pa_autospawn_lock_done(TRUE); + + autospawn_locked = FALSE; + autospawn_fd = -1; } pa_assert_se(pa_close(daemon_pipe[0]) == 0); @@ -766,8 +781,29 @@ int main(int argc, char *argv[]) { pa_set_env("PULSE_SYSTEM", conf->system_instance ? "1" : "0"); pa_log_info(_("This is PulseAudio %s"), PACKAGE_VERSION); + pa_log_debug(_("Compilation host: %s"), CANONICAL_HOST); + pa_log_debug(_("Compilation CFLAGS: %s"), PA_CFLAGS); + + s = pa_uname_string(); + pa_log_debug(_("Running on host: %s"), s); + pa_xfree(s); + pa_log_info(_("Page size is %lu bytes"), (unsigned long) PA_PAGE_SIZE); +#ifdef HAVE_VALGRIND_MEMCHECK_H + pa_log_debug(_("Compiled with Valgrind support: yes")); +#else + pa_log_debug(_("Compiled with Valgrind support: no")); +#endif + + pa_log_debug(_("Running in valgrind mode: %s"), pa_yes_no(pa_in_valgrind())); + +#ifdef __OPTIMIZE__ + pa_log_debug(_("Optimized build: yes")); +#else + pa_log_debug(_("Optimized build: no")); +#endif + if (!(s = pa_machine_id())) { pa_log(_("Failed to get machine ID")); goto finish; @@ -823,7 +859,7 @@ int main(int argc, char *argv[]) { pa_assert_se(mainloop = pa_mainloop_new()); - if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm))) { + if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm, conf->shm_size))) { pa_log(_("pa_core_new() failed.")); goto finish; } @@ -838,6 +874,7 @@ int main(int argc, char *argv[]) { c->realtime_priority = conf->realtime_priority; c->realtime_scheduling = !!conf->realtime_scheduling; c->disable_remixing = !!conf->disable_remixing; + c->disable_lfe_remixing = !!conf->disable_lfe_remixing; c->running_as_daemon = !!conf->daemonize; c->disallow_exit = conf->disallow_exit; @@ -917,8 +954,12 @@ int main(int argc, char *argv[]) { finish: - if (autospawn_lock_fd >= 0) - pa_unlock_lockfile(lf, autospawn_lock_fd); + if (autospawn_fd >= 0) { + if (autospawn_locked) + pa_autospawn_lock_release(); + + pa_autospawn_lock_done(FALSE); + } if (lf) pa_xfree(lf); diff --git a/src/daemon/system.pa.in b/src/daemon/system.pa.in index f6052c4b..27e42815 100755 --- a/src/daemon/system.pa.in +++ b/src/daemon/system.pa.in @@ -34,8 +34,9 @@ load-module module-esound-protocol-unix .endif load-module module-native-protocol-unix -### Automatically restore the volume of playback streams -load-module module-volume-restore +### Automatically restore the volume of streams and devices +load-module module-stream-restore +load-module module-device-restore ### Automatically restore the default sink/source when changed by the user during runtime load-module module-default-device-restore diff --git a/src/map-file b/src/map-file index b6d3b63d..ca523b91 100644 --- a/src/map-file +++ b/src/map-file @@ -9,6 +9,7 @@ pa_browser_unref; pa_bytes_per_second; pa_bytes_snprint; pa_bytes_to_usec; +pa_channel_map_compatible; pa_channel_map_equal; pa_channel_map_init; pa_channel_map_init_auto; @@ -97,7 +98,10 @@ pa_context_unload_module; pa_context_unref; pa_cvolume_avg; pa_cvolume_channels_equal_to; +pa_cvolume_compatible; pa_cvolume_equal; +pa_cvolume_init; +pa_cvolume_max; pa_cvolume_remap; pa_cvolume_set; pa_cvolume_snprint; @@ -158,6 +162,7 @@ pa_proplist_update; pa_sample_format_to_string; pa_sample_size; pa_sample_spec_equal; +pa_sample_spec_init; pa_sample_spec_snprint; pa_sample_spec_valid; pa_signal_done; @@ -222,7 +227,10 @@ pa_stream_update_timing_info; pa_stream_writable_size; pa_stream_write; pa_strerror; +pa_sw_cvolume_divide; pa_sw_cvolume_multiply; +pa_sw_cvolume_snprint_dB; +pa_sw_volume_divide; pa_sw_volume_from_dB; pa_sw_volume_from_linear; pa_sw_volume_multiply; diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 8abf834d..20dc400f 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -30,6 +30,7 @@ #include <pulse/sample.h> #include <pulse/xmalloc.h> +#include <pulse/timeval.h> #include <pulsecore/log.h> #include <pulsecore/macro.h> @@ -39,7 +40,7 @@ #include "alsa-util.h" struct pa_alsa_fdlist { - int num_fds; + unsigned num_fds; struct pollfd *fds; /* This is a temporary buffer used to avoid lots of mallocs */ struct pollfd *work_fds; @@ -50,16 +51,17 @@ struct pa_alsa_fdlist { pa_defer_event *defer; pa_io_event **ios; - int polled; + pa_bool_t polled; void (*cb)(void *userdata); void *userdata; }; -static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void *userdata) { +static void io_cb(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) { struct pa_alsa_fdlist *fdl = userdata; - int err, i; + int err; + unsigned i; unsigned short revents; pa_assert(a); @@ -71,11 +73,11 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io if (fdl->polled) return; - fdl->polled = 1; + fdl->polled = TRUE; memcpy(fdl->work_fds, fdl->fds, sizeof(struct pollfd) * fdl->num_fds); - for (i = 0;i < fdl->num_fds; i++) { + for (i = 0; i < fdl->num_fds; i++) { if (e == fdl->ios[i]) { if (events & PA_IO_EVENT_INPUT) fdl->work_fds[i].revents |= POLLIN; @@ -102,9 +104,10 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io snd_mixer_handle_events(fdl->mixer); } -static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *userdata) { +static void defer_cb(pa_mainloop_api*a, pa_defer_event* e, void *userdata) { struct pa_alsa_fdlist *fdl = userdata; - int num_fds, i, err; + unsigned num_fds, i; + int err; struct pollfd *temp; pa_assert(a); @@ -113,8 +116,7 @@ static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *u a->defer_enable(fdl->defer, 0); - num_fds = snd_mixer_poll_descriptors_count(fdl->mixer); - pa_assert(num_fds > 0); + num_fds = (unsigned) snd_mixer_poll_descriptors_count(fdl->mixer); if (num_fds != fdl->num_fds) { if (fdl->fds) @@ -132,7 +134,7 @@ static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *u return; } - fdl->polled = 0; + fdl->polled = FALSE; if (memcmp(fdl->fds, fdl->work_fds, sizeof(struct pollfd) * num_fds) == 0) return; @@ -176,7 +178,7 @@ struct pa_alsa_fdlist *pa_alsa_fdlist_new(void) { fdl->m = NULL; fdl->defer = NULL; fdl->ios = NULL; - fdl->polled = 0; + fdl->polled = FALSE; return fdl; } @@ -190,9 +192,9 @@ void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl) { } if (fdl->ios) { - int i; + unsigned i; pa_assert(fdl->m); - for (i = 0;i < fdl->num_fds;i++) + for (i = 0; i < fdl->num_fds; i++) fdl->m->io_free(fdl->ios[i]); pa_xfree(fdl->ios); } @@ -369,11 +371,18 @@ int pa_alsa_set_hw_params( goto finish; if (_periods > 0) { - dir = 1; + + /* First we pass 0 as direction to get exactly what we asked + * for. That this is necessary is presumably a bug in ALSA */ + + dir = 0; if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) { - dir = -1; - if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) - goto finish; + dir = 1; + if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) { + dir = -1; + if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) + goto finish; + } } } @@ -403,7 +412,7 @@ int pa_alsa_set_hw_params( /* If the sample rate deviates too much, we need to resample */ if (r < ss->rate*.95 || r > ss->rate*1.05) ss->rate = r; - ss->channels = c; + ss->channels = (uint8_t) c; ss->format = f; pa_assert(_periods > 0); @@ -420,6 +429,8 @@ int pa_alsa_set_hw_params( ret = 0; + snd_pcm_nonblock(pcm_handle, 1); + finish: return ret; @@ -568,40 +579,60 @@ snd_pcm_t *pa_alsa_open_by_device_id( continue; d = pa_sprintf_malloc("%s:%s", device_table[i].name, dev_id); - pa_log_debug("Trying %s...", d); - if ((err = snd_pcm_open(&pcm_handle, d, mode, - SND_PCM_NONBLOCK| - SND_PCM_NO_AUTO_RESAMPLE| - SND_PCM_NO_AUTO_CHANNELS| - SND_PCM_NO_AUTO_FORMAT | - SND_PCM_NO_SOFTVOL)) < 0) { - pa_log_info("Couldn't open PCM device %s: %s", d, snd_strerror(err)); - pa_xfree(d); - continue; - } + for (;;) { + pa_log_debug("Trying %s...", d); + + /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <= + * 1.0.17a would then ignore the SND_PCM_NO_xxx + * flags. Instead we enable nonblock mode afterwards via + * snd_pcm_nonblock(). Also see + * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */ + + if ((err = snd_pcm_open(&pcm_handle, d, mode, + /* SND_PCM_NONBLOCK| */ + SND_PCM_NO_AUTO_RESAMPLE| + SND_PCM_NO_AUTO_CHANNELS| + SND_PCM_NO_AUTO_FORMAT)) < 0) { + pa_log_info("Couldn't open PCM device %s: %s", d, snd_strerror(err)); + break; + } - try_ss.channels = device_table[i].map.channels; - try_ss.rate = ss->rate; - try_ss.format = ss->format; + try_ss.channels = device_table[i].map.channels; + try_ss.rate = ss->rate; + try_ss.format = ss->format; - if ((err = pa_alsa_set_hw_params(pcm_handle, &try_ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, TRUE)) < 0) { - pa_log_info("PCM device %s refused our hw parameters: %s", d, snd_strerror(err)); - pa_xfree(d); - snd_pcm_close(pcm_handle); - continue; + if ((err = pa_alsa_set_hw_params(pcm_handle, &try_ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, TRUE)) < 0) { + + if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) { + char *t; + + t = pa_sprintf_malloc("plug:%s", d); + pa_xfree(d); + d = t; + + snd_pcm_close(pcm_handle); + continue; + } + + pa_log_info("PCM device %s refused our hw parameters: %s", d, snd_strerror(err)); + snd_pcm_close(pcm_handle); + break; + } + + *ss = try_ss; + *map = device_table[i].map; + pa_assert(map->channels == ss->channels); + *dev = d; + return pcm_handle; } - *ss = try_ss; - *map = device_table[i].map; - pa_assert(map->channels == ss->channels); - *dev = d; - return pcm_handle; + pa_xfree(d); } /* OK, we didn't find any good device, so let's try the raw plughw: stuff */ - d = pa_sprintf_malloc("plughw:%s", dev_id); + d = pa_sprintf_malloc("hw:%s", dev_id); pa_log_debug("Trying %s as last resort...", d); pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, tsched_size, use_mmap, use_tsched); pa_xfree(d); @@ -635,8 +666,16 @@ snd_pcm_t *pa_alsa_open_by_device_string( d = pa_xstrdup(device); for (;;) { + pa_log_debug("Trying %s...", d); + + /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <= + * 1.0.17a would then ignore the SND_PCM_NO_xxx flags. Instead + * we enable nonblock mode afterwards via + * snd_pcm_nonblock(). Also see + * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */ - if ((err = snd_pcm_open(&pcm_handle, d, mode, SND_PCM_NONBLOCK| + if ((err = snd_pcm_open(&pcm_handle, d, mode, + /*SND_PCM_NONBLOCK|*/ SND_PCM_NO_AUTO_RESAMPLE| SND_PCM_NO_AUTO_CHANNELS| SND_PCM_NO_AUTO_FORMAT)) < 0) { @@ -647,24 +686,23 @@ snd_pcm_t *pa_alsa_open_by_device_string( if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, FALSE)) < 0) { - if (err == -EPERM) { - /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */ + /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */ - if (pa_startswith(d, "hw:")) { - char *t = pa_sprintf_malloc("plughw:%s", d+3); - pa_log_debug("Opening the device as '%s' didn't work, retrying with '%s'.", d, t); - pa_xfree(d); - d = t; + if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) { + char *t; - snd_pcm_close(pcm_handle); - continue; - } - - pa_log("Failed to set hardware parameters on %s: %s", d, snd_strerror(err)); + t = pa_sprintf_malloc("plug:%s", d); pa_xfree(d); + d = t; + snd_pcm_close(pcm_handle); - return NULL; + continue; } + + pa_log("Failed to set hardware parameters on %s: %s", d, snd_strerror(err)); + pa_xfree(d); + snd_pcm_close(pcm_handle); + return NULL; } *dev = d; @@ -808,7 +846,7 @@ int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel if (channel_map->channels > 1 && ((playback && snd_mixer_selem_has_playback_volume_joined(elem)) || (!playback && snd_mixer_selem_has_capture_volume_joined(elem)))) { - pa_log_info("ALSA device lacks independant volume controls for each channel, falling back to software volume control."); + pa_log_info("ALSA device lacks independant volume controls for each channel."); return -1; } @@ -820,7 +858,7 @@ int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel id = alsa_channel_ids[channel_map->map[i]]; if (!is_mono && id == SND_MIXER_SCHN_UNKNOWN) { - pa_log_info("Configured channel map contains channel '%s' that is unknown to the ALSA mixer. Falling back to software volume control.", pa_channel_position_to_string(channel_map->map[i])); + pa_log_info("Configured channel map contains channel '%s' that is unknown to the ALSA mixer.", pa_channel_position_to_string(channel_map->map[i])); return -1; } @@ -832,7 +870,7 @@ int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel if ((playback && (!snd_mixer_selem_has_playback_channel(elem, id) || (is_mono && !snd_mixer_selem_is_playback_mono(elem)))) || (!playback && (!snd_mixer_selem_has_capture_channel(elem, id) || (is_mono && !snd_mixer_selem_is_capture_mono(elem))))) { - pa_log_info("ALSA device lacks separate volumes control for channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map->map[i])); + pa_log_info("ALSA device lacks separate volumes control for channel '%s'", pa_channel_position_to_string(channel_map->map[i])); return -1; } @@ -850,56 +888,6 @@ int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel return 0; } -void pa_alsa_0dB_playback(snd_mixer_elem_t *elem) { - long min, max, v; - - pa_assert(elem); - - /* Try to enable 0 dB if possible. If ALSA cannot do dB, then use - * raw volume levels and fix them to 75% */ - - if (snd_mixer_selem_set_playback_dB_all(elem, 0, -1) >= 0) - return; - - if (snd_mixer_selem_set_playback_dB_all(elem, 0, 1) >= 0) - return; - - if (snd_mixer_selem_get_playback_volume_range(elem, &min, &max) < 0) - return; - - v = min + ((max - min) * 3) / 4; /* 75% */ - - if (v <= min) - v = max; - - snd_mixer_selem_set_playback_volume_all(elem, v); -} - -void pa_alsa_0dB_capture(snd_mixer_elem_t *elem) { - long min, max, v; - - pa_assert(elem); - - /* Try to enable 0 dB if possible. If ALSA cannot do dB, then use - * raw volume levels and fix them to 75% */ - - if (snd_mixer_selem_set_capture_dB_all(elem, 0, -1) >= 0) - return; - - if (snd_mixer_selem_set_capture_dB_all(elem, 0, 1) >= 0) - return; - - if (snd_mixer_selem_get_capture_volume_range(elem, &min, &max) < 0) - return; - - v = min + ((max - min) * 3) / 4; /* 75% */ - - if (v <= min) - v = max; - - snd_mixer_selem_set_capture_volume_all(elem, v); -} - void pa_alsa_dump(snd_pcm_t *pcm) { int err; snd_output_t *out; @@ -945,12 +933,17 @@ void pa_alsa_dump_status(snd_pcm_t *pcm) { static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) { va_list ap; + char *alsa_file; + + alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file); va_start(ap, fmt); - pa_log_levelv_meta(PA_LOG_WARN, file, line, function, fmt, ap); + pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap); va_end(ap); + + pa_xfree(alsa_file); } static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0); @@ -1058,6 +1051,12 @@ int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) { pa_log_warn("Got POLLNVAL from ALSA"); if (revents & POLLHUP) pa_log_warn("Got POLLHUP from ALSA"); + if (revents & POLLPRI) + pa_log_warn("Got POLLPRI from ALSA"); + if (revents & POLLIN) + pa_log_warn("Got POLLIN from ALSA"); + if (revents & POLLOUT) + pa_log_warn("Got POLLOUT from ALSA"); state = snd_pcm_state(pcm); pa_log_warn("PCM state is %s", snd_pcm_state_name(state)); @@ -1106,10 +1105,10 @@ pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) { return NULL; } - item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, n); + item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n); pollfd = pa_rtpoll_item_get_pollfd(item, NULL); - if ((err = snd_pcm_poll_descriptors(pcm, pollfd, n)) < 0) { + if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) { pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err)); pa_rtpoll_item_free(item); return NULL; @@ -1117,3 +1116,62 @@ pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) { return item; } + +snd_pcm_sframes_t pa_alsa_safe_avail_update(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) { + snd_pcm_sframes_t n; + size_t k; + + pa_assert(pcm); + pa_assert(hwbuf_size > 0); + pa_assert(ss); + + /* Some ALSA driver expose weird bugs, let's inform the user about + * what is going on */ + + n = snd_pcm_avail_update(pcm); + + if (n <= 0) + return n; + + k = (size_t) n * pa_frame_size(ss); + + if (k >= hwbuf_size * 3 || + k >= pa_bytes_per_second(ss)*10) + pa_log("snd_pcm_avail_update() returned a value that is exceptionally large: %lu bytes (%lu ms) " + "Most likely this is an ALSA driver bug. Please report this issue to the PulseAudio developers.", + (unsigned long) k, (unsigned long) pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC); + + return n; +} + +int pa_alsa_safe_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames, size_t hwbuf_size, const pa_sample_spec *ss) { + int r; + snd_pcm_uframes_t before; + size_t k; + + pa_assert(pcm); + pa_assert(areas); + pa_assert(offset); + pa_assert(frames); + pa_assert(hwbuf_size > 0); + pa_assert(ss); + + before = *frames; + + r = snd_pcm_mmap_begin(pcm, areas, offset, frames); + + if (r < 0) + return r; + + k = (size_t) *frames * pa_frame_size(ss); + + if (*frames > before || + k >= hwbuf_size * 3 || + k >= pa_bytes_per_second(ss)*10) + + pa_log("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms) " + "Most likely this is an ALSA driver bug. Please report this issue to the PulseAudio developers.", + (unsigned long) k, (unsigned long) pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC); + + return r; +} diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index 4de8bcd2..aaa01c78 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -26,6 +26,7 @@ #include <asoundlib.h> #include <pulse/sample.h> +#include <pulse/volume.h> #include <pulse/mainloop-api.h> #include <pulse/channelmap.h> #include <pulse/proplist.h> @@ -79,9 +80,6 @@ snd_pcm_t *pa_alsa_open_by_device_string( int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel_map, snd_mixer_selem_channel_id_t mixer_map[], pa_bool_t playback); -void pa_alsa_0dB_playback(snd_mixer_elem_t *elem); -void pa_alsa_0dB_capture(snd_mixer_elem_t *elem); - void pa_alsa_dump(snd_pcm_t *pcm); void pa_alsa_dump_status(snd_pcm_t *pcm); @@ -94,4 +92,7 @@ int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents); pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll); +snd_pcm_sframes_t pa_alsa_safe_avail_update(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss); +int pa_alsa_safe_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames, size_t hwbuf_size, const pa_sample_spec *ss); + #endif diff --git a/src/modules/bluetooth/Makefile b/src/modules/bluetooth/Makefile new file mode 120000 index 00000000..efe5a336 --- /dev/null +++ b/src/modules/bluetooth/Makefile @@ -0,0 +1 @@ +../../pulse/Makefile
\ No newline at end of file diff --git a/src/modules/bluetooth/ipc.c b/src/modules/bluetooth/ipc.c new file mode 100644 index 00000000..98256998 --- /dev/null +++ b/src/modules/bluetooth/ipc.c @@ -0,0 +1,118 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2008 Marcel Holtmann <marcel@holtmann.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "ipc.h" + +/* This table contains the string representation for messages */ +static const char *strmsg[] = { + "BT_GETCAPABILITIES_REQ", + "BT_GETCAPABILITIES_RSP", + "BT_SETCONFIGURATION_REQ", + "BT_SETCONFIGURATION_RSP", + "BT_STREAMSTART_REQ", + "BT_STREAMSTART_RSP", + "BT_STREAMSTOP_REQ", + "BT_STREAMSTOP_RSP", + "BT_STREAMSUSPEND_IND", + "BT_STREAMRESUME_IND", + "BT_CONTROL_REQ", + "BT_CONTROL_RSP", + "BT_CONTROL_IND", + "BT_STREAMFD_IND", +}; + +int bt_audio_service_open(void) +{ + int sk; + int err; + struct sockaddr_un addr = { + AF_UNIX, BT_IPC_SOCKET_NAME + }; + + sk = socket(PF_LOCAL, SOCK_STREAM, 0); + if (sk < 0) { + err = errno; + fprintf(stderr, "%s: Cannot open socket: %s (%d)\n", + __FUNCTION__, strerror(err), err); + errno = err; + return -1; + } + + if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + err = errno; + fprintf(stderr, "%s: connect() failed: %s (%d)\n", + __FUNCTION__, strerror(err), err); + close(sk); + errno = err; + return -1; + } + + return sk; +} + +int bt_audio_service_close(int sk) +{ + return close(sk); +} + +int bt_audio_service_get_data_fd(int sk) +{ + char cmsg_b[CMSG_SPACE(sizeof(int))], m; + int err, ret; + struct iovec iov = { &m, sizeof(m) }; + struct msghdr msgh; + struct cmsghdr *cmsg; + + memset(&msgh, 0, sizeof(msgh)); + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + msgh.msg_control = &cmsg_b; + msgh.msg_controllen = CMSG_LEN(sizeof(int)); + + ret = (int) recvmsg(sk, &msgh, 0); + if (ret < 0) { + err = errno; + fprintf(stderr, "%s: Unable to receive fd: %s (%d)\n", + __FUNCTION__, strerror(err), err); + errno = err; + return -1; + } + + /* Receive auxiliary data in msgh */ + for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msgh, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET + && cmsg->cmsg_type == SCM_RIGHTS) + return (*(int *) CMSG_DATA(cmsg)); + } + + errno = EINVAL; + return -1; +} + +const char *bt_audio_strmsg(int type) +{ + if (type < 0 || (size_t) type > (sizeof(strmsg) / sizeof(strmsg[0]))) + return NULL; + + return strmsg[type]; +} diff --git a/src/modules/bluetooth/ipc.h b/src/modules/bluetooth/ipc.h new file mode 100644 index 00000000..ae85e727 --- /dev/null +++ b/src/modules/bluetooth/ipc.h @@ -0,0 +1,308 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2008 Marcel Holtmann <marcel@holtmann.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* + Message sequence chart of streaming sequence for A2DP transport + + Audio daemon User + on snd_pcm_open + <--BT_GETCAPABILITIES_REQ + + BT_GETCAPABILITIES_RSP--> + + on snd_pcm_hw_params + <--BT_SETCONFIGURATION_REQ + + BT_SETCONFIGURATION_RSP--> + + on snd_pcm_prepare + <--BT_STREAMSTART_REQ + + <Moves to streaming state> + BT_STREAMSTART_RSP--> + + BT_STREAMFD_IND --> + + < streams data > + .......... + + on snd_pcm_drop/snd_pcm_drain + + <--BT_STREAMSTOP_REQ + + <Moves to open state> + BT_STREAMSTOP_RSP--> + + on IPC close or appl crash + <Moves to idle> + + */ + +#ifndef BT_AUDIOCLIENT_H +#define BT_AUDIOCLIENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <errno.h> + +#define BT_AUDIO_IPC_PACKET_SIZE 128 +#define BT_IPC_SOCKET_NAME "\0/org/bluez/audio" + +/* Generic message header definition, except for RSP messages */ +typedef struct { + uint8_t msg_type; +} __attribute__ ((packed)) bt_audio_msg_header_t; + +/* Generic message header definition, for all RSP messages */ +typedef struct { + bt_audio_msg_header_t msg_h; + uint8_t posix_errno; +} __attribute__ ((packed)) bt_audio_rsp_msg_header_t; + +/* Messages list */ +#define BT_GETCAPABILITIES_REQ 0 +#define BT_GETCAPABILITIES_RSP 1 + +#define BT_SETCONFIGURATION_REQ 2 +#define BT_SETCONFIGURATION_RSP 3 + +#define BT_STREAMSTART_REQ 4 +#define BT_STREAMSTART_RSP 5 + +#define BT_STREAMSTOP_REQ 6 +#define BT_STREAMSTOP_RSP 7 + +#define BT_STREAMSUSPEND_IND 8 +#define BT_STREAMRESUME_IND 9 + +#define BT_CONTROL_REQ 10 +#define BT_CONTROL_RSP 11 +#define BT_CONTROL_IND 12 + +#define BT_STREAMFD_IND 13 + +/* BT_GETCAPABILITIES_REQ */ + +#define BT_CAPABILITIES_TRANSPORT_A2DP 0 +#define BT_CAPABILITIES_TRANSPORT_SCO 1 +#define BT_CAPABILITIES_TRANSPORT_ANY 2 + +#define BT_CAPABILITIES_ACCESS_MODE_READ 1 +#define BT_CAPABILITIES_ACCESS_MODE_WRITE 2 +#define BT_CAPABILITIES_ACCESS_MODE_READWRITE 3 + +#define BT_FLAG_AUTOCONNECT 1 + +struct bt_getcapabilities_req { + bt_audio_msg_header_t h; + char device[18]; /* Address of the remote Device */ + uint8_t transport; /* Requested transport */ + uint8_t flags; /* Requested flags */ +} __attribute__ ((packed)); + +/* BT_GETCAPABILITIES_RSP */ + +/** + * SBC Codec parameters as per A2DP profile 1.0 § 4.3 + */ + +#define BT_SBC_SAMPLING_FREQ_16000 (1 << 3) +#define BT_SBC_SAMPLING_FREQ_32000 (1 << 2) +#define BT_SBC_SAMPLING_FREQ_44100 (1 << 1) +#define BT_SBC_SAMPLING_FREQ_48000 1 + +#define BT_A2DP_CHANNEL_MODE_MONO (1 << 3) +#define BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL (1 << 2) +#define BT_A2DP_CHANNEL_MODE_STEREO (1 << 1) +#define BT_A2DP_CHANNEL_MODE_JOINT_STEREO 1 + +#define BT_A2DP_BLOCK_LENGTH_4 (1 << 3) +#define BT_A2DP_BLOCK_LENGTH_8 (1 << 2) +#define BT_A2DP_BLOCK_LENGTH_12 (1 << 1) +#define BT_A2DP_BLOCK_LENGTH_16 1 + +#define BT_A2DP_SUBBANDS_4 (1 << 1) +#define BT_A2DP_SUBBANDS_8 1 + +#define BT_A2DP_ALLOCATION_SNR (1 << 1) +#define BT_A2DP_ALLOCATION_LOUDNESS 1 + +#define BT_MPEG_SAMPLING_FREQ_16000 (1 << 5) +#define BT_MPEG_SAMPLING_FREQ_22050 (1 << 4) +#define BT_MPEG_SAMPLING_FREQ_24000 (1 << 3) +#define BT_MPEG_SAMPLING_FREQ_32000 (1 << 2) +#define BT_MPEG_SAMPLING_FREQ_44100 (1 << 1) +#define BT_MPEG_SAMPLING_FREQ_48000 1 + +#define BT_MPEG_LAYER_1 (1 << 2) +#define BT_MPEG_LAYER_2 (1 << 1) +#define BT_MPEG_LAYER_3 1 + +typedef struct { + uint8_t channel_mode; + uint8_t frequency; + uint8_t allocation_method; + uint8_t subbands; + uint8_t block_length; + uint8_t min_bitpool; + uint8_t max_bitpool; +} __attribute__ ((packed)) sbc_capabilities_t; + +typedef struct { + uint8_t channel_mode; + uint8_t crc; + uint8_t layer; + uint8_t frequency; + uint8_t mpf; + uint16_t bitrate; +} __attribute__ ((packed)) mpeg_capabilities_t; + +struct bt_getcapabilities_rsp { + bt_audio_rsp_msg_header_t rsp_h; + uint8_t transport; /* Granted transport */ + sbc_capabilities_t sbc_capabilities; /* A2DP only */ + mpeg_capabilities_t mpeg_capabilities; /* A2DP only */ + uint16_t sampling_rate; /* SCO only */ +} __attribute__ ((packed)); + +/* BT_SETCONFIGURATION_REQ */ +struct bt_setconfiguration_req { + bt_audio_msg_header_t h; + char device[18]; /* Address of the remote Device */ + uint8_t transport; /* Requested transport */ + uint8_t access_mode; /* Requested access mode */ + sbc_capabilities_t sbc_capabilities; /* A2DP only - only one of this field + and next one must be filled */ + mpeg_capabilities_t mpeg_capabilities; /* A2DP only */ +} __attribute__ ((packed)); + +/* BT_SETCONFIGURATION_RSP */ +struct bt_setconfiguration_rsp { + bt_audio_rsp_msg_header_t rsp_h; + uint8_t transport; /* Granted transport */ + uint8_t access_mode; /* Granted access mode */ + uint16_t link_mtu; /* Max length that transport supports */ +} __attribute__ ((packed)); + +/* BT_STREAMSTART_REQ */ +#define BT_STREAM_ACCESS_READ 0 +#define BT_STREAM_ACCESS_WRITE 1 +#define BT_STREAM_ACCESS_READWRITE 2 +struct bt_streamstart_req { + bt_audio_msg_header_t h; +} __attribute__ ((packed)); + +/* BT_STREAMSTART_RSP */ +struct bt_streamstart_rsp { + bt_audio_rsp_msg_header_t rsp_h; +} __attribute__ ((packed)); + +/* BT_STREAMFD_IND */ +/* This message is followed by one byte of data containing the stream data fd + as ancilliary data */ +struct bt_streamfd_ind { + bt_audio_msg_header_t h; +} __attribute__ ((packed)); + +/* BT_STREAMSTOP_REQ */ +struct bt_streamstop_req { + bt_audio_msg_header_t h; +} __attribute__ ((packed)); + +/* BT_STREAMSTOP_RSP */ +struct bt_streamstop_rsp { + bt_audio_rsp_msg_header_t rsp_h; +} __attribute__ ((packed)); + +/* BT_STREAMSUSPEND_IND */ +struct bt_streamsuspend_ind { + bt_audio_msg_header_t h; +} __attribute__ ((packed)); + +/* BT_STREAMRESUME_IND */ +struct bt_streamresume_ind { + bt_audio_msg_header_t h; +} __attribute__ ((packed)); + +/* BT_CONTROL_REQ */ + +#define BT_CONTROL_KEY_POWER 0x40 +#define BT_CONTROL_KEY_VOL_UP 0x41 +#define BT_CONTROL_KEY_VOL_DOWN 0x42 +#define BT_CONTROL_KEY_MUTE 0x43 +#define BT_CONTROL_KEY_PLAY 0x44 +#define BT_CONTROL_KEY_STOP 0x45 +#define BT_CONTROL_KEY_PAUSE 0x46 +#define BT_CONTROL_KEY_RECORD 0x47 +#define BT_CONTROL_KEY_REWIND 0x48 +#define BT_CONTROL_KEY_FAST_FORWARD 0x49 +#define BT_CONTROL_KEY_EJECT 0x4A +#define BT_CONTROL_KEY_FORWARD 0x4B +#define BT_CONTROL_KEY_BACKWARD 0x4C + +struct bt_control_req { + bt_audio_msg_header_t h; + uint8_t mode; /* Control Mode */ + uint8_t key; /* Control Key */ +} __attribute__ ((packed)); + +/* BT_CONTROL_RSP */ +struct bt_control_rsp { + bt_audio_rsp_msg_header_t rsp_h; + uint8_t mode; /* Control Mode */ + uint8_t key; /* Control Key */ +} __attribute__ ((packed)); + +/* BT_CONTROL_IND */ +struct bt_control_ind { + bt_audio_msg_header_t h; + uint8_t mode; /* Control Mode */ + uint8_t key; /* Control Key */ +} __attribute__ ((packed)); + +/* Function declaration */ + +/* Opens a connection to the audio service: return a socket descriptor */ +int bt_audio_service_open(void); + +/* Closes a connection to the audio service */ +int bt_audio_service_close(int sk); + +/* Receives stream data file descriptor : must be called after a +BT_STREAMFD_IND message is returned */ +int bt_audio_service_get_data_fd(int sk); + +/* Human readable message type string */ +const char *bt_audio_strmsg(int type); + +#ifdef __cplusplus +} +#endif + +#endif /* BT_AUDIOCLIENT_H */ diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c new file mode 100644 index 00000000..3460fe9a --- /dev/null +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -0,0 +1,922 @@ +/*** + This file is part of PulseAudio. + + Copyright 2008 Joao Paulo Rechi Vita + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <errno.h> +#include <poll.h> +#include <sys/ioctl.h> +#include <linux/sockios.h> +#include <arpa/inet.h> + +#include <pulse/xmalloc.h> +#include <pulse/timeval.h> +#include <pulse/sample.h> +#include <pulsecore/module.h> +#include <pulsecore/modargs.h> +#include <pulsecore/core-util.h> +#include <pulsecore/core-error.h> +#include <pulsecore/socket-util.h> +#include <pulsecore/thread.h> +#include <pulsecore/thread-mq.h> +#include <pulsecore/rtpoll.h> +#include <pulsecore/time-smoother.h> +#include <pulsecore/rtclock.h> + +#include "../dbus-util.h" +#include "module-bluetooth-device-symdef.h" +#include "ipc.h" +#include "sbc.h" +#include "rtp.h" + +#define DEFAULT_SINK_NAME "bluetooth_sink" +#define BUFFER_SIZE 2048 +#define MAX_BITPOOL 64 +#define MIN_BITPOOL 2U +#define SOL_SCO 17 +#define SCO_TXBUFS 0x03 +#define SCO_RXBUFS 0x04 + +PA_MODULE_AUTHOR("Joao Paulo Rechi Vita"); +PA_MODULE_DESCRIPTION("Bluetooth audio sink and source"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_USAGE( + "sink_name=<name of the device> " + "address=<address of the device> " + "profile=<a2dp|hsp>"); + +struct bt_a2dp { + sbc_capabilities_t sbc_capabilities; + sbc_t sbc; /* Codec data */ + pa_bool_t sbc_initialized; /* Keep track if the encoder is initialized */ + size_t codesize; /* SBC codesize */ + unsigned samples; /* Number of encoded samples */ + uint8_t buffer[BUFFER_SIZE]; /* Codec transfer buffer */ + size_t count; /* Codec transfer buffer counter */ + + unsigned total_samples; /* Cumulative number of codec samples */ + uint16_t seq_num; /* Cumulative packet sequence */ + unsigned frame_count; /* Current frames in buffer*/ +}; + +struct userdata { + pa_core *core; + pa_module *module; + pa_sink *sink; + + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + pa_rtpoll_item *rtpoll_item; + pa_thread *thread; + + uint64_t offset; + pa_smoother *smoother; + + char *name; + char *addr; + char *profile; + pa_sample_spec ss; + + int audioservice_fd; + int stream_fd; + + uint8_t transport; + char *strtransport; + size_t link_mtu; + size_t block_size; + pa_usec_t latency; + + struct bt_a2dp a2dp; +}; + +static const char* const valid_modargs[] = { + "sink_name", + "address", + "profile", + "rate", + "channels", + NULL +}; + +static int bt_audioservice_send(int sk, const bt_audio_msg_header_t *msg) { + int e; + pa_log_debug("sending %s", bt_audio_strmsg(msg->msg_type)); + if (send(sk, msg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0) + e = 0; + else { + e = -errno; + pa_log_error("Error sending data to audio service: %s(%d)", pa_cstrerror(errno), errno); + } + return e; +} + +static int bt_audioservice_recv(int sk, bt_audio_msg_header_t *inmsg) { + int e; + const char *type; + + pa_log_debug("trying to receive msg from audio service..."); + if (recv(sk, inmsg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0) { + type = bt_audio_strmsg(inmsg->msg_type); + if (type) { + pa_log_debug("Received %s", type); + e = 0; + } + else { + e = -EINVAL; + pa_log_error("Bogus message type %d received from audio service", inmsg->msg_type); + } + } + else { + e = -errno; + pa_log_error("Error receiving data from audio service: %s(%d)", pa_cstrerror(errno), errno); + } + + return e; +} + +static int bt_audioservice_expect(int sk, bt_audio_msg_header_t *rsp_hdr, int expected_type) { + int e = bt_audioservice_recv(sk, rsp_hdr); + if (e == 0) { + if (rsp_hdr->msg_type != expected_type) { + e = -EINVAL; + pa_log_error("Bogus message %s received while %s was expected", bt_audio_strmsg(rsp_hdr->msg_type), + bt_audio_strmsg(expected_type)); + } + } + return e; +} + +static int bt_getcaps(struct userdata *u) { + int e; + union { + bt_audio_rsp_msg_header_t rsp_hdr; + struct bt_getcapabilities_req getcaps_req; + struct bt_getcapabilities_rsp getcaps_rsp; + uint8_t buf[BT_AUDIO_IPC_PACKET_SIZE]; + } msg; + + memset(msg.buf, 0, BT_AUDIO_IPC_PACKET_SIZE); + msg.getcaps_req.h.msg_type = BT_GETCAPABILITIES_REQ; + strncpy(msg.getcaps_req.device, u->addr, 18); + if (strcasecmp(u->profile, "a2dp") == 0) + msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_A2DP; + else if (strcasecmp(u->profile, "hsp") == 0) + msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_SCO; + else { + pa_log_error("Invalid profile argument: %s", u->profile); + return -1; + } + msg.getcaps_req.flags = BT_FLAG_AUTOCONNECT; + + e = bt_audioservice_send(u->audioservice_fd, &msg.getcaps_req.h); + if (e < 0) { + pa_log_error("Failed to send GETCAPABILITIES_REQ"); + return e; + } + + e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_GETCAPABILITIES_RSP); + if (e < 0) { + pa_log_error("Failed to expect for GETCAPABILITIES_RSP"); + return e; + } + if (msg.rsp_hdr.posix_errno != 0) { + pa_log_error("BT_GETCAPABILITIES failed : %s (%d)", pa_cstrerror(msg.rsp_hdr.posix_errno), msg.rsp_hdr.posix_errno); + return -msg.rsp_hdr.posix_errno; + } + + if ((u->transport = msg.getcaps_rsp.transport) == BT_CAPABILITIES_TRANSPORT_A2DP) + u->a2dp.sbc_capabilities = msg.getcaps_rsp.sbc_capabilities; + + return 0; +} + +static uint8_t default_bitpool(uint8_t freq, uint8_t mode) { + switch (freq) { + case BT_SBC_SAMPLING_FREQ_16000: + case BT_SBC_SAMPLING_FREQ_32000: + return 53; + case BT_SBC_SAMPLING_FREQ_44100: + switch (mode) { + case BT_A2DP_CHANNEL_MODE_MONO: + case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: + return 31; + case BT_A2DP_CHANNEL_MODE_STEREO: + case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: + return 53; + default: + pa_log_warn("Invalid channel mode %u", mode); + return 53; + } + case BT_SBC_SAMPLING_FREQ_48000: + switch (mode) { + case BT_A2DP_CHANNEL_MODE_MONO: + case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: + return 29; + case BT_A2DP_CHANNEL_MODE_STEREO: + case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: + return 51; + default: + pa_log_warn("Invalid channel mode %u", mode); + return 51; + } + default: + pa_log_warn("Invalid sampling freq %u", freq); + return 53; + } +} + +static int bt_a2dp_init(struct userdata *u) { + sbc_capabilities_t *cap = &u->a2dp.sbc_capabilities; + uint8_t max_bitpool, min_bitpool; + unsigned i; + + static const struct { + uint32_t rate; + uint8_t cap; + } freq_table[] = { + { 16000U, BT_SBC_SAMPLING_FREQ_16000 }, + { 32000U, BT_SBC_SAMPLING_FREQ_32000 }, + { 44100U, BT_SBC_SAMPLING_FREQ_44100 }, + { 48000U, BT_SBC_SAMPLING_FREQ_48000 } + }; + + /* Find the lowest freq that is at least as high as the requested + * sampling rate */ + for (i = 0; i < PA_ELEMENTSOF(freq_table); i++) + if (freq_table[i].rate >= u->ss.rate || i == PA_ELEMENTSOF(freq_table)-1 ) { + u->ss.rate = freq_table[i].rate; + cap->frequency = freq_table[i].cap; + break; + } + + if (u->ss.channels >= 2) { + if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) + cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; + else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) + cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO; + else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) + cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; + + u->ss.channels = 2; + } else { + if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) + cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO; + } + + if (!cap->channel_mode) { + pa_log_error("No supported channel modes"); + return -1; + } + + if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16) + cap->block_length = BT_A2DP_BLOCK_LENGTH_16; + else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12) + cap->block_length = BT_A2DP_BLOCK_LENGTH_12; + else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8) + cap->block_length = BT_A2DP_BLOCK_LENGTH_8; + else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4) + cap->block_length = BT_A2DP_BLOCK_LENGTH_4; + else { + pa_log_error("No supported block lengths"); + return -1; + } + + if (cap->subbands & BT_A2DP_SUBBANDS_8) + cap->subbands = BT_A2DP_SUBBANDS_8; + else if (cap->subbands & BT_A2DP_SUBBANDS_4) + cap->subbands = BT_A2DP_SUBBANDS_4; + else { + pa_log_error("No supported subbands"); + return -1; + } + + if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS) + cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS; + else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR) + cap->allocation_method = BT_A2DP_ALLOCATION_SNR; + + min_bitpool = (uint8_t) PA_MAX(MIN_BITPOOL, cap->min_bitpool); + max_bitpool = (uint8_t) PA_MIN(default_bitpool(cap->frequency, cap->channel_mode), cap->max_bitpool); + + cap->min_bitpool = (uint8_t) min_bitpool; + cap->max_bitpool = (uint8_t) max_bitpool; + + return 0; +} + +static void bt_a2dp_setup(struct bt_a2dp *a2dp) { + sbc_capabilities_t active_capabilities = a2dp->sbc_capabilities; + + if (a2dp->sbc_initialized) + sbc_reinit(&a2dp->sbc, 0); + else + sbc_init(&a2dp->sbc, 0); + a2dp->sbc_initialized = TRUE; + + if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000) + a2dp->sbc.frequency = SBC_FREQ_16000; + + if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000) + a2dp->sbc.frequency = SBC_FREQ_32000; + + if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100) + a2dp->sbc.frequency = SBC_FREQ_44100; + + if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000) + a2dp->sbc.frequency = SBC_FREQ_48000; + + if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO) + a2dp->sbc.mode = SBC_MODE_MONO; + + if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) + a2dp->sbc.mode = SBC_MODE_DUAL_CHANNEL; + + if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) + a2dp->sbc.mode = SBC_MODE_STEREO; + + if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) + a2dp->sbc.mode = SBC_MODE_JOINT_STEREO; + + a2dp->sbc.allocation = (uint8_t) (active_capabilities.allocation_method == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR : SBC_AM_LOUDNESS); + + switch (active_capabilities.subbands) { + case BT_A2DP_SUBBANDS_4: + a2dp->sbc.subbands = SBC_SB_4; + break; + case BT_A2DP_SUBBANDS_8: + a2dp->sbc.subbands = SBC_SB_8; + break; + } + + switch (active_capabilities.block_length) { + case BT_A2DP_BLOCK_LENGTH_4: + a2dp->sbc.blocks = SBC_BLK_4; + break; + case BT_A2DP_BLOCK_LENGTH_8: + a2dp->sbc.blocks = SBC_BLK_8; + break; + case BT_A2DP_BLOCK_LENGTH_12: + a2dp->sbc.blocks = SBC_BLK_12; + break; + case BT_A2DP_BLOCK_LENGTH_16: + a2dp->sbc.blocks = SBC_BLK_16; + break; + } + + a2dp->sbc.bitpool = active_capabilities.max_bitpool; + a2dp->codesize = (uint16_t) sbc_get_codesize(&a2dp->sbc); + a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); +} + +static int bt_setconf(struct userdata *u) { + int e; + union { + bt_audio_rsp_msg_header_t rsp_hdr; + struct bt_setconfiguration_req setconf_req; + struct bt_setconfiguration_rsp setconf_rsp; + uint8_t buf[BT_AUDIO_IPC_PACKET_SIZE]; + } msg; + + if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { + e = bt_a2dp_init(u); + if (e < 0) { + pa_log_error("a2dp_init error"); + return e; + } + u->ss.format = PA_SAMPLE_S16LE; + } + else + u->ss.format = PA_SAMPLE_U8; + + memset(msg.buf, 0, BT_AUDIO_IPC_PACKET_SIZE); + msg.setconf_req.h.msg_type = BT_SETCONFIGURATION_REQ; + strncpy(msg.setconf_req.device, u->addr, 18); + msg.setconf_req.transport = u->transport; + if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) + msg.setconf_req.sbc_capabilities = u->a2dp.sbc_capabilities; + msg.setconf_req.access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE; + + e = bt_audioservice_send(u->audioservice_fd, &msg.setconf_req.h); + if (e < 0) { + pa_log_error("Failed to send BT_SETCONFIGURATION_REQ"); + return e; + } + + e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_SETCONFIGURATION_RSP); + if (e < 0) { + pa_log_error("Failed to expect BT_SETCONFIGURATION_RSP"); + return e; + } + + if (msg.rsp_hdr.posix_errno != 0) { + pa_log_error("BT_SETCONFIGURATION failed : %s(%d)", pa_cstrerror(msg.rsp_hdr.posix_errno), msg.rsp_hdr.posix_errno); + return -msg.rsp_hdr.posix_errno; + } + + u->transport = msg.setconf_rsp.transport; + u->strtransport = (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP ? pa_xstrdup("A2DP") : pa_xstrdup("SCO")); + u->link_mtu = msg.setconf_rsp.link_mtu; + + /* setup SBC encoder now we agree on parameters */ + if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { + bt_a2dp_setup(&u->a2dp); + u->block_size = u->a2dp.codesize; + pa_log_info("sbc parameters:\n\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n", + u->a2dp.sbc.allocation, u->a2dp.sbc.subbands, u->a2dp.sbc.blocks, u->a2dp.sbc.bitpool); + } + else + u->block_size = u->link_mtu; + + return 0; +} + +static int bt_getstreamfd(struct userdata *u) { + int e; +// uint32_t period_count = io->buffer_size / io->period_size; + union { + bt_audio_rsp_msg_header_t rsp_hdr; + struct bt_streamstart_req start_req; + struct bt_streamfd_ind streamfd_ind; + uint8_t buf[BT_AUDIO_IPC_PACKET_SIZE]; + } msg; + + memset(msg.buf, 0, BT_AUDIO_IPC_PACKET_SIZE); + msg.start_req.h.msg_type = BT_STREAMSTART_REQ; + + e = bt_audioservice_send(u->audioservice_fd, &msg.start_req.h); + if (e < 0) { + pa_log_error("Failed to send BT_STREAMSTART_REQ"); + return e; + } + + e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_STREAMSTART_RSP); + if (e < 0) { + pa_log_error("Failed to expect BT_STREAMSTART_RSP"); + return e; + } + + if (msg.rsp_hdr.posix_errno != 0) { + pa_log_error("BT_START failed : %s(%d)", pa_cstrerror(msg.rsp_hdr.posix_errno), msg.rsp_hdr.posix_errno); + return -msg.rsp_hdr.posix_errno; + } + + e = bt_audioservice_expect(u->audioservice_fd, &msg.streamfd_ind.h, BT_STREAMFD_IND); + if (e < 0) { + pa_log_error("Failed to expect BT_STREAMFD_IND"); + return e; + } + + if (u->stream_fd >= 0) + pa_close(u->stream_fd); + + u->stream_fd = bt_audio_service_get_data_fd(u->audioservice_fd); + if (u->stream_fd < 0) { + pa_log_error("Failed to get data fd: %s (%d)",pa_cstrerror(errno), errno); + return -errno; + } + +// if (setsockopt(u->stream_fd, SOL_SCO, SCO_TXBUFS, &period_count, sizeof(period_count)) == 0) +// return 0; +// if (setsockopt(u->stream_fd, SOL_SCO, SO_SNDBUF, &period_count, sizeof(period_count)) == 0) +// return 0; +// /* FIXME : handle error codes */ + pa_make_fd_nonblock(u->stream_fd); +// pa_make_socket_low_delay(u->stream_fd); + + return 0; +} + +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; + + pa_log_debug("got message: %d", code); + switch (code) { + + case PA_SINK_MESSAGE_SET_STATE: + switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) { + case PA_SINK_SUSPENDED: + pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state)); + pa_smoother_pause(u->smoother, pa_rtclock_usec()); + break; + case PA_SINK_IDLE: + case PA_SINK_RUNNING: + if (u->sink->thread_info.state == PA_SINK_SUSPENDED) + pa_smoother_resume(u->smoother, pa_rtclock_usec()); + break; + case PA_SINK_UNLINKED: + case PA_SINK_INIT: + ; + } + break; + + case PA_SINK_MESSAGE_GET_LATENCY: { + pa_usec_t w, r; +/* r = pa_smoother_get(u->smoother, pa_rtclock_usec()); */ +/* /\* w = pa_bytes_to_usec(u->offset + (uint64_t) u->memchunk.length, &u->sink->sample_spec); *\/ */ + *((pa_usec_t*) data) = /*w > r ? w - r :*/ 0; + return 0; + } + + } + + return pa_sink_process_msg(o, code, data, offset, chunk); +} + +static int sco_process_render(struct userdata *u) { + void *p; + int ret = 0; + pa_memchunk memchunk; + + pa_sink_render_full(u->sink, u->block_size, &memchunk); + + p = pa_memblock_acquire(memchunk.memblock); + + for (;;) { + ssize_t l; + + l = pa_loop_write(u->stream_fd, (uint8_t*) p, memchunk.length, NULL); + pa_log_debug("Memblock written to socket: %li bytes", (long) l); + + pa_assert(l != 0); + + if (l > 0) { + u->offset += (uint64_t) l; + break; + } + + if (errno == EINTR) + pa_log_debug("EINTR"); + else if (errno == EAGAIN) + pa_log_debug("EAGAIN"); + else { + pa_log_error("Failed to write data to FIFO: %s", pa_cstrerror(errno)); + ret = -1; + break; + } + } + + pa_memblock_release(memchunk.memblock); + pa_memblock_unref(memchunk.memblock); + + return ret; +} + +static int a2dp_process_render(struct userdata *u) { + int written; + + struct bt_a2dp *a2dp = &u->a2dp; + struct rtp_header *header = (void *) a2dp->buffer; + struct rtp_payload *payload = (void *) (a2dp->buffer + sizeof(*header)); + + pa_assert(u); + + do { + /* Render some data */ + int frame_size, encoded; + void *p; + pa_memchunk memchunk; + + pa_sink_render_full(u->sink, u->block_size, &memchunk); + + p = pa_memblock_acquire(memchunk.memblock); + + frame_size = (uint16_t) sbc_get_frame_length(&a2dp->sbc); + pa_log_debug("SBC frame_size: %d", frame_size); + + encoded = sbc_encode(&a2dp->sbc, p, (int) a2dp->codesize, a2dp->buffer + a2dp->count, + (int) (sizeof(a2dp->buffer) - a2dp->count), &written); + pa_log_debug("SBC: encoded: %d; written: %d", encoded, written); + + pa_memblock_release(memchunk.memblock); + pa_memblock_unref(memchunk.memblock); + + if (encoded <= 0) { + pa_log_error("SBC encoding error (%d)", encoded); + return -1; + } + + a2dp->count += (size_t) written; + a2dp->frame_count++; + a2dp->samples += (unsigned) encoded / frame_size; + a2dp->total_samples += (unsigned) encoded / frame_size; + + } while (a2dp->count + (size_t) written <= u->link_mtu); + + /* write it to the fifo */ + memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload)); + payload->frame_count = a2dp->frame_count; + header->v = 2; + header->pt = 1; + header->sequence_number = htons(a2dp->seq_num); + header->timestamp = htonl(a2dp->total_samples); + header->ssrc = htonl(1); + + for (;;) { + ssize_t l; + + l = pa_loop_write(u->stream_fd, a2dp->buffer, a2dp->count, NULL); + pa_log_debug("avdtp_write: requested %lu bytes; written %li bytes", (unsigned long) a2dp->count, (long) l); + + pa_assert(l != 0); + + if (l > 0) + break; + + if (errno == EINTR) + pa_log_debug("EINTR"); + else if (errno == EAGAIN) + pa_log_debug("EAGAIN"); + else { + pa_log_error("Failed to write data to FIFO: %s", pa_cstrerror(errno)); + return -1; + } + } + + u->offset += a2dp->codesize*a2dp->frame_count; + + /* Reset buffer of data to send */ + a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); + a2dp->frame_count = 0; + a2dp->samples = 0; + a2dp->seq_num++; + + return 0; +} + +static void thread_func(void *userdata) { + struct userdata *u = userdata; + + pa_assert(u); + + pa_log_debug("IO Thread starting up"); + + if (u->core->realtime_scheduling) + pa_make_realtime(u->core->realtime_priority); + + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); + + pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec()); + + for (;;) { + int ret, l; + struct pollfd *pollfd; + uint64_t n; + pa_usec_t usec; + + if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) + if (u->sink->thread_info.rewind_requested) + pa_sink_process_rewind(u->sink, 0); + + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + + if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) { + if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { + if ((l = a2dp_process_render(u)) < 0) + goto fail; + } else { + if ((l = sco_process_render(u)) < 0) + goto fail; + } + pollfd->revents = 0; + + /* feed the time smoother */ + n = u->offset; + if (ioctl(u->stream_fd, SIOCOUTQ, &l) >= 0 && l > 0) + n -= (uint64_t) l; + usec = pa_bytes_to_usec(n, &u->sink->sample_spec); + if (usec > u->latency) + usec -= u->latency; + else + usec = 0; + pa_smoother_put(u->smoother, pa_rtclock_usec(), usec); + } + + /* Hmm, nothing to do. Let's sleep */ + pa_log_debug("IO thread going to sleep"); + pollfd->events = (short) (PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0); + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) { + pa_log_error("rtpoll_run < 0"); + goto fail; + } + pa_log_debug("IO thread waking up"); + + if (ret == 0) { + pa_log_debug("rtpoll_run == 0"); + goto finish; + } + + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + if (pollfd->revents & ~POLLOUT) { + pa_log_error("FIFO shutdown."); + goto fail; + } + } + +fail: + /* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */ + pa_log_debug("IO thread failed"); + pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL); + pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); + +finish: + pa_log_debug("IO thread shutting down"); +} + +int pa__init(pa_module* m) { + int e; + pa_modargs *ma; + uint32_t channels; + pa_sink_new_data data; + struct pollfd *pollfd; + struct userdata *u; + + pa_assert(m); + m->userdata = u = pa_xnew0(struct userdata, 1); + u->module = m; + u->core = m->core; + u->audioservice_fd = -1; + u->stream_fd = -1; + u->transport = (uint8_t) -1; + u->offset = 0; + u->latency = 0; + u->a2dp.sbc_initialized = FALSE; + u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10); + u->rtpoll = pa_rtpoll_new(); + pa_thread_mq_init(&u->thread_mq, u->core->mainloop, u->rtpoll); + u->rtpoll_item = NULL; + u->ss = m->core->default_sample_spec; + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log_error("Failed to parse module arguments"); + goto fail; + } + if (!(u->name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME)))) { + pa_log_error("Failed to get device name from module arguments"); + goto fail; + } + if (!(u->addr = pa_xstrdup(pa_modargs_get_value(ma, "address", NULL)))) { + pa_log_error("Failed to get device address from module arguments"); + goto fail; + } + if (!(u->profile = pa_xstrdup(pa_modargs_get_value(ma, "profile", NULL)))) { + pa_log_error("Failed to get profile from module arguments"); + goto fail; + } + if (pa_modargs_get_value_u32(ma, "rate", &u->ss.rate) < 0) { + pa_log_error("Failed to get rate from module arguments"); + goto fail; + } + + channels = u->ss.channels; + if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0) { + pa_log_error("Failed to get channels from module arguments"); + goto fail; + } + u->ss.channels = (uint8_t) channels; + + /* connect to the bluez audio service */ + u->audioservice_fd = bt_audio_service_open(); + if (u->audioservice_fd <= 0) { + pa_log_error("Couldn't connect to bluetooth audio service"); + goto fail; + } + pa_log_debug("Connected to the bluetooth audio service"); + + /* queries device capabilities */ + e = bt_getcaps(u); + if (e < 0) { + pa_log_error("Failed to get device capabilities"); + goto fail; + } + pa_log_debug("Got device capabilities"); + + /* configures the connection */ + e = bt_setconf(u); + if (e < 0) { + pa_log_error("Failed to set config"); + goto fail; + } + pa_log_debug("Connection to the device configured"); + + /* gets the device socket */ + e = bt_getstreamfd(u); + if (e < 0) { + pa_log_error("Failed to get stream fd (%d)", e); + goto fail; + } + pa_log_debug("Got the device socket"); + + /* create sink */ + pa_sink_new_data_init(&data); + data.driver = __FILE__; + data.module = m; + pa_sink_new_data_set_name(&data, u->name); + pa_sink_new_data_set_sample_spec(&data, &u->ss); + pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->name); + pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Bluetooth %s '%s' (%s)", u->strtransport, u->name, u->addr); + pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile); + pa_proplist_setf(data.proplist, PA_PROP_DEVICE_API, "bluez"); + pa_proplist_setf(data.proplist, PA_PROP_DEVICE_CLASS, "sound"); + pa_proplist_setf(data.proplist, PA_PROP_DEVICE_CONNECTOR, "bluetooth"); +/* pa_proplist_setf(data.proplist, PA_PROP_DEVICE_FORM_FACTOR, "headset"); /\*FIXME*\/ */ +/* pa_proplist_setf(data.proplist, PA_PROP_DEVICE_VENDOR_PRODUCT_ID, "product_id"); /\*FIXME*\/ */ +/* pa_proplist_setf(data.proplist, PA_PROP_DEVICE_SERIAL, "serial"); /\*FIXME*\/ */ + u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY); + pa_sink_new_data_done(&data); + if (!u->sink) { + pa_log_error("Failed to create sink"); + goto fail; + } + u->sink->userdata = u; + u->sink->parent.process_msg = sink_process_msg; + pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); + pa_sink_set_rtpoll(u->sink, u->rtpoll); + + u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1); + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + pollfd->fd = u->stream_fd; + pollfd->events = pollfd->revents = 0; + + /* start rt thread */ + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log_error("Failed to create IO thread"); + goto fail; + } + pa_sink_put(u->sink); + + pa_modargs_free(ma); + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(m); + return -1; +} + +void pa__done(pa_module *m) { + struct userdata *u; + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->sink) + pa_sink_unlink(u->sink); + + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); + } + + if (u->sink) + pa_sink_unref(u->sink); + + pa_thread_mq_done(&u->thread_mq); + + if (u->rtpoll_item) + pa_rtpoll_item_free(u->rtpoll_item); + + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); + + if (u->smoother) + pa_smoother_free(u->smoother); + + pa_xfree(u->name); + pa_xfree(u->addr); + pa_xfree(u->profile); + pa_xfree(u->strtransport); + + if (u->stream_fd >= 0) + pa_close(u->stream_fd); + + if (u->audioservice_fd >= 0) + pa_close(u->audioservice_fd); + + pa_xfree(u); +} diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c new file mode 100644 index 00000000..36c0a35e --- /dev/null +++ b/src/modules/bluetooth/module-bluetooth-discover.c @@ -0,0 +1,558 @@ +/*** + This file is part of PulseAudio. + + Copyright 2008 Joao Paulo Rechi Vita + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <pulse/xmalloc.h> +#include <pulsecore/module.h> +#include <pulsecore/modargs.h> +#include <pulsecore/macro.h> +#include <pulsecore/llist.h> +#include <pulsecore/core-util.h> + +#include "../dbus-util.h" +#include "module-bluetooth-discover-symdef.h" + +PA_MODULE_AUTHOR("Joao Paulo Rechi Vita"); +PA_MODULE_DESCRIPTION("Detect available bluetooth audio devices and load bluetooth audio drivers"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_USAGE(""); + +struct module { + char *profile; + pa_module *pa_m; + PA_LLIST_FIELDS(struct module); +}; + +struct uuid { + char *uuid; + PA_LLIST_FIELDS(struct uuid); +}; + +struct device { + char *name; + char *object_path; + int paired; + char *alias; + int connected; + PA_LLIST_HEAD(struct uuid, uuid_list); + char *address; + int class; + int trusted; + PA_LLIST_HEAD(struct module, module_list); + PA_LLIST_FIELDS(struct device); +}; + +struct userdata { + pa_module *module; + pa_dbus_connection *conn; + PA_LLIST_HEAD(struct device, device_list); +}; + +static struct module *module_new(const char *profile, pa_module *pa_m) { + struct module *m; + + m = pa_xnew(struct module, 1); + m->profile = pa_xstrdup(profile); + m->pa_m = pa_m; + PA_LLIST_INIT(struct module, m); + + return m; +} + +static void module_free(struct module *m) { + pa_assert(m); + + pa_xfree(m->profile); + pa_xfree(m); +} + +static struct module* module_find(struct device *d, const char *profile) { + struct module *m; + + for (m = d->module_list; d; d = d->next) + if (pa_streq(m->profile, profile)) + return m; + + return NULL; +} + +static struct uuid *uuid_new(const char *uuid) { + struct uuid *node; + + node = pa_xnew(struct uuid, 1); + node->uuid = pa_xstrdup(uuid); + PA_LLIST_INIT(struct uuid, node); + + return node; +} + +static void uuid_free(struct uuid *uuid) { + pa_assert(uuid); + + pa_xfree(uuid->uuid); + pa_xfree(uuid); +} + +static struct device *device_new(const char *object_path) { + struct device *node; + + node = pa_xnew(struct device, 1); + node->name = NULL; + node->object_path = pa_xstrdup(object_path); + node->paired = -1; + node->alias = NULL; + node->connected = -1; + PA_LLIST_HEAD_INIT(struct uuid, node->uuid_list); + node->address = NULL; + node->class = -1; + node->trusted = -1; + PA_LLIST_HEAD_INIT(struct module, node->module_list); + PA_LLIST_INIT(struct device, node); + + return node; +} + +static void device_free(struct device *device) { + struct module *m; + struct uuid *i; + + pa_assert(device); + + while ((m = device->module_list)) { + PA_LLIST_REMOVE(struct module, device->module_list, m); + module_free(m); + } + + while ((i = device->uuid_list)) { + PA_LLIST_REMOVE(struct uuid, device->uuid_list, i); + uuid_free(i); + } + + pa_xfree(device->name); + pa_xfree(device->object_path); + pa_xfree(device->alias); + pa_xfree(device->address); + pa_xfree(device); +} + +static struct device* device_find(struct userdata *u, const char *path) { + struct device *i; + + for (i = u->device_list; i; i = i->next) + if (pa_streq(i->object_path, path)) + return i; + + return NULL; +} + +static int parse_device_property(struct userdata *u, struct device *d, DBusMessageIter *i) { + const char *key; + DBusMessageIter variant_i; + + pa_assert(u); + pa_assert(d); + pa_assert(i); + + if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) { + pa_log("Property name not a string."); + return -1; + } + + dbus_message_iter_get_basic(i, &key); + + if (!dbus_message_iter_next(i)) { + pa_log("Property value missing"); + return -1; + } + + if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_VARIANT) { + pa_log("Property value not a variant."); + return -1; + } + + dbus_message_iter_recurse(i, &variant_i); + + pa_log_debug("Parsing device property %s", key); + + switch (dbus_message_iter_get_arg_type(&variant_i)) { + + case DBUS_TYPE_STRING: { + + const char *value; + dbus_message_iter_get_basic(&variant_i, &value); + + if (pa_streq(key, "Name")) { + pa_xfree(d->name); + d->name = pa_xstrdup(value); + } else if (pa_streq(key, "Alias")) { + pa_xfree(d->alias); + d->alias = pa_xstrdup(value); + } else if (pa_streq(key, "Address")) { + pa_xfree(d->address); + d->address = pa_xstrdup(value); + } + + break; + } + + case DBUS_TYPE_BOOLEAN: { + + dbus_bool_t value; + dbus_message_iter_get_basic(&variant_i, &value); + + if (pa_streq(key, "Paired")) + d->paired = !!value; + else if (pa_streq(key, "Connected")) + d->connected = !!value; + else if (pa_streq(key, "Trusted")) + d->trusted = !!value; + + break; + } + + case DBUS_TYPE_UINT32: { + + uint32_t value; + dbus_message_iter_get_basic(&variant_i, &value); + + if (pa_streq(key, "Class")) + d->class = (int) value; + + break; + } + + case DBUS_TYPE_ARRAY: { + + DBusMessageIter ai; + dbus_message_iter_recurse(&variant_i, &ai); + + if (dbus_message_iter_get_arg_type(&ai) == DBUS_TYPE_STRING && + pa_streq(key, "UUIDs")) { + + while (dbus_message_iter_get_arg_type(&ai) != DBUS_TYPE_INVALID) { + struct uuid *node; + const char *value; + + dbus_message_iter_get_basic(&ai, &value); + node = uuid_new(value); + PA_LLIST_PREPEND(struct uuid, d->uuid_list, node); + + if (!dbus_message_iter_next(&ai)) + break; + } + } + + break; + } + } + + return 0; +} + +static int get_device_properties(struct userdata *u, struct device *d) { + DBusError e; + DBusMessage *m = NULL, *r = NULL; + DBusMessageIter arg_i, element_i; + int ret = -1; + + pa_assert(u); + pa_assert(d); + + dbus_error_init(&e); + + pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->object_path, "org.bluez.Device", "GetProperties")); + + r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e); + + if (!r) { + pa_log("org.bluez.Device.GetProperties failed: %s", e.message); + goto finish; + } + + if (!dbus_message_iter_init(r, &arg_i)) { + pa_log("org.bluez.Device.GetProperties reply has no arguments"); + goto finish; + } + + if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) { + pa_log("org.bluez.Device.GetProperties argument is not an array"); + goto finish; + } + + dbus_message_iter_recurse(&arg_i, &element_i); + while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) { + + if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter dict_i; + + dbus_message_iter_recurse(&element_i, &dict_i); + + if (parse_device_property(u, d, &dict_i) < 0) + goto finish; + } + + if (!dbus_message_iter_next(&element_i)) + break; + } + + ret = 0; + +finish: + if (m) + dbus_message_unref(m); + if (r) + dbus_message_unref(r); + + dbus_error_free(&e); + + return ret; +} + +static void load_module_for_device(struct userdata *u, struct device *d, const char *profile) { + char *args; + pa_module *pa_m; + struct module *m; + + pa_assert(u); + pa_assert(d); + + get_device_properties(u, d); + args = pa_sprintf_malloc("sink_name=\"%s\" address=\"%s\" profile=\"%s\"", d->name, d->address, profile); + pa_m = pa_module_load(u->module->core, "module-bluetooth-device", args); + pa_xfree(args); + + if (!pa_m) { + pa_log_debug("Failed to load module for device %s", d->object_path); + return; + } + + m = module_new(profile, pa_m); + PA_LLIST_PREPEND(struct module, d->module_list, m); +} + +static void unload_module_for_device(struct userdata *u, struct device *d, const char *profile) { + struct module *m; + + pa_assert(u); + pa_assert(d); + + if (!(m = module_find(d, profile))) + return; + + pa_module_unload_request(m->pa_m, TRUE); + + PA_LLIST_REMOVE(struct module, d->module_list, m); + module_free(m); +} + +static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *userdata) { + DBusMessageIter arg_i; + DBusError err; + const char *value; + struct userdata *u; + + pa_assert(bus); + pa_assert(msg); + pa_assert(userdata); + u = userdata; + + dbus_error_init(&err); + + pa_log_debug("dbus: interface=%s, path=%s, member=%s\n", + dbus_message_get_interface(msg), + dbus_message_get_path(msg), + dbus_message_get_member(msg)); + + if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceRemoved")) { + + if (!dbus_message_iter_init(msg, &arg_i)) + pa_log("dbus: message has no parameters"); + else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH) + pa_log("dbus: argument is not object path"); + else { + struct device *d; + + dbus_message_iter_get_basic(&arg_i, &value); + pa_log_debug("hcid: device %s removed", value); + + if ((d = device_find(u, value))) { + PA_LLIST_REMOVE(struct device, u->device_list, d); + device_free(d); + } + } + + } else if (dbus_message_is_signal(msg, "org.bluez.Headset", "PropertyChanged") || + dbus_message_is_signal(msg, "org.bluez.AudioSink", "PropertyChanged")) { + + struct device *d; + const char *profile; + DBusMessageIter variant_i; + dbus_bool_t connected; + + if (!dbus_message_iter_init(msg, &arg_i)) { + pa_log("dbus: message has no parameters"); + goto done; + } + + if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_STRING) { + pa_log("Property name not a string."); + goto done; + } + + dbus_message_iter_get_basic(&arg_i, &value); + + if (!pa_streq(value, "Connected")) + goto done; + + if (!dbus_message_iter_next(&arg_i)) { + pa_log("Property value missing"); + goto done; + } + + if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_VARIANT) { + pa_log("Property value not a variant."); + goto done; + } + + dbus_message_iter_recurse(&arg_i, &variant_i); + + if (dbus_message_iter_get_arg_type(&variant_i) != DBUS_TYPE_BOOLEAN) { + pa_log("Property value not a boolean."); + goto done; + } + + dbus_message_iter_get_basic(&variant_i, &connected); + + if (dbus_message_is_signal(msg, "org.bluez.Headset", "PropertyChanged")) + profile = "hsp"; + else + profile = "a2dp"; + + d = device_find(u, dbus_message_get_path(msg)); + + if (connected) { + if (!d) { + d = device_new(dbus_message_get_path(msg)); + PA_LLIST_PREPEND(struct device, u->device_list, d); + } + + load_module_for_device(u, d, profile); + } else if (d) + unload_module_for_device(u, d, profile); + } + +done: + dbus_error_free(&err); + return DBUS_HANDLER_RESULT_HANDLED; +} + +void pa__done(pa_module* m) { + struct userdata *u; + struct device *i; + + pa_assert(m); + + if (!(u = m->userdata)) + return; + + while ((i = u->device_list)) { + PA_LLIST_REMOVE(struct device, u->device_list, i); + device_free(i); + } + + if (u->conn) { + DBusError error; + dbus_error_init(&error); + + dbus_bus_remove_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'", &error); + dbus_error_free(&error); + + dbus_bus_remove_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged'", &error); + dbus_error_free(&error); + + dbus_bus_remove_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'", &error); + dbus_error_free(&error); + + dbus_connection_remove_filter(pa_dbus_connection_get(u->conn), filter_cb, u); + + pa_dbus_connection_unref(u->conn); + } + + pa_xfree(u); +} + +int pa__init(pa_module* m) { + DBusError err; + struct userdata *u; + + pa_assert(m); + dbus_error_init(&err); + + m->userdata = u = pa_xnew(struct userdata, 1); + u->module = m; + PA_LLIST_HEAD_INIT(struct device, u->device_list); + + /* connect to the bus */ + u->conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &err); + if (dbus_error_is_set(&err) || (u->conn == NULL) ) { + pa_log("Failed to get D-Bus connection: %s", err.message); + goto fail; + } + + /* dynamic detection of bluetooth audio devices */ + if (!dbus_connection_add_filter(pa_dbus_connection_get(u->conn), filter_cb, u, NULL)) { + pa_log_error("Failed to add filter function"); + goto fail; + } + + dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'", &err); + if (dbus_error_is_set(&err)) { + pa_log_error("Unable to subscribe to org.bluez.Adapter signals: %s: %s", err.name, err.message); + goto fail; + } + + dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged'", &err); + if (dbus_error_is_set(&err)) { + pa_log_error("Unable to subscribe to org.bluez.Headset signals: %s: %s", err.name, err.message); + goto fail; + } + + dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'", &err); + if (dbus_error_is_set(&err)) { + pa_log_error("Unable to subscribe to org.bluez.AudioSink signals: %s: %s", err.name, err.message); + goto fail; + } + + return 0; + +fail: + dbus_error_free(&err); + pa__done(m); + + return -1; +} diff --git a/src/modules/module-bt-proximity.c b/src/modules/bluetooth/module-bluetooth-proximity.c index f924c3cb..4cfaaf5b 100644 --- a/src/modules/module-bt-proximity.c +++ b/src/modules/bluetooth/module-bluetooth-proximity.c @@ -43,8 +43,8 @@ #include <pulsecore/core-error.h> #include <pulsecore/start-child.h> -#include "dbus-util.h" -#include "module-bt-proximity-symdef.h" +#include "../dbus-util.h" +#include "module-bluetooth-proximity-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering"); PA_MODULE_DESCRIPTION("Bluetooth Proximity Volume Control"); diff --git a/src/modules/bt-proximity-helper.c b/src/modules/bluetooth/proximity-helper.c index 3767f01c..3767f01c 100644 --- a/src/modules/bt-proximity-helper.c +++ b/src/modules/bluetooth/proximity-helper.c diff --git a/src/modules/bluetooth/rtp.h b/src/modules/bluetooth/rtp.h new file mode 100644 index 00000000..690bd43a --- /dev/null +++ b/src/modules/bluetooth/rtp.h @@ -0,0 +1,76 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2008 Marcel Holtmann <marcel@holtmann.org> + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#if __BYTE_ORDER == __LITTLE_ENDIAN + +struct rtp_header { + uint8_t cc:4; + uint8_t x:1; + uint8_t p:1; + uint8_t v:2; + + uint8_t pt:7; + uint8_t m:1; + + uint16_t sequence_number; + uint32_t timestamp; + uint32_t ssrc; + uint32_t csrc[0]; +} __attribute__ ((packed)); + +struct rtp_payload { + uint8_t frame_count:4; + uint8_t rfa0:1; + uint8_t is_last_fragment:1; + uint8_t is_first_fragment:1; + uint8_t is_fragmented:1; +} __attribute__ ((packed)); + +#elif __BYTE_ORDER == __BIG_ENDIAN + +struct rtp_header { + uint8_t v:2; + uint8_t p:1; + uint8_t x:1; + uint8_t cc:4; + + uint8_t m:1; + uint8_t pt:7; + + uint16_t sequence_number; + uint32_t timestamp; + uint32_t ssrc; + uint32_t csrc[0]; +} __attribute__ ((packed)); + +struct rtp_payload { + uint8_t is_fragmented:1; + uint8_t is_first_fragment:1; + uint8_t is_last_fragment:1; + uint8_t rfa0:1; + uint8_t frame_count:4; +} __attribute__ ((packed)); + +#else +#error "Unknown byte order" +#endif diff --git a/src/modules/bluetooth/sbc.c b/src/modules/bluetooth/sbc.c new file mode 100644 index 00000000..02a6143d --- /dev/null +++ b/src/modules/bluetooth/sbc.c @@ -0,0 +1,1411 @@ +/* + * + * Bluetooth low-complexity, subband codec (SBC) library + * + * Copyright (C) 2004-2008 Marcel Holtmann <marcel@holtmann.org> + * Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch> + * Copyright (C) 2005-2008 Brad Midgley <bmidgley@xmission.com> + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* todo items: + + use a log2 table for byte integer scale factors calculation (sum log2 results + for high and low bytes) fill bitpool by 16 bits instead of one at a time in + bits allocation/bitpool generation port to the dsp + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> + +#include "sbc_math.h" +#include "sbc_tables.h" + +#include "sbc.h" + +#define SBC_SYNCWORD 0x9C + +/* This structure contains an unpacked SBC frame. + Yes, there is probably quite some unused space herein */ +struct sbc_frame { + uint8_t frequency; + uint8_t block_mode; + uint8_t blocks; + enum { + MONO = SBC_MODE_MONO, + DUAL_CHANNEL = SBC_MODE_DUAL_CHANNEL, + STEREO = SBC_MODE_STEREO, + JOINT_STEREO = SBC_MODE_JOINT_STEREO + } mode; + uint8_t channels; + enum { + LOUDNESS = SBC_AM_LOUDNESS, + SNR = SBC_AM_SNR + } allocation; + uint8_t subband_mode; + uint8_t subbands; + uint8_t bitpool; + uint8_t codesize; + uint8_t length; + + /* bit number x set means joint stereo has been used in subband x */ + uint8_t joint; + + /* only the lower 4 bits of every element are to be used */ + uint8_t scale_factor[2][8]; + + /* raw integer subband samples in the frame */ + + int32_t sb_sample_f[16][2][8]; + int32_t sb_sample[16][2][8]; /* modified subband samples */ + int16_t pcm_sample[2][16*8]; /* original pcm audio samples */ +}; + +struct sbc_decoder_state { + int subbands; + int32_t V[2][170]; + int offset[2][16]; +}; + +struct sbc_encoder_state { + int subbands; + int position[2]; + int32_t X[2][160]; +}; + +/* + * Calculates the CRC-8 of the first len bits in data + */ +static const uint8_t crc_table[256] = { + 0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53, + 0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB, + 0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E, + 0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76, + 0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4, + 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C, + 0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19, + 0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1, + 0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40, + 0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8, + 0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D, + 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65, + 0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7, + 0x7C, 0x61, 0x46, 0x5B, 0x08, 0x15, 0x32, 0x2F, + 0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A, + 0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2, + 0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75, + 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D, + 0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8, + 0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50, + 0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2, + 0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A, + 0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F, + 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7, + 0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66, + 0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E, + 0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB, + 0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43, + 0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1, + 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09, + 0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C, + 0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4 +}; + +static uint8_t sbc_crc8(const uint8_t *data, size_t len) +{ + uint8_t crc = 0x0f; + size_t i; + uint8_t octet; + + for (i = 0; i < len / 8; i++) + crc = crc_table[crc ^ data[i]]; + + octet = data[i]; + for (i = 0; i < len % 8; i++) { + unsigned char bit = ((octet ^ crc) & 0x80) >> 7; + + crc = ((crc & 0x7f) << 1) ^ (bit ? 0x1d : 0); + + octet = octet << 1; + } + + return crc; +} + +/* + * Code straight from the spec to calculate the bits array + * Takes a pointer to the frame in question, a pointer to the bits array and + * the sampling frequency (as 2 bit integer) + */ +static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8]) +{ + uint8_t sf = frame->frequency; + + if (frame->mode == MONO || frame->mode == DUAL_CHANNEL) { + int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice; + int ch, sb; + + for (ch = 0; ch < frame->channels; ch++) { + max_bitneed = 0; + if (frame->allocation == SNR) { + for (sb = 0; sb < frame->subbands; sb++) { + bitneed[ch][sb] = frame->scale_factor[ch][sb]; + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } + } else { + for (sb = 0; sb < frame->subbands; sb++) { + if (frame->scale_factor[ch][sb] == 0) + bitneed[ch][sb] = -5; + else { + if (frame->subbands == 4) + loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb]; + else + loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb]; + if (loudness > 0) + bitneed[ch][sb] = loudness / 2; + else + bitneed[ch][sb] = loudness; + } + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } + } + + bitcount = 0; + slicecount = 0; + bitslice = max_bitneed + 1; + do { + bitslice--; + bitcount += slicecount; + slicecount = 0; + for (sb = 0; sb < frame->subbands; sb++) { + if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16)) + slicecount++; + else if (bitneed[ch][sb] == bitslice + 1) + slicecount += 2; + } + } while (bitcount + slicecount < frame->bitpool); + + if (bitcount + slicecount == frame->bitpool) { + bitcount += slicecount; + bitslice--; + } + + for (sb = 0; sb < frame->subbands; sb++) { + if (bitneed[ch][sb] < bitslice + 2) + bits[ch][sb] = 0; + else { + bits[ch][sb] = bitneed[ch][sb] - bitslice; + if (bits[ch][sb] > 16) + bits[ch][sb] = 16; + } + } + + for (sb = 0; bitcount < frame->bitpool && sb < frame->subbands; sb++) { + if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) { + bits[ch][sb]++; + bitcount++; + } else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) { + bits[ch][sb] = 2; + bitcount += 2; + } + } + + for (sb = 0; bitcount < frame->bitpool && sb < frame->subbands; sb++) { + if (bits[ch][sb] < 16) { + bits[ch][sb]++; + bitcount++; + } + } + + } + + } else if (frame->mode == STEREO || frame->mode == JOINT_STEREO) { + int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice; + int ch, sb; + + max_bitneed = 0; + if (frame->allocation == SNR) { + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + bitneed[ch][sb] = frame->scale_factor[ch][sb]; + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } + } + } else { + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (frame->scale_factor[ch][sb] == 0) + bitneed[ch][sb] = -5; + else { + if (frame->subbands == 4) + loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb]; + else + loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb]; + if (loudness > 0) + bitneed[ch][sb] = loudness / 2; + else + bitneed[ch][sb] = loudness; + } + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } + } + } + + bitcount = 0; + slicecount = 0; + bitslice = max_bitneed + 1; + do { + bitslice--; + bitcount += slicecount; + slicecount = 0; + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16)) + slicecount++; + else if (bitneed[ch][sb] == bitslice + 1) + slicecount += 2; + } + } + } while (bitcount + slicecount < frame->bitpool); + + if (bitcount + slicecount == frame->bitpool) { + bitcount += slicecount; + bitslice--; + } + + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (bitneed[ch][sb] < bitslice + 2) { + bits[ch][sb] = 0; + } else { + bits[ch][sb] = bitneed[ch][sb] - bitslice; + if (bits[ch][sb] > 16) + bits[ch][sb] = 16; + } + } + } + + ch = 0; + sb = 0; + while (bitcount < frame->bitpool) { + if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) { + bits[ch][sb]++; + bitcount++; + } else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) { + bits[ch][sb] = 2; + bitcount += 2; + } + if (ch == 1) { + ch = 0; + sb++; + if (sb >= frame->subbands) break; + } else + ch = 1; + } + + ch = 0; + sb = 0; + while (bitcount < frame->bitpool) { + if (bits[ch][sb] < 16) { + bits[ch][sb]++; + bitcount++; + } + if (ch == 1) { + ch = 0; + sb++; + if (sb >= frame->subbands) break; + } else + ch = 1; + } + + } + +} + +/* + * Unpacks a SBC frame at the beginning of the stream in data, + * which has at most len bytes into frame. + * Returns the length in bytes of the packed frame, or a negative + * value on error. The error codes are: + * + * -1 Data stream too short + * -2 Sync byte incorrect + * -3 CRC8 incorrect + * -4 Bitpool value out of bounds + */ +static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, + size_t len) +{ + int consumed; + /* Will copy the parts of the header that are relevant to crc + * calculation here */ + uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + int crc_pos = 0; + int32_t temp; + + int audio_sample; + int ch, sb, blk, bit; /* channel, subband, block and bit standard + counters */ + int bits[2][8]; /* bits distribution */ + uint32_t levels[2][8]; /* levels derived from that */ + + if (len < 4) + return -1; + + if (data[0] != SBC_SYNCWORD) + return -2; + + frame->frequency = (data[1] >> 6) & 0x03; + + frame->block_mode = (data[1] >> 4) & 0x03; + switch (frame->block_mode) { + case SBC_BLK_4: + frame->blocks = 4; + break; + case SBC_BLK_8: + frame->blocks = 8; + break; + case SBC_BLK_12: + frame->blocks = 12; + break; + case SBC_BLK_16: + frame->blocks = 16; + break; + } + + frame->mode = (data[1] >> 2) & 0x03; + switch (frame->mode) { + case MONO: + frame->channels = 1; + break; + case DUAL_CHANNEL: /* fall-through */ + case STEREO: + case JOINT_STEREO: + frame->channels = 2; + break; + } + + frame->allocation = (data[1] >> 1) & 0x01; + + frame->subband_mode = (data[1] & 0x01); + frame->subbands = frame->subband_mode ? 8 : 4; + + frame->bitpool = data[2]; + + if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) && + frame->bitpool > 16 * frame->subbands) + return -4; + + if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) && + frame->bitpool > 32 * frame->subbands) + return -4; + + /* data[3] is crc, we're checking it later */ + + consumed = 32; + + crc_header[0] = data[1]; + crc_header[1] = data[2]; + crc_pos = 16; + + if (frame->mode == JOINT_STEREO) { + if (len * 8 < consumed + frame->subbands) + return -1; + + frame->joint = 0x00; + for (sb = 0; sb < frame->subbands - 1; sb++) + frame->joint |= ((data[4] >> (7 - sb)) & 0x01) << sb; + if (frame->subbands == 4) + crc_header[crc_pos / 8] = data[4] & 0xf0; + else + crc_header[crc_pos / 8] = data[4]; + + consumed += frame->subbands; + crc_pos += frame->subbands; + } + + if (len * 8 < consumed + (4 * frame->subbands * frame->channels)) + return -1; + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + /* FIXME assert(consumed % 4 == 0); */ + frame->scale_factor[ch][sb] = + (data[consumed >> 3] >> (4 - (consumed & 0x7))) & 0x0F; + crc_header[crc_pos >> 3] |= + frame->scale_factor[ch][sb] << (4 - (crc_pos & 0x7)); + + consumed += 4; + crc_pos += 4; + } + } + + if (data[3] != sbc_crc8(crc_header, crc_pos)) + return -3; + + sbc_calculate_bits(frame, bits); + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) + levels[ch][sb] = (1 << bits[ch][sb]) - 1; + } + + for (blk = 0; blk < frame->blocks; blk++) { + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (levels[ch][sb] > 0) { + audio_sample = 0; + for (bit = 0; bit < bits[ch][sb]; bit++) { + if (consumed > len * 8) + return -1; + + if ((data[consumed >> 3] >> (7 - (consumed & 0x7))) & 0x01) + audio_sample |= 1 << (bits[ch][sb] - bit - 1); + + consumed++; + } + + frame->sb_sample[blk][ch][sb] = + (((audio_sample << 1) | 1) << frame->scale_factor[ch][sb]) / + levels[ch][sb] - (1 << frame->scale_factor[ch][sb]); + } else + frame->sb_sample[blk][ch][sb] = 0; + } + } + } + + if (frame->mode == JOINT_STEREO) { + for (blk = 0; blk < frame->blocks; blk++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (frame->joint & (0x01 << sb)) { + temp = frame->sb_sample[blk][0][sb] + + frame->sb_sample[blk][1][sb]; + frame->sb_sample[blk][1][sb] = + frame->sb_sample[blk][0][sb] - + frame->sb_sample[blk][1][sb]; + frame->sb_sample[blk][0][sb] = temp; + } + } + } + } + + if ((consumed & 0x7) != 0) + consumed += 8 - (consumed & 0x7); + + return consumed >> 3; +} + +static void sbc_decoder_init(struct sbc_decoder_state *state, + const struct sbc_frame *frame) +{ + int i, ch; + + memset(state->V, 0, sizeof(state->V)); + state->subbands = frame->subbands; + + for (ch = 0; ch < 2; ch++) + for (i = 0; i < frame->subbands * 2; i++) + state->offset[ch][i] = (10 * i + 10); +} + +static inline void sbc_synthesize_four(struct sbc_decoder_state *state, + struct sbc_frame *frame, int ch, int blk) +{ + int i, k, idx; + int32_t *v = state->V[ch]; + int *offset = state->offset[ch]; + + for (i = 0; i < 8; i++) { + /* Shifting */ + offset[i]--; + if (offset[i] < 0) { + offset[i] = 79; + memcpy(v + 80, v, 9 * sizeof(*v)); + } + + /* Distribute the new matrix value to the shifted position */ + v[offset[i]] = SCALE4_STAGED1( + MULA(synmatrix4[i][0], frame->sb_sample[blk][ch][0], + MULA(synmatrix4[i][1], frame->sb_sample[blk][ch][1], + MULA(synmatrix4[i][2], frame->sb_sample[blk][ch][2], + MUL (synmatrix4[i][3], frame->sb_sample[blk][ch][3]))))); + } + + /* Compute the samples */ + for (idx = 0, i = 0; i < 4; i++, idx += 5) { + k = (i + 4) & 0xf; + + /* Store in output, Q0 */ + frame->pcm_sample[ch][blk * 4 + i] = SCALE4_STAGED2( + MULA(v[offset[i] + 0], sbc_proto_4_40m0[idx + 0], + MULA(v[offset[k] + 1], sbc_proto_4_40m1[idx + 0], + MULA(v[offset[i] + 2], sbc_proto_4_40m0[idx + 1], + MULA(v[offset[k] + 3], sbc_proto_4_40m1[idx + 1], + MULA(v[offset[i] + 4], sbc_proto_4_40m0[idx + 2], + MULA(v[offset[k] + 5], sbc_proto_4_40m1[idx + 2], + MULA(v[offset[i] + 6], sbc_proto_4_40m0[idx + 3], + MULA(v[offset[k] + 7], sbc_proto_4_40m1[idx + 3], + MULA(v[offset[i] + 8], sbc_proto_4_40m0[idx + 4], + MUL( v[offset[k] + 9], sbc_proto_4_40m1[idx + 4]))))))))))); + } +} + +static inline void sbc_synthesize_eight(struct sbc_decoder_state *state, + struct sbc_frame *frame, int ch, int blk) +{ + int i, j, k, idx; + int *offset = state->offset[ch]; + + for (i = 0; i < 16; i++) { + /* Shifting */ + offset[i]--; + if (offset[i] < 0) { + offset[i] = 159; + for (j = 0; j < 9; j++) + state->V[ch][j + 160] = state->V[ch][j]; + } + + /* Distribute the new matrix value to the shifted position */ + state->V[ch][offset[i]] = SCALE8_STAGED1( + MULA(synmatrix8[i][0], frame->sb_sample[blk][ch][0], + MULA(synmatrix8[i][1], frame->sb_sample[blk][ch][1], + MULA(synmatrix8[i][2], frame->sb_sample[blk][ch][2], + MULA(synmatrix8[i][3], frame->sb_sample[blk][ch][3], + MULA(synmatrix8[i][4], frame->sb_sample[blk][ch][4], + MULA(synmatrix8[i][5], frame->sb_sample[blk][ch][5], + MULA(synmatrix8[i][6], frame->sb_sample[blk][ch][6], + MUL( synmatrix8[i][7], frame->sb_sample[blk][ch][7]))))))))); + } + + /* Compute the samples */ + for (idx = 0, i = 0; i < 8; i++, idx += 5) { + k = (i + 8) & 0xf; + + /* Store in output */ + frame->pcm_sample[ch][blk * 8 + i] = SCALE8_STAGED2( // Q0 + MULA(state->V[ch][offset[i] + 0], sbc_proto_8_80m0[idx + 0], + MULA(state->V[ch][offset[k] + 1], sbc_proto_8_80m1[idx + 0], + MULA(state->V[ch][offset[i] + 2], sbc_proto_8_80m0[idx + 1], + MULA(state->V[ch][offset[k] + 3], sbc_proto_8_80m1[idx + 1], + MULA(state->V[ch][offset[i] + 4], sbc_proto_8_80m0[idx + 2], + MULA(state->V[ch][offset[k] + 5], sbc_proto_8_80m1[idx + 2], + MULA(state->V[ch][offset[i] + 6], sbc_proto_8_80m0[idx + 3], + MULA(state->V[ch][offset[k] + 7], sbc_proto_8_80m1[idx + 3], + MULA(state->V[ch][offset[i] + 8], sbc_proto_8_80m0[idx + 4], + MUL( state->V[ch][offset[k] + 9], sbc_proto_8_80m1[idx + 4]))))))))))); + } +} + +static int sbc_synthesize_audio(struct sbc_decoder_state *state, + struct sbc_frame *frame) +{ + int ch, blk; + + switch (frame->subbands) { + case 4: + for (ch = 0; ch < frame->channels; ch++) { + for (blk = 0; blk < frame->blocks; blk++) + sbc_synthesize_four(state, frame, ch, blk); + } + return frame->blocks * 4; + + case 8: + for (ch = 0; ch < frame->channels; ch++) { + for (blk = 0; blk < frame->blocks; blk++) + sbc_synthesize_eight(state, frame, ch, blk); + } + return frame->blocks * 8; + + default: + return -EIO; + } +} + +static void sbc_encoder_init(struct sbc_encoder_state *state, + const struct sbc_frame *frame) +{ + memset(&state->X, 0, sizeof(state->X)); + state->subbands = frame->subbands; + state->position[0] = state->position[1] = 9 * frame->subbands; +} + +static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) +{ + sbc_fixed_t t[8], s[5]; + + t[0] = SCALE4_STAGE1( /* Q8 */ + MULA(_sbc_proto_4[0], in[8] - in[32], /* Q18 */ + MUL( _sbc_proto_4[1], in[16] - in[24]))); + + t[1] = SCALE4_STAGE1( + MULA(_sbc_proto_4[2], in[1], + MULA(_sbc_proto_4[3], in[9], + MULA(_sbc_proto_4[4], in[17], + MULA(_sbc_proto_4[5], in[25], + MUL( _sbc_proto_4[6], in[33])))))); + + t[2] = SCALE4_STAGE1( + MULA(_sbc_proto_4[7], in[2], + MULA(_sbc_proto_4[8], in[10], + MULA(_sbc_proto_4[9], in[18], + MULA(_sbc_proto_4[10], in[26], + MUL( _sbc_proto_4[11], in[34])))))); + + t[3] = SCALE4_STAGE1( + MULA(_sbc_proto_4[12], in[3], + MULA(_sbc_proto_4[13], in[11], + MULA(_sbc_proto_4[14], in[19], + MULA(_sbc_proto_4[15], in[27], + MUL( _sbc_proto_4[16], in[35])))))); + + t[4] = SCALE4_STAGE1( + MULA(_sbc_proto_4[17], in[4] + in[36], + MULA(_sbc_proto_4[18], in[12] + in[28], + MUL( _sbc_proto_4[19], in[20])))); + + t[5] = SCALE4_STAGE1( + MULA(_sbc_proto_4[16], in[5], + MULA(_sbc_proto_4[15], in[13], + MULA(_sbc_proto_4[14], in[21], + MULA(_sbc_proto_4[13], in[29], + MUL( _sbc_proto_4[12], in[37])))))); + + /* don't compute t[6]... this term always multiplies + * with cos(pi/2) = 0 */ + + t[7] = SCALE4_STAGE1( + MULA(_sbc_proto_4[6], in[7], + MULA(_sbc_proto_4[5], in[15], + MULA(_sbc_proto_4[4], in[23], + MULA(_sbc_proto_4[3], in[31], + MUL( _sbc_proto_4[2], in[39])))))); + + s[0] = MUL( _anamatrix4[0], t[0] + t[4]); + s[1] = MUL( _anamatrix4[2], t[2]); + s[2] = MULA(_anamatrix4[1], t[1] + t[3], + MUL(_anamatrix4[3], t[5])); + s[3] = MULA(_anamatrix4[3], t[1] + t[3], + MUL(_anamatrix4[1], -t[5] + t[7])); + s[4] = MUL( _anamatrix4[3], t[7]); + + out[0] = SCALE4_STAGE2( s[0] + s[1] + s[2] + s[4]); /* Q0 */ + out[1] = SCALE4_STAGE2(-s[0] + s[1] + s[3]); + out[2] = SCALE4_STAGE2(-s[0] + s[1] - s[3]); + out[3] = SCALE4_STAGE2( s[0] + s[1] - s[2] - s[4]); +} + +static inline void sbc_analyze_four(struct sbc_encoder_state *state, + struct sbc_frame *frame, int ch, int blk) +{ + int32_t *x = &state->X[ch][state->position[ch]]; + int16_t *pcm = &frame->pcm_sample[ch][blk * 4]; + + /* Input 4 Audio Samples */ + x[40] = x[0] = pcm[3]; + x[41] = x[1] = pcm[2]; + x[42] = x[2] = pcm[1]; + x[43] = x[3] = pcm[0]; + + _sbc_analyze_four(x, frame->sb_sample_f[blk][ch]); + + state->position[ch] -= 4; + if (state->position[ch] < 0) + state->position[ch] = 36; +} + +static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) +{ + sbc_fixed_t t[8], s[8]; + + t[0] = SCALE8_STAGE1( /* Q10 */ + MULA(_sbc_proto_8[0], (in[16] - in[64]), /* Q18 = Q18 * Q0 */ + MULA(_sbc_proto_8[1], (in[32] - in[48]), + MULA(_sbc_proto_8[2], in[4], + MULA(_sbc_proto_8[3], in[20], + MULA(_sbc_proto_8[4], in[36], + MUL( _sbc_proto_8[5], in[52]))))))); + + t[1] = SCALE8_STAGE1( + MULA(_sbc_proto_8[6], in[2], + MULA(_sbc_proto_8[7], in[18], + MULA(_sbc_proto_8[8], in[34], + MULA(_sbc_proto_8[9], in[50], + MUL(_sbc_proto_8[10], in[66])))))); + + t[2] = SCALE8_STAGE1( + MULA(_sbc_proto_8[11], in[1], + MULA(_sbc_proto_8[12], in[17], + MULA(_sbc_proto_8[13], in[33], + MULA(_sbc_proto_8[14], in[49], + MULA(_sbc_proto_8[15], in[65], + MULA(_sbc_proto_8[16], in[3], + MULA(_sbc_proto_8[17], in[19], + MULA(_sbc_proto_8[18], in[35], + MULA(_sbc_proto_8[19], in[51], + MUL( _sbc_proto_8[20], in[67]))))))))))); + + t[3] = SCALE8_STAGE1( + MULA( _sbc_proto_8[21], in[5], + MULA( _sbc_proto_8[22], in[21], + MULA( _sbc_proto_8[23], in[37], + MULA( _sbc_proto_8[24], in[53], + MULA( _sbc_proto_8[25], in[69], + MULA(-_sbc_proto_8[15], in[15], + MULA(-_sbc_proto_8[14], in[31], + MULA(-_sbc_proto_8[13], in[47], + MULA(-_sbc_proto_8[12], in[63], + MUL( -_sbc_proto_8[11], in[79]))))))))))); + + t[4] = SCALE8_STAGE1( + MULA( _sbc_proto_8[26], in[6], + MULA( _sbc_proto_8[27], in[22], + MULA( _sbc_proto_8[28], in[38], + MULA( _sbc_proto_8[29], in[54], + MULA( _sbc_proto_8[30], in[70], + MULA(-_sbc_proto_8[10], in[14], + MULA(-_sbc_proto_8[9], in[30], + MULA(-_sbc_proto_8[8], in[46], + MULA(-_sbc_proto_8[7], in[62], + MUL( -_sbc_proto_8[6], in[78]))))))))))); + + t[5] = SCALE8_STAGE1( + MULA( _sbc_proto_8[31], in[7], + MULA( _sbc_proto_8[32], in[23], + MULA( _sbc_proto_8[33], in[39], + MULA( _sbc_proto_8[34], in[55], + MULA( _sbc_proto_8[35], in[71], + MULA(-_sbc_proto_8[20], in[13], + MULA(-_sbc_proto_8[19], in[29], + MULA(-_sbc_proto_8[18], in[45], + MULA(-_sbc_proto_8[17], in[61], + MUL( -_sbc_proto_8[16], in[77]))))))))))); + + t[6] = SCALE8_STAGE1( + MULA( _sbc_proto_8[36], (in[8] + in[72]), + MULA( _sbc_proto_8[37], (in[24] + in[56]), + MULA( _sbc_proto_8[38], in[40], + MULA(-_sbc_proto_8[39], in[12], + MULA(-_sbc_proto_8[5], in[28], + MULA(-_sbc_proto_8[4], in[44], + MULA(-_sbc_proto_8[3], in[60], + MUL( -_sbc_proto_8[2], in[76]))))))))); + + t[7] = SCALE8_STAGE1( + MULA( _sbc_proto_8[35], in[9], + MULA( _sbc_proto_8[34], in[25], + MULA( _sbc_proto_8[33], in[41], + MULA( _sbc_proto_8[32], in[57], + MULA( _sbc_proto_8[31], in[73], + MULA(-_sbc_proto_8[25], in[11], + MULA(-_sbc_proto_8[24], in[27], + MULA(-_sbc_proto_8[23], in[43], + MULA(-_sbc_proto_8[22], in[59], + MUL( -_sbc_proto_8[21], in[75]))))))))))); + + s[0] = MULA( _anamatrix8[0], t[0], + MUL( _anamatrix8[1], t[6])); + s[1] = MUL( _anamatrix8[7], t[1]); + s[2] = MULA( _anamatrix8[2], t[2], + MULA( _anamatrix8[3], t[3], + MULA( _anamatrix8[4], t[5], + MUL( _anamatrix8[5], t[7])))); + s[3] = MUL( _anamatrix8[6], t[4]); + s[4] = MULA( _anamatrix8[3], t[2], + MULA(-_anamatrix8[5], t[3], + MULA(-_anamatrix8[2], t[5], + MUL( -_anamatrix8[4], t[7])))); + s[5] = MULA( _anamatrix8[4], t[2], + MULA(-_anamatrix8[2], t[3], + MULA( _anamatrix8[5], t[5], + MUL( _anamatrix8[3], t[7])))); + s[6] = MULA( _anamatrix8[1], t[0], + MUL( -_anamatrix8[0], t[6])); + s[7] = MULA( _anamatrix8[5], t[2], + MULA(-_anamatrix8[4], t[3], + MULA( _anamatrix8[3], t[5], + MUL( -_anamatrix8[2], t[7])))); + + out[0] = SCALE8_STAGE2( s[0] + s[1] + s[2] + s[3]); + out[1] = SCALE8_STAGE2( s[1] - s[3] + s[4] + s[6]); + out[2] = SCALE8_STAGE2( s[1] - s[3] + s[5] - s[6]); + out[3] = SCALE8_STAGE2(-s[0] + s[1] + s[3] + s[7]); + out[4] = SCALE8_STAGE2(-s[0] + s[1] + s[3] - s[7]); + out[5] = SCALE8_STAGE2( s[1] - s[3] - s[5] - s[6]); + out[6] = SCALE8_STAGE2( s[1] - s[3] - s[4] + s[6]); + out[7] = SCALE8_STAGE2( s[0] + s[1] - s[2] + s[3]); +} + +static inline void sbc_analyze_eight(struct sbc_encoder_state *state, + struct sbc_frame *frame, int ch, + int blk) +{ + int32_t *x = &state->X[ch][state->position[ch]]; + int16_t *pcm = &frame->pcm_sample[ch][blk * 8]; + + /* Input 8 Audio Samples */ + x[80] = x[0] = pcm[7]; + x[81] = x[1] = pcm[6]; + x[82] = x[2] = pcm[5]; + x[83] = x[3] = pcm[4]; + x[84] = x[4] = pcm[3]; + x[85] = x[5] = pcm[2]; + x[86] = x[6] = pcm[1]; + x[87] = x[7] = pcm[0]; + + _sbc_analyze_eight(x, frame->sb_sample_f[blk][ch]); + + state->position[ch] -= 8; + if (state->position[ch] < 0) + state->position[ch] = 72; +} + +static int sbc_analyze_audio(struct sbc_encoder_state *state, + struct sbc_frame *frame) +{ + int ch, blk; + + switch (frame->subbands) { + case 4: + for (ch = 0; ch < frame->channels; ch++) + for (blk = 0; blk < frame->blocks; blk++) + sbc_analyze_four(state, frame, ch, blk); + return frame->blocks * 4; + + case 8: + for (ch = 0; ch < frame->channels; ch++) + for (blk = 0; blk < frame->blocks; blk++) + sbc_analyze_eight(state, frame, ch, blk); + return frame->blocks * 8; + + default: + return -EIO; + } +} + +/* + * Packs the SBC frame from frame into the memory at data. At most len + * bytes will be used, should more memory be needed an appropriate + * error code will be returned. Returns the length of the packed frame + * on success or a negative value on error. + * + * The error codes are: + * -1 Not enough memory reserved + * -2 Unsupported sampling rate + * -3 Unsupported number of blocks + * -4 Unsupported number of subbands + * -5 Bitpool value out of bounds + * -99 not implemented + */ + +static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) +{ + int produced; + /* Will copy the header parts for CRC-8 calculation here */ + uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + int crc_pos = 0; + + uint16_t audio_sample; + + int ch, sb, blk, bit; /* channel, subband, block and bit counters */ + int bits[2][8]; /* bits distribution */ + int levels[2][8]; /* levels are derived from that */ + + u_int32_t scalefactor[2][8]; /* derived from frame->scale_factor */ + + data[0] = SBC_SYNCWORD; + + data[1] = (frame->frequency & 0x03) << 6; + + data[1] |= (frame->block_mode & 0x03) << 4; + + data[1] |= (frame->mode & 0x03) << 2; + + data[1] |= (frame->allocation & 0x01) << 1; + + switch (frame->subbands) { + case 4: + /* Nothing to do */ + break; + case 8: + data[1] |= 0x01; + break; + default: + return -4; + break; + } + + data[2] = frame->bitpool; + + if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) && + frame->bitpool > frame->subbands << 4) + return -5; + + if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) && + frame->bitpool > frame->subbands << 5) + return -5; + + /* Can't fill in crc yet */ + + produced = 32; + + crc_header[0] = data[1]; + crc_header[1] = data[2]; + crc_pos = 16; + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + frame->scale_factor[ch][sb] = 0; + scalefactor[ch][sb] = 2; + for (blk = 0; blk < frame->blocks; blk++) { + while (scalefactor[ch][sb] < fabs(frame->sb_sample_f[blk][ch][sb])) { + frame->scale_factor[ch][sb]++; + scalefactor[ch][sb] *= 2; + } + } + } + } + + if (frame->mode == JOINT_STEREO) { + /* like frame->sb_sample but joint stereo */ + int32_t sb_sample_j[16][2]; + /* scalefactor and scale_factor in joint case */ + u_int32_t scalefactor_j[2]; + uint8_t scale_factor_j[2]; + + frame->joint = 0; + + for (sb = 0; sb < frame->subbands - 1; sb++) { + scale_factor_j[0] = 0; + scalefactor_j[0] = 2; + scale_factor_j[1] = 0; + scalefactor_j[1] = 2; + + for (blk = 0; blk < frame->blocks; blk++) { + /* Calculate joint stereo signal */ + sb_sample_j[blk][0] = + (frame->sb_sample_f[blk][0][sb] + + frame->sb_sample_f[blk][1][sb]) >> 1; + sb_sample_j[blk][1] = + (frame->sb_sample_f[blk][0][sb] - + frame->sb_sample_f[blk][1][sb]) >> 1; + + /* calculate scale_factor_j and scalefactor_j for joint case */ + while (scalefactor_j[0] < fabs(sb_sample_j[blk][0])) { + scale_factor_j[0]++; + scalefactor_j[0] *= 2; + } + while (scalefactor_j[1] < fabs(sb_sample_j[blk][1])) { + scale_factor_j[1]++; + scalefactor_j[1] *= 2; + } + } + + /* decide whether to join this subband */ + if ((scalefactor[0][sb] + scalefactor[1][sb]) > + (scalefactor_j[0] + scalefactor_j[1]) ) { + /* use joint stereo for this subband */ + frame->joint |= 1 << sb; + frame->scale_factor[0][sb] = scale_factor_j[0]; + frame->scale_factor[1][sb] = scale_factor_j[1]; + scalefactor[0][sb] = scalefactor_j[0]; + scalefactor[1][sb] = scalefactor_j[1]; + for (blk = 0; blk < frame->blocks; blk++) { + frame->sb_sample_f[blk][0][sb] = + sb_sample_j[blk][0]; + frame->sb_sample_f[blk][1][sb] = + sb_sample_j[blk][1]; + } + } + } + + data[4] = 0; + for (sb = 0; sb < frame->subbands - 1; sb++) + data[4] |= ((frame->joint >> sb) & 0x01) << (frame->subbands - 1 - sb); + + crc_header[crc_pos >> 3] = data[4]; + + produced += frame->subbands; + crc_pos += frame->subbands; + } + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + data[produced >> 3] <<= 4; + crc_header[crc_pos >> 3] <<= 4; + data[produced >> 3] |= frame->scale_factor[ch][sb] & 0x0F; + crc_header[crc_pos >> 3] |= frame->scale_factor[ch][sb] & 0x0F; + + produced += 4; + crc_pos += 4; + } + } + + /* align the last crc byte */ + if (crc_pos % 8) + crc_header[crc_pos >> 3] <<= 8 - (crc_pos % 8); + + data[3] = sbc_crc8(crc_header, crc_pos); + + sbc_calculate_bits(frame, bits); + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) + levels[ch][sb] = (1 << bits[ch][sb]) - 1; + } + + for (blk = 0; blk < frame->blocks; blk++) { + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (levels[ch][sb] > 0) { + audio_sample = + (uint16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >> + (frame->scale_factor[ch][sb] + 1)) + + levels[ch][sb]) >> 1); + audio_sample <<= 16 - bits[ch][sb]; + for (bit = 0; bit < bits[ch][sb]; bit++) { + data[produced >> 3] <<= 1; + if (audio_sample & 0x8000) + data[produced >> 3] |= 0x1; + audio_sample <<= 1; + produced++; + } + } + } + } + } + + /* align the last byte */ + if (produced % 8) { + data[produced >> 3] <<= 8 - (produced % 8); + } + + return (produced + 7) >> 3; +} + +struct sbc_priv { + int init; + struct sbc_frame frame; + struct sbc_decoder_state dec_state; + struct sbc_encoder_state enc_state; +}; + +static void sbc_set_defaults(sbc_t *sbc, unsigned long flags) +{ + sbc->frequency = SBC_FREQ_44100; + sbc->mode = SBC_MODE_STEREO; + sbc->subbands = SBC_SB_8; + sbc->blocks = SBC_BLK_16; + sbc->bitpool = 32; +#if __BYTE_ORDER == __LITTLE_ENDIAN + sbc->endian = SBC_LE; +#elif __BYTE_ORDER == __BIG_ENDIAN + sbc->endian = SBC_BE; +#else +#error "Unknown byte order" +#endif +} + +int sbc_init(sbc_t *sbc, unsigned long flags) +{ + if (!sbc) + return -EIO; + + memset(sbc, 0, sizeof(sbc_t)); + + sbc->priv = malloc(sizeof(struct sbc_priv)); + if (!sbc->priv) + return -ENOMEM; + + memset(sbc->priv, 0, sizeof(struct sbc_priv)); + + sbc_set_defaults(sbc, flags); + + return 0; +} + +int sbc_parse(sbc_t *sbc, void *input, int input_len) +{ + return sbc_decode(sbc, input, input_len, NULL, 0, NULL); +} + +int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *written) +{ + struct sbc_priv *priv; + char *ptr; + int i, ch, framelen, samples; + + if (!sbc && !input) + return -EIO; + + priv = sbc->priv; + + framelen = sbc_unpack_frame(input, &priv->frame, input_len); + + if (!priv->init) { + sbc_decoder_init(&priv->dec_state, &priv->frame); + priv->init = 1; + + sbc->frequency = priv->frame.frequency; + sbc->mode = priv->frame.mode; + sbc->subbands = priv->frame.subband_mode; + sbc->blocks = priv->frame.block_mode; + sbc->allocation = priv->frame.allocation; + sbc->bitpool = priv->frame.bitpool; + + priv->frame.codesize = sbc_get_codesize(sbc); + priv->frame.length = sbc_get_frame_length(sbc); + } + + if (!output) + return framelen; + + if (written) + *written = 0; + + samples = sbc_synthesize_audio(&priv->dec_state, &priv->frame); + + ptr = output; + + if (output_len < samples * priv->frame.channels * 2) + samples = output_len / (priv->frame.channels * 2); + + for (i = 0; i < samples; i++) { + for (ch = 0; ch < priv->frame.channels; ch++) { + int16_t s; + s = priv->frame.pcm_sample[ch][i]; + +#if __BYTE_ORDER == __LITTLE_ENDIAN + if (sbc->endian == SBC_BE) { +#elif __BYTE_ORDER == __BIG_ENDIAN + if (sbc->endian == SBC_LE) { +#else +#error "Unknown byte order" +#endif + *ptr++ = (s & 0xff00) >> 8; + *ptr++ = (s & 0x00ff); + } else { + *ptr++ = (s & 0x00ff); + *ptr++ = (s & 0xff00) >> 8; + } + } + } + + if (written) + *written = samples * priv->frame.channels * 2; + + return framelen; +} + +int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *written) +{ + struct sbc_priv *priv; + char *ptr; + int i, ch, framelen, samples; + + if (!sbc && !input) + return -EIO; + + priv = sbc->priv; + + if (written) + *written = 0; + + if (!priv->init) { + priv->frame.frequency = sbc->frequency; + priv->frame.mode = sbc->mode; + priv->frame.channels = sbc->mode == SBC_MODE_MONO ? 1 : 2; + priv->frame.allocation = sbc->allocation; + priv->frame.subband_mode = sbc->subbands; + priv->frame.subbands = sbc->subbands ? 8 : 4; + priv->frame.block_mode = sbc->blocks; + priv->frame.blocks = 4 + (sbc->blocks * 4); + priv->frame.bitpool = sbc->bitpool; + priv->frame.codesize = sbc_get_codesize(sbc); + priv->frame.length = sbc_get_frame_length(sbc); + + sbc_encoder_init(&priv->enc_state, &priv->frame); + priv->init = 1; + } + + /* input must be large enough to encode a complete frame */ + if (input_len < priv->frame.codesize) + return 0; + + /* output must be large enough to receive the encoded frame */ + if (!output || output_len < priv->frame.length) + return -ENOSPC; + + ptr = input; + + for (i = 0; i < priv->frame.subbands * priv->frame.blocks; i++) { + for (ch = 0; ch < priv->frame.channels; ch++) { + int16_t s; +#if __BYTE_ORDER == __LITTLE_ENDIAN + if (sbc->endian == SBC_BE) +#elif __BYTE_ORDER == __BIG_ENDIAN + if (sbc->endian == SBC_LE) +#else +#error "Unknown byte order" +#endif + s = (ptr[0] & 0xff) << 8 | (ptr[1] & 0xff); + else + s = (ptr[0] & 0xff) | (ptr[1] & 0xff) << 8; + ptr += 2; + priv->frame.pcm_sample[ch][i] = s; + } + } + + samples = sbc_analyze_audio(&priv->enc_state, &priv->frame); + + framelen = sbc_pack_frame(output, &priv->frame, output_len); + + if (written) + *written = framelen; + + return samples * priv->frame.channels * 2; +} + +void sbc_finish(sbc_t *sbc) +{ + if (!sbc) + return; + + if (sbc->priv) + free(sbc->priv); + + memset(sbc, 0, sizeof(sbc_t)); +} + +int sbc_get_frame_length(sbc_t *sbc) +{ + int ret; + uint8_t subbands, channels, blocks, joint; + struct sbc_priv *priv; + + priv = sbc->priv; + if (!priv->init) { + subbands = sbc->subbands ? 8 : 4; + blocks = 4 + (sbc->blocks * 4); + channels = sbc->mode == SBC_MODE_MONO ? 1 : 2; + joint = sbc->mode == SBC_MODE_JOINT_STEREO ? 1 : 0; + } else { + subbands = priv->frame.subbands; + blocks = priv->frame.blocks; + channels = priv->frame.channels; + joint = priv->frame.joint; + } + + ret = 4 + (4 * subbands * channels) / 8; + + /* This term is not always evenly divide so we round it up */ + if (channels == 1) + ret += ((blocks * channels * sbc->bitpool) + 7) / 8; + else + ret += (((joint ? subbands : 0) + blocks * sbc->bitpool) + 7) + / 8; + + return ret; +} + +int sbc_get_frame_duration(sbc_t *sbc) +{ + uint8_t subbands, blocks; + uint16_t frequency; + struct sbc_priv *priv; + + priv = sbc->priv; + if (!priv->init) { + subbands = sbc->subbands ? 8 : 4; + blocks = 4 + (sbc->blocks * 4); + } else { + subbands = priv->frame.subbands; + blocks = priv->frame.blocks; + } + + switch (sbc->frequency) { + case SBC_FREQ_16000: + frequency = 16000; + break; + + case SBC_FREQ_32000: + frequency = 32000; + break; + + case SBC_FREQ_44100: + frequency = 44100; + break; + + case SBC_FREQ_48000: + frequency = 48000; + break; + default: + return 0; + } + + return (1000000 * blocks * subbands) / frequency; +} + +int sbc_get_codesize(sbc_t *sbc) +{ + uint8_t subbands, channels, blocks; + struct sbc_priv *priv; + + priv = sbc->priv; + if (!priv->init) { + subbands = sbc->subbands ? 8 : 4; + blocks = 4 + (sbc->blocks * 4); + channels = sbc->mode == SBC_MODE_MONO ? 1 : 2; + } else { + subbands = priv->frame.subbands; + blocks = priv->frame.blocks; + channels = priv->frame.channels; + } + + return subbands * blocks * channels * 2; +} + +int sbc_reinit(sbc_t *sbc, unsigned long flags) +{ + struct sbc_priv *priv; + + if (!sbc || !sbc->priv) + return -EIO; + + priv = sbc->priv; + + if (priv->init == 1) + memset(sbc->priv, 0, sizeof(struct sbc_priv)); + + sbc_set_defaults(sbc, flags); + + return 0; +} diff --git a/src/modules/bluetooth/sbc.h b/src/modules/bluetooth/sbc.h new file mode 100644 index 00000000..ab47e329 --- /dev/null +++ b/src/modules/bluetooth/sbc.h @@ -0,0 +1,97 @@ +/* + * + * Bluetooth low-complexity, subband codec (SBC) library + * + * Copyright (C) 2004-2008 Marcel Holtmann <marcel@holtmann.org> + * Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch> + * Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com> + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __SBC_H +#define __SBC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +/* sampling frequency */ +#define SBC_FREQ_16000 0x00 +#define SBC_FREQ_32000 0x01 +#define SBC_FREQ_44100 0x02 +#define SBC_FREQ_48000 0x03 + +/* blocks */ +#define SBC_BLK_4 0x00 +#define SBC_BLK_8 0x01 +#define SBC_BLK_12 0x02 +#define SBC_BLK_16 0x03 + +/* channel mode */ +#define SBC_MODE_MONO 0x00 +#define SBC_MODE_DUAL_CHANNEL 0x01 +#define SBC_MODE_STEREO 0x02 +#define SBC_MODE_JOINT_STEREO 0x03 + +/* allocation method */ +#define SBC_AM_LOUDNESS 0x00 +#define SBC_AM_SNR 0x01 + +/* subbands */ +#define SBC_SB_4 0x00 +#define SBC_SB_8 0x01 + +/* Data endianess */ +#define SBC_LE 0x00 +#define SBC_BE 0x01 + +struct sbc_struct { + unsigned long flags; + + uint8_t frequency; + uint8_t blocks; + uint8_t subbands; + uint8_t mode; + uint8_t allocation; + uint8_t bitpool; + uint8_t endian; + + void *priv; +}; + +typedef struct sbc_struct sbc_t; + +int sbc_init(sbc_t *sbc, unsigned long flags); +int sbc_reinit(sbc_t *sbc, unsigned long flags); +int sbc_parse(sbc_t *sbc, void *input, int input_len); +int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *len); +int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *written); +int sbc_get_frame_length(sbc_t *sbc); +int sbc_get_frame_duration(sbc_t *sbc); +int sbc_get_codesize(sbc_t *sbc); +void sbc_finish(sbc_t *sbc); + +#ifdef __cplusplus +} +#endif + +#endif /* __SBC_H */ diff --git a/src/modules/bluetooth/sbc_math.h b/src/modules/bluetooth/sbc_math.h new file mode 100644 index 00000000..b3d87a62 --- /dev/null +++ b/src/modules/bluetooth/sbc_math.h @@ -0,0 +1,72 @@ +/* + * + * Bluetooth low-complexity, subband codec (SBC) library + * + * Copyright (C) 2004-2008 Marcel Holtmann <marcel@holtmann.org> + * Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch> + * Copyright (C) 2005-2008 Brad Midgley <bmidgley@xmission.com> + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#define fabs(x) ((x) < 0 ? -(x) : (x)) +/* C does not provide an explicit arithmetic shift right but this will + always be correct and every compiler *should* generate optimal code */ +#define ASR(val, bits) ((-2 >> 1 == -1) ? \ + ((int32_t)(val)) >> (bits) : ((int32_t) (val)) / (1 << (bits))) + +#define SCALE_PROTO4_TBL 15 +#define SCALE_ANA4_TBL 17 +#define SCALE_PROTO8_TBL 16 +#define SCALE_ANA8_TBL 17 +#define SCALE_SPROTO4_TBL 12 +#define SCALE_SPROTO8_TBL 14 +#define SCALE_NPROTO4_TBL 11 +#define SCALE_NPROTO8_TBL 11 +#define SCALE4_STAGE1_BITS 15 +#define SCALE4_STAGE2_BITS 16 +#define SCALE4_STAGED1_BITS 15 +#define SCALE4_STAGED2_BITS 16 +#define SCALE8_STAGE1_BITS 15 +#define SCALE8_STAGE2_BITS 15 +#define SCALE8_STAGED1_BITS 15 +#define SCALE8_STAGED2_BITS 16 + +typedef int32_t sbc_fixed_t; + +#define SCALE4_STAGE1(src) ASR(src, SCALE4_STAGE1_BITS) +#define SCALE4_STAGE2(src) ASR(src, SCALE4_STAGE2_BITS) +#define SCALE4_STAGED1(src) ASR(src, SCALE4_STAGED1_BITS) +#define SCALE4_STAGED2(src) ASR(src, SCALE4_STAGED2_BITS) +#define SCALE8_STAGE1(src) ASR(src, SCALE8_STAGE1_BITS) +#define SCALE8_STAGE2(src) ASR(src, SCALE8_STAGE2_BITS) +#define SCALE8_STAGED1(src) ASR(src, SCALE8_STAGED1_BITS) +#define SCALE8_STAGED2(src) ASR(src, SCALE8_STAGED2_BITS) + +#define SBC_FIXED_0(val) { val = 0; } +#define MUL(a, b) ((a) * (b)) +#ifdef __arm__ +#define MULA(a, b, res) ({ \ + int tmp = res; \ + __asm__( \ + "mla %0, %2, %3, %0" \ + : "=&r" (tmp) \ + : "0" (tmp), "r" (a), "r" (b)); \ + tmp; }) +#else +#define MULA(a, b, res) ((a) * (b) + (res)) +#endif diff --git a/src/modules/bluetooth/sbc_tables.h b/src/modules/bluetooth/sbc_tables.h new file mode 100644 index 00000000..7ac4e68b --- /dev/null +++ b/src/modules/bluetooth/sbc_tables.h @@ -0,0 +1,167 @@ +/* + * + * Bluetooth low-complexity, subband codec (SBC) library + * + * Copyright (C) 2004-2008 Marcel Holtmann <marcel@holtmann.org> + * Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch> + * Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com> + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* A2DP specification: Appendix B, page 69 */ +static const int sbc_offset4[4][4] = { + { -1, 0, 0, 0 }, + { -2, 0, 0, 1 }, + { -2, 0, 0, 1 }, + { -2, 0, 0, 1 } +}; + +/* A2DP specification: Appendix B, page 69 */ +static const int sbc_offset8[4][8] = { + { -2, 0, 0, 0, 0, 0, 0, 1 }, + { -3, 0, 0, 0, 0, 0, 1, 2 }, + { -4, 0, 0, 0, 0, 0, 1, 2 }, + { -4, 0, 0, 0, 0, 0, 1, 2 } +}; + +#define SP4(val) ASR(val, SCALE_PROTO4_TBL) +#define SA4(val) ASR(val, SCALE_ANA4_TBL) +#define SP8(val) ASR(val, SCALE_PROTO8_TBL) +#define SA8(val) ASR(val, SCALE_ANA8_TBL) +#define SS4(val) ASR(val, SCALE_SPROTO4_TBL) +#define SS8(val) ASR(val, SCALE_SPROTO8_TBL) +#define SN4(val) ASR(val, SCALE_NPROTO4_TBL) +#define SN8(val) ASR(val, SCALE_NPROTO8_TBL) + +static const int32_t _sbc_proto_4[20] = { + SP4(0x02cb3e8c), SP4(0x22b63dc0), SP4(0x002329cc), SP4(0x053b7548), + SP4(0x31eab940), SP4(0xec1f5e60), SP4(0xff3773a8), SP4(0x0061c5a7), + SP4(0x07646680), SP4(0x3f239480), SP4(0xf89f23a8), SP4(0x007a4737), + SP4(0x00b32807), SP4(0x083ddc80), SP4(0x4825e480), SP4(0x0191e578), + SP4(0x00ff11ca), SP4(0x00fb7991), SP4(0x069fdc58), SP4(0x4b584000) +}; + +static const int32_t _anamatrix4[4] = { + SA4(0x2d413cc0), SA4(0x3b20d780), SA4(0x40000000), SA4(0x187de2a0) +}; + +static const int32_t _sbc_proto_8[40] = { + SP8(0x02e5cd20), SP8(0x22d0c200), SP8(0x006bfe27), SP8(0x07808930), + SP8(0x3f1c8800), SP8(0xf8810d70), SP8(0x002cfdc6), SP8(0x055acf28), + SP8(0x31f566c0), SP8(0xebfe57e0), SP8(0xff27c437), SP8(0x001485cc), + SP8(0x041c6e58), SP8(0x2a7cfa80), SP8(0xe4c4a240), SP8(0xfe359e4c), + SP8(0x0048b1f8), SP8(0x0686ce30), SP8(0x38eec5c0), SP8(0xf2a1b9f0), + SP8(0xffe8904a), SP8(0x0095698a), SP8(0x0824a480), SP8(0x443b3c00), + SP8(0xfd7badc8), SP8(0x00d3e2d9), SP8(0x00c183d2), SP8(0x084e1950), + SP8(0x4810d800), SP8(0x017f43fe), SP8(0x01056dd8), SP8(0x00e9cb9f), + SP8(0x07d7d090), SP8(0x4a708980), SP8(0x0488fae8), SP8(0x0113bd20), + SP8(0x0107b1a8), SP8(0x069fb3c0), SP8(0x4b3db200), SP8(0x00763f48) +}; + +static const int32_t sbc_proto_4_40m0[] = { + SS4(0x00000000), SS4(0xffa6982f), SS4(0xfba93848), SS4(0x0456c7b8), + SS4(0x005967d1), SS4(0xfffb9ac7), SS4(0xff589157), SS4(0xf9c2a8d8), + SS4(0x027c1434), SS4(0x0019118b), SS4(0xfff3c74c), SS4(0xff137330), + SS4(0xf81b8d70), SS4(0x00ec1b8b), SS4(0xfff0b71a), SS4(0xffe99b00), + SS4(0xfef84470), SS4(0xf6fb4370), SS4(0xffcdc351), SS4(0xffe01dc7) +}; + +static const int32_t sbc_proto_4_40m1[] = { + SS4(0xffe090ce), SS4(0xff2c0475), SS4(0xf694f800), SS4(0xff2c0475), + SS4(0xffe090ce), SS4(0xffe01dc7), SS4(0xffcdc351), SS4(0xf6fb4370), + SS4(0xfef84470), SS4(0xffe99b00), SS4(0xfff0b71a), SS4(0x00ec1b8b), + SS4(0xf81b8d70), SS4(0xff137330), SS4(0xfff3c74c), SS4(0x0019118b), + SS4(0x027c1434), SS4(0xf9c2a8d8), SS4(0xff589157), SS4(0xfffb9ac7) +}; + +static const int32_t sbc_proto_8_80m0[] = { + SS8(0x00000000), SS8(0xfe8d1970), SS8(0xee979f00), SS8(0x11686100), + SS8(0x0172e690), SS8(0xfff5bd1a), SS8(0xfdf1c8d4), SS8(0xeac182c0), + SS8(0x0d9daee0), SS8(0x00e530da), SS8(0xffe9811d), SS8(0xfd52986c), + SS8(0xe7054ca0), SS8(0x0a00d410), SS8(0x006c1de4), SS8(0xffdba705), + SS8(0xfcbc98e8), SS8(0xe3889d20), SS8(0x06af2308), SS8(0x000bb7db), + SS8(0xffca00ed), SS8(0xfc3fbb68), SS8(0xe071bc00), SS8(0x03bf7948), + SS8(0xffc4e05c), SS8(0xffb54b3b), SS8(0xfbedadc0), SS8(0xdde26200), + SS8(0x0142291c), SS8(0xff960e94), SS8(0xff9f3e17), SS8(0xfbd8f358), + SS8(0xdbf79400), SS8(0xff405e01), SS8(0xff7d4914), SS8(0xff8b1a31), + SS8(0xfc1417b8), SS8(0xdac7bb40), SS8(0xfdbb828c), SS8(0xff762170) +}; + +static const int32_t sbc_proto_8_80m1[] = { + SS8(0xff7c272c), SS8(0xfcb02620), SS8(0xda612700), SS8(0xfcb02620), + SS8(0xff7c272c), SS8(0xff762170), SS8(0xfdbb828c), SS8(0xdac7bb40), + SS8(0xfc1417b8), SS8(0xff8b1a31), SS8(0xff7d4914), SS8(0xff405e01), + SS8(0xdbf79400), SS8(0xfbd8f358), SS8(0xff9f3e17), SS8(0xff960e94), + SS8(0x0142291c), SS8(0xdde26200), SS8(0xfbedadc0), SS8(0xffb54b3b), + SS8(0xffc4e05c), SS8(0x03bf7948), SS8(0xe071bc00), SS8(0xfc3fbb68), + SS8(0xffca00ed), SS8(0x000bb7db), SS8(0x06af2308), SS8(0xe3889d20), + SS8(0xfcbc98e8), SS8(0xffdba705), SS8(0x006c1de4), SS8(0x0a00d410), + SS8(0xe7054ca0), SS8(0xfd52986c), SS8(0xffe9811d), SS8(0x00e530da), + SS8(0x0d9daee0), SS8(0xeac182c0), SS8(0xfdf1c8d4), SS8(0xfff5bd1a) +}; + +static const int32_t _anamatrix8[8] = { + SA8(0x3b20d780), SA8(0x187de2a0), SA8(0x3ec52f80), SA8(0x3536cc40), + SA8(0x238e7680), SA8(0x0c7c5c20), SA8(0x2d413cc0), SA8(0x40000000) +}; + +static const int32_t synmatrix4[8][4] = { + { SN4(0x05a82798), SN4(0xfa57d868), SN4(0xfa57d868), SN4(0x05a82798) }, + { SN4(0x030fbc54), SN4(0xf89be510), SN4(0x07641af0), SN4(0xfcf043ac) }, + { SN4(0x00000000), SN4(0x00000000), SN4(0x00000000), SN4(0x00000000) }, + { SN4(0xfcf043ac), SN4(0x07641af0), SN4(0xf89be510), SN4(0x030fbc54) }, + { SN4(0xfa57d868), SN4(0x05a82798), SN4(0x05a82798), SN4(0xfa57d868) }, + { SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) }, + { SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000) }, + { SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) } +}; + +static const int32_t synmatrix8[16][8] = { + { SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798), + SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798) }, + { SN8(0x0471ced0), SN8(0xf8275a10), SN8(0x018f8b84), SN8(0x06a6d988), + SN8(0xf9592678), SN8(0xfe70747c), SN8(0x07d8a5f0), SN8(0xfb8e3130) }, + { SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac), + SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54) }, + { SN8(0x018f8b84), SN8(0xfb8e3130), SN8(0x06a6d988), SN8(0xf8275a10), + SN8(0x07d8a5f0), SN8(0xf9592678), SN8(0x0471ced0), SN8(0xfe70747c) }, + { SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), + SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000) }, + { SN8(0xfe70747c), SN8(0x0471ced0), SN8(0xf9592678), SN8(0x07d8a5f0), + SN8(0xf8275a10), SN8(0x06a6d988), SN8(0xfb8e3130), SN8(0x018f8b84) }, + { SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54), + SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac) }, + { SN8(0xfb8e3130), SN8(0x07d8a5f0), SN8(0xfe70747c), SN8(0xf9592678), + SN8(0x06a6d988), SN8(0x018f8b84), SN8(0xf8275a10), SN8(0x0471ced0) }, + { SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868), + SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868) }, + { SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0), + SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) }, + { SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0), + SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) }, + { SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c), + SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) }, + { SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), + SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000) }, + { SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c), + SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) }, + { SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0), + SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) }, + { SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0), + SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) } +}; diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c index 8e0066bc..d2abf087 100644 --- a/src/modules/dbus-util.c +++ b/src/modules/dbus-util.c @@ -90,7 +90,7 @@ static pa_io_event_flags_t get_watch_flags(DBusWatch *watch) { } /* pa_io_event_cb_t IO event handler */ -static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) { +static void handle_io_event(pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) { unsigned int flags = 0; DBusWatch *watch = userdata; @@ -126,7 +126,7 @@ static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, const struc dbus_timeout_handle(timeout); /* restart it for the next scheduled time */ - pa_timeval_add(&next, dbus_timeout_get_interval(timeout) * 1000); + pa_timeval_add(&next, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); ea->time_restart(e, &next); } } @@ -192,7 +192,7 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) { return FALSE; pa_gettimeofday(&tv); - pa_timeval_add(&tv, dbus_timeout_get_interval(timeout) * 1000); + pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event, timeout); @@ -227,7 +227,7 @@ static void toggle_timeout(DBusTimeout *timeout, void *data) { struct timeval tv; pa_gettimeofday(&tv); - pa_timeval_add(&tv, dbus_timeout_get_interval(timeout) * 1000); + pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); c->mainloop->time_restart(ev, &tv); } else diff --git a/src/modules/gconf/Makefile b/src/modules/gconf/Makefile index 316beb72..efe5a336 100644..120000 --- a/src/modules/gconf/Makefile +++ b/src/modules/gconf/Makefile @@ -1,13 +1 @@ -# This is a dirty trick just to ease compilation with emacs -# -# This file is not intended to be distributed or anything -# -# So: don't touch it, even better ignore it! - -all: - $(MAKE) -C ../.. - -clean: - $(MAKE) -C ../.. clean - -.PHONY: all clean +../../pulse/Makefile
\ No newline at end of file diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index e2b0f7c0..845ede50 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -96,7 +96,7 @@ static int fill_buf(struct userdata *u) { if ((r = pa_read(u->fd, u->buf + u->buf_fill, BUF_MAX - u->buf_fill, &u->fd_type)) <= 0) return -1; - u->buf_fill += r; + u->buf_fill += (size_t) r; return 0; } @@ -123,7 +123,7 @@ static char *read_string(struct userdata *u) { if ((e = memchr(u->buf, 0, u->buf_fill))) { char *ret = pa_xstrdup(u->buf); - u->buf_fill -= e - u->buf +1; + u->buf_fill -= (size_t) (e - u->buf +1); memmove(u->buf, e+1, u->buf_fill); return ret; } @@ -164,10 +164,10 @@ static void unload_all_modules(struct userdata *u, struct module_info*m) { static void load_module( struct userdata *u, struct module_info *m, - int i, + unsigned i, const char *name, const char *args, - int is_new) { + pa_bool_t is_new) { pa_module *mod; @@ -378,7 +378,16 @@ void pa__done(pa_module*m) { if (u->pid != (pid_t) -1) { kill(u->pid, SIGTERM); - waitpid(u->pid, NULL, 0); + + for (;;) { + if (waitpid(u->pid, NULL, 0) >= 0) + break; + + if (errno != EINTR) { + pa_log("waitpid() failed: %s", pa_cstrerror(errno)); + break; + } + } } if (u->io_event) @@ -387,7 +396,6 @@ void pa__done(pa_module*m) { if (u->fd >= 0) pa_close(u->fd); - if (u->module_infos) pa_hashmap_free(u->module_infos, module_info_free, u); diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index aad6801e..6dea172f 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -28,6 +28,10 @@ #include <asoundlib.h> +#ifdef HAVE_VALGRIND_MEMCHECK_H +#include <valgrind/memcheck.h> +#endif + #include <pulse/xmalloc.h> #include <pulse/util.h> #include <pulse/timeval.h> @@ -68,8 +72,7 @@ PA_MODULE_USAGE( "mmap=<enable memory mapping?> " "tsched=<enable system timer based scheduling mode?> " "tsched_buffer_size=<buffer size when using timer based scheduling> " - "tsched_buffer_watermark=<lower fill watermark> " - "mixer_reset=<reset hw volume and mute settings to sane defaults when falling back to software?>"); + "tsched_buffer_watermark=<lower fill watermark>"); static const char* const valid_modargs[] = { "sink_name", @@ -85,7 +88,6 @@ static const char* const valid_modargs[] = { "tsched", "tsched_buffer_size", "tsched_buffer_watermark", - "mixer_reset", NULL }; @@ -112,6 +114,8 @@ struct userdata { long hw_volume_max, hw_volume_min; long hw_dB_max, hw_dB_min; pa_bool_t hw_dB_supported; + pa_bool_t mixer_seperate_channels; + pa_cvolume hardware_volume; size_t frame_size, fragment_size, hwbuf_size, tsched_watermark; unsigned nfragments; @@ -139,7 +143,7 @@ static void fix_tsched_watermark(struct userdata *u) { size_t min_sleep, min_wakeup; pa_assert(u); - max_use = u->hwbuf_size - u->hwbuf_unused_frames * u->frame_size; + max_use = u->hwbuf_size - (size_t) u->hwbuf_unused_frames * u->frame_size; min_sleep = pa_usec_to_bytes(TSCHED_MIN_SLEEP_USEC, &u->sink->sample_spec); min_wakeup = pa_usec_to_bytes(TSCHED_MIN_WAKEUP_USEC, &u->sink->sample_spec); @@ -212,8 +216,8 @@ static int try_recover(struct userdata *u, const char *call, int err) { static size_t check_left_to_play(struct userdata *u, snd_pcm_sframes_t n) { size_t left_to_play; - if (n*u->frame_size < u->hwbuf_size) - left_to_play = u->hwbuf_size - (n*u->frame_size); + if ((size_t) n*u->frame_size < u->hwbuf_size) + left_to_play = u->hwbuf_size - ((size_t) n*u->frame_size); else left_to_play = 0; @@ -237,9 +241,9 @@ static size_t check_left_to_play(struct userdata *u, snd_pcm_sframes_t n) { return left_to_play; } -static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) { +static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled) { int work_done = 0; - pa_usec_t max_sleep_usec, process_usec; + pa_usec_t max_sleep_usec = 0, process_usec = 0; size_t left_to_play; pa_assert(u); @@ -257,9 +261,9 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) { /* First we determine how many samples are missing to fill the * buffer up to 100% */ - if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) { + if (PA_UNLIKELY((n = pa_alsa_safe_avail_update(u->pcm_handle, u->hwbuf_size, &u->sink->sample_spec)) < 0)) { - if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0) + if ((r = try_recover(u, "snd_pcm_avail_update", (int) n)) == 0) continue; return r; @@ -275,14 +279,23 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) { * need to guarantee that clients only have to keep around * a single hw buffer length. */ - if (pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) > process_usec+max_sleep_usec/2) + if (!polled && + pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) > process_usec+max_sleep_usec/2) break; - if (PA_UNLIKELY(n <= u->hwbuf_unused_frames)) + if (PA_UNLIKELY(n <= u->hwbuf_unused_frames)) { + + if (polled) + pa_log("ALSA woke us up to write new data to the device, but there was actually nothing to write! " + "Most likely this is an ALSA driver bug. Please report this issue to the PulseAudio developers."); + break; + } n -= u->hwbuf_unused_frames; + polled = FALSE; + /* pa_log_debug("Filling up"); */ for (;;) { @@ -291,10 +304,11 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) { int err; const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t offset, frames = (snd_pcm_uframes_t) n; + snd_pcm_sframes_t sframes; /* pa_log_debug("%lu frames to write", (unsigned long) frames); */ - if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) { + if (PA_UNLIKELY((err = pa_alsa_safe_mmap_begin(u->pcm_handle, &areas, &offset, &frames, u->hwbuf_size, &u->sink->sample_spec)) < 0)) { if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0) continue; @@ -326,9 +340,9 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) { * a little bit longer around? */ pa_memblock_unref_fixed(chunk.memblock); - if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) { + if (PA_UNLIKELY((sframes = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) { - if ((r = try_recover(u, "snd_pcm_mmap_commit", err)) == 0) + if ((r = try_recover(u, "snd_pcm_mmap_commit", (int) sframes)) == 0) continue; return r; @@ -336,7 +350,7 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) { work_done = 1; - u->frame_index += frames; + u->frame_index += (int64_t) frames; u->since_start += frames * u->frame_size; /* pa_log_debug("wrote %lu frames", (unsigned long) frames); */ @@ -344,7 +358,7 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) { if (frames >= (snd_pcm_uframes_t) n) break; - n -= frames; + n -= (snd_pcm_sframes_t) frames; } } @@ -352,9 +366,9 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) { return work_done; } -static int unix_write(struct userdata *u, pa_usec_t *sleep_usec) { +static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled) { int work_done = 0; - pa_usec_t max_sleep_usec, process_usec; + pa_usec_t max_sleep_usec = 0, process_usec = 0; size_t left_to_play; pa_assert(u); @@ -369,9 +383,9 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec) { snd_pcm_hwsync(u->pcm_handle); - if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) { + if (PA_UNLIKELY((n = pa_alsa_safe_avail_update(u->pcm_handle, u->hwbuf_size, &u->sink->sample_spec)) < 0)) { - if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0) + if ((r = try_recover(u, "snd_pcm_avail_update", (int) n)) == 0) continue; return r; @@ -387,14 +401,23 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec) { * need to guarantee that clients only have to keep around * a single hw buffer length. */ - if (pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) > process_usec+max_sleep_usec/2) + if (!polled && + pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) > process_usec+max_sleep_usec/2) break; - if (PA_UNLIKELY(n <= u->hwbuf_unused_frames)) + if (PA_UNLIKELY(n <= u->hwbuf_unused_frames)) { + + if (polled) + pa_log("ALSA woke us up to write new data to the device, but there was actually nothing to write! " + "Most likely this is an ALSA driver bug. Please report this issue to the PulseAudio developers."); + break; + } n -= u->hwbuf_unused_frames; + polled = FALSE; + for (;;) { snd_pcm_sframes_t frames; void *p; @@ -402,31 +425,31 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec) { /* pa_log_debug("%lu frames to write", (unsigned long) frames); */ if (u->memchunk.length <= 0) - pa_sink_render(u->sink, n * u->frame_size, &u->memchunk); + pa_sink_render(u->sink, (size_t) n * u->frame_size, &u->memchunk); pa_assert(u->memchunk.length > 0); - frames = u->memchunk.length / u->frame_size; + frames = (snd_pcm_sframes_t) (u->memchunk.length / u->frame_size); if (frames > n) frames = n; p = pa_memblock_acquire(u->memchunk.memblock); - frames = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, frames); + frames = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, (snd_pcm_uframes_t) frames); pa_memblock_release(u->memchunk.memblock); pa_assert(frames != 0); if (PA_UNLIKELY(frames < 0)) { - if ((r = try_recover(u, "snd_pcm_writei", n)) == 0) + if ((r = try_recover(u, "snd_pcm_writei", (int) frames)) == 0) continue; return r; } - u->memchunk.index += frames * u->frame_size; - u->memchunk.length -= frames * u->frame_size; + u->memchunk.index += (size_t) frames * u->frame_size; + u->memchunk.length -= (size_t) frames * u->frame_size; if (u->memchunk.length <= 0) { pa_memblock_unref(u->memchunk.memblock); @@ -436,7 +459,7 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec) { work_done = 1; u->frame_index += frames; - u->since_start += frames * u->frame_size; + u->since_start += (size_t) frames * u->frame_size; /* pa_log_debug("wrote %lu frames", (unsigned long) frames); */ @@ -490,7 +513,7 @@ static void update_smoother(struct userdata *u) { /* now1 = pa_timeval_load(×tamp); */ now1 = pa_rtclock_usec(); - now2 = pa_bytes_to_usec(frames * u->frame_size, &u->sink->sample_spec); + now2 = pa_bytes_to_usec((uint64_t) frames * u->frame_size, &u->sink->sample_spec); pa_smoother_put(u->smoother, now1, now2); } @@ -504,7 +527,7 @@ static pa_usec_t sink_get_latency(struct userdata *u) { now1 = pa_rtclock_usec(); now2 = pa_smoother_get(u->smoother, now1); - delay = (int64_t) pa_bytes_to_usec(u->frame_index * u->frame_size, &u->sink->sample_spec) - (int64_t) now2; + delay = (int64_t) pa_bytes_to_usec((uint64_t) u->frame_index * u->frame_size, &u->sink->sample_spec) - (int64_t) now2; if (delay > 0) r = (pa_usec_t) delay; @@ -534,8 +557,8 @@ static int suspend(struct userdata *u) { pa_smoother_pause(u->smoother, pa_rtclock_usec()); - /* Let's suspend */ - snd_pcm_drain(u->pcm_handle); + /* Let's suspend -- we don't call snd_pcm_drain() here since that might + * take awfully long with our long buffer sizes today. */ snd_pcm_close(u->pcm_handle); u->pcm_handle = NULL; @@ -564,7 +587,7 @@ static int update_sw_params(struct userdata *u) { if ((latency = pa_sink_get_requested_latency_within_thread(u->sink)) != (pa_usec_t) -1) { size_t b; - pa_log_debug("latency set to %0.2f", (double) latency / PA_USEC_PER_MSEC); + pa_log_debug("latency set to %0.2fms", (double) latency / PA_USEC_PER_MSEC); b = pa_usec_to_bytes(latency, &u->sink->sample_spec); @@ -573,9 +596,9 @@ static int update_sw_params(struct userdata *u) { if (PA_UNLIKELY(b < u->frame_size)) b = u->frame_size; - u->hwbuf_unused_frames = - PA_LIKELY(b < u->hwbuf_size) ? - ((u->hwbuf_size - b) / u->frame_size) : 0; + u->hwbuf_unused_frames = (snd_pcm_sframes_t) + (PA_LIKELY(b < u->hwbuf_size) ? + ((u->hwbuf_size - b) / u->frame_size) : 0); fix_tsched_watermark(u); } @@ -584,7 +607,7 @@ static int update_sw_params(struct userdata *u) { pa_log_debug("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames); /* We need at last one frame in the used part of the buffer */ - avail_min = u->hwbuf_unused_frames + 1; + avail_min = (snd_pcm_uframes_t) u->hwbuf_unused_frames + 1; if (u->use_tsched) { pa_usec_t sleep_usec, process_usec; @@ -600,7 +623,7 @@ static int update_sw_params(struct userdata *u) { return err; } - pa_sink_set_max_request(u->sink, u->hwbuf_size - u->hwbuf_unused_frames * u->frame_size); + pa_sink_set_max_request(u->sink, u->hwbuf_size - (size_t) u->hwbuf_unused_frames * u->frame_size); return 0; } @@ -618,7 +641,11 @@ static int unsuspend(struct userdata *u) { pa_log_info("Trying resume..."); snd_config_update_free_global(); - if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { + if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK, + /*SND_PCM_NONBLOCK|*/ + SND_PCM_NO_AUTO_RESAMPLE| + SND_PCM_NO_AUTO_CHANNELS| + SND_PCM_NO_AUTO_FORMAT)) < 0) { pa_log("Error opening PCM device %s: %s", u->device_name, snd_strerror(err)); goto fail; } @@ -645,7 +672,9 @@ static int unsuspend(struct userdata *u) { } if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) { - pa_log_warn("Resume failed, couldn't restore original fragment settings."); + pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)", + (unsigned long) u->nfragments, (unsigned long) u->fragment_size, + (unsigned long) nfrags, period_size * u->frame_size); goto fail; } @@ -737,40 +766,101 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) { return 0; if (mask & SND_CTL_EVENT_MASK_VALUE) { - pa_sink_get_volume(u->sink); - pa_sink_get_mute(u->sink); + pa_sink_get_volume(u->sink, TRUE); + pa_sink_get_mute(u->sink, TRUE); } return 0; } +static pa_volume_t from_alsa_volume(struct userdata *u, long alsa_vol) { + + return (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / + (double) (u->hw_volume_max - u->hw_volume_min)); +} + +static long to_alsa_volume(struct userdata *u, pa_volume_t vol) { + long alsa_vol; + + alsa_vol = (long) round(((double) vol * (double) (u->hw_volume_max - u->hw_volume_min)) + / PA_VOLUME_NORM) + u->hw_volume_min; + + return PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max); +} + static int sink_get_volume_cb(pa_sink *s) { struct userdata *u = s->userdata; int err; - int i; + unsigned i; + pa_cvolume r; + char t[PA_CVOLUME_SNPRINT_MAX]; pa_assert(u); pa_assert(u->mixer_elem); - for (i = 0; i < s->sample_spec.channels; i++) { - long alsa_vol; + if (u->mixer_seperate_channels) { - pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, u->mixer_map[i])); + r.channels = s->sample_spec.channels; - if (u->hw_dB_supported) { + for (i = 0; i < s->sample_spec.channels; i++) { + long alsa_vol; - if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) >= 0) { - s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0); - continue; + if (u->hw_dB_supported) { + + if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0) + goto fail; + +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol)); +#endif + + r.values[i] = pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0); + } else { + + if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0) + goto fail; + + r.values[i] = from_alsa_volume(u, alsa_vol); } + } + + } else { + long alsa_vol; + + if (u->hw_dB_supported) { + + if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0) + goto fail; + +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol)); +#endif + + pa_cvolume_set(&r, s->sample_spec.channels, pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0)); + + } else { + + if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0) + goto fail; - u->hw_dB_supported = FALSE; + pa_cvolume_set(&r, s->sample_spec.channels, from_alsa_volume(u, alsa_vol)); } + } - if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0) - goto fail; + pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &r)); + + if (!pa_cvolume_equal(&u->hardware_volume, &r)) { + + u->hardware_volume = s->volume = r; + + if (u->hw_dB_supported) { + pa_cvolume reset; + + /* Hmm, so the hardware volume changed, let's reset our software volume */ - s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min)); + pa_cvolume_reset(&reset, s->sample_spec.channels); + pa_sink_set_soft_volume(s, &reset); + } } return 0; @@ -784,44 +874,101 @@ fail: static int sink_set_volume_cb(pa_sink *s) { struct userdata *u = s->userdata; int err; - int i; + unsigned i; + pa_cvolume r; pa_assert(u); pa_assert(u->mixer_elem); - for (i = 0; i < s->sample_spec.channels; i++) { - long alsa_vol; - pa_volume_t vol; + if (u->mixer_seperate_channels) { + + r.channels = s->sample_spec.channels; + + for (i = 0; i < s->sample_spec.channels; i++) { + long alsa_vol; + pa_volume_t vol; + + vol = s->volume.values[i]; + + if (u->hw_dB_supported) { - pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, u->mixer_map[i])); + alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100); + alsa_vol += u->hw_dB_max; + alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max); - vol = PA_MIN(s->volume.values[i], PA_VOLUME_NORM); + if ((err = snd_mixer_selem_set_playback_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, 1)) < 0) + goto fail; + + if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0) + goto fail; + + r.values[i] = pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0); + + } else { + alsa_vol = to_alsa_volume(u, vol); + + if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0) + goto fail; + + if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0) + goto fail; + + r.values[i] = from_alsa_volume(u, alsa_vol); + } + } + + } else { + pa_volume_t vol; + long alsa_vol; + + vol = pa_cvolume_max(&s->volume); if (u->hw_dB_supported) { alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100); + alsa_vol += u->hw_dB_max; alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max); - if ((err = snd_mixer_selem_set_playback_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, -1)) >= 0) { + if ((err = snd_mixer_selem_set_playback_dB_all(u->mixer_elem, alsa_vol, 1)) < 0) + goto fail; + + if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0) + goto fail; - if (snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0) - s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0); + pa_cvolume_set(&r, s->volume.channels, pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0)); - continue; - } + } else { + alsa_vol = to_alsa_volume(u, vol); - u->hw_dB_supported = FALSE; + if ((err = snd_mixer_selem_set_playback_volume_all(u->mixer_elem, alsa_vol)) < 0) + goto fail; + if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0) + goto fail; + + pa_cvolume_set(&r, s->sample_spec.channels, from_alsa_volume(u, alsa_vol)); } + } - alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; - alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max); + u->hardware_volume = r; - if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0) - goto fail; + if (u->hw_dB_supported) { + char t[PA_CVOLUME_SNPRINT_MAX]; - if (snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0) - s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min)); - } + /* Match exactly what the user requested by software */ + + pa_sw_cvolume_divide(&r, &s->volume, &r); + pa_sink_set_soft_volume(s, &r); + + pa_log_debug("Requested volume: %s", pa_cvolume_snprint(t, sizeof(t), &s->volume)); + pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &u->hardware_volume)); + pa_log_debug("Calculated software volume: %s", pa_cvolume_snprint(t, sizeof(t), &r)); + + } else + + /* We can't match exactly what the user requested, hence let's + * at least tell the user about it */ + + s->volume = r; return 0; @@ -903,7 +1050,7 @@ static int process_rewind(struct userdata *u) { snd_pcm_hwsync(u->pcm_handle); if ((unused = snd_pcm_avail_update(u->pcm_handle)) < 0) { - pa_log("snd_pcm_avail_update() failed: %s", snd_strerror(unused)); + pa_log("snd_pcm_avail_update() failed: %s", snd_strerror((int) unused)); return -1; } @@ -922,15 +1069,15 @@ static int process_rewind(struct userdata *u) { pa_log_debug("Limited to %lu bytes.", (unsigned long) rewind_nbytes); - in_frames = (snd_pcm_sframes_t) rewind_nbytes / u->frame_size; + in_frames = (snd_pcm_sframes_t) (rewind_nbytes / u->frame_size); pa_log_debug("before: %lu", (unsigned long) in_frames); - if ((out_frames = snd_pcm_rewind(u->pcm_handle, in_frames)) < 0) { - pa_log("snd_pcm_rewind() failed: %s", snd_strerror(out_frames)); + if ((out_frames = snd_pcm_rewind(u->pcm_handle, (snd_pcm_uframes_t) in_frames)) < 0) { + pa_log("snd_pcm_rewind() failed: %s", snd_strerror((int) out_frames)); return -1; } pa_log_debug("after: %lu", (unsigned long) out_frames); - rewind_nbytes = out_frames * u->frame_size; + rewind_nbytes = (size_t) out_frames * u->frame_size; if (rewind_nbytes <= 0) pa_log_info("Tried rewind, but was apparently not possible."); @@ -955,6 +1102,7 @@ finish: static void thread_func(void *userdata) { struct userdata *u = userdata; + unsigned short revents = 0; pa_assert(u); @@ -974,16 +1122,16 @@ static void thread_func(void *userdata) { /* Render some data and write it to the dsp */ if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) { int work_done; - pa_usec_t sleep_usec; + pa_usec_t sleep_usec = 0; if (u->sink->thread_info.rewind_requested) if (process_rewind(u) < 0) goto fail; if (u->use_mmap) - work_done = mmap_write(u, &sleep_usec); + work_done = mmap_write(u, &sleep_usec, revents & POLLOUT); else - work_done = unix_write(u, &sleep_usec); + work_done = unix_write(u, &sleep_usec, revents & POLLOUT); if (work_done < 0) goto fail; @@ -1042,7 +1190,7 @@ static void thread_func(void *userdata) { pa_rtpoll_set_timer_disabled(u->rtpoll); /* Hmm, nothing to do. Let's sleep */ - if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0) + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) goto fail; if (ret == 0) @@ -1051,7 +1199,6 @@ static void thread_func(void *userdata) { /* Tell ALSA about this and process its response */ if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) { struct pollfd *pollfd; - unsigned short revents = 0; int err; unsigned n; @@ -1062,7 +1209,7 @@ static void thread_func(void *userdata) { goto fail; } - if (revents & (POLLERR|POLLNVAL|POLLHUP)) { + if (revents & (POLLIN|POLLERR|POLLNVAL|POLLHUP|POLLPRI)) { if (pa_alsa_recover_from_poll(u->pcm_handle, revents) < 0) goto fail; @@ -1071,8 +1218,9 @@ static void thread_func(void *userdata) { } if (revents && u->use_tsched) - pa_log_debug("Wakeup from ALSA! (%i)", revents); - } + pa_log_debug("Wakeup from ALSA!%s%s", (revents & POLLIN) ? " INPUT" : "", (revents & POLLOUT) ? " OUTPUT" : ""); + } else + revents = 0; } fail: @@ -1100,7 +1248,7 @@ int pa__init(pa_module*m) { const char *name; char *name_buf = NULL; pa_bool_t namereg_fail; - pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, mixer_reset = TRUE; + pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d; pa_usec_t usec; pa_sink_new_data data; @@ -1124,11 +1272,11 @@ int pa__init(pa_module*m) { frame_size = pa_frame_size(&ss); nfrags = m->core->default_n_fragments; - frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss); + frag_size = (uint32_t) pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss); if (frag_size <= 0) - frag_size = frame_size; - tsched_size = pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC, &ss); - tsched_watermark = pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC, &ss); + frag_size = (uint32_t) frame_size; + tsched_size = (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC, &ss); + tsched_watermark = (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC, &ss); if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 || @@ -1153,15 +1301,10 @@ int pa__init(pa_module*m) { } if (use_tsched && !pa_rtclock_hrtimer()) { - pa_log("Disabling timer-based scheduling because high-resolution timers are not available from the kernel."); + pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel."); use_tsched = FALSE; } - if (pa_modargs_get_value_boolean(ma, "mixer_reset", &mixer_reset) < 0) { - pa_log("Failed to parse mixer_reset argument."); - goto fail; - } - u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; @@ -1313,7 +1456,7 @@ int pa__init(pa_module*m) { pa_sink_set_rtpoll(u->sink, u->rtpoll); u->frame_size = frame_size; - u->fragment_size = frag_size = period_frames * frame_size; + u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size); u->nfragments = nfrags; u->hwbuf_size = u->fragment_size * nfrags; u->hwbuf_unused_frames = 0; @@ -1322,6 +1465,8 @@ int pa__init(pa_module*m) { u->hw_dB_supported = FALSE; u->hw_dB_min = u->hw_dB_max = 0; u->hw_volume_min = u->hw_volume_max = 0; + u->mixer_seperate_channels = FALSE; + pa_cvolume_mute(&u->hardware_volume, u->sink->sample_spec.channels); if (use_tsched) fix_tsched_watermark(u); @@ -1349,76 +1494,60 @@ int pa__init(pa_module*m) { if (u->mixer_handle) { pa_assert(u->mixer_elem); - if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) - - if (pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, TRUE) >= 0 && - snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) >= 0) { - - pa_bool_t suitable = TRUE; + if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) { + pa_bool_t suitable = FALSE; + if (snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) < 0) + pa_log_info("Failed to get volume range. Falling back to software volume control."); + else if (u->hw_volume_min >= u->hw_volume_max) + pa_log_warn("Your kernel driver is broken: it reports a volume range from %li to %li which makes no sense.", u->hw_volume_min, u->hw_volume_max); + else { pa_log_info("Volume ranges from %li to %li.", u->hw_volume_min, u->hw_volume_max); + suitable = TRUE; + } - if (u->hw_volume_min > u->hw_volume_max) { - - pa_log_info("Minimal volume %li larger than maximum volume %li. Strange stuff Falling back to software volume control.", u->hw_volume_min, u->hw_volume_max); - suitable = FALSE; - - } else if (u->hw_volume_max - u->hw_volume_min < 3) { - - pa_log_info("Device has less than 4 volume levels. Falling back to software volume control."); - suitable = FALSE; - - } else if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) >= 0) { - - /* u->hw_dB_max = 0; u->hw_dB_min = -3000; Use this to make valgrind shut up */ - - pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", u->hw_dB_min/100.0, u->hw_dB_max/100.0); - - /* Let's see if this thing actually is useful for muting */ - if (u->hw_dB_min > -6000) { - pa_log_info("Device cannot attenuate for more than -60 dB (only %0.2f dB supported), falling back to software volume control.", ((double) u->hw_dB_min) / 100); - - suitable = FALSE; - } else if (u->hw_dB_max < 0) { - - pa_log_info("Device is still attenuated at maximum volume setting (%0.2f dB is maximum). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_max) / 100); - suitable = FALSE; + if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) < 0) + pa_log_info("Mixer doesn't support dB information."); + else { +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_min, sizeof(u->hw_dB_min)); + VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_max, sizeof(u->hw_dB_max)); +#endif - } else if (u->hw_dB_min >= u->hw_dB_max) { + if (u->hw_dB_min >= u->hw_dB_max) + pa_log_warn("Your kernel driver is broken: it reports a volume range from %0.2f dB to %0.2f dB which makes no sense.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0); + else { + pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0); + u->hw_dB_supported = TRUE; + } + } - pa_log_info("Minimal dB (%0.2f) larger or equal to maximum dB (%0.2f). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_min) / 100, ((double) u->hw_dB_max) / 100); - suitable = FALSE; + if (suitable && + !u->hw_dB_supported && + u->hw_volume_max - u->hw_volume_min < 3) { - } else { + pa_log_info("Device doesn't do dB volume and has less than 4 volume levels. Falling back to software volume control."); + suitable = FALSE; + } - if (u->hw_dB_max > 0) { - /* dB > 0 means overamplification, and clipping, we don't want that here */ - pa_log_info("Device can do overamplification for %0.2f dB. Limiting to 0 db", ((double) u->hw_dB_max) / 100); - u->hw_dB_max = 0; - } + if (suitable) { + u->mixer_seperate_channels = pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, TRUE) >= 0; - u->hw_dB_supported = TRUE; - } - } + u->sink->get_volume = sink_get_volume_cb; + u->sink->set_volume = sink_set_volume_cb; + u->sink->flags |= PA_SINK_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SINK_DECIBEL_VOLUME : 0); + pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported"); - if (suitable) { - u->sink->get_volume = sink_get_volume_cb; - u->sink->set_volume = sink_set_volume_cb; - u->sink->flags |= PA_SINK_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SINK_DECIBEL_VOLUME : 0); - pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported"); - - } else if (mixer_reset) { - pa_log_info("Using software volume control. Trying to reset sound card to 0 dB."); - pa_alsa_0dB_playback(u->mixer_elem); - } else - pa_log_info("Using software volume control. Leaving hw mixer controls untouched."); - } + } else + pa_log_info("Using software volume control."); + } if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) { u->sink->get_mute = sink_get_mute_cb; u->sink->set_mute = sink_set_mute_cb; u->sink->flags |= PA_SINK_HW_MUTE_CTRL; - } + } else + pa_log_info("Using software mute control."); u->mixer_fdl = pa_alsa_fdlist_new(); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 1cc467d9..f796ef14 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -28,6 +28,10 @@ #include <asoundlib.h> +#ifdef HAVE_VALGRIND_MEMCHECK_H +#include <valgrind/memcheck.h> +#endif + #include <pulse/xmalloc.h> #include <pulse/util.h> #include <pulse/timeval.h> @@ -69,8 +73,7 @@ PA_MODULE_USAGE( "mmap=<enable memory mapping?> " "tsched=<enable system timer based scheduling mode?> " "tsched_buffer_size=<buffer size when using timer based scheduling> " - "tsched_buffer_watermark=<upper fill watermark> " - "mixer_reset=<reset hw volume and mute settings to sane defaults when falling back to software?>"); + "tsched_buffer_watermark=<upper fill watermark>"); static const char* const valid_modargs[] = { "source_name", @@ -86,7 +89,6 @@ static const char* const valid_modargs[] = { "tsched", "tsched_buffer_size", "tsched_buffer_watermark", - "mixer_reset", NULL }; @@ -113,6 +115,9 @@ struct userdata { long hw_volume_max, hw_volume_min; long hw_dB_max, hw_dB_min; pa_bool_t hw_dB_supported; + pa_bool_t mixer_seperate_channels; + + pa_cvolume hardware_volume; size_t frame_size, fragment_size, hwbuf_size, tsched_watermark; unsigned nfragments; @@ -136,7 +141,7 @@ static void fix_tsched_watermark(struct userdata *u) { size_t min_sleep, min_wakeup; pa_assert(u); - max_use = u->hwbuf_size - u->hwbuf_unused_frames * u->frame_size; + max_use = u->hwbuf_size - (size_t) u->hwbuf_unused_frames * u->frame_size; min_sleep = pa_usec_to_bytes(TSCHED_MIN_SLEEP_USEC, &u->source->sample_spec); min_wakeup = pa_usec_to_bytes(TSCHED_MIN_WAKEUP_USEC, &u->source->sample_spec); @@ -206,9 +211,10 @@ static int try_recover(struct userdata *u, const char *call, int err) { static size_t check_left_to_record(struct userdata *u, snd_pcm_sframes_t n) { size_t left_to_record; + size_t rec_space = u->hwbuf_size - (size_t) u->hwbuf_unused_frames*u->frame_size; - if (n*u->frame_size < u->hwbuf_size) - left_to_record = u->hwbuf_size - (n*u->frame_size); + if ((size_t) n*u->frame_size < rec_space) + left_to_record = rec_space - ((size_t) n*u->frame_size); else left_to_record = 0; @@ -232,9 +238,9 @@ static size_t check_left_to_record(struct userdata *u, snd_pcm_sframes_t n) { return left_to_record; } -static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) { +static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled) { int work_done = 0; - pa_usec_t max_sleep_usec, process_usec; + pa_usec_t max_sleep_usec = 0, process_usec = 0; size_t left_to_record; pa_assert(u); @@ -249,9 +255,9 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) { snd_pcm_hwsync(u->pcm_handle); - if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) { + if (PA_UNLIKELY((n = pa_alsa_safe_avail_update(u->pcm_handle, u->hwbuf_size, &u->source->sample_spec)) < 0)) { - if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0) + if ((r = try_recover(u, "snd_pcm_avail_update", (int) n)) == 0) continue; return r; @@ -260,11 +266,20 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) { left_to_record = check_left_to_record(u, n); if (u->use_tsched) - if (pa_bytes_to_usec(left_to_record, &u->source->sample_spec) > process_usec+max_sleep_usec/2) + if (!polled && + pa_bytes_to_usec(left_to_record, &u->source->sample_spec) > process_usec+max_sleep_usec/2) break; - if (PA_UNLIKELY(n <= 0)) + if (PA_UNLIKELY(n <= 0)) { + + if (polled) + pa_log("ALSA woke us up to read new data from the device, but there was actually nothing to read! " + "Most likely this is an ALSA driver bug. Please report this issue to the PulseAudio device."); + break; + } + + polled = FALSE; for (;;) { int err; @@ -272,10 +287,11 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) { snd_pcm_uframes_t offset, frames = (snd_pcm_uframes_t) n; pa_memchunk chunk; void *p; + snd_pcm_sframes_t sframes; /* pa_log_debug("%lu frames to read", (unsigned long) frames); */ - if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) { + if (PA_UNLIKELY((err = pa_alsa_safe_mmap_begin(u->pcm_handle, &areas, &offset, &frames, u->hwbuf_size, &u->source->sample_spec)) < 0)) { if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0) continue; @@ -304,9 +320,9 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) { pa_source_post(u->source, &chunk); pa_memblock_unref_fixed(chunk.memblock); - if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) { + if (PA_UNLIKELY((sframes = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) { - if ((r = try_recover(u, "snd_pcm_mmap_commit", err)) == 0) + if ((r = try_recover(u, "snd_pcm_mmap_commit", (int) sframes)) == 0) continue; return r; @@ -314,14 +330,14 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) { work_done = 1; - u->frame_index += frames; + u->frame_index += (int64_t) frames; /* pa_log_debug("read %lu frames", (unsigned long) frames); */ if (frames >= (snd_pcm_uframes_t) n) break; - n -= frames; + n -= (snd_pcm_sframes_t) frames; } } @@ -329,9 +345,9 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) { return work_done; } -static int unix_read(struct userdata *u, pa_usec_t *sleep_usec) { +static int unix_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled) { int work_done = 0; - pa_usec_t max_sleep_usec, process_usec; + pa_usec_t max_sleep_usec = 0, process_usec = 0; size_t left_to_record; pa_assert(u); @@ -346,9 +362,9 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec) { snd_pcm_hwsync(u->pcm_handle); - if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) { + if (PA_UNLIKELY((n = pa_alsa_safe_avail_update(u->pcm_handle, u->hwbuf_size, &u->source->sample_spec)) < 0)) { - if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0) + if ((r = try_recover(u, "snd_pcm_avail_update", (int) n)) == 0) continue; return r; @@ -357,11 +373,20 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec) { left_to_record = check_left_to_record(u, n); if (u->use_tsched) - if (pa_bytes_to_usec(left_to_record, &u->source->sample_spec) > process_usec+max_sleep_usec/2) + if (!polled && + pa_bytes_to_usec(left_to_record, &u->source->sample_spec) > process_usec+max_sleep_usec/2) break; - if (PA_UNLIKELY(n <= 0)) + if (PA_UNLIKELY(n <= 0)) { + + if (polled) + pa_log("ALSA woke us up to read new data from the device, but there was actually nothing to read! " + "Most likely this is an ALSA driver bug. Please report this issue to the PulseAudio developers."); + return work_done; + } + + polled = FALSE; for (;;) { void *p; @@ -370,7 +395,7 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec) { chunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1); - frames = pa_memblock_get_length(chunk.memblock) / u->frame_size; + frames = (snd_pcm_sframes_t) (pa_memblock_get_length(chunk.memblock) / u->frame_size); if (frames > n) frames = n; @@ -378,7 +403,7 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec) { /* pa_log_debug("%lu frames to read", (unsigned long) n); */ p = pa_memblock_acquire(chunk.memblock); - frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, frames); + frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, (snd_pcm_uframes_t) frames); pa_memblock_release(chunk.memblock); pa_assert(frames != 0); @@ -386,14 +411,14 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec) { if (PA_UNLIKELY(frames < 0)) { pa_memblock_unref(chunk.memblock); - if ((r = try_recover(u, "snd_pcm_readi", n)) == 0) + if ((r = try_recover(u, "snd_pcm_readi", (int) (frames))) == 0) continue; return r; } chunk.index = 0; - chunk.length = frames * u->frame_size; + chunk.length = (size_t) frames * u->frame_size; pa_source_post(u->source, &chunk); pa_memblock_unref(chunk.memblock); @@ -437,7 +462,7 @@ static void update_smoother(struct userdata *u) { frames = u->frame_index + delay; now1 = pa_rtclock_usec(); - now2 = pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec); + now2 = pa_bytes_to_usec((uint64_t) frames * u->frame_size, &u->source->sample_spec); pa_smoother_put(u->smoother, now1, now2); } @@ -452,7 +477,7 @@ static pa_usec_t source_get_latency(struct userdata *u) { now1 = pa_rtclock_usec(); now2 = pa_smoother_get(u->smoother, now1); - delay = (int64_t) now2 - pa_bytes_to_usec(u->frame_index * u->frame_size, &u->source->sample_spec); + delay = (int64_t) now2 - (int64_t) pa_bytes_to_usec((uint64_t) u->frame_index * u->frame_size, &u->source->sample_spec); if (delay > 0) r = (pa_usec_t) delay; @@ -508,7 +533,7 @@ static int update_sw_params(struct userdata *u) { if ((latency = pa_source_get_requested_latency_within_thread(u->source)) != (pa_usec_t) -1) { size_t b; - pa_log_debug("latency set to %0.2f", (double) latency / PA_USEC_PER_MSEC); + pa_log_debug("latency set to %0.2fms", (double) latency / PA_USEC_PER_MSEC); b = pa_usec_to_bytes(latency, &u->source->sample_spec); @@ -517,9 +542,9 @@ static int update_sw_params(struct userdata *u) { if (PA_UNLIKELY(b < u->frame_size)) b = u->frame_size; - u->hwbuf_unused_frames = - PA_LIKELY(b < u->hwbuf_size) ? - ((u->hwbuf_size - b) / u->frame_size) : 0; + u->hwbuf_unused_frames = (snd_pcm_sframes_t) + (PA_LIKELY(b < u->hwbuf_size) ? + ((u->hwbuf_size - b) / u->frame_size) : 0); fix_tsched_watermark(u); } @@ -559,7 +584,12 @@ static int unsuspend(struct userdata *u) { pa_log_info("Trying resume..."); snd_config_update_free_global(); - if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { + + if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE, + /*SND_PCM_NONBLOCK|*/ + SND_PCM_NO_AUTO_RESAMPLE| + SND_PCM_NO_AUTO_CHANNELS| + SND_PCM_NO_AUTO_FORMAT)) < 0) { pa_log("Error opening PCM device %s: %s", u->device_name, snd_strerror(err)); goto fail; } @@ -586,7 +616,9 @@ static int unsuspend(struct userdata *u) { } if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) { - pa_log_warn("Resume failed, couldn't restore original fragment settings."); + pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)", + (unsigned long) u->nfragments, (unsigned long) u->fragment_size, + (unsigned long) nfrags, period_size * u->frame_size); goto fail; } @@ -680,40 +712,101 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) { return 0; if (mask & SND_CTL_EVENT_MASK_VALUE) { - pa_source_get_volume(u->source); - pa_source_get_mute(u->source); + pa_source_get_volume(u->source, TRUE); + pa_source_get_mute(u->source, TRUE); } return 0; } +static pa_volume_t from_alsa_volume(struct userdata *u, long alsa_vol) { + + return (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / + (double) (u->hw_volume_max - u->hw_volume_min)); +} + +static long to_alsa_volume(struct userdata *u, pa_volume_t vol) { + long alsa_vol; + + alsa_vol = (long) round(((double) vol * (double) (u->hw_volume_max - u->hw_volume_min)) + / PA_VOLUME_NORM) + u->hw_volume_min; + + return PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max); +} + static int source_get_volume_cb(pa_source *s) { struct userdata *u = s->userdata; int err; - int i; + unsigned i; + pa_cvolume r; + char t[PA_CVOLUME_SNPRINT_MAX]; pa_assert(u); pa_assert(u->mixer_elem); - for (i = 0; i < s->sample_spec.channels; i++) { - long alsa_vol; + if (u->mixer_seperate_channels) { - pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, u->mixer_map[i])); + r.channels = s->sample_spec.channels; - if (u->hw_dB_supported) { + for (i = 0; i < s->sample_spec.channels; i++) { + long alsa_vol; - if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) >= 0) { - s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0); - continue; + if (u->hw_dB_supported) { + + if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0) + goto fail; + +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol)); +#endif + + r.values[i] = pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0); + } else { + + if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0) + goto fail; + + r.values[i] = from_alsa_volume(u, alsa_vol); } + } + + } else { + long alsa_vol; + + if (u->hw_dB_supported) { + + if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0) + goto fail; + +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol)); +#endif + + pa_cvolume_set(&r, s->sample_spec.channels, pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0)); + + } else { - u->hw_dB_supported = FALSE; + if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0) + goto fail; + + pa_cvolume_set(&r, s->sample_spec.channels, from_alsa_volume(u, alsa_vol)); } + } - if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0) - goto fail; + pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &r)); + + if (!pa_cvolume_equal(&u->hardware_volume, &r)) { + + u->hardware_volume = s->volume = r; + + if (u->hw_dB_supported) { + pa_cvolume reset; + + /* Hmm, so the hardware volume changed, let's reset our software volume */ - s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min)); + pa_cvolume_reset(&reset, s->sample_spec.channels); + pa_source_set_soft_volume(s, &reset); + } } return 0; @@ -727,44 +820,101 @@ fail: static int source_set_volume_cb(pa_source *s) { struct userdata *u = s->userdata; int err; - int i; + unsigned i; + pa_cvolume r; pa_assert(u); pa_assert(u->mixer_elem); - for (i = 0; i < s->sample_spec.channels; i++) { - long alsa_vol; - pa_volume_t vol; + if (u->mixer_seperate_channels) { + + r.channels = s->sample_spec.channels; + + for (i = 0; i < s->sample_spec.channels; i++) { + long alsa_vol; + pa_volume_t vol; - pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, u->mixer_map[i])); + vol = s->volume.values[i]; - vol = PA_MIN(s->volume.values[i], PA_VOLUME_NORM); + if (u->hw_dB_supported) { + + alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100); + alsa_vol += u->hw_dB_max; + alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max); + + if ((err = snd_mixer_selem_set_capture_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, 1)) < 0) + goto fail; + + if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0) + goto fail; + + r.values[i] = pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0); + + } else { + alsa_vol = to_alsa_volume(u, vol); + + if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0) + goto fail; + + if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0) + goto fail; + + r.values[i] = from_alsa_volume(u, alsa_vol); + } + } + + } else { + pa_volume_t vol; + long alsa_vol; + + vol = pa_cvolume_max(&s->volume); if (u->hw_dB_supported) { alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100); + alsa_vol += u->hw_dB_max; alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max); + if ((err = snd_mixer_selem_set_capture_dB_all(u->mixer_elem, alsa_vol, 1)) < 0) + goto fail; - if ((err = snd_mixer_selem_set_capture_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, -1)) >= 0) { + if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0) + goto fail; - if (snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0) - s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0); + pa_cvolume_set(&r, s->volume.channels, pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0)); - continue; - } + } else { + alsa_vol = to_alsa_volume(u, vol); + + if ((err = snd_mixer_selem_set_capture_volume_all(u->mixer_elem, alsa_vol)) < 0) + goto fail; - u->hw_dB_supported = FALSE; + if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0) + goto fail; + + pa_cvolume_set(&r, s->sample_spec.channels, from_alsa_volume(u, alsa_vol)); } + } - alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; - alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max); + u->hardware_volume = r; - if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0) - goto fail; + if (u->hw_dB_supported) { + char t[PA_CVOLUME_SNPRINT_MAX]; - if (snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0) - s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min)); - } + /* Match exactly what the user requested by software */ + + pa_sw_cvolume_divide(&r, &s->volume, &r); + pa_source_set_soft_volume(s, &r); + + pa_log_debug("Requested volume: %s", pa_cvolume_snprint(t, sizeof(t), &s->volume)); + pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &u->hardware_volume)); + pa_log_debug("Calculated software volume: %s", pa_cvolume_snprint(t, sizeof(t), &r)); + + } else + + /* We can't match exactly what the user requested, hence let's + * at least tell the user about it */ + + s->volume = r; return 0; @@ -818,6 +968,7 @@ static void source_update_requested_latency_cb(pa_source *s) { static void thread_func(void *userdata) { struct userdata *u = userdata; + unsigned short revents = 0; pa_assert(u); @@ -837,12 +988,12 @@ static void thread_func(void *userdata) { /* Read some data and pass it to the sources */ if (PA_SOURCE_IS_OPENED(u->source->thread_info.state)) { int work_done = 0; - pa_usec_t sleep_usec; + pa_usec_t sleep_usec = 0; if (u->use_mmap) - work_done = mmap_read(u, &sleep_usec); + work_done = mmap_read(u, &sleep_usec, revents & POLLIN); else - work_done = unix_read(u, &sleep_usec); + work_done = unix_read(u, &sleep_usec, revents & POLLIN); if (work_done < 0) goto fail; @@ -875,7 +1026,7 @@ static void thread_func(void *userdata) { pa_rtpoll_set_timer_disabled(u->rtpoll); /* Hmm, nothing to do. Let's sleep */ - if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0) + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) goto fail; if (ret == 0) @@ -884,7 +1035,6 @@ static void thread_func(void *userdata) { /* Tell ALSA about this and process its response */ if (PA_SOURCE_IS_OPENED(u->source->thread_info.state)) { struct pollfd *pollfd; - unsigned short revents = 0; int err; unsigned n; @@ -895,7 +1045,7 @@ static void thread_func(void *userdata) { goto fail; } - if (revents & (POLLERR|POLLNVAL|POLLHUP)) { + if (revents & (POLLOUT|POLLERR|POLLNVAL|POLLHUP|POLLPRI)) { if (pa_alsa_recover_from_poll(u->pcm_handle, revents) < 0) goto fail; @@ -903,8 +1053,9 @@ static void thread_func(void *userdata) { } if (revents && u->use_tsched) - pa_log_debug("Wakeup from ALSA! (%i)", revents); - } + pa_log_debug("Wakeup from ALSA!%s%s", (revents & POLLIN) ? " INPUT" : "", (revents & POLLOUT) ? " OUTPUT" : ""); + } else + revents = 0; } fail: @@ -932,7 +1083,7 @@ int pa__init(pa_module*m) { const char *name; char *name_buf = NULL; pa_bool_t namereg_fail; - pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, mixer_reset = TRUE; + pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d; pa_source_new_data data; snd_pcm_info_alloca(&pcm_info); @@ -955,11 +1106,11 @@ int pa__init(pa_module*m) { frame_size = pa_frame_size(&ss); nfrags = m->core->default_n_fragments; - frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss); + frag_size = (uint32_t) pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss); if (frag_size <= 0) - frag_size = frame_size; - tsched_size = pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC, &ss); - tsched_watermark = pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC, &ss); + frag_size = (uint32_t) frame_size; + tsched_size = (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC, &ss); + tsched_watermark = (uint32_t) pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC, &ss); if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 || @@ -984,15 +1135,10 @@ int pa__init(pa_module*m) { } if (use_tsched && !pa_rtclock_hrtimer()) { - pa_log("Disabling timer-based scheduling because high-resolution timers are not available from the kernel."); + pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel."); use_tsched = FALSE; } - if (pa_modargs_get_value_boolean(ma, "mixer_reset", &mixer_reset) < 0) { - pa_log("Failed to parse mixer_reset argument."); - goto fail; - } - u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; @@ -1137,7 +1283,7 @@ int pa__init(pa_module*m) { pa_source_set_rtpoll(u->source, u->rtpoll); u->frame_size = frame_size; - u->fragment_size = frag_size = period_frames * frame_size; + u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size); u->nfragments = nfrags; u->hwbuf_size = u->fragment_size * nfrags; u->hwbuf_unused_frames = 0; @@ -1146,6 +1292,8 @@ int pa__init(pa_module*m) { u->hw_dB_supported = FALSE; u->hw_dB_min = u->hw_dB_max = 0; u->hw_volume_min = u->hw_volume_max = 0; + u->mixer_seperate_channels = FALSE; + pa_cvolume_mute(&u->hardware_volume, u->source->sample_spec.channels); if (use_tsched) fix_tsched_watermark(u); @@ -1168,67 +1316,59 @@ int pa__init(pa_module*m) { if (u->mixer_handle) { pa_assert(u->mixer_elem); - if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) - if (pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, FALSE) >= 0 && - snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) >= 0) { - - pa_bool_t suitable = TRUE; + if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) { + pa_bool_t suitable = FALSE; + if (snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) < 0) + pa_log_info("Failed to get volume range. Falling back to software volume control."); + else if (u->hw_volume_min >= u->hw_volume_max) + pa_log_warn("Your kernel driver is broken: it reports a volume range from %li to %li which makes no sense.", u->hw_volume_min, u->hw_volume_max); + else { pa_log_info("Volume ranges from %li to %li.", u->hw_volume_min, u->hw_volume_max); + suitable = TRUE; + } - if (u->hw_volume_min > u->hw_volume_max) { - - pa_log_info("Minimal volume %li larger than maximum volume %li. Strange stuff Falling back to software volume control.", u->hw_volume_min, u->hw_volume_max); - suitable = FALSE; - - } else if (u->hw_volume_max - u->hw_volume_min < 3) { - - pa_log_info("Device has less than 4 volume levels. Falling back to software volume control."); - suitable = FALSE; - - } else if (snd_mixer_selem_get_capture_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) >= 0) { - - pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", u->hw_dB_min/100.0, u->hw_dB_max/100.0); - - /* Let's see if this thing actually is useful for muting */ - if (u->hw_dB_min > -6000) { - pa_log_info("Device cannot attenuate for more than -60 dB (only %0.2f dB supported), falling back to software volume control.", ((double) u->hw_dB_min) / 100); - - suitable = FALSE; - } else if (u->hw_dB_max < 0) { - - pa_log_info("Device is still attenuated at maximum volume setting (%0.2f dB is maximum). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_max) / 100); - suitable = FALSE; - - } else if (u->hw_dB_min >= u->hw_dB_max) { - - pa_log_info("Minimal dB (%0.2f) larger or equal to maximum dB (%0.2f). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_min) / 100, ((double) u->hw_dB_max) / 100); - suitable = FALSE; + if (snd_mixer_selem_get_capture_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) < 0) + pa_log_info("Mixer doesn't support dB information."); + else { +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_min, sizeof(u->hw_dB_min)); + VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_max, sizeof(u->hw_dB_max)); +#endif - } else - u->hw_dB_supported = TRUE; + if (u->hw_dB_min >= u->hw_dB_max) + pa_log_warn("Your kernel driver is broken: it reports a volume range from %0.2f dB to %0.2f dB which makes no sense.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0); + else { + pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0); + u->hw_dB_supported = TRUE; } + } - if (suitable) { - u->source->get_volume = source_get_volume_cb; - u->source->set_volume = source_set_volume_cb; - u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SOURCE_DECIBEL_VOLUME : 0); - pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported"); - - } else if (mixer_reset) { - pa_log_info("Using software volume control. Trying to reset sound card to 0 dB."); - pa_alsa_0dB_capture(u->mixer_elem); - } else - pa_log_info("Using software volume control. Leaving hw mixer controls untouched."); + if (suitable && + !u->hw_dB_supported && + u->hw_volume_max - u->hw_volume_min < 3) { + pa_log_info("Device has less than 4 volume levels. Falling back to software volume control."); + suitable = FALSE; } + if (suitable) { + u->mixer_seperate_channels = pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, FALSE) >= 0; + + u->source->get_volume = source_get_volume_cb; + u->source->set_volume = source_set_volume_cb; + u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SOURCE_DECIBEL_VOLUME : 0); + pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported"); + } else + pa_log_info("Using software volume control."); + } if (snd_mixer_selem_has_capture_switch(u->mixer_elem)) { u->source->get_mute = source_get_mute_cb; u->source->set_mute = source_set_mute_cb; u->source->flags |= PA_SOURCE_HW_MUTE_CTRL; - } + } else + pa_log_info("Using software mute control."); u->mixer_fdl = pa_alsa_fdlist_new(); diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 1bfe4b4c..d61d127a 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -206,9 +206,9 @@ static void adjust_rates(struct userdata *u) { continue; if (o->total_latency < target_latency) - r -= (uint32_t) (((((double) target_latency - o->total_latency))/u->adjust_time)*r/PA_USEC_PER_SEC); + r -= (uint32_t) ((((double) (target_latency - o->total_latency))/(double)u->adjust_time)*(double)r/PA_USEC_PER_SEC); else if (o->total_latency > target_latency) - r += (uint32_t) (((((double) o->total_latency - target_latency))/u->adjust_time)*r/PA_USEC_PER_SEC); + r += (uint32_t) ((((double) (o->total_latency - target_latency))/(double)u->adjust_time)*(double)r/PA_USEC_PER_SEC); if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1)) { pa_log_warn("[%s] sample rates too different, not adjusting (%u vs. %u).", pa_proplist_gets(o->sink_input->proplist, PA_PROP_MEDIA_NAME), base_rate, r); @@ -233,7 +233,7 @@ static void time_callback(pa_mainloop_api*a, pa_time_event* e, const struct time adjust_rates(u); pa_gettimeofday(&n); - n.tv_sec += u->adjust_time; + n.tv_sec += (time_t) u->adjust_time; u->sink->core->mainloop->time_restart(e, &n); } @@ -389,7 +389,7 @@ static void request_memblock(struct output *o, size_t length) { /* OK, we need to prepare new data, but only if the sink is actually running */ if (pa_atomic_load(&o->userdata->thread_info.running)) - pa_asyncmsgq_send(o->outq, PA_MSGOBJECT(o->userdata->sink), SINK_MESSAGE_NEED, o, length, NULL); + pa_asyncmsgq_send(o->outq, PA_MSGOBJECT(o->userdata->sink), SINK_MESSAGE_NEED, o, (int64_t) length, NULL); } /* Called from I/O thread context */ @@ -1159,7 +1159,7 @@ int pa__init(pa_module*m) { if (u->adjust_time > 0) { struct timeval tv; pa_gettimeofday(&tv); - tv.tv_sec += u->adjust_time; + tv.tv_sec += (time_t) u->adjust_time; u->time_event = m->core->mainloop->time_new(m->core->mainloop, &tv, time_callback, u); } diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 09b720df..1616d47c 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -236,16 +236,16 @@ int pa__init(pa_module*m) { goto fail; } -#if HAVE_ALSA +#ifdef HAVE_ALSA if ((n = detect_alsa(m->core, just_one)) <= 0) #endif #if HAVE_OSS if ((n = detect_oss(m->core, just_one)) <= 0) #endif -#if HAVE_SOLARIS +#ifdef HAVE_SOLARIS if ((n = detect_solaris(m->core, just_one)) <= 0) #endif -#if OS_IS_WIN32 +#ifdef OS_IS_WIN32 if ((n = detect_waveout(m->core, just_one)) <= 0) #endif { diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c index 3d731f12..86a78810 100644 --- a/src/modules/module-device-restore.c +++ b/src/modules/module-device-restore.c @@ -106,7 +106,7 @@ static struct entry* read_entry(struct userdata *u, char *name) { pa_assert(name); key.dptr = name; - key.dsize = strlen(name); + key.dsize = (int) strlen(name); data = gdbm_fetch(u->gdbm_file, key); @@ -179,8 +179,8 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 name = pa_sprintf_malloc("sink:%s", sink->name); entry.channel_map = sink->channel_map; - entry.volume = *pa_sink_get_volume(sink); - entry.muted = pa_sink_get_mute(sink); + entry.volume = *pa_sink_get_volume(sink, FALSE); + entry.muted = pa_sink_get_mute(sink, FALSE); } else { pa_source *source; @@ -192,8 +192,8 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 name = pa_sprintf_malloc("source:%s", source->name); entry.channel_map = source->channel_map; - entry.volume = *pa_source_get_volume(source); - entry.muted = pa_source_get_mute(source); + entry.volume = *pa_source_get_volume(source, FALSE); + entry.muted = pa_source_get_mute(source, FALSE); } if ((old = read_entry(u, name))) { @@ -210,7 +210,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 } key.dptr = name; - key.dsize = strlen(name); + key.dsize = (int) strlen(name); data.dptr = (void*) &entry; data.dsize = sizeof(entry); @@ -288,6 +288,7 @@ int pa__init(pa_module*m) { pa_source *source; uint32_t idx; pa_bool_t restore_volume = TRUE, restore_muted = TRUE; + int gdbm_cache_size; pa_assert(m); @@ -337,6 +338,10 @@ int pa__init(pa_module*m) { goto fail; } + /* By default the cache of gdbm is rather large, let's reduce it a bit to save memory */ + gdbm_cache_size = 10; + gdbm_setopt(u->gdbm_file, GDBM_CACHESIZE, &gdbm_cache_size, sizeof(gdbm_cache_size)); + pa_log_info("Sucessfully opened database file '%s'.", fname); pa_xfree(fname); diff --git a/src/modules/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c index f75335d5..882dba8c 100644 --- a/src/modules/module-esound-compat-spawnpid.c +++ b/src/modules/module-esound-compat-spawnpid.c @@ -62,7 +62,7 @@ int pa__init(pa_module*m) { goto finish; } - if (kill(pid, SIGUSR1) < 0) + if (kill((pid_t) pid, SIGUSR1) < 0) pa_log_warn("kill(%u) failed: %s", pid, pa_cstrerror(errno)); pa_module_unload_request(m, TRUE); diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index f748808e..14f1810a 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -165,7 +165,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse pa_usec_t w, r; r = pa_smoother_get(u->smoother, pa_rtclock_usec()); - w = pa_bytes_to_usec(u->offset + u->memchunk.length, &u->sink->sample_spec); + w = pa_bytes_to_usec((uint64_t) u->offset + u->memchunk.length, &u->sink->sample_spec); *((pa_usec_t*) data) = w > r ? w - r : 0; break; @@ -250,8 +250,8 @@ static void thread_func(void *userdata) { } else { u->offset += l; - u->memchunk.index += l; - u->memchunk.length -= l; + u->memchunk.index += (size_t) l; + u->memchunk.length -= (size_t) l; if (u->memchunk.length <= 0) { pa_memblock_unref(u->memchunk.memblock); @@ -285,7 +285,7 @@ static void thread_func(void *userdata) { } #endif - usec = pa_bytes_to_usec(n, &u->sink->sample_spec); + usec = pa_bytes_to_usec((uint64_t) n, &u->sink->sample_spec); if (usec > u->latency) usec -= u->latency; @@ -296,7 +296,7 @@ static void thread_func(void *userdata) { } /* Hmm, nothing to do. Let's sleep */ - pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0; + pollfd->events = (short) (PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0); } if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) @@ -342,7 +342,7 @@ static int do_write(struct userdata *u) { return -1; } - u->write_index += r; + u->write_index += (size_t) r; pa_assert(u->write_index <= u->write_length); if (u->write_index == u->write_length) { @@ -458,7 +458,7 @@ static int do_read(struct userdata *u) { return -1; } - u->read_index += r; + u->read_index += (size_t) r; pa_assert(u->read_index <= u->read_length); if (u->read_index == u->read_length) @@ -468,7 +468,7 @@ static int do_read(struct userdata *u) { return 0; } -static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) { +static void io_callback(pa_iochannel *io, void*userdata) { struct userdata *u = userdata; pa_assert(u); @@ -483,7 +483,7 @@ static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) { } } -static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, void *userdata) { +static void on_connection(pa_socket_client *c, pa_iochannel*io, void *userdata) { struct userdata *u = userdata; pa_socket_client_unref(u->client); @@ -545,7 +545,7 @@ int pa__init(pa_module*m) { u->format = (ss.format == PA_SAMPLE_U8 ? ESD_BITS8 : ESD_BITS16) | (ss.channels == 2 ? ESD_STEREO : ESD_MONO); - u->rate = ss.rate; + u->rate = (int32_t) ss.rate; u->block_size = pa_usec_to_bytes(PA_USEC_PER_SEC/20, &ss); u->read_data = u->write_data = NULL; diff --git a/src/modules/module-flat-volume.c b/src/modules/module-flat-volume.c new file mode 100644 index 00000000..9bc8055a --- /dev/null +++ b/src/modules/module-flat-volume.c @@ -0,0 +1,224 @@ +/*** + This file is part of PulseAudio. + + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). + Copyright 2004-2006, 2008 Lennart Poettering + + Contact: Marc-Andre Lureau <marc-andre.lureau@nokia.com> + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <regex.h> +#include <stdio.h> +#include <stdlib.h> + +#include <pulse/xmalloc.h> + +#include <pulsecore/core-error.h> +#include <pulsecore/module.h> +#include <pulsecore/core-util.h> +#include <pulsecore/log.h> +#include <pulsecore/sink-input.h> +#include <pulsecore/core-util.h> +#include <pulsecore/macro.h> + +#include "module-flat-volume-symdef.h" + +PA_MODULE_AUTHOR("Marc-Andre Lureau"); +PA_MODULE_DESCRIPTION("Flat volume"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_USAGE(""); + +struct userdata { + pa_subscription *subscription; + pa_hook_slot *sink_input_set_volume_hook_slot; + pa_hook_slot *sink_input_fixate_hook_slot; +}; + +static void process_input_volume_change( + pa_cvolume *dest_volume, + const pa_cvolume *dest_virtual_volume, + pa_channel_map *dest_channel_map, + pa_sink_input *this, + pa_sink *sink) { + + pa_sink_input *i; + uint32_t idx; + pa_cvolume max_volume, sink_volume; + + pa_assert(dest_volume); + pa_assert(dest_virtual_volume); + pa_assert(dest_channel_map); + pa_assert(sink); + + if (!(sink->flags & PA_SINK_DECIBEL_VOLUME)) + return; + + pa_log_debug("Sink input volume changed"); + + max_volume = *dest_virtual_volume; + pa_cvolume_remap(&max_volume, dest_channel_map, &sink->channel_map); + + for (i = PA_SINK_INPUT(pa_idxset_first(sink->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(sink->inputs, &idx))) { + /* skip this sink-input if we are processing a volume change request */ + if (this && this == i) + continue; + + if (pa_cvolume_max(&i->virtual_volume) > pa_cvolume_max(&max_volume)) { + max_volume = i->virtual_volume; + pa_cvolume_remap(&max_volume, &i->channel_map, &sink->channel_map); + } + } + + /* Set the master volume, and normalize inputs */ + if (!pa_cvolume_equal(&max_volume, &sink->volume)) { + + pa_sink_set_volume(sink, &max_volume); + + pa_log_debug("sink = %.2f (changed)", (double)pa_cvolume_avg(&sink->volume)/PA_VOLUME_NORM); + + /* Now, normalize each of the internal volume (client sink-input volume / sink master volume) */ + for (i = PA_SINK_INPUT(pa_idxset_first(sink->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(sink->inputs, &idx))) { + /* skip this sink-input if we are processing a volume change request */ + if (this && this == i) + continue; + + sink_volume = max_volume; + pa_cvolume_remap(&sink_volume, &sink->channel_map, &i->channel_map); + pa_sw_cvolume_divide(&i->volume, &i->virtual_volume, &sink_volume); + pa_log_debug("sink input { id = %d, flat = %.2f, true = %.2f }", + i->index, + (double)pa_cvolume_avg(&i->virtual_volume)/PA_VOLUME_NORM, + (double)pa_cvolume_avg(&i->volume)/PA_VOLUME_NORM); + pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, &i->volume, 1), 0, NULL, pa_xfree); + } + } else + pa_log_debug("sink = %.2f", (double)pa_cvolume_avg(&sink->volume)/PA_VOLUME_NORM); + + /* and this one */ + + sink_volume = max_volume; + pa_cvolume_remap(&sink_volume, &sink->channel_map, dest_channel_map); + pa_sw_cvolume_divide(dest_volume, dest_virtual_volume, &sink_volume); + pa_log_debug("caller sink input: { id = %d, flat = %.2f, true = %.2f }", + this ? (int)this->index : -1, + (double)pa_cvolume_avg(dest_virtual_volume)/PA_VOLUME_NORM, + (double)pa_cvolume_avg(dest_volume)/PA_VOLUME_NORM); +} + +static pa_hook_result_t sink_input_set_volume_hook_callback(pa_core *c, pa_sink_input_set_volume_data *this, struct userdata *u) { + pa_assert(this); + pa_assert(this->sink_input); + + process_input_volume_change(&this->volume, &this->virtual_volume, &this->sink_input->channel_map, + this->sink_input, this->sink_input->sink); + + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *core, pa_sink_input_new_data *this, struct userdata *u) { + pa_assert(this); + pa_assert(this->sink); + + process_input_volume_change(&this->volume, &this->virtual_volume, &this->channel_map, + NULL, this->sink); + + return PA_HOOK_OK; +} + +static void subscribe_callback(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { + struct userdata *u = userdata; + pa_sink *sink; + pa_sink_input *i; + uint32_t iidx; + pa_cvolume sink_volume; + + pa_assert(core); + pa_assert(u); + + if (t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW) && + t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE)) + return; + + if (!(sink = pa_idxset_get_by_index(core->sinks, idx))) + return; + + if (!(sink->flags & PA_SINK_DECIBEL_VOLUME)) + return; + + pa_log_debug("Sink volume changed"); + pa_log_debug("sink = %.2f", (double)pa_cvolume_avg(pa_sink_get_volume(sink, FALSE)) / PA_VOLUME_NORM); + + sink_volume = *pa_sink_get_volume(sink, FALSE); + + for (i = PA_SINK_INPUT(pa_idxset_first(sink->inputs, &iidx)); i; i = PA_SINK_INPUT(pa_idxset_next(sink->inputs, &iidx))) { + pa_cvolume si_volume; + + si_volume = sink_volume; + pa_cvolume_remap(&si_volume, &sink->channel_map, &i->channel_map); + pa_sw_cvolume_multiply(&i->virtual_volume, &i->volume, &si_volume); + pa_log_debug("sink input = { id = %d, flat = %.2f, true = %.2f }", + i->index, + (double)pa_cvolume_avg(&i->virtual_volume)/PA_VOLUME_NORM, + (double)pa_cvolume_avg(&i->volume)/PA_VOLUME_NORM); + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); + } +} + +int pa__init(pa_module*m) { + struct userdata *u; + + pa_assert(m); + + u = pa_xnew(struct userdata, 1); + m->userdata = u; + + u->sink_input_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_fixate_hook_callback, u); + u->sink_input_set_volume_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_set_volume_hook_callback, u); + + u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK, subscribe_callback, u); + + return 0; +} + +void pa__done(pa_module*m) { + struct userdata* u; + + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->subscription) + pa_subscription_free(u->subscription); + + if (u->sink_input_set_volume_hook_slot) + pa_hook_slot_free(u->sink_input_set_volume_hook_slot); + if (u->sink_input_fixate_hook_slot) + pa_hook_slot_free(u->sink_input_fixate_hook_slot); + + pa_xfree(u); +} diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index caa7a1fa..c76a366c 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -108,7 +108,7 @@ static void hal_device_free(struct device* d) { pa_xfree(d); } -static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { +static void hal_device_free_cb(void *d, void *data) { hal_device_free(d); } @@ -405,7 +405,7 @@ static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, const s dbus_error_init(&error); if (!pa_hashmap_get(td->u->devices, td->udi)) { - int b; + dbus_bool_t b; struct device *d; b = libhal_device_exists(td->u->context, td->udi, &error); @@ -433,7 +433,7 @@ static void device_added_cb(LibHalContext *context, const char *udi) { struct timeval tv; struct timerdata *t; struct userdata *u; - int good = 0; + pa_bool_t good = FALSE; pa_assert_se(u = libhal_ctx_get_user_data(context)); @@ -749,17 +749,17 @@ int pa__init(pa_module*m) { } if ((api = pa_modargs_get_value(ma, "api", NULL))) { - int good = 0; + pa_bool_t good = FALSE; #ifdef HAVE_ALSA if (strcmp(api, CAPABILITY_ALSA) == 0) { - good = 1; + good = TRUE; api = CAPABILITY_ALSA; } #endif #ifdef HAVE_OSS if (strcmp(api, CAPABILITY_OSS) == 0) { - good = 1; + good = TRUE; api = CAPABILITY_OSS; } #endif diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index edc543a8..555cb825 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -130,12 +130,12 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse void *p; pa_assert(offset > 0); - nbytes = offset * pa_frame_size(&u->sink->sample_spec); + nbytes = (size_t) offset * pa_frame_size(&u->sink->sample_spec); pa_sink_render_full(u->sink, nbytes, &chunk); p = (uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index; - pa_deinterleave(p, u->buffer, u->channels, sizeof(float), offset); + pa_deinterleave(p, u->buffer, u->channels, sizeof(float), (unsigned) offset); pa_memblock_release(chunk.memblock); pa_memblock_unref(chunk.memblock); @@ -149,10 +149,10 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse ss.channels = 1; for (c = 0; c < u->channels; c++) - pa_silence_memory(u->buffer[c], offset * pa_sample_size(&ss), &ss); + pa_silence_memory(u->buffer[c], (size_t) offset * pa_sample_size(&ss), &ss); } - u->frames_in_buffer = offset; + u->frames_in_buffer = (jack_nframes_t) offset; u->saved_frame_time = * (jack_nframes_t*) data; u->saved_frame_time_valid = TRUE; @@ -342,7 +342,7 @@ int pa__init(pa_module*m) { pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client)); - ss.channels = u->channels = channels; + u->channels = ss.channels = (uint8_t) channels; ss.rate = jack_get_sample_rate(u->client); ss.format = PA_SAMPLE_FLOAT32NE; diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 03f9d15c..9eccbbfa 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -116,7 +116,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off if (u->source->thread_info.state == PA_SOURCE_RUNNING) pa_source_post(u->source, chunk); - u->saved_frame_time = offset; + u->saved_frame_time = (jack_nframes_t) offset; u->saved_frame_time_valid = TRUE; return 0; @@ -309,7 +309,7 @@ int pa__init(pa_module*m) { pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client)); - ss.channels = u->channels = channels; + u->channels = ss.channels = (uint8_t) channels; ss.rate = jack_get_sample_rate(u->client); ss.format = PA_SAMPLE_FLOAT32NE; diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c index 23eeb340..a27ed712 100644 --- a/src/modules/module-ladspa-sink.c +++ b/src/modules/module-ladspa-sink.c @@ -187,7 +187,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk pa_assert(tchunk.length > 0); fs = pa_frame_size(&i->sample_spec); - n = PA_MIN(tchunk.length, u->block_size) / fs; + n = (unsigned) (PA_MIN(tchunk.length, u->block_size) / fs); pa_assert(n > 0); @@ -359,6 +359,16 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s } } +/* Called from main context */ +static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + return u->sink != dest; +} + int pa__init(pa_module*m) { struct userdata *u; pa_sample_spec ss; @@ -502,9 +512,9 @@ int pa__init(pa_module*m) { u->block_size = pa_frame_align(pa_mempool_block_size_max(m->core->mempool), &ss); - u->input = (LADSPA_Data*) pa_xnew(uint8_t, u->block_size); + u->input = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size); if (LADSPA_IS_INPLACE_BROKEN(d->Properties)) - u->output = (LADSPA_Data*) pa_xnew(uint8_t, u->block_size); + u->output = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size); else u->output = u->input; @@ -530,8 +540,8 @@ int pa__init(pa_module*m) { char *k; unsigned long h; - u->control = pa_xnew(LADSPA_Data, n_control); - use_default = pa_xnew(pa_bool_t, n_control); + u->control = pa_xnew(LADSPA_Data, (unsigned) n_control); + use_default = pa_xnew(pa_bool_t, (unsigned) n_control); p = 0; while ((k = pa_split(cdata, ",", &state)) && p < n_control) { @@ -552,7 +562,7 @@ int pa__init(pa_module*m) { pa_xfree(k); use_default[p] = FALSE; - u->control[p++] = f; + u->control[p++] = (LADSPA_Data) f; } /* The previous loop doesn't take the last control value into account @@ -601,8 +611,8 @@ int pa__init(pa_module*m) { upper = d->PortRangeHints[p].UpperBound; if (LADSPA_IS_HINT_SAMPLE_RATE(hint)) { - lower *= ss.rate; - upper *= ss.rate; + lower *= (LADSPA_Data) ss.rate; + upper *= (LADSPA_Data) ss.rate; } switch (hint & LADSPA_HINT_DEFAULT_MASK) { @@ -617,23 +627,23 @@ int pa__init(pa_module*m) { case LADSPA_HINT_DEFAULT_LOW: if (LADSPA_IS_HINT_LOGARITHMIC(hint)) - u->control[h] = exp(log(lower) * 0.75 + log(upper) * 0.25); + u->control[h] = (LADSPA_Data) exp(log(lower) * 0.75 + log(upper) * 0.25); else - u->control[h] = lower * 0.75 + upper * 0.25; + u->control[h] = (LADSPA_Data) (lower * 0.75 + upper * 0.25); break; case LADSPA_HINT_DEFAULT_MIDDLE: if (LADSPA_IS_HINT_LOGARITHMIC(hint)) - u->control[h] = exp(log(lower) * 0.5 + log(upper) * 0.5); + u->control[h] = (LADSPA_Data) exp(log(lower) * 0.5 + log(upper) * 0.5); else - u->control[h] = lower * 0.5 + upper * 0.5; + u->control[h] = (LADSPA_Data) (lower * 0.5 + upper * 0.5); break; case LADSPA_HINT_DEFAULT_HIGH: if (LADSPA_IS_HINT_LOGARITHMIC(hint)) - u->control[h] = exp(log(lower) * 0.25 + log(upper) * 0.75); + u->control[h] = (LADSPA_Data) exp(log(lower) * 0.25 + log(upper) * 0.75); else - u->control[h] = lower * 0.25 + upper * 0.75; + u->control[h] = (LADSPA_Data) (lower * 0.25 + upper * 0.75); break; case LADSPA_HINT_DEFAULT_0: @@ -737,6 +747,7 @@ int pa__init(pa_module*m) { u->sink_input->attach = sink_input_attach_cb; u->sink_input->detach = sink_input_detach_cb; u->sink_input->state_change = sink_input_state_change_cb; + u->sink_input->may_move_to = sink_input_may_move_to_cb; u->sink_input->userdata = u; pa_sink_put(u->sink); diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c index f34f7be3..97e97dc7 100644 --- a/src/modules/module-lirc.c +++ b/src/modules/module-lirc.c @@ -65,7 +65,7 @@ struct userdata { static int lirc_in_use = 0; -static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) { +static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) { struct userdata *u = userdata; char *name = NULL, *code = NULL; @@ -122,7 +122,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC pa_log("Failed to get sink '%s'", u->sink_name); else { int i; - pa_cvolume cv = *pa_sink_get_volume(s); + pa_cvolume cv = *pa_sink_get_volume(s, FALSE); #define DELTA (PA_VOLUME_NORM/20) @@ -159,7 +159,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC case MUTE_TOGGLE: - pa_sink_set_mute(s, !pa_sink_get_mute(s)); + pa_sink_set_mute(s, !pa_sink_get_mute(s, FALSE)); break; case INVALID: diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index 7da77c0d..21f176a4 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -76,7 +76,7 @@ struct userdata { pa_module *module; }; -static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) { +static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) { struct userdata *u = userdata; pa_assert(io); @@ -113,7 +113,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC pa_log("Failed to get sink '%s'", u->sink_name); else { int i; - pa_cvolume cv = *pa_sink_get_volume(s); + pa_cvolume cv = *pa_sink_get_volume(s, FALSE); #define DELTA (PA_VOLUME_NORM/20) @@ -142,7 +142,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC case MUTE_TOGGLE: - pa_sink_set_mute(s, !pa_sink_get_mute(s)); + pa_sink_set_mute(s, !pa_sink_get_mute(s, FALSE)); break; case INVALID: diff --git a/src/modules/module-native-protocol-fd.c b/src/modules/module-native-protocol-fd.c index fa9c0e4f..f17f435a 100644 --- a/src/modules/module-native-protocol-fd.c +++ b/src/modules/module-native-protocol-fd.c @@ -48,7 +48,8 @@ static const char* const valid_modargs[] = { int pa__init(pa_module*m) { pa_iochannel *io; pa_modargs *ma; - int fd, r = -1; + int32_t fd; + int r = -1; pa_native_options *options = NULL; pa_assert(m); @@ -63,18 +64,16 @@ int pa__init(pa_module*m) { goto finish; } - options = pa_native_options_new(); - options->module = m; - options->auth_anonymous = TRUE; + m->userdata = pa_native_protocol_get(m->core); io = pa_iochannel_new(m->core->mainloop, fd, fd); - m->userdata = pa_native_protocol_get(m->core); + options = pa_native_options_new(); + options->module = m; + options->auth_anonymous = TRUE; pa_native_protocol_connect(m->userdata, io, options); - pa_native_options_unref(options); - r = 0; finish: diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 9162960f..470c622e 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -137,13 +137,13 @@ static void process_rewind(struct userdata *u, pa_usec_t now) { pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes); if (u->timestamp <= now) - return; + goto do_nothing; delay = u->timestamp - now; in_buffer = pa_usec_to_bytes(delay, &u->sink->sample_spec); if (in_buffer <= 0) - return; + goto do_nothing; if (rewind_nbytes > in_buffer) rewind_nbytes = in_buffer; @@ -152,6 +152,11 @@ static void process_rewind(struct userdata *u, pa_usec_t now) { u->timestamp -= pa_bytes_to_usec(rewind_nbytes, &u->sink->sample_spec); pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes); + return; + +do_nothing: + + pa_sink_process_rewind(u->sink, 0); } static void process_render(struct userdata *u, pa_usec_t now) { diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 15b1e956..23a32549 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -258,7 +258,7 @@ static int mmap_write(struct userdata *u) { u->out_mmap_saved_nfrags = 0; if (info.blocks > 0) - mmap_fill_memblocks(u, info.blocks); + mmap_fill_memblocks(u, (unsigned) info.blocks); return info.blocks; } @@ -336,7 +336,7 @@ static int mmap_read(struct userdata *u) { u->in_mmap_saved_nfrags = 0; if (info.blocks > 0) { - mmap_post_memblocks(u, info.blocks); + mmap_post_memblocks(u, (unsigned) info.blocks); mmap_clear_memblocks(u, u->in_nfrags/2); } @@ -356,12 +356,12 @@ static pa_usec_t mmap_sink_get_latency(struct userdata *u) { u->out_mmap_saved_nfrags += info.blocks; - bpos = ((u->out_mmap_current + u->out_mmap_saved_nfrags) * u->out_fragment_size) % u->out_hwbuf_size; + bpos = ((u->out_mmap_current + (unsigned) u->out_mmap_saved_nfrags) * u->out_fragment_size) % u->out_hwbuf_size; if (bpos <= (size_t) info.ptr) - n = u->out_hwbuf_size - (info.ptr - bpos); + n = u->out_hwbuf_size - ((size_t) info.ptr - bpos); else - n = bpos - info.ptr; + n = bpos - (size_t) info.ptr; /* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->out_fragment_size, u->out_fragments); */ @@ -380,12 +380,12 @@ static pa_usec_t mmap_source_get_latency(struct userdata *u) { } u->in_mmap_saved_nfrags += info.blocks; - bpos = ((u->in_mmap_current + u->in_mmap_saved_nfrags) * u->in_fragment_size) % u->in_hwbuf_size; + bpos = ((u->in_mmap_current + (unsigned) u->in_mmap_saved_nfrags) * u->in_fragment_size) % u->in_hwbuf_size; if (bpos <= (size_t) info.ptr) - n = info.ptr - bpos; + n = (size_t) info.ptr - bpos; else - n = u->in_hwbuf_size - bpos + info.ptr; + n = u->in_hwbuf_size - bpos + (size_t) info.ptr; /* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->in_fragment_size, u->in_fragments); */ @@ -404,7 +404,7 @@ static pa_usec_t io_sink_get_latency(struct userdata *u) { pa_log_info("Device doesn't support SNDCTL_DSP_GETODELAY: %s", pa_cstrerror(errno)); u->use_getodelay = 0; } else - r = pa_bytes_to_usec(arg, &u->sink->sample_spec); + r = pa_bytes_to_usec((size_t) arg, &u->sink->sample_spec); } @@ -415,7 +415,7 @@ static pa_usec_t io_sink_get_latency(struct userdata *u) { pa_log_info("Device doesn't support SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno)); u->use_getospace = 0; } else - r = pa_bytes_to_usec(info.bytes, &u->sink->sample_spec); + r = pa_bytes_to_usec((size_t) info.bytes, &u->sink->sample_spec); } if (u->memchunk.memblock) @@ -437,7 +437,7 @@ static pa_usec_t io_source_get_latency(struct userdata *u) { pa_log_info("Device doesn't support SNDCTL_DSP_GETISPACE: %s", pa_cstrerror(errno)); u->use_getispace = 0; } else - r = pa_bytes_to_usec(info.bytes, &u->source->sample_spec); + r = pa_bytes_to_usec((size_t) info.bytes, &u->source->sample_spec); } return r; @@ -528,8 +528,9 @@ static int unsuspend(struct userdata *u) { if ((u->fd = pa_oss_open(u->device_name, &m, NULL)) < 0) { pa_log_warn("Resume failed, device busy (%s)", pa_cstrerror(errno)); return -1; + } - if (m != u->mode) + if (m != u->mode) { pa_log_warn("Resume failed, couldn't open device with original access mode."); goto fail; } @@ -859,7 +860,7 @@ static int source_set_volume(pa_source *s) { static void thread_func(void *userdata) { struct userdata *u = userdata; int write_type = 0, read_type = 0; - unsigned short revents = 0; + short revents = 0; pa_assert(u); @@ -898,7 +899,7 @@ static void thread_func(void *userdata) { ssize_t l; pa_bool_t loop = FALSE, work_done = FALSE; - l = u->out_fragment_size; + l = (ssize_t) u->out_fragment_size; if (u->use_getospace) { audio_buf_info info; @@ -919,14 +920,14 @@ static void thread_func(void *userdata) { /* Round down to multiples of the fragment size, * because OSS needs that (at least some versions * do) */ - l = (l/u->out_fragment_size) * u->out_fragment_size; + l = (l/(ssize_t) u->out_fragment_size) * (ssize_t) u->out_fragment_size; /* Hmm, so poll() signalled us that we can read * something, but GETOSPACE told us there was nothing? * Hmm, make the best of it, try to read some data, to * avoid spinning forever. */ if (l <= 0 && (revents & POLLOUT)) { - l = u->out_fragment_size; + l = (ssize_t) u->out_fragment_size; loop = FALSE; } @@ -935,7 +936,7 @@ static void thread_func(void *userdata) { ssize_t t; if (u->memchunk.length <= 0) - pa_sink_render(u->sink, l, &u->memchunk); + pa_sink_render(u->sink, (size_t) l, &u->memchunk); pa_assert(u->memchunk.length > 0); @@ -965,8 +966,8 @@ static void thread_func(void *userdata) { } else { - u->memchunk.index += t; - u->memchunk.length -= t; + u->memchunk.index += (size_t) t; + u->memchunk.length -= (size_t) t; if (u->memchunk.length <= 0) { pa_memblock_unref(u->memchunk.memblock); @@ -1009,7 +1010,7 @@ static void thread_func(void *userdata) { pa_memchunk memchunk; pa_bool_t loop = FALSE, work_done = FALSE; - l = u->in_fragment_size; + l = (ssize_t) u->in_fragment_size; if (u->use_getispace) { audio_buf_info info; @@ -1023,15 +1024,16 @@ static void thread_func(void *userdata) { } } - l = (l/u->in_fragment_size) * u->in_fragment_size; + l = (l/(ssize_t) u->in_fragment_size) * (ssize_t) u->in_fragment_size; if (l <= 0 && (revents & POLLIN)) { - l = u->in_fragment_size; + l = (ssize_t) u->in_fragment_size; loop = FALSE; } while (l > 0) { - ssize_t t, k; + ssize_t t; + size_t k; pa_assert(l > 0); @@ -1039,8 +1041,8 @@ static void thread_func(void *userdata) { k = pa_memblock_get_length(memchunk.memblock); - if (k > l) - k = l; + if (k > (size_t) l) + k = (size_t) l; k = (k/u->frame_size)*u->frame_size; @@ -1071,7 +1073,7 @@ static void thread_func(void *userdata) { } else { memchunk.index = 0; - memchunk.length = t; + memchunk.length = (size_t) t; pa_source_post(u->source, &memchunk); pa_memblock_unref(memchunk.memblock); @@ -1099,9 +1101,9 @@ static void thread_func(void *userdata) { pa_assert(u->fd >= 0); pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); - pollfd->events = - ((u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) ? POLLIN : 0) | - ((u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) ? POLLOUT : 0); + pollfd->events = (short) + (((u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) ? POLLIN : 0) | + ((u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) ? POLLOUT : 0)); } /* Hmm, nothing to do. Let's sleep */ @@ -1179,10 +1181,10 @@ int pa__init(pa_module*m) { goto fail; } - nfrags = m->core->default_n_fragments; - frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*1000, &ss); + nfrags = (int) m->core->default_n_fragments; + frag_size = (int) pa_usec_to_bytes(m->core->default_fragment_size_msec*1000, &ss); if (frag_size <= 0) - frag_size = pa_frame_size(&ss); + frag_size = (int) pa_frame_size(&ss); if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { pa_log("Failed to parse fragments arguments"); @@ -1238,8 +1240,8 @@ int pa__init(pa_module*m) { u->mode = mode; u->frame_size = pa_frame_size(&ss); u->device_name = pa_xstrdup(dev); - u->in_nfrags = u->out_nfrags = u->nfrags = nfrags; - u->out_fragment_size = u->in_fragment_size = u->frag_size = frag_size; + u->in_nfrags = u->out_nfrags = (uint32_t) (u->nfrags = nfrags); + u->out_fragment_size = u->in_fragment_size = (uint32_t) (u->frag_size = frag_size); u->use_mmap = use_mmap; u->rtpoll = pa_rtpoll_new(); pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); @@ -1248,15 +1250,15 @@ int pa__init(pa_module*m) { if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) { pa_log_info("Input -- %u fragments of size %u.", info.fragstotal, info.fragsize); - u->in_fragment_size = info.fragsize; - u->in_nfrags = info.fragstotal; + u->in_fragment_size = (uint32_t) info.fragsize; + u->in_nfrags = (uint32_t) info.fragstotal; u->use_getispace = TRUE; } if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) { pa_log_info("Output -- %u fragments of size %u.", info.fragstotal, info.fragsize); - u->out_fragment_size = info.fragsize; - u->out_nfrags = info.fragstotal; + u->out_fragment_size = (uint32_t) info.fragsize; + u->out_nfrags = (uint32_t) info.fragstotal; u->use_getospace = TRUE; } diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index f389cd06..ae230b2c 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -145,8 +145,8 @@ static int process_render(struct userdata *u) { } else { - u->memchunk.index += l; - u->memchunk.length -= l; + u->memchunk.index += (size_t) l; + u->memchunk.length -= (size_t) l; if (u->memchunk.length <= 0) { pa_memblock_unref(u->memchunk.memblock); @@ -189,7 +189,7 @@ static void thread_func(void *userdata) { } /* Hmm, nothing to do. Let's sleep */ - pollfd->events = u->sink->thread_info.state == PA_SINK_RUNNING ? POLLOUT : 0; + pollfd->events = (short) (u->sink->thread_info.state == PA_SINK_RUNNING ? POLLOUT : 0); if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) goto fail; diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index b0de34ca..25151d95 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -135,9 +135,9 @@ static void thread_func(void *userdata) { } else { - u->memchunk.length = l; + u->memchunk.length = (size_t) l; pa_source_post(u->source, &u->memchunk); - u->memchunk.index += l; + u->memchunk.index += (size_t) l; if (u->memchunk.index >= pa_memblock_get_length(u->memchunk.memblock)) { pa_memblock_unref(u->memchunk.memblock); @@ -149,7 +149,7 @@ static void thread_func(void *userdata) { } /* Hmm, nothing to do. Let's sleep */ - pollfd->events = u->source->thread_info.state == PA_SOURCE_RUNNING ? POLLIN : 0; + pollfd->events = (short) (u->source->thread_info.state == PA_SOURCE_RUNNING ? POLLIN : 0); if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) goto fail; diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 8136c6fc..aefd4020 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -148,7 +148,7 @@ # include <pulsecore/esound.h> # define TCPWRAP_SERVICE "esound" # define IPV4_PORT ESD_DEFAULT_PORT -# define MODULE_ARGUMENTS_COMMON "sink", "source", "auth-anonymous", "cookie", "auth-cookie", "auth-cookie-enabled" +# define MODULE_ARGUMENTS_COMMON "sink", "source", "auth-anonymous", "cookie", "auth-cookie", "auth-cookie-enabled", # ifdef USE_TCP_SOCKETS # include "module-esound-protocol-tcp-symdef.h" @@ -260,7 +260,7 @@ int pa__init(pa_module*m) { goto fail; } - u = pa_xnew0(struct userdata, 1); + m->userdata = u = pa_xnew0(struct userdata, 1); u->module = m; #if defined(USE_PROTOCOL_SIMPLE) @@ -299,11 +299,11 @@ int pa__init(pa_module*m) { listen_on = pa_modargs_get_value(ma, "listen", NULL); if (listen_on) { - u->socket_server_ipv6 = pa_socket_server_new_ipv6_string(m->core->mainloop, listen_on, port, TCPWRAP_SERVICE); - u->socket_server_ipv4 = pa_socket_server_new_ipv4_string(m->core->mainloop, listen_on, port, TCPWRAP_SERVICE); + u->socket_server_ipv6 = pa_socket_server_new_ipv6_string(m->core->mainloop, listen_on, (uint16_t) port, TCPWRAP_SERVICE); + u->socket_server_ipv4 = pa_socket_server_new_ipv4_string(m->core->mainloop, listen_on, (uint16_t) port, TCPWRAP_SERVICE); } else { - u->socket_server_ipv6 = pa_socket_server_new_ipv6_any(m->core->mainloop, port, TCPWRAP_SERVICE); - u->socket_server_ipv4 = pa_socket_server_new_ipv4_any(m->core->mainloop, port, TCPWRAP_SERVICE); + u->socket_server_ipv6 = pa_socket_server_new_ipv6_any(m->core->mainloop, (uint16_t) port, TCPWRAP_SERVICE); + u->socket_server_ipv4 = pa_socket_server_new_ipv4_any(m->core->mainloop, (uint16_t) port, TCPWRAP_SERVICE); } if (!u->socket_server_ipv4 && !u->socket_server_ipv6) @@ -327,7 +327,7 @@ int pa__init(pa_module*m) { /* This socket doesn't reside in our own runtime dir but in * /tmp/.esd/, hence we have to create the dir first */ - if (pa_make_secure_parent_dir(u->socket_path, pa_in_system_mode() ? 0755 : 0700, (uid_t)-1, (gid_t)-1) < 0) { + if (pa_make_secure_parent_dir(u->socket_path, pa_in_system_mode() ? 0755U : 0700U, (uid_t)-1, (gid_t)-1) < 0) { pa_log("Failed to create socket directory '%s': %s\n", u->socket_path, pa_cstrerror(errno)); goto fail; } @@ -368,8 +368,6 @@ int pa__init(pa_module*m) { # endif #endif - m->userdata = u; - if (ma) pa_modargs_free(ma); @@ -390,7 +388,8 @@ void pa__done(pa_module*m) { pa_assert(m); - u = m->userdata; + if (!(u = m->userdata)) + return; #if defined(USE_PROTOCOL_SIMPLE) if (u->simple_protocol) { diff --git a/src/modules/module-raop-discover.c b/src/modules/module-raop-discover.c new file mode 100644 index 00000000..3706d921 --- /dev/null +++ b/src/modules/module-raop-discover.c @@ -0,0 +1,380 @@ +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2008 Colin Guthrie + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <avahi-client/client.h> +#include <avahi-client/lookup.h> +#include <avahi-common/alternative.h> +#include <avahi-common/error.h> +#include <avahi-common/domain.h> +#include <avahi-common/malloc.h> + +#include <pulse/xmalloc.h> +#include <pulse/util.h> + +#include <pulsecore/sink.h> +#include <pulsecore/source.h> +#include <pulsecore/native-common.h> +#include <pulsecore/core-util.h> +#include <pulsecore/log.h> +#include <pulsecore/core-subscribe.h> +#include <pulsecore/hashmap.h> +#include <pulsecore/modargs.h> +#include <pulsecore/namereg.h> +#include <pulsecore/avahi-wrap.h> + +#include "module-raop-discover-symdef.h" + +PA_MODULE_AUTHOR("Colin Guthrie"); +PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Discovery of Airtunes"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); + +#define SERVICE_TYPE_SINK "_raop._tcp" + +static const char* const valid_modargs[] = { + NULL +}; + +struct tunnel { + AvahiIfIndex interface; + AvahiProtocol protocol; + char *name, *type, *domain; + uint32_t module_index; +}; + +struct userdata { + pa_core *core; + pa_module *module; + AvahiPoll *avahi_poll; + AvahiClient *client; + AvahiServiceBrowser *sink_browser; + + pa_hashmap *tunnels; +}; + +static unsigned tunnel_hash(const void *p) { + const struct tunnel *t = p; + + return + (unsigned) t->interface + + (unsigned) t->protocol + + pa_idxset_string_hash_func(t->name) + + pa_idxset_string_hash_func(t->type) + + pa_idxset_string_hash_func(t->domain); +} + +static int tunnel_compare(const void *a, const void *b) { + const struct tunnel *ta = a, *tb = b; + int r; + + if (ta->interface != tb->interface) + return 1; + if (ta->protocol != tb->protocol) + return 1; + if ((r = strcmp(ta->name, tb->name))) + return r; + if ((r = strcmp(ta->type, tb->type))) + return r; + if ((r = strcmp(ta->domain, tb->domain))) + return r; + + return 0; +} + +static struct tunnel *tunnel_new( + AvahiIfIndex interface, AvahiProtocol protocol, + const char *name, const char *type, const char *domain) { + + struct tunnel *t; + t = pa_xnew(struct tunnel, 1); + t->interface = interface; + t->protocol = protocol; + t->name = pa_xstrdup(name); + t->type = pa_xstrdup(type); + t->domain = pa_xstrdup(domain); + t->module_index = PA_IDXSET_INVALID; + return t; +} + +static void tunnel_free(struct tunnel *t) { + pa_assert(t); + pa_xfree(t->name); + pa_xfree(t->type); + pa_xfree(t->domain); + pa_xfree(t); +} + +static void resolver_cb( + AvahiServiceResolver *r, + AvahiIfIndex interface, AvahiProtocol protocol, + AvahiResolverEvent event, + const char *name, const char *type, const char *domain, + const char *host_name, const AvahiAddress *a, uint16_t port, + AvahiStringList *txt, + AvahiLookupResultFlags flags, + void *userdata) { + + struct userdata *u = userdata; + struct tunnel *tnl; + + pa_assert(u); + + tnl = tunnel_new(interface, protocol, name, type, domain); + + if (event != AVAHI_RESOLVER_FOUND) + pa_log("Resolving of '%s' failed: %s", name, avahi_strerror(avahi_client_errno(u->client))); + else { + char *device = NULL, *dname, *vname, *args; + char at[AVAHI_ADDRESS_STR_MAX]; + AvahiStringList *l; + pa_module *m; + + for (l = txt; l; l = l->next) { + char *key, *value; + pa_assert_se(avahi_string_list_get_pair(l, &key, &value, NULL) == 0); + + pa_log_debug("Found key: '%s' with value: '%s'", key, value); + if (strcmp(key, "device") == 0) { + pa_xfree(device); + device = value; + value = NULL; + } + avahi_free(key); + avahi_free(value); + } + + if (device) + dname = pa_sprintf_malloc("airtunes.%s.%s", host_name, device); + else + dname = pa_sprintf_malloc("airtunes.%s", host_name); + + if (!(vname = pa_namereg_make_valid_name(dname))) { + pa_log("Cannot construct valid device name from '%s'.", dname); + avahi_free(device); + pa_xfree(dname); + goto finish; + } + pa_xfree(dname); + + /* + TODO: allow this syntax of server name in things.... + args = pa_sprintf_malloc("server=[%s]:%u " + "sink_name=%s", + avahi_address_snprint(at, sizeof(at), a), port, + vname);*/ + args = pa_sprintf_malloc("server=%s " + "sink_name=%s", + avahi_address_snprint(at, sizeof(at), a), + vname); + + pa_log_debug("Loading module-raop-sink with arguments '%s'", args); + + if ((m = pa_module_load(u->core, "module-raop-sink", args))) { + tnl->module_index = m->index; + pa_hashmap_put(u->tunnels, tnl, tnl); + tnl = NULL; + } + + pa_xfree(vname); + pa_xfree(args); + avahi_free(device); + } + +finish: + + avahi_service_resolver_free(r); + + if (tnl) + tunnel_free(tnl); +} + +static void browser_cb( + AvahiServiceBrowser *b, + AvahiIfIndex interface, AvahiProtocol protocol, + AvahiBrowserEvent event, + const char *name, const char *type, const char *domain, + AvahiLookupResultFlags flags, + void *userdata) { + + struct userdata *u = userdata; + struct tunnel *t; + + pa_assert(u); + + if (flags & AVAHI_LOOKUP_RESULT_LOCAL) + return; + + t = tunnel_new(interface, protocol, name, type, domain); + + if (event == AVAHI_BROWSER_NEW) { + + if (!pa_hashmap_get(u->tunnels, t)) + if (!(avahi_service_resolver_new(u->client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolver_cb, u))) + pa_log("avahi_service_resolver_new() failed: %s", avahi_strerror(avahi_client_errno(u->client))); + + /* We ignore the returned resolver object here, since the we don't + * need to attach any special data to it, and we can still destory + * it from the callback */ + + } else if (event == AVAHI_BROWSER_REMOVE) { + struct tunnel *t2; + + if ((t2 = pa_hashmap_get(u->tunnels, t))) { + pa_module_unload_by_index(u->core, t2->module_index, TRUE); + pa_hashmap_remove(u->tunnels, t2); + tunnel_free(t2); + } + } + + tunnel_free(t); +} + +static void client_callback(AvahiClient *c, AvahiClientState state, void *userdata) { + struct userdata *u = userdata; + + pa_assert(c); + pa_assert(u); + + u->client = c; + + switch (state) { + case AVAHI_CLIENT_S_REGISTERING: + case AVAHI_CLIENT_S_RUNNING: + case AVAHI_CLIENT_S_COLLISION: + + if (!u->sink_browser) { + + if (!(u->sink_browser = avahi_service_browser_new( + c, + AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, + SERVICE_TYPE_SINK, + NULL, + 0, + browser_cb, u))) { + + pa_log("avahi_service_browser_new() failed: %s", avahi_strerror(avahi_client_errno(c))); + pa_module_unload_request(u->module, TRUE); + } + } + + break; + + case AVAHI_CLIENT_FAILURE: + if (avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) { + int error; + + pa_log_debug("Avahi daemon disconnected."); + + if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) { + pa_log("avahi_client_new() failed: %s", avahi_strerror(error)); + pa_module_unload_request(u->module, TRUE); + } + } + + /* Fall through */ + + case AVAHI_CLIENT_CONNECTING: + + if (u->sink_browser) { + avahi_service_browser_free(u->sink_browser); + u->sink_browser = NULL; + } + + break; + + default: ; + } +} + +int pa__init(pa_module*m) { + + struct userdata *u; + pa_modargs *ma = NULL; + int error; + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments."); + goto fail; + } + + m->userdata = u = pa_xnew(struct userdata, 1); + u->core = m->core; + u->module = m; + u->sink_browser = NULL; + + u->tunnels = pa_hashmap_new(tunnel_hash, tunnel_compare); + + u->avahi_poll = pa_avahi_poll_new(m->core->mainloop); + + if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) { + pa_log("pa_avahi_client_new() failed: %s", avahi_strerror(error)); + goto fail; + } + + pa_modargs_free(ma); + + return 0; + +fail: + pa__done(m); + + if (ma) + pa_modargs_free(ma); + + return -1; +} + +void pa__done(pa_module*m) { + struct userdata*u; + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->client) + avahi_client_free(u->client); + + if (u->avahi_poll) + pa_avahi_poll_free(u->avahi_poll); + + if (u->tunnels) { + struct tunnel *t; + + while ((t = pa_hashmap_steal_first(u->tunnels))) { + pa_module_unload_by_index(u->core, t->module_index, TRUE); + tunnel_free(t); + } + + pa_hashmap_free(u->tunnels, NULL, NULL); + } + + pa_xfree(u); +} diff --git a/src/modules/module-raop-sink.c b/src/modules/module-raop-sink.c new file mode 100644 index 00000000..62f0a73c --- /dev/null +++ b/src/modules/module-raop-sink.c @@ -0,0 +1,675 @@ +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2008 Colin Guthrie + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <sys/stat.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <limits.h> +#include <poll.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <sys/ioctl.h> + +#ifdef HAVE_LINUX_SOCKIOS_H +#include <linux/sockios.h> +#endif + +#include <pulse/xmalloc.h> +#include <pulse/timeval.h> + +#include <pulsecore/core-error.h> +#include <pulsecore/iochannel.h> +#include <pulsecore/sink.h> +#include <pulsecore/module.h> +#include <pulsecore/core-util.h> +#include <pulsecore/modargs.h> +#include <pulsecore/log.h> +#include <pulsecore/socket-client.h> +#include <pulsecore/authkey.h> +#include <pulsecore/thread-mq.h> +#include <pulsecore/thread.h> +#include <pulsecore/time-smoother.h> +#include <pulsecore/rtclock.h> +#include <pulsecore/socket-util.h> + +#include "module-raop-sink-symdef.h" +#include "rtp.h" +#include "sdp.h" +#include "sap.h" +#include "raop_client.h" + +PA_MODULE_AUTHOR("Colin Guthrie"); +PA_MODULE_DESCRIPTION("RAOP Sink (Apple Airtunes)"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_USAGE( + "sink_name=<name for the sink> " + "server=<address> " + "format=<sample format> " + "channels=<number of channels> " + "rate=<sample rate>"); + +#define DEFAULT_SINK_NAME "airtunes" + +struct userdata { + pa_core *core; + pa_module *module; + pa_sink *sink; + + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + pa_rtpoll_item *rtpoll_item; + pa_thread *thread; + + pa_memchunk raw_memchunk; + pa_memchunk encoded_memchunk; + + void *write_data; + size_t write_length, write_index; + + void *read_data; + size_t read_length, read_index; + + pa_usec_t latency; + + pa_volume_t volume; + pa_bool_t muted; + + /*esd_format_t format;*/ + int32_t rate; + + pa_smoother *smoother; + int fd; + + int64_t offset; + int64_t encoding_overhead; + int32_t next_encoding_overhead; + double encoding_ratio; + + pa_raop_client *raop; + + size_t block_size; +}; + +static const char* const valid_modargs[] = { + "server", + "rate", + "format", + "channels", + "sink_name", + NULL +}; + +enum { + SINK_MESSAGE_PASS_SOCKET = PA_SINK_MESSAGE_MAX, + SINK_MESSAGE_RIP_SOCKET +}; + +static void on_connection(PA_GCC_UNUSED int fd, void*userdata) { + struct userdata *u = userdata; + pa_assert(u); + + pa_assert(u->fd < 0); + u->fd = fd; + + /* Set the initial volume */ + pa_raop_client_set_volume(u->raop, u->volume); + + pa_log_debug("Connection authenticated, handing fd to IO thread..."); + + pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_PASS_SOCKET, NULL, 0, NULL, NULL); +} + +static void on_close(void*userdata) { + struct userdata *u = userdata; + pa_assert(u); + + pa_log_debug("Connection closed, informing IO thread..."); + + pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_RIP_SOCKET, NULL, 0, NULL, NULL); +} + +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; + + switch (code) { + + case PA_SINK_MESSAGE_SET_STATE: + + switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) { + + case PA_SINK_SUSPENDED: + pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state)); + + pa_smoother_pause(u->smoother, pa_rtclock_usec()); + + /* Issue a FLUSH if we are connected */ + if (u->fd >= 0) { + pa_raop_flush(u->raop); + } + break; + + case PA_SINK_IDLE: + case PA_SINK_RUNNING: + + if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { + pa_smoother_resume(u->smoother, pa_rtclock_usec()); + + /* The connection can be closed when idle, so check to + see if we need to reestablish it */ + if (u->fd < 0) + pa_raop_connect(u->raop); + else + pa_raop_flush(u->raop); + } + + break; + + case PA_SINK_UNLINKED: + case PA_SINK_INIT: + ; + } + + break; + + case PA_SINK_MESSAGE_GET_LATENCY: { + pa_usec_t w, r; + + r = pa_smoother_get(u->smoother, pa_rtclock_usec()); + w = pa_bytes_to_usec((u->offset - u->encoding_overhead + (u->encoded_memchunk.length / u->encoding_ratio)), &u->sink->sample_spec); + + *((pa_usec_t*) data) = w > r ? w - r : 0; + break; + } + + case SINK_MESSAGE_PASS_SOCKET: { + struct pollfd *pollfd; + + pa_assert(!u->rtpoll_item); + + u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1); + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + pollfd->fd = u->fd; + pollfd->events = POLLOUT; + /*pollfd->events = */pollfd->revents = 0; + + if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { + /* Our stream has been suspended so we just flush it.... */ + pa_raop_flush(u->raop); + } + return 0; + } + + case SINK_MESSAGE_RIP_SOCKET: { + pa_assert(u->fd >= 0); + + pa_close(u->fd); + u->fd = -1; + + if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { + + pa_log_debug("RTSP control connection closed, but we're suspended so let's not worry about it... we'll open it again later"); + + if (u->rtpoll_item) + pa_rtpoll_item_free(u->rtpoll_item); + u->rtpoll_item = NULL; + } else { + /* Quesiton: is this valid here: or should we do some sort of: + return pa_sink_process_msg(PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL); + ?? */ + pa_module_unload_request(u->module, TRUE); + } + return 0; + } + } + + return pa_sink_process_msg(o, code, data, offset, chunk); +} + +static int sink_get_volume_cb(pa_sink *s) { + struct userdata *u = s->userdata; + int i; + + pa_assert(u); + + for (i = 0; i < s->sample_spec.channels; i++) { + s->volume.values[i] = u->volume; + } + + return 0; +} + +static int sink_set_volume_cb(pa_sink *s) { + struct userdata *u = s->userdata; + int rv; + + pa_assert(u); + + /* If we're muted, we fake it */ + if (u->muted) + return 0; + + pa_assert(s->sample_spec.channels > 0); + + /* Avoid pointless volume sets */ + if (u->volume == s->volume.values[0]) + return 0; + + rv = pa_raop_client_set_volume(u->raop, s->volume.values[0]); + if (0 == rv) + u->volume = s->volume.values[0]; + + return rv; +} + +static int sink_get_mute_cb(pa_sink *s) { + struct userdata *u = s->userdata; + + pa_assert(u); + + s->muted = u->muted; + return 0; +} + +static int sink_set_mute_cb(pa_sink *s) { + struct userdata *u = s->userdata; + int rv; + + pa_assert(u); + + rv = pa_raop_client_set_volume(u->raop, (s->muted ? PA_VOLUME_MUTED : u->volume)); + u->muted = s->muted; + return rv; +} + +static void thread_func(void *userdata) { + struct userdata *u = userdata; + int write_type = 0; + pa_memchunk silence; + uint32_t silence_overhead = 0; + double silence_ratio = 0; + + pa_assert(u); + + pa_log_debug("Thread starting up"); + + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); + + pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec()); + + /* Create a chunk of memory that is our encoded silence sample. */ + pa_memchunk_reset(&silence); + + for (;;) { + int ret; + + if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) + if (u->sink->thread_info.rewind_requested) + pa_sink_process_rewind(u->sink, 0); + + if (u->rtpoll_item) { + struct pollfd *pollfd; + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + + /* Render some data and write it to the fifo */ + if (/*PA_SINK_IS_OPENED(u->sink->thread_info.state) && */pollfd->revents) { + pa_usec_t usec; + int64_t n; + void *p; + + if (!silence.memblock) { + pa_memchunk silence_tmp; + + pa_memchunk_reset(&silence_tmp); + silence_tmp.memblock = pa_memblock_new(u->core->mempool, 4096); + silence_tmp.length = 4096; + p = pa_memblock_acquire(silence_tmp.memblock); + memset(p, 0, 4096); + pa_memblock_release(silence_tmp.memblock); + pa_raop_client_encode_sample(u->raop, &silence_tmp, &silence); + pa_assert(0 == silence_tmp.length); + silence_overhead = silence_tmp.length - 4096; + silence_ratio = silence_tmp.length / 4096; + pa_memblock_unref(silence_tmp.memblock); + } + + for (;;) { + ssize_t l; + + if (u->encoded_memchunk.length <= 0) { + if (u->encoded_memchunk.memblock) + pa_memblock_unref(u->encoded_memchunk.memblock); + if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) { + size_t rl; + + /* We render real data */ + if (u->raw_memchunk.length <= 0) { + if (u->raw_memchunk.memblock) + pa_memblock_unref(u->raw_memchunk.memblock); + pa_memchunk_reset(&u->raw_memchunk); + + /* Grab unencoded data */ + pa_sink_render(u->sink, u->block_size, &u->raw_memchunk); + } + pa_assert(u->raw_memchunk.length > 0); + + /* Encode it */ + rl = u->raw_memchunk.length; + u->encoding_overhead += u->next_encoding_overhead; + pa_raop_client_encode_sample(u->raop, &u->raw_memchunk, &u->encoded_memchunk); + u->next_encoding_overhead = (u->encoded_memchunk.length - (rl - u->raw_memchunk.length)); + u->encoding_ratio = u->encoded_memchunk.length / (rl - u->raw_memchunk.length); + } else { + /* We render some silence into our memchunk */ + memcpy(&u->encoded_memchunk, &silence, sizeof(pa_memchunk)); + pa_memblock_ref(silence.memblock); + + /* Calculate/store some values to be used with the smoother */ + u->next_encoding_overhead = silence_overhead; + u->encoding_ratio = silence_ratio; + } + } + pa_assert(u->encoded_memchunk.length > 0); + + p = pa_memblock_acquire(u->encoded_memchunk.memblock); + l = pa_write(u->fd, (uint8_t*) p + u->encoded_memchunk.index, u->encoded_memchunk.length, &write_type); + pa_memblock_release(u->encoded_memchunk.memblock); + + pa_assert(l != 0); + + if (l < 0) { + + if (errno == EINTR) + continue; + else if (errno == EAGAIN) { + + /* OK, we filled all socket buffers up + * now. */ + goto filled_up; + + } else { + pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno)); + goto fail; + } + + } else { + u->offset += l; + + u->encoded_memchunk.index += l; + u->encoded_memchunk.length -= l; + + pollfd->revents = 0; + + if (u->encoded_memchunk.length > 0) { + /* we've completely written the encoded data, so update our overhead */ + u->encoding_overhead += u->next_encoding_overhead; + + /* OK, we wrote less that we asked for, + * hence we can assume that the socket + * buffers are full now */ + goto filled_up; + } + } + } + + filled_up: + + /* At this spot we know that the socket buffers are + * fully filled up. This is the best time to estimate + * the playback position of the server */ + + n = u->offset - u->encoding_overhead; + +#ifdef SIOCOUTQ + { + int l; + if (ioctl(u->fd, SIOCOUTQ, &l) >= 0 && l > 0) + n -= (l / u->encoding_ratio); + } +#endif + + usec = pa_bytes_to_usec(n, &u->sink->sample_spec); + + if (usec > u->latency) + usec -= u->latency; + else + usec = 0; + + pa_smoother_put(u->smoother, pa_rtclock_usec(), usec); + } + + /* Hmm, nothing to do. Let's sleep */ + pollfd->events = POLLOUT; /*PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;*/ + } + + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) + goto fail; + + if (ret == 0) + goto finish; + + if (u->rtpoll_item) { + struct pollfd* pollfd; + + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + + if (pollfd->revents & ~POLLOUT) { + if (u->sink->thread_info.state != PA_SINK_SUSPENDED) { + pa_log("FIFO shutdown."); + goto fail; + } + + /* We expect this to happen on occasion if we are not sending data. + It's perfectly natural and normal and natural */ + if (u->rtpoll_item) + pa_rtpoll_item_free(u->rtpoll_item); + u->rtpoll_item = NULL; + } + } + } + +fail: + /* If this was no regular exit from the loop we have to continue + * processing messages until we received PA_MESSAGE_SHUTDOWN */ + pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL); + pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); + +finish: + if (silence.memblock) + pa_memblock_unref(silence.memblock); + pa_log_debug("Thread shutting down"); +} + +int pa__init(pa_module*m) { + struct userdata *u = NULL; + pa_sample_spec ss; + pa_modargs *ma = NULL; + const char *server; + pa_sink_new_data data; + + pa_assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("failed to parse module arguments"); + goto fail; + } + + ss = m->core->default_sample_spec; + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + pa_log("invalid sample format specification"); + goto fail; + } + + if ((/*ss.format != PA_SAMPLE_U8 &&*/ ss.format != PA_SAMPLE_S16NE) || + (ss.channels > 2)) { + pa_log("sample type support is limited to mono/stereo and U8 or S16NE sample data"); + goto fail; + } + + u = pa_xnew0(struct userdata, 1); + u->core = m->core; + u->module = m; + m->userdata = u; + u->fd = -1; + u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10); + pa_memchunk_reset(&u->raw_memchunk); + pa_memchunk_reset(&u->encoded_memchunk); + u->offset = 0; + u->encoding_overhead = 0; + u->next_encoding_overhead = 0; + u->encoding_ratio = 1.0; + + u->volume = roundf(0.7 * PA_VOLUME_NORM); + u->muted = FALSE; + + u->rtpoll = pa_rtpoll_new(); + pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); + u->rtpoll_item = NULL; + + /*u->format = + (ss.format == PA_SAMPLE_U8 ? ESD_BITS8 : ESD_BITS16) | + (ss.channels == 2 ? ESD_STEREO : ESD_MONO);*/ + u->rate = ss.rate; + u->block_size = pa_usec_to_bytes(PA_USEC_PER_SEC/20, &ss); + + u->read_data = u->write_data = NULL; + u->read_index = u->write_index = u->read_length = u->write_length = 0; + + /*u->state = STATE_AUTH;*/ + u->latency = 0; + + if (!(server = pa_modargs_get_value(ma, "server", NULL))) { + pa_log("No server argument given."); + goto fail; + } + + pa_sink_new_data_init(&data); + data.driver = __FILE__; + data.module = m; + pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME)); + pa_sink_new_data_set_sample_spec(&data, &ss); + pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, server); + pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Airtunes sink '%s'", server); + + u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY|PA_SINK_NETWORK); + pa_sink_new_data_done(&data); + + if (!u->sink) { + pa_log("Failed to create sink."); + goto fail; + } + + u->sink->parent.process_msg = sink_process_msg; + u->sink->userdata = u; + u->sink->get_volume = sink_get_volume_cb; + u->sink->set_volume = sink_set_volume_cb; + u->sink->get_mute = sink_get_mute_cb; + u->sink->set_mute = sink_set_mute_cb; + u->sink->flags = PA_SINK_LATENCY|PA_SINK_NETWORK|PA_SINK_HW_VOLUME_CTRL; + + pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); + pa_sink_set_rtpoll(u->sink, u->rtpoll); + + if (!(u->raop = pa_raop_client_new(u->core, server))) { + pa_log("Failed to connect to server."); + goto fail; + } + + pa_raop_client_set_callback(u->raop, on_connection, u); + pa_raop_client_set_closed_callback(u->raop, on_close, u); + + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); + goto fail; + } + + pa_sink_put(u->sink); + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(m); + + return -1; +} + +void pa__done(pa_module*m) { + struct userdata *u; + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->sink) + pa_sink_unlink(u->sink); + + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); + } + + pa_thread_mq_done(&u->thread_mq); + + if (u->sink) + pa_sink_unref(u->sink); + + if (u->rtpoll_item) + pa_rtpoll_item_free(u->rtpoll_item); + + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); + + if (u->raw_memchunk.memblock) + pa_memblock_unref(u->raw_memchunk.memblock); + + if (u->encoded_memchunk.memblock) + pa_memblock_unref(u->encoded_memchunk.memblock); + + if (u->raop) + pa_raop_client_free(u->raop); + + pa_xfree(u->read_data); + pa_xfree(u->write_data); + + if (u->smoother) + pa_smoother_free(u->smoother); + + if (u->fd >= 0) + pa_close(u->fd); + + pa_xfree(u); +} diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c index 5b2be118..976a8ce5 100644 --- a/src/modules/module-remap-sink.c +++ b/src/modules/module-remap-sink.c @@ -274,6 +274,16 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s } } +/* Called from main context */ +static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + return u->sink != dest; +} + int pa__init(pa_module*m) { struct userdata *u; pa_sample_spec ss; @@ -386,6 +396,7 @@ int pa__init(pa_module*m) { u->sink_input->detach = sink_input_detach_cb; u->sink_input->kill = sink_input_kill_cb; u->sink_input->state_change = sink_input_state_change_cb; + u->sink_input->may_move_to = sink_input_may_move_to_cb; u->sink_input->userdata = u; pa_sink_put(u->sink); diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index a6324526..21565cc4 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -116,13 +116,13 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s pa_sink_input_request_rewind(i, 0, FALSE, TRUE); } -static void calc_sine(float *f, size_t l, float freq) { +static void calc_sine(float *f, size_t l, double freq) { size_t i; l /= sizeof(float); for (i = 0; i < l; i++) - f[i] = (float) sin((double) i/l*M_PI*2*freq)/2; + f[i] = (float) sin((double) i/(double)l*M_PI*2*freq)/2; } int pa__init(pa_module*m) { @@ -163,7 +163,7 @@ int pa__init(pa_module*m) { u->memblock = pa_memblock_new(m->core->mempool, pa_bytes_per_second(&ss)); p = pa_memblock_acquire(u->memblock); - calc_sine(p, pa_memblock_get_length(u->memblock), frequency); + calc_sine(p, pa_memblock_get_length(u->memblock), (double) frequency); pa_memblock_release(u->memblock); pa_sink_input_new_data_init(&data); diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index ec4e7c79..55897004 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -134,7 +134,7 @@ static char *get_name(pa_proplist *p, const char *prefix) { else if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_NAME))) return pa_sprintf_malloc("%s-by-media-name:%s", prefix, r); - return NULL; + return pa_sprintf_malloc("%s-fallback:%s", prefix, r); } static struct entry* read_entry(struct userdata *u, char *name) { @@ -145,7 +145,7 @@ static struct entry* read_entry(struct userdata *u, char *name) { pa_assert(name); key.dptr = name; - key.dsize = strlen(name); + key.dsize = (int) strlen(name); data = gdbm_fetch(u->gdbm_file, key); @@ -277,7 +277,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 } key.dptr = name; - key.dsize = strlen(name); + key.dsize = (int) strlen(name); data.dptr = (void*) &entry; data.dsize = sizeof(entry); @@ -306,8 +306,11 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n if (u->restore_device && (s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK, TRUE))) { - pa_log_info("Restoring device for stream %s.", name); - new_data->sink = s; + if (!new_data->sink) { + pa_log_info("Restoring device for stream %s.", name); + new_data->sink = s; + } else + pa_log_info("Not restore device for stream %s, because already set.", name); } pa_xfree(e); @@ -330,13 +333,20 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu if ((e = read_entry(u, name))) { if (u->restore_volume) { - pa_log_info("Restoring volume for sink input %s.", name); - pa_sink_input_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map)); + + if (!new_data->volume_is_set) { + pa_log_info("Restoring volume for sink input %s.", name); + pa_sink_input_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map)); + } else + pa_log_debug("Not restoring volume for sink input %s, because already set.", name); } if (u->restore_muted) { - pa_log_info("Restoring mute state for sink input %s.", name); - pa_sink_input_new_data_set_muted(new_data, e->muted); + if (!new_data->muted_is_set) { + pa_log_info("Restoring mute state for sink input %s.", name); + pa_sink_input_new_data_set_muted(new_data, e->muted); + } else + pa_log_debug("Not restoring mute state for sink input %s, because already set.", name); } pa_xfree(e); @@ -360,10 +370,14 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou pa_source *s; if (u->restore_device && + !new_data->direct_on_input && (s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE, TRUE))) { - pa_log_info("Restoring device for stream %s.", name); - new_data->source = s; + if (!new_data->source) { + pa_log_info("Restoring device for stream %s.", name); + new_data->source = s; + } else + pa_log_info("Not restoring device for stream %s, because already set", name); } pa_xfree(e); @@ -408,7 +422,7 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) { char *n; pa_sink *s; - if (!(n = get_name(si->proplist, "sink_input"))) + if (!(n = get_name(si->proplist, "sink-input"))) continue; if (strcmp(name, n)) { @@ -417,8 +431,9 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) { } if (u->restore_volume) { + pa_cvolume v = e->volume; pa_log_info("Restoring volume for sink input %s.", name); - pa_sink_input_set_volume(si, pa_cvolume_remap(&e->volume, &e->channel_map, &si->channel_map)); + pa_sink_input_set_volume(si, pa_cvolume_remap(&v, &e->channel_map, &si->channel_map)); } if (u->restore_muted) { @@ -490,7 +505,7 @@ static void dump_database(struct userdata *u) { static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) { struct userdata *u; uint32_t command; - pa_tagstruct *reply; + pa_tagstruct *reply = NULL; pa_assert(p); pa_assert(m); @@ -529,7 +544,7 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio next_key = gdbm_nextkey(u->gdbm_file, key); - name = pa_xstrndup(key.dptr, key.dsize); + name = pa_xstrndup(key.dptr, (size_t) key.dsize); pa_xfree(key.dptr); if ((e = read_entry(u, name))) { @@ -552,7 +567,7 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio case SUBCOMMAND_WRITE: { uint32_t mode; - pa_bool_t apply_immediately; + pa_bool_t apply_immediately = FALSE; if (pa_tagstruct_getu32(t, &mode) < 0 || pa_tagstruct_get_boolean(t, &apply_immediately) < 0) @@ -571,6 +586,7 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio pa_bool_t muted; struct entry entry; datum key, data; + int k; memset(&entry, 0, sizeof(entry)); @@ -588,12 +604,12 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio pa_strlcpy(entry.device, device, sizeof(entry.device)); key.dptr = (void*) name; - key.dsize = strlen(name); + key.dsize = (int) strlen(name); data.dptr = (void*) &entry; data.dsize = sizeof(entry); - if (gdbm_store(u->gdbm_file, key, data, mode == PA_UPDATE_REPLACE ? GDBM_REPLACE : GDBM_INSERT) == 1) + if ((k = gdbm_store(u->gdbm_file, key, data, mode == PA_UPDATE_REPLACE ? GDBM_REPLACE : GDBM_INSERT)) == 0) if (apply_immediately) apply_entry(u, name, &entry); } @@ -613,7 +629,7 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio goto fail; key.dptr = (void*) name; - key.dsize = strlen(name); + key.dsize = (int) strlen(name); gdbm_delete(u->gdbm_file, key); } @@ -670,6 +686,7 @@ int pa__init(pa_module*m) { pa_source_output *so; uint32_t idx; pa_bool_t restore_device = TRUE, restore_volume = TRUE, restore_muted = TRUE; + int gdbm_cache_size; pa_assert(m); @@ -730,6 +747,10 @@ int pa__init(pa_module*m) { goto fail; } + /* By default the cache of gdbm is rather large, let's reduce it a bit to save memory */ + gdbm_cache_size = 10; + gdbm_setopt(u->gdbm_file, GDBM_CACHESIZE, &gdbm_cache_size, sizeof(gdbm_cache_size)); + pa_log_info("Sucessfully opened database file '%s'.", fname); pa_xfree(fname); diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c index bc7c023c..8ab84e08 100644 --- a/src/modules/module-suspend-on-idle.c +++ b/src/modules/module-suspend-on-idle.c @@ -83,12 +83,12 @@ static void timeout_cb(pa_mainloop_api*a, pa_time_event* e, const struct timeval d->userdata->core->mainloop->time_restart(d->time_event, NULL); - if (d->sink && pa_sink_used_by(d->sink) <= 0 && pa_sink_get_state(d->sink) != PA_SINK_SUSPENDED) { + if (d->sink && pa_sink_check_suspend(d->sink) <= 0 && pa_sink_get_state(d->sink) != PA_SINK_SUSPENDED) { pa_log_info("Sink %s idle for too long, suspending ...", d->sink->name); pa_sink_suspend(d->sink, TRUE); } - if (d->source && pa_source_used_by(d->source) <= 0 && pa_source_get_state(d->source) != PA_SOURCE_SUSPENDED) { + if (d->source && pa_source_check_suspend(d->source) <= 0 && pa_source_get_state(d->source) != PA_SOURCE_SUSPENDED) { pa_log_info("Source %s idle for too long, suspending ...", d->source->name); pa_source_suspend(d->source, TRUE); } @@ -158,7 +158,7 @@ static pa_hook_result_t sink_input_unlink_hook_cb(pa_core *c, pa_sink_input *s, pa_sink_input_assert_ref(s); pa_assert(u); - if (pa_sink_used_by(s->sink) <= 0) { + if (pa_sink_check_suspend(s->sink) <= 0) { struct device_info *d; if ((d = pa_hashmap_get(u->device_infos, s->sink))) restart(d); @@ -172,7 +172,7 @@ static pa_hook_result_t source_output_unlink_hook_cb(pa_core *c, pa_source_outpu pa_source_output_assert_ref(s); pa_assert(u); - if (pa_source_used_by(s->source) <= 0) { + if (pa_source_check_suspend(s->source) <= 0) { struct device_info *d; if ((d = pa_hashmap_get(u->device_infos, s->source))) restart(d); @@ -191,7 +191,7 @@ static pa_hook_result_t sink_input_move_hook_cb(pa_core *c, pa_sink_input_move_h if ((d = pa_hashmap_get(u->device_infos, data->destination))) resume(d); - if (pa_sink_used_by(data->sink_input->sink) <= 1) + if (pa_sink_check_suspend(data->sink_input->sink) <= 1) if ((d = pa_hashmap_get(u->device_infos, data->sink_input->sink))) restart(d); @@ -208,7 +208,7 @@ static pa_hook_result_t source_output_move_hook_cb(pa_core *c, pa_source_output_ if ((d = pa_hashmap_get(u->device_infos, data->destination))) resume(d); - if (pa_source_used_by(data->source_output->source) <= 1) + if (pa_source_check_suspend(data->source_output->source) <= 1) if ((d = pa_hashmap_get(u->device_infos, data->source_output->source))) restart(d); @@ -266,8 +266,8 @@ static pa_hook_result_t device_new_hook_cb(pa_core *c, pa_object *o, struct user d->time_event = c->mainloop->time_new(c->mainloop, NULL, timeout_cb, d); pa_hashmap_put(u->device_infos, o, d); - if ((d->sink && pa_sink_used_by(d->sink) <= 0) || - (d->source && pa_source_used_by(d->source) <= 0)) + if ((d->sink && pa_sink_check_suspend(d->sink) <= 0) || + (d->source && pa_source_check_suspend(d->source) <= 0)) restart(d); return PA_HOOK_OK; @@ -313,7 +313,7 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s pa_sink *s = PA_SINK(o); pa_sink_state_t state = pa_sink_get_state(s); - if (pa_sink_used_by(s) <= 0) { + if (pa_sink_check_suspend(s) <= 0) { if (PA_SINK_IS_OPENED(state)) restart(d); @@ -324,7 +324,7 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s pa_source *s = PA_SOURCE(o); pa_source_state_t state = pa_source_get_state(s); - if (pa_source_used_by(s) <= 0) { + if (pa_source_check_suspend(s) <= 0) { if (PA_SOURCE_IS_OPENED(state)) restart(d); @@ -337,7 +337,7 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; - uint32_t timeout = 1; + uint32_t timeout = 5; uint32_t idx; pa_sink *sink; pa_source *source; diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 79ce1dd2..a46d6e59 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -159,7 +159,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = command_suspended, [PA_COMMAND_RECORD_STREAM_SUSPENDED] = command_suspended, [PA_COMMAND_PLAYBACK_STREAM_MOVED] = command_moved, - [PA_COMMAND_RECORD_STREAM_MOVED] = command_moved, + [PA_COMMAND_RECORD_STREAM_MOVED] = command_moved }; struct userdata { @@ -178,7 +178,7 @@ struct userdata { #ifdef TUNNEL_SINK char *sink_name; pa_sink *sink; - int32_t requested_bytes; + size_t requested_bytes; #else char *source_name; pa_source *source; @@ -389,7 +389,7 @@ static void send_data(struct userdata *u) { u->requested_bytes -= memchunk.length; - u->counter += memchunk.length; + u->counter += (int64_t) memchunk.length; } } @@ -417,7 +417,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse case PA_SINK_MESSAGE_GET_LATENCY: { pa_usec_t yl, yr, *usec = data; - yl = pa_bytes_to_usec(u->counter, &u->sink->sample_spec); + yl = pa_bytes_to_usec((uint64_t) u->counter, &u->sink->sample_spec); yr = pa_smoother_get(u->smoother, pa_rtclock_usec()); *usec = yl > yr ? yl - yr : 0; @@ -444,10 +444,10 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse case SINK_MESSAGE_UPDATE_LATENCY: { pa_usec_t y; - y = pa_bytes_to_usec(u->counter, &u->sink->sample_spec); + y = pa_bytes_to_usec((uint64_t) u->counter, &u->sink->sample_spec); if (y > (pa_usec_t) offset || offset < 0) - y -= offset; + y -= (pa_usec_t) offset; else y = 0; @@ -465,7 +465,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse pa_pstream_send_memblock(u->pstream, u->channel, 0, PA_SEEK_RELATIVE, chunk); - u->counter_delta += chunk->length; + u->counter_delta += (int64_t) chunk->length; return 0; } @@ -508,7 +508,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off switch (code) { - case PA_SINK_MESSAGE_SET_STATE: { + case PA_SOURCE_MESSAGE_SET_STATE: { int r; if ((r = pa_source_process_msg(o, code, data, offset, chunk)) >= 0) @@ -520,7 +520,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off case PA_SOURCE_MESSAGE_GET_LATENCY: { pa_usec_t yr, yl, *usec = data; - yl = pa_bytes_to_usec(u->counter, &PA_SINK(o)->sample_spec); + yl = pa_bytes_to_usec((uint64_t) u->counter, &PA_SOURCE(o)->sample_spec); yr = pa_smoother_get(u->smoother, pa_rtclock_usec()); *usec = yr > yl ? yr - yl : 0; @@ -532,7 +532,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off if (PA_SOURCE_IS_OPENED(u->source->thread_info.state)) pa_source_post(u->source, chunk); - u->counter += chunk->length; + u->counter += (int64_t) chunk->length; return 0; @@ -544,10 +544,10 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off case SOURCE_MESSAGE_UPDATE_LATENCY: { pa_usec_t y; - y = pa_bytes_to_usec(u->counter, &u->source->sample_spec); + y = pa_bytes_to_usec((uint64_t) u->counter, &u->source->sample_spec); if (offset >= 0 || y > (pa_usec_t) -offset) - y += offset; + y += (pa_usec_t) offset; else y = 0; @@ -736,9 +736,9 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint /* Add the length of our server-side buffer */ if (write_index >= read_index) - delay += (int64_t) pa_bytes_to_usec(write_index-read_index, ss); + delay += (int64_t) pa_bytes_to_usec((uint64_t) (write_index-read_index), ss); else - delay -= (int64_t) pa_bytes_to_usec(read_index-write_index, ss); + delay -= (int64_t) pa_bytes_to_usec((uint64_t) (read_index-write_index), ss); /* Our measurements are already out of date, hence correct by the * * transport latency */ @@ -750,9 +750,9 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint /* Now correct by what we have have read/written since we requested the update */ #ifdef TUNNEL_SINK - delay += (int64_t) pa_bytes_to_usec(u->counter_delta, ss); + delay += (int64_t) pa_bytes_to_usec((uint64_t) u->counter_delta, ss); #else - delay -= (int64_t) pa_bytes_to_usec(u->counter_delta, ss); + delay -= (int64_t) pa_bytes_to_usec((uint64_t) u->counter_delta, ss); #endif #ifdef TUNNEL_SINK @@ -1425,11 +1425,11 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t u->maxlength = 4*1024*1024; #ifdef TUNNEL_SINK - u->tlength = pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_TLENGTH_MSEC, &u->sink->sample_spec); - u->minreq = pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_MINREQ_MSEC, &u->sink->sample_spec); + u->tlength = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_TLENGTH_MSEC, &u->sink->sample_spec); + u->minreq = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_MINREQ_MSEC, &u->sink->sample_spec); u->prebuf = u->tlength; #else - u->fragsize = pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_FRAGSIZE_MSEC, &u->source->sample_spec); + u->fragsize = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_FRAGSIZE_MSEC, &u->source->sample_spec); #endif #ifdef TUNNEL_SINK @@ -1494,6 +1494,13 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t #endif } + if (u->version >= 14) { +#ifdef TUNNEL_SINK + pa_tagstruct_put_boolean(reply, FALSE); /* volume_set */ +#endif + pa_tagstruct_put_boolean(reply, TRUE); /* early rquests */ + } + pa_pstream_send_tagstruct(u->pstream, reply); pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u, NULL); @@ -1548,7 +1555,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o pa_asyncmsgq_send(u->source->asyncmsgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_POST, PA_UINT_TO_PTR(seek), offset, chunk); - u->counter_delta += chunk->length; + u->counter_delta += (int64_t) chunk->length; } #endif diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 0fb17a0d..aac0d046 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -103,7 +103,7 @@ static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) { if (k <= 0 || k > (long) PA_CHANNELS_MAX) return NULL; - v->channels = (unsigned) k; + v->channels = (uint8_t) k; for (i = 0; i < v->channels; i++) { p += strspn(p, WHITESPACE); diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c index ae16b9ae..e93721c1 100644 --- a/src/modules/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -82,7 +82,7 @@ static int x11_event_cb(pa_x11_wrapper *w, XEvent *e, void *userdata) { bne = (XkbBellNotifyEvent*) e; - if (pa_scache_play_item_by_name(u->core, u->scache_item, u->sink_name, TRUE, (bne->percent*PA_VOLUME_NORM)/100, NULL, NULL) < 0) { + if (pa_scache_play_item_by_name(u->core, u->scache_item, u->sink_name, TRUE, ((pa_volume_t) bne->percent*PA_VOLUME_NORM)/100U, NULL, NULL) < 0) { pa_log_info("Ringing bell failed, reverting to X11 device bell."); XkbForceDeviceBell(pa_x11_wrapper_get_display(w), bne->device, bne->bell_class, bne->bell_id, bne->percent); } diff --git a/src/modules/module-x11-xsmp.c b/src/modules/module-x11-xsmp.c index 12e100b7..57d182fd 100644 --- a/src/modules/module-x11-xsmp.c +++ b/src/modules/module-x11-xsmp.c @@ -181,7 +181,7 @@ int pa__init(pa_module*m) { prop_program.name = (char*) SmProgram; prop_program.type = (char*) SmARRAY8; val_program.value = (char*) PACKAGE_NAME; - val_program.length = strlen(val_program.value); + val_program.length = (int) strlen(val_program.value); prop_program.num_vals = 1; prop_program.vals = &val_program; prop_list[0] = &prop_program; @@ -190,7 +190,7 @@ int pa__init(pa_module*m) { prop_user.type = (char*) SmARRAY8; pa_get_user_name(t, sizeof(t)); val_user.value = t; - val_user.length = strlen(val_user.value); + val_user.length = (int) strlen(val_user.value); prop_user.num_vals = 1; prop_user.vals = &val_user; prop_list[1] = &prop_user; diff --git a/src/modules/module-zeroconf-discover.c b/src/modules/module-zeroconf-discover.c index a4fbf020..c8087abb 100644 --- a/src/modules/module-zeroconf-discover.c +++ b/src/modules/module-zeroconf-discover.c @@ -173,9 +173,9 @@ static void resolver_cb( device = value; value = NULL; } else if (strcmp(key, "rate") == 0) - ss.rate = atoi(value); + ss.rate = (uint32_t) atoi(value); else if (strcmp(key, "channels") == 0) - ss.channels = atoi(value); + ss.channels = (uint8_t) atoi(value); else if (strcmp(key, "format") == 0) ss.format = pa_parse_sample_format(value); else if (strcmp(key, "channel_map") == 0) { diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index 2791e165..f766030d 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -204,10 +204,10 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { if (ss->channels != channels) { pa_log_warn("device doesn't support %i channels, using %i channels.", ss->channels, channels); - ss->channels = channels; + ss->channels = (uint8_t) channels; } - speed = ss->rate; + speed = (int) ss->rate; if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0) { pa_log("SNDCTL_DSP_SPEED: %s", pa_cstrerror(errno)); return -1; @@ -219,7 +219,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { /* If the sample rate deviates too much, we need to resample */ if (speed < ss->rate*.95 || speed > ss->rate*1.05) - ss->rate = speed; + ss->rate = (uint32_t) speed; } return 0; diff --git a/src/modules/raop/base64.c b/src/modules/raop/base64.c new file mode 100644 index 00000000..8918def8 --- /dev/null +++ b/src/modules/raop/base64.c @@ -0,0 +1,126 @@ +/*** + This file is part of PulseAudio. + + Copyright 2008 Colin Guthrie + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* + This file was originally inspired by a file developed by + Kungliga Tekniska H�gskolan +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <string.h> + +#include <pulse/xmalloc.h> + +#include "base64.h" + +static const char base64_chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static int pos(char c) +{ + if (c >= 'A' && c <= 'Z') return c - 'A' + 0; + if (c >= 'a' && c <= 'z') return c - 'a' + 26; + if (c >= '0' && c <= '9') return c - '0' + 52; + if (c == '+') return 62; + if (c == '/') return 63; +} + +int pa_base64_encode(const void *data, int size, char **str) +{ + char *s, *p; + int i; + int c; + const unsigned char *q; + + p = s = pa_xnew(char, size * 4 / 3 + 4); + q = (const unsigned char *) data; + i = 0; + for (i = 0; i < size;) { + c = q[i++]; + c *= 256; + if (i < size) + c += q[i]; + i++; + c *= 256; + if (i < size) + c += q[i]; + i++; + p[0] = base64_chars[(c & 0x00fc0000) >> 18]; + p[1] = base64_chars[(c & 0x0003f000) >> 12]; + p[2] = base64_chars[(c & 0x00000fc0) >> 6]; + p[3] = base64_chars[(c & 0x0000003f) >> 0]; + if (i > size) + p[3] = '='; + if (i > size + 1) + p[2] = '='; + p += 4; + } + *p = 0; + *str = s; + return strlen(s); +} + +#define DECODE_ERROR 0xffffffff + +static unsigned int token_decode(const char *token) +{ + int i; + unsigned int val = 0; + int marker = 0; + if (strlen(token) < 4) + return DECODE_ERROR; + for (i = 0; i < 4; i++) { + val *= 64; + if (token[i] == '=') + marker++; + else if (marker > 0) + return DECODE_ERROR; + else + val += pos(token[i]); + } + if (marker > 2) + return DECODE_ERROR; + return (marker << 24) | val; +} + +int pa_base64_decode(const char *str, void *data) +{ + const char *p; + unsigned char *q; + + q = data; + for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) { + unsigned int val = token_decode(p); + unsigned int marker = (val >> 24) & 0xff; + if (val == DECODE_ERROR) + return -1; + *q++ = (val >> 16) & 0xff; + if (marker < 2) + *q++ = (val >> 8) & 0xff; + if (marker < 1) + *q++ = val & 0xff; + } + return q - (unsigned char *) data; +} diff --git a/src/modules/raop/base64.h b/src/modules/raop/base64.h new file mode 100644 index 00000000..dac0e707 --- /dev/null +++ b/src/modules/raop/base64.h @@ -0,0 +1,34 @@ +#ifndef foobase64hfoo +#define foobase64hfoo + +/*** + This file is part of PulseAudio. + + Copyright 2008 Colin Guthrie + Copyright Kungliga Tekniska Høgskolan + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* + This file was originally inspired by a file developed by + Kungliga Tekniska Høgskolan +*/ + +int pa_base64_encode(const void *data, int size, char **str); +int pa_base64_decode(const char *str, void *data); + +#endif diff --git a/src/modules/raop/raop_client.c b/src/modules/raop/raop_client.c new file mode 100644 index 00000000..4627545e --- /dev/null +++ b/src/modules/raop/raop_client.c @@ -0,0 +1,561 @@ +/*** + This file is part of PulseAudio. + + Copyright 2008 Colin Guthrie + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <sys/ioctl.h> + +#ifdef HAVE_SYS_FILIO_H +#include <sys/filio.h> +#endif + +/* TODO: Replace OpenSSL with NSS */ +#include <openssl/err.h> +#include <openssl/rand.h> +#include <openssl/aes.h> +#include <openssl/rsa.h> +#include <openssl/engine.h> + +#include <pulse/xmalloc.h> + +#include <pulsecore/core-error.h> +#include <pulsecore/core-util.h> +#include <pulsecore/socket-util.h> +#include <pulsecore/log.h> +#include <pulsecore/macro.h> +#include <pulsecore/strbuf.h> +#include <pulsecore/random.h> +#include <pulsecore/poll.h> + +#include "raop_client.h" +#include "rtsp_client.h" +#include "base64.h" + +#define AES_CHUNKSIZE 16 + +#define JACK_STATUS_DISCONNECTED 0 +#define JACK_STATUS_CONNECTED 1 + +#define JACK_TYPE_ANALOG 0 +#define JACK_TYPE_DIGITAL 1 + +#define VOLUME_DEF -30 +#define VOLUME_MIN -144 +#define VOLUME_MAX 0 + + +struct pa_raop_client { + pa_core *core; + char *host; + char *sid; + pa_rtsp_client *rtsp; + + uint8_t jack_type; + uint8_t jack_status; + + /* Encryption Related bits */ + AES_KEY aes; + uint8_t aes_iv[AES_CHUNKSIZE]; /* initialization vector for aes-cbc */ + uint8_t aes_nv[AES_CHUNKSIZE]; /* next vector for aes-cbc */ + uint8_t aes_key[AES_CHUNKSIZE]; /* key for aes-cbc */ + + pa_socket_client *sc; + int fd; + + uint16_t seq; + uint32_t rtptime; + + pa_raop_client_cb_t callback; + void* userdata; + pa_raop_client_closed_cb_t closed_callback; + void* closed_userdata; +}; + +/** + * Function to write bits into a buffer. + * @param buffer Handle to the buffer. It will be incremented if new data requires it. + * @param bit_pos A pointer to a position buffer to keep track the current write location (0 for MSB, 7 for LSB) + * @param size A pointer to the byte size currently written. This allows the calling function to do simple buffer overflow checks + * @param data The data to write + * @param data_bit_len The number of bits from data to write + */ +static inline void bit_writer(uint8_t **buffer, uint8_t *bit_pos, int *size, uint8_t data, uint8_t data_bit_len) { + int bits_left, bit_overflow; + uint8_t bit_data; + + if (!data_bit_len) + return; + + /* If bit pos is zero, we will definatly use at least one bit from the current byte so size increments. */ + if (!*bit_pos) + *size += 1; + + /* Calc the number of bits left in the current byte of buffer */ + bits_left = 7 - *bit_pos + 1; + /* Calc the overflow of bits in relation to how much space we have left... */ + bit_overflow = bits_left - data_bit_len; + if (bit_overflow >= 0) { + /* We can fit the new data in our current byte */ + /* As we write from MSB->LSB we need to left shift by the overflow amount */ + bit_data = data << bit_overflow; + if (*bit_pos) + **buffer |= bit_data; + else + **buffer = bit_data; + /* If our data fits exactly into the current byte, we need to increment our pointer */ + if (0 == bit_overflow) { + /* Do not increment size as it will be incremeneted on next call as bit_pos is zero */ + *buffer += 1; + *bit_pos = 0; + } else { + *bit_pos += data_bit_len; + } + } else { + /* bit_overflow is negative, there for we will need a new byte from our buffer */ + /* Firstly fill up what's left in the current byte */ + bit_data = data >> -bit_overflow; + **buffer |= bit_data; + /* Increment our buffer pointer and size counter*/ + *buffer += 1; + *size += 1; + **buffer = data << (8 + bit_overflow); + *bit_pos = -bit_overflow; + } +} + +static int rsa_encrypt(uint8_t *text, int len, uint8_t *res) { + const char n[] = + "59dE8qLieItsH1WgjrcFRKj6eUWqi+bGLOX1HL3U3GhC/j0Qg90u3sG/1CUtwC" + "5vOYvfDmFI6oSFXi5ELabWJmT2dKHzBJKa3k9ok+8t9ucRqMd6DZHJ2YCCLlDR" + "KSKv6kDqnw4UwPdpOMXziC/AMj3Z/lUVX1G7WSHCAWKf1zNS1eLvqr+boEjXuB" + "OitnZ/bDzPHrTOZz0Dew0uowxf/+sG+NCK3eQJVxqcaJ/vEHKIVd2M+5qL71yJ" + "Q+87X6oV3eaYvt3zWZYD6z5vYTcrtij2VZ9Zmni/UAaHqn9JdsBWLUEpVviYnh" + "imNVvYFZeCXg/IdTQ+x4IRdiXNv5hEew=="; + const char e[] = "AQAB"; + uint8_t modules[256]; + uint8_t exponent[8]; + int size; + RSA *rsa; + + rsa = RSA_new(); + size = pa_base64_decode(n, modules); + rsa->n = BN_bin2bn(modules, size, NULL); + size = pa_base64_decode(e, exponent); + rsa->e = BN_bin2bn(exponent, size, NULL); + + size = RSA_public_encrypt(len, text, res, rsa, RSA_PKCS1_OAEP_PADDING); + RSA_free(rsa); + return size; +} + +static int aes_encrypt(pa_raop_client* c, uint8_t *data, int size) +{ + uint8_t *buf; + int i=0, j; + + pa_assert(c); + + memcpy(c->aes_nv, c->aes_iv, AES_CHUNKSIZE); + while (i+AES_CHUNKSIZE <= size) { + buf = data + i; + for (j=0; j<AES_CHUNKSIZE; ++j) + buf[j] ^= c->aes_nv[j]; + + AES_encrypt(buf, buf, &c->aes); + memcpy(c->aes_nv, buf, AES_CHUNKSIZE); + i += AES_CHUNKSIZE; + } + return i; +} + +static inline void rtrimchar(char *str, char rc) +{ + char *sp = str + strlen(str) - 1; + while (sp >= str && *sp == rc) { + *sp = '\0'; + sp -= 1; + } +} + +static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata) { + pa_raop_client *c = userdata; + + pa_assert(sc); + pa_assert(c); + pa_assert(c->sc == sc); + pa_assert(c->fd < 0); + pa_assert(c->callback); + + pa_socket_client_unref(c->sc); + c->sc = NULL; + + if (!io) { + pa_log("Connection failed: %s", pa_cstrerror(errno)); + return; + } + + c->fd = pa_iochannel_get_send_fd(io); + + pa_iochannel_set_noclose(io, TRUE); + pa_iochannel_socket_set_sndbuf(io, 1024); + pa_iochannel_free(io); + + pa_make_tcp_socket_low_delay(c->fd); + + pa_log_debug("Connection established"); + c->callback(c->fd, c->userdata); +} + +static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist* headers, void *userdata) +{ + pa_raop_client* c = userdata; + pa_assert(c); + pa_assert(rtsp); + pa_assert(rtsp == c->rtsp); + + switch (state) { + case STATE_CONNECT: { + int i; + uint8_t rsakey[512]; + char *key, *iv, *sac, *sdp; + uint16_t rand_data; + const char *ip; + char *url; + + pa_log_debug("RAOP: CONNECTED"); + ip = pa_rtsp_localip(c->rtsp); + /* First of all set the url properly */ + url = pa_sprintf_malloc("rtsp://%s/%s", ip, c->sid); + pa_rtsp_set_url(c->rtsp, url); + pa_xfree(url); + + /* Now encrypt our aes_public key to send to the device */ + i = rsa_encrypt(c->aes_key, AES_CHUNKSIZE, rsakey); + pa_base64_encode(rsakey, i, &key); + rtrimchar(key, '='); + pa_base64_encode(c->aes_iv, AES_CHUNKSIZE, &iv); + rtrimchar(iv, '='); + + pa_random(&rand_data, sizeof(rand_data)); + pa_base64_encode(&rand_data, AES_CHUNKSIZE, &sac); + rtrimchar(sac, '='); + pa_rtsp_add_header(c->rtsp, "Apple-Challenge", sac); + sdp = pa_sprintf_malloc( + "v=0\r\n" + "o=iTunes %s 0 IN IP4 %s\r\n" + "s=iTunes\r\n" + "c=IN IP4 %s\r\n" + "t=0 0\r\n" + "m=audio 0 RTP/AVP 96\r\n" + "a=rtpmap:96 AppleLossless\r\n" + "a=fmtp:96 4096 0 16 40 10 14 2 255 0 0 44100\r\n" + "a=rsaaeskey:%s\r\n" + "a=aesiv:%s\r\n", + c->sid, ip, c->host, key, iv); + pa_rtsp_announce(c->rtsp, sdp); + pa_xfree(key); + pa_xfree(iv); + pa_xfree(sac); + pa_xfree(sdp); + break; + } + + case STATE_ANNOUNCE: + pa_log_debug("RAOP: ANNOUNCED"); + pa_rtsp_remove_header(c->rtsp, "Apple-Challenge"); + pa_rtsp_setup(c->rtsp); + break; + + case STATE_SETUP: { + char *aj = pa_xstrdup(pa_headerlist_gets(headers, "Audio-Jack-Status")); + pa_log_debug("RAOP: SETUP"); + if (aj) { + char *token, *pc; + char delimiters[] = ";"; + const char* token_state = NULL; + c->jack_type = JACK_TYPE_ANALOG; + c->jack_status = JACK_STATUS_DISCONNECTED; + + while ((token = pa_split(aj, delimiters, &token_state))) { + if ((pc = strstr(token, "="))) { + *pc = 0; + if (!strcmp(token, "type") && !strcmp(pc+1, "digital")) { + c->jack_type = JACK_TYPE_DIGITAL; + } + } else { + if (!strcmp(token,"connected")) + c->jack_status = JACK_STATUS_CONNECTED; + } + pa_xfree(token); + } + pa_xfree(aj); + } else { + pa_log_warn("Audio Jack Status missing"); + } + pa_rtsp_record(c->rtsp, &c->seq, &c->rtptime); + break; + } + + case STATE_RECORD: { + uint32_t port = pa_rtsp_serverport(c->rtsp); + pa_log_debug("RAOP: RECORDED"); + + if (!(c->sc = pa_socket_client_new_string(c->core->mainloop, c->host, port))) { + pa_log("failed to connect to server '%s:%d'", c->host, port); + return; + } + pa_socket_client_set_callback(c->sc, on_connection, c); + break; + } + + case STATE_FLUSH: + pa_log_debug("RAOP: FLUSHED"); + break; + + case STATE_TEARDOWN: + case STATE_SET_PARAMETER: + pa_log_debug("RAOP: SET_PARAMETER"); + break; + case STATE_DISCONNECTED: + pa_assert(c->closed_callback); + pa_assert(c->rtsp); + + pa_log_debug("RTSP control channel closed"); + pa_rtsp_client_free(c->rtsp); + c->rtsp = NULL; + if (c->fd > 0) { + /* We do not close the fd, we leave it to the closed callback to do that */ + c->fd = -1; + } + if (c->sc) { + pa_socket_client_unref(c->sc); + c->sc = NULL; + } + pa_xfree(c->sid); + c->sid = NULL; + c->closed_callback(c->closed_userdata); + break; + } +} + +pa_raop_client* pa_raop_client_new(pa_core *core, const char* host) +{ + pa_raop_client* c = pa_xnew0(pa_raop_client, 1); + + pa_assert(core); + pa_assert(host); + + c->core = core; + c->fd = -1; + c->host = pa_xstrdup(host); + + if (pa_raop_connect(c)) { + pa_raop_client_free(c); + return NULL; + } + return c; +} + + +void pa_raop_client_free(pa_raop_client* c) +{ + pa_assert(c); + + if (c->rtsp) + pa_rtsp_client_free(c->rtsp); + pa_xfree(c->host); + pa_xfree(c); +} + + +int pa_raop_connect(pa_raop_client* c) +{ + char *sci; + struct { + uint32_t a; + uint32_t b; + uint32_t c; + } rand_data; + + pa_assert(c); + + if (c->rtsp) { + pa_log_debug("Connection already in progress"); + return 0; + } + + c->rtsp = pa_rtsp_client_new(c->core->mainloop, c->host, 5000, "iTunes/4.6 (Macintosh; U; PPC Mac OS X 10.3)"); + + /* Initialise the AES encryption system */ + pa_random(c->aes_iv, sizeof(c->aes_iv)); + pa_random(c->aes_key, sizeof(c->aes_key)); + memcpy(c->aes_nv, c->aes_iv, sizeof(c->aes_nv)); + AES_set_encrypt_key(c->aes_key, 128, &c->aes); + + /* Generate random instance id */ + pa_random(&rand_data, sizeof(rand_data)); + c->sid = pa_sprintf_malloc("%u", rand_data.a); + sci = pa_sprintf_malloc("%08x%08x",rand_data.b, rand_data.c); + pa_rtsp_add_header(c->rtsp, "Client-Instance", sci); + pa_xfree(sci); + pa_rtsp_set_callback(c->rtsp, rtsp_cb, c); + return pa_rtsp_connect(c->rtsp); +} + + +int pa_raop_flush(pa_raop_client* c) +{ + pa_assert(c); + + pa_rtsp_flush(c->rtsp, c->seq, c->rtptime); + return 0; +} + + +int pa_raop_client_set_volume(pa_raop_client* c, pa_volume_t volume) +{ + int rv; + double db; + char *param; + + pa_assert(c); + + db = pa_sw_volume_to_dB(volume); + if (db < VOLUME_MIN) + db = VOLUME_MIN; + else if (db > VOLUME_MAX) + db = VOLUME_MAX; + + param = pa_sprintf_malloc("volume: %0.6f\r\n", db); + + /* We just hit and hope, cannot wait for the callback */ + rv = pa_rtsp_setparameter(c->rtsp, param); + pa_xfree(param); + return rv; +} + + +int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchunk* encoded) +{ + uint16_t len; + size_t bufmax; + uint8_t *bp, bpos; + uint8_t *ibp, *maxibp; + int size; + uint8_t *b, *p; + uint32_t bsize; + size_t length; + static uint8_t header[] = { + 0x24, 0x00, 0x00, 0x00, + 0xF0, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }; + int header_size = sizeof(header); + + pa_assert(c); + pa_assert(c->fd > 0); + pa_assert(raw); + pa_assert(raw->memblock); + pa_assert(raw->length > 0); + pa_assert(encoded); + + /* We have to send 4 byte chunks */ + bsize = (int)(raw->length / 4); + length = bsize * 4; + + /* Leave 16 bytes extra to allow for the ALAC header which is about 55 bits */ + bufmax = length + header_size + 16; + pa_memchunk_reset(encoded); + encoded->memblock = pa_memblock_new(c->core->mempool, bufmax); + b = pa_memblock_acquire(encoded->memblock); + memcpy(b, header, header_size); + + /* Now write the actual samples */ + bp = b + header_size; + size = bpos = 0; + bit_writer(&bp,&bpos,&size,1,3); /* channel=1, stereo */ + bit_writer(&bp,&bpos,&size,0,4); /* unknown */ + bit_writer(&bp,&bpos,&size,0,8); /* unknown */ + bit_writer(&bp,&bpos,&size,0,4); /* unknown */ + bit_writer(&bp,&bpos,&size,1,1); /* hassize */ + bit_writer(&bp,&bpos,&size,0,2); /* unused */ + bit_writer(&bp,&bpos,&size,1,1); /* is-not-compressed */ + + /* size of data, integer, big endian */ + bit_writer(&bp,&bpos,&size,(bsize>>24)&0xff,8); + bit_writer(&bp,&bpos,&size,(bsize>>16)&0xff,8); + bit_writer(&bp,&bpos,&size,(bsize>>8)&0xff,8); + bit_writer(&bp,&bpos,&size,(bsize)&0xff,8); + + ibp = p = pa_memblock_acquire(raw->memblock); + maxibp = p + raw->length - 4; + while (ibp <= maxibp) { + /* Byte swap stereo data */ + bit_writer(&bp,&bpos,&size,*(ibp+1),8); + bit_writer(&bp,&bpos,&size,*(ibp+0),8); + bit_writer(&bp,&bpos,&size,*(ibp+3),8); + bit_writer(&bp,&bpos,&size,*(ibp+2),8); + ibp += 4; + raw->index += 4; + raw->length -= 4; + } + pa_memblock_release(raw->memblock); + encoded->length = header_size + size; + + /* store the lenght (endian swapped: make this better) */ + len = size + header_size - 4; + *(b + 2) = len >> 8; + *(b + 3) = len & 0xff; + + /* encrypt our data */ + aes_encrypt(c, (b + header_size), size); + + /* We're done with the chunk */ + pa_memblock_release(encoded->memblock); + + return 0; +} + + +void pa_raop_client_set_callback(pa_raop_client* c, pa_raop_client_cb_t callback, void *userdata) +{ + pa_assert(c); + + c->callback = callback; + c->userdata = userdata; +} + +void pa_raop_client_set_closed_callback(pa_raop_client* c, pa_raop_client_closed_cb_t callback, void *userdata) +{ + pa_assert(c); + + c->closed_callback = callback; + c->closed_userdata = userdata; +} diff --git a/src/modules/raop/raop_client.h b/src/modules/raop/raop_client.h new file mode 100644 index 00000000..ec3136a7 --- /dev/null +++ b/src/modules/raop/raop_client.h @@ -0,0 +1,46 @@ +#ifndef fooraopclientfoo +#define fooraopclientfoo + +/*** + This file is part of PulseAudio. + + Copyright 2008 Colin Guthrie + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include <pulse/mainloop-api.h> +#include <pulsecore/iochannel.h> +#include <pulsecore/core.h> + +typedef struct pa_raop_client pa_raop_client; + +pa_raop_client* pa_raop_client_new(pa_core *core, const char* host); +void pa_raop_client_free(pa_raop_client* c); + +int pa_raop_connect(pa_raop_client* c); +int pa_raop_flush(pa_raop_client* c); + +int pa_raop_client_set_volume(pa_raop_client* c, pa_volume_t volume); +int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchunk* encoded); + +typedef void (*pa_raop_client_cb_t)(int fd, void *userdata); +void pa_raop_client_set_callback(pa_raop_client* c, pa_raop_client_cb_t callback, void *userdata); + +typedef void (*pa_raop_client_closed_cb_t)(void *userdata); +void pa_raop_client_set_closed_callback(pa_raop_client* c, pa_raop_client_closed_cb_t callback, void *userdata); + +#endif diff --git a/src/modules/rtp/Makefile b/src/modules/rtp/Makefile index 316beb72..efe5a336 100644..120000 --- a/src/modules/rtp/Makefile +++ b/src/modules/rtp/Makefile @@ -1,13 +1 @@ -# This is a dirty trick just to ease compilation with emacs -# -# This file is not intended to be distributed or anything -# -# So: don't touch it, even better ignore it! - -all: - $(MAKE) -C ../.. - -clean: - $(MAKE) -C ../.. clean - -.PHONY: all clean +../../pulse/Makefile
\ No newline at end of file diff --git a/src/modules/rtp/headerlist.c b/src/modules/rtp/headerlist.c new file mode 100644 index 00000000..0fef835b --- /dev/null +++ b/src/modules/rtp/headerlist.c @@ -0,0 +1,186 @@ +/*** + This file is part of PulseAudio. + + Copyright 2008 Colin Guthrie + Copyright 2007 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> + +#include <pulse/xmalloc.h> + +#include <pulsecore/hashmap.h> +#include <pulsecore/strbuf.h> +#include <pulsecore/core-util.h> + +#include "headerlist.h" + +struct header { + char *key; + void *value; + size_t nbytes; +}; + +#define MAKE_HASHMAP(p) ((pa_hashmap*) (p)) +#define MAKE_HEADERLIST(p) ((pa_headerlist*) (p)) + +static void header_free(struct header *hdr) { + pa_assert(hdr); + + pa_xfree(hdr->key); + pa_xfree(hdr->value); + pa_xfree(hdr); +} + +pa_headerlist* pa_headerlist_new(void) { + return MAKE_HEADERLIST(pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func)); +} + +void pa_headerlist_free(pa_headerlist* p) { + struct header *hdr; + + while ((hdr = pa_hashmap_steal_first(MAKE_HASHMAP(p)))) + header_free(hdr); + + pa_hashmap_free(MAKE_HASHMAP(p), NULL, NULL); +} + +int pa_headerlist_puts(pa_headerlist *p, const char *key, const char *value) { + struct header *hdr; + pa_bool_t add = FALSE; + + pa_assert(p); + pa_assert(key); + + if (!(hdr = pa_hashmap_get(MAKE_HASHMAP(p), key))) { + hdr = pa_xnew(struct header, 1); + hdr->key = pa_xstrdup(key); + add = TRUE; + } else + pa_xfree(hdr->value); + + hdr->value = pa_xstrdup(value); + hdr->nbytes = strlen(value)+1; + + if (add) + pa_hashmap_put(MAKE_HASHMAP(p), hdr->key, hdr); + + return 0; +} + +int pa_headerlist_putsappend(pa_headerlist *p, const char *key, const char *value) { + struct header *hdr; + pa_bool_t add = FALSE; + + pa_assert(p); + pa_assert(key); + + if (!(hdr = pa_hashmap_get(MAKE_HASHMAP(p), key))) { + hdr = pa_xnew(struct header, 1); + hdr->key = pa_xstrdup(key); + hdr->value = pa_xstrdup(value); + add = TRUE; + } else { + void *newval = pa_sprintf_malloc("%s%s", (char*)hdr->value, value); + pa_xfree(hdr->value); + hdr->value = newval; + } + hdr->nbytes = strlen(hdr->value)+1; + + if (add) + pa_hashmap_put(MAKE_HASHMAP(p), hdr->key, hdr); + + return 0; +} + +const char *pa_headerlist_gets(pa_headerlist *p, const char *key) { + struct header *hdr; + + pa_assert(p); + pa_assert(key); + + if (!(hdr = pa_hashmap_get(MAKE_HASHMAP(p), key))) + return NULL; + + if (hdr->nbytes <= 0) + return NULL; + + if (((char*) hdr->value)[hdr->nbytes-1] != 0) + return NULL; + + if (strlen((char*) hdr->value) != hdr->nbytes-1) + return NULL; + + return (char*) hdr->value; +} + +int pa_headerlist_remove(pa_headerlist *p, const char *key) { + struct header *hdr; + + pa_assert(p); + pa_assert(key); + + if (!(hdr = pa_hashmap_remove(MAKE_HASHMAP(p), key))) + return -1; + + header_free(hdr); + return 0; +} + +const char *pa_headerlist_iterate(pa_headerlist *p, void **state) { + struct header *hdr; + + if (!(hdr = pa_hashmap_iterate(MAKE_HASHMAP(p), state, NULL))) + return NULL; + + return hdr->key; +} + +char *pa_headerlist_to_string(pa_headerlist *p) { + const char *key; + void *state = NULL; + pa_strbuf *buf; + + pa_assert(p); + + buf = pa_strbuf_new(); + + while ((key = pa_headerlist_iterate(p, &state))) { + + const char *v; + + if ((v = pa_headerlist_gets(p, key))) + pa_strbuf_printf(buf, "%s: %s\r\n", key, v); + } + + return pa_strbuf_tostring_free(buf); +} + +int pa_headerlist_contains(pa_headerlist *p, const char *key) { + pa_assert(p); + pa_assert(key); + + if (!(pa_hashmap_get(MAKE_HASHMAP(p), key))) + return 0; + + return 1; +} diff --git a/src/modules/rtp/headerlist.h b/src/modules/rtp/headerlist.h new file mode 100644 index 00000000..4b9c6433 --- /dev/null +++ b/src/modules/rtp/headerlist.h @@ -0,0 +1,46 @@ +#ifndef foopulseheaderlisthfoo +#define foopulseheaderlisthfoo + +/*** + This file is part of PulseAudio. + + Copyright 2008 Colin Guthrie + Copyright 2007 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include <pulsecore/macro.h> + +typedef struct pa_headerlist pa_headerlist; + +pa_headerlist* pa_headerlist_new(void); +void pa_headerlist_free(pa_headerlist* p); + +int pa_headerlist_puts(pa_headerlist *p, const char *key, const char *value); +int pa_headerlist_putsappend(pa_headerlist *p, const char *key, const char *value); + +const char *pa_headerlist_gets(pa_headerlist *p, const char *key); + +int pa_headerlist_remove(pa_headerlist *p, const char *key); + +const char *pa_headerlist_iterate(pa_headerlist *p, void **state); + +char *pa_headerlist_to_string(pa_headerlist *p); + +int pa_headerlist_contains(pa_headerlist *p, const char *key); + +#endif diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index e04e4611..e35773cc 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -238,25 +238,25 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) { else delta = j; - pa_memblockq_seek(s->memblockq, delta * s->rtp_context.frame_size, PA_SEEK_RELATIVE); + pa_memblockq_seek(s->memblockq, delta * (int64_t) s->rtp_context.frame_size, PA_SEEK_RELATIVE); pa_rtclock_get(&now); - pa_smoother_put(s->smoother, pa_timeval_load(&now), pa_bytes_to_usec(pa_memblockq_get_write_index(s->memblockq), &s->sink_input->sample_spec)); + pa_smoother_put(s->smoother, pa_timeval_load(&now), pa_bytes_to_usec((uint64_t) pa_memblockq_get_write_index(s->memblockq), &s->sink_input->sample_spec)); if (pa_memblockq_push(s->memblockq, &chunk) < 0) { pa_log_warn("Queue overrun"); - pa_memblockq_seek(s->memblockq, chunk.length, PA_SEEK_RELATIVE); + pa_memblockq_seek(s->memblockq, (int64_t) chunk.length, PA_SEEK_RELATIVE); } - pa_log("blocks in q: %u", pa_memblockq_get_nblocks(s->memblockq)); +/* pa_log("blocks in q: %u", pa_memblockq_get_nblocks(s->memblockq)); */ pa_memblock_unref(chunk.memblock); /* The next timestamp we expect */ - s->offset = s->rtp_context.timestamp + (chunk.length / s->rtp_context.frame_size); + s->offset = s->rtp_context.timestamp + (uint32_t) (chunk.length / s->rtp_context.frame_size); - pa_atomic_store(&s->timestamp, now.tv_sec); + pa_atomic_store(&s->timestamp, (int) now.tv_sec); if (s->last_rate_update + RATE_UPDATE_INTERVAL < pa_timeval_load(&now)) { pa_usec_t wi, ri, render_delay, sink_delay = 0, latency, fix; @@ -265,7 +265,7 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) { pa_log("Updating sample rate"); wi = pa_smoother_get(s->smoother, pa_timeval_load(&now)); - ri = pa_bytes_to_usec(pa_memblockq_get_read_index(s->memblockq), &s->sink_input->sample_spec); + ri = pa_bytes_to_usec((uint64_t) pa_memblockq_get_read_index(s->memblockq), &s->sink_input->sample_spec); if (PA_MSGOBJECT(s->sink_input->sink)->process_msg(PA_MSGOBJECT(s->sink_input->sink), PA_SINK_MESSAGE_GET_LATENCY, &sink_delay, 0, NULL) < 0) sink_delay = 0; @@ -291,7 +291,7 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) { fix = latency - s->intended_latency; /* How many samples is this per second? */ - fix_samples = fix * s->sink_input->thread_info.sample_spec.rate / RATE_UPDATE_INTERVAL; + fix_samples = (unsigned) (fix * (pa_usec_t) s->sink_input->thread_info.sample_spec.rate / (pa_usec_t) RATE_UPDATE_INTERVAL); /* Check if deviation is in bounds */ if (fix_samples > s->sink_input->sample_spec.rate*.20) @@ -431,7 +431,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in s->smoother = pa_smoother_new(PA_USEC_PER_SEC*5, PA_USEC_PER_SEC*2, TRUE, 10); pa_smoother_set_time_offset(s->smoother, pa_timeval_load(&now)); s->last_rate_update = pa_timeval_load(&now); - pa_atomic_store(&s->timestamp, now.tv_sec); + pa_atomic_store(&s->timestamp, (int) now.tv_sec); if ((fd = mcast_socket((const struct sockaddr*) &sdp_info->sa, sdp_info->salen)) < 0) goto fail; @@ -566,7 +566,7 @@ static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event } else { struct timeval now; pa_rtclock_get(&now); - pa_atomic_store(&s->timestamp, now.tv_sec); + pa_atomic_store(&s->timestamp, (int) now.tv_sec); pa_sdp_info_destroy(&info); } diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 5e542253..8d1e92fe 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -67,10 +67,12 @@ PA_MODULE_USAGE( "destination=<destination IP address> " "port=<port number> " "mtu=<maximum transfer unit> " - "loop=<loopback to local host?>" + "loop=<loopback to local host?> " + "ttl=<ttl value>" ); #define DEFAULT_PORT 46000 +#define DEFAULT_TTL 1 #define SAP_PORT 9875 #define DEFAULT_DESTINATION "224.0.0.56" #define MEMBLOCKQ_MAXLENGTH (1024*170) @@ -86,6 +88,7 @@ static const char* const valid_modargs[] = { "port", "mtu" , "loop", + "ttl", NULL }; @@ -167,7 +170,9 @@ int pa__init(pa_module*m) { pa_modargs *ma = NULL; const char *dest; uint32_t port = DEFAULT_PORT, mtu; - int af, fd = -1, sap_fd = -1; + uint32_t ttl = DEFAULT_TTL; + sa_family_t af; + int fd = -1, sap_fd = -1; pa_source *s; pa_sample_spec ss; pa_channel_map cm; @@ -219,14 +224,14 @@ int pa__init(pa_module*m) { payload = pa_rtp_payload_from_sample_spec(&ss); - mtu = pa_frame_align(DEFAULT_MTU, &ss); + mtu = (uint32_t) pa_frame_align(DEFAULT_MTU, &ss); if (pa_modargs_get_value_u32(ma, "mtu", &mtu) < 0 || mtu < 1 || mtu % pa_frame_size(&ss) != 0) { pa_log("Invalid MTU."); goto fail; } - port = DEFAULT_PORT + ((rand() % 512) << 1); + port = DEFAULT_PORT + ((uint32_t) (rand() % 512) << 1); if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { pa_log("port= expects a numerical argument between 1 and 65535."); goto fail; @@ -235,16 +240,21 @@ int pa__init(pa_module*m) { if (port & 1) pa_log_warn("Port number not even as suggested in RFC3550!"); + if (pa_modargs_get_value_u32(ma, "ttl", &ttl) < 0 || ttl < 1 || ttl > 0xFF) { + pa_log("ttl= expects a numerical argument between 1 and 255."); + goto fail; + } + dest = pa_modargs_get_value(ma, "destination", DEFAULT_DESTINATION); if (inet_pton(AF_INET6, dest, &sa6.sin6_addr) > 0) { sa6.sin6_family = af = AF_INET6; - sa6.sin6_port = htons(port); + sa6.sin6_port = htons((uint16_t) port); sap_sa6 = sa6; sap_sa6.sin6_port = htons(SAP_PORT); } else if (inet_pton(AF_INET, dest, &sa4.sin_addr) > 0) { sa4.sin_family = af = AF_INET; - sa4.sin_port = htons(port); + sa4.sin_port = htons((uint16_t) port); sap_sa4 = sa4; sap_sa4.sin_port = htons(SAP_PORT); } else { @@ -257,7 +267,7 @@ int pa__init(pa_module*m) { goto fail; } - if (connect(fd, af == AF_INET ? (struct sockaddr*) &sa4 : (struct sockaddr*) &sa6, af == AF_INET ? sizeof(sa4) : sizeof(sa6)) < 0) { + if (connect(fd, af == AF_INET ? (struct sockaddr*) &sa4 : (struct sockaddr*) &sa6, (socklen_t) (af == AF_INET ? sizeof(sa4) : sizeof(sa6))) < 0) { pa_log("connect() failed: %s", pa_cstrerror(errno)); goto fail; } @@ -267,7 +277,7 @@ int pa__init(pa_module*m) { goto fail; } - if (connect(sap_fd, af == AF_INET ? (struct sockaddr*) &sap_sa4 : (struct sockaddr*) &sap_sa6, af == AF_INET ? sizeof(sap_sa4) : sizeof(sap_sa6)) < 0) { + if (connect(sap_fd, af == AF_INET ? (struct sockaddr*) &sap_sa4 : (struct sockaddr*) &sap_sa6, (socklen_t) (af == AF_INET ? sizeof(sap_sa4) : sizeof(sap_sa6))) < 0) { pa_log("connect() failed: %s", pa_cstrerror(errno)); goto fail; } @@ -279,6 +289,15 @@ int pa__init(pa_module*m) { goto fail; } + if (ttl != DEFAULT_TTL) { + int _ttl = (int) ttl; + + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &_ttl, sizeof(_ttl)) < 0) { + pa_log("IP_MULTICAST_TTL failed: %s", pa_cstrerror(errno)); + goto fail; + } + } + /* If the socket queue is full, let's drop packets */ pa_make_fd_nonblock(fd); pa_make_udp_socket_low_delay(fd); @@ -290,13 +309,14 @@ int pa__init(pa_module*m) { pa_proplist_sets(data.proplist, "rtp.destination", dest); pa_proplist_setf(data.proplist, "rtp.mtu", "%lu", (unsigned long) mtu); pa_proplist_setf(data.proplist, "rtp.port", "%lu", (unsigned long) port); + pa_proplist_setf(data.proplist, "rtp.ttl", "%lu", (unsigned long) ttl); data.driver = __FILE__; data.module = m; data.source = s; pa_source_output_new_data_set_sample_spec(&data, &ss); pa_source_output_new_data_set_channel_map(&data, &cm); - o = pa_source_output_new(m->core, &data, 0); + o = pa_source_output_new(m->core, &data, PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND); pa_source_output_new_data_done(&data); if (!o) { @@ -335,14 +355,14 @@ int pa__init(pa_module*m) { p = pa_sdp_build(af, af == AF_INET ? (void*) &((struct sockaddr_in*) &sa_dst)->sin_addr : (void*) &((struct sockaddr_in6*) &sa_dst)->sin6_addr, af == AF_INET ? (void*) &sa4.sin_addr : (void*) &sa6.sin6_addr, - n, port, payload, &ss); + n, (uint16_t) port, payload, &ss); pa_xfree(n); pa_rtp_context_init_send(&u->rtp_context, fd, m->core->cookie, payload, pa_frame_size(&ss)); pa_sap_context_init_send(&u->sap_context, sap_fd, p); - pa_log_info("RTP stream initialized with mtu %u on %s:%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, u->rtp_context.ssrc, payload, u->rtp_context.sequence); + pa_log_info("RTP stream initialized with mtu %u on %s:%u ttl=%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, ttl, u->rtp_context.ssrc, payload, u->rtp_context.sequence); pa_log_info("SDP-Data:\n%s\nEOF", p); pa_sap_send(&u->sap_context, 0); diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index 5a33ebc2..88351010 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -50,7 +50,7 @@ pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssr c->sequence = (uint16_t) (rand()*rand()); c->timestamp = 0; c->ssrc = ssrc ? ssrc : (uint32_t) (rand()*rand()); - c->payload = payload & 127; + c->payload = (uint8_t) (payload & 127U); c->frame_size = frame_size; pa_memchunk_reset(&c->memchunk); @@ -99,7 +99,8 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { if (r < 0 || n >= size || iov_idx >= MAX_IOVECS) { uint32_t header[3]; struct msghdr m; - int k, i; + ssize_t k; + int i; if (n > 0) { header[0] = htonl(((uint32_t) 2 << 30) | ((uint32_t) c->payload << 16) | ((uint32_t) c->sequence)); @@ -112,7 +113,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { m.msg_name = NULL; m.msg_namelen = 0; m.msg_iov = iov; - m.msg_iovlen = iov_idx; + m.msg_iovlen = (size_t) iov_idx; m.msg_control = NULL; m.msg_controllen = 0; m.msg_flags = 0; @@ -128,7 +129,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { } else k = 0; - c->timestamp += n/c->frame_size; + c->timestamp += (unsigned) (n/c->frame_size); if (k < 0) { if (errno != EAGAIN && errno != EINTR) /* If the queue is full, just ignore it */ @@ -162,7 +163,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { struct msghdr m; struct iovec iov; uint32_t header; - int cc; + unsigned cc; ssize_t r; pa_assert(c); @@ -197,7 +198,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { chunk->index = c->memchunk.index; iov.iov_base = (uint8_t*) pa_memblock_acquire(chunk->memblock) + chunk->index; - iov.iov_len = size; + iov.iov_len = (size_t) size; m.msg_name = NULL; m.msg_namelen = 0; @@ -246,16 +247,16 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { } cc = (header >> 24) & 0xF; - c->payload = (header >> 16) & 127; - c->sequence = header & 0xFFFF; + c->payload = (uint8_t) ((header >> 16) & 127U); + c->sequence = (uint16_t) (header & 0xFFFFU); - if (12 + cc*4 > size) { + if (12 + cc*4 > (unsigned) size) { pa_log_warn("RTP packet too short. (CSRC)"); goto fail; } chunk->index += 12 + cc*4; - chunk->length = size - 12 + cc*4; + chunk->length = (size_t) size - 12 + cc*4; if (chunk->length % c->frame_size != 0) { pa_log_warn("Bad RTP packet size."); diff --git a/src/modules/rtp/rtsp_client.c b/src/modules/rtp/rtsp_client.c new file mode 100644 index 00000000..9eb3d964 --- /dev/null +++ b/src/modules/rtp/rtsp_client.c @@ -0,0 +1,542 @@ +/*** + This file is part of PulseAudio. + + Copyright 2008 Colin Guthrie + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <sys/ioctl.h> + +#ifdef HAVE_SYS_FILIO_H +#include <sys/filio.h> +#endif + +#include <pulse/xmalloc.h> + +#include <pulsecore/core-error.h> +#include <pulsecore/core-util.h> +#include <pulsecore/socket-util.h> +#include <pulsecore/log.h> +#include <pulsecore/macro.h> +#include <pulsecore/strbuf.h> +#include <pulsecore/poll.h> +#include <pulsecore/ioline.h> + +#include "rtsp_client.h" + +struct pa_rtsp_client { + pa_mainloop_api *mainloop; + char *hostname; + uint16_t port; + + pa_socket_client *sc; + pa_iochannel *io; + pa_ioline *ioline; + + pa_rtsp_cb_t callback; + + void *userdata; + const char *useragent; + + pa_rtsp_state state; + uint8_t waiting; + + pa_headerlist* headers; + char *last_header; + pa_strbuf *header_buffer; + pa_headerlist* response_headers; + + char *localip; + char *url; + uint16_t rtp_port; + uint32_t cseq; + char *session; + char *transport; +}; + +pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char* hostname, uint16_t port, const char* useragent) { + pa_rtsp_client *c; + + pa_assert(mainloop); + pa_assert(hostname); + pa_assert(port > 0); + + c = pa_xnew0(pa_rtsp_client, 1); + c->mainloop = mainloop; + c->hostname = pa_xstrdup(hostname); + c->port = port; + c->headers = pa_headerlist_new(); + + if (useragent) + c->useragent = useragent; + else + c->useragent = "PulseAudio RTSP Client"; + + return c; +} + + +void pa_rtsp_client_free(pa_rtsp_client* c) { + if (c) { + if (c->sc) + pa_socket_client_unref(c->sc); + if (c->ioline) + pa_ioline_close(c->ioline); + else if (c->io) + pa_iochannel_free(c->io); + + pa_xfree(c->hostname); + pa_xfree(c->url); + pa_xfree(c->localip); + pa_xfree(c->session); + pa_xfree(c->transport); + pa_xfree(c->last_header); + if (c->header_buffer) + pa_strbuf_free(c->header_buffer); + if (c->response_headers) + pa_headerlist_free(c->response_headers); + pa_headerlist_free(c->headers); + } + pa_xfree(c); +} + + +static void headers_read(pa_rtsp_client *c) { + char* token; + char delimiters[] = ";"; + + pa_assert(c); + pa_assert(c->response_headers); + pa_assert(c->callback); + + /* Deal with a SETUP response */ + if (STATE_SETUP == c->state) { + const char* token_state = NULL; + const char* pc = NULL; + c->session = pa_xstrdup(pa_headerlist_gets(c->response_headers, "Session")); + c->transport = pa_xstrdup(pa_headerlist_gets(c->response_headers, "Transport")); + + if (!c->session || !c->transport) { + pa_headerlist_free(c->response_headers); + c->response_headers = NULL; + pa_log("Invalid SETUP response."); + return; + } + + /* Now parse out the server port component of the response. */ + while ((token = pa_split(c->transport, delimiters, &token_state))) { + if ((pc = strstr(token, "="))) { + if (0 == strncmp(token, "server_port", 11)) { + pa_atou(pc+1, (uint32_t*)(&c->rtp_port)); + pa_xfree(token); + break; + } + } + pa_xfree(token); + } + if (0 == c->rtp_port) { + /* Error no server_port in response */ + pa_headerlist_free(c->response_headers); + c->response_headers = NULL; + pa_log("Invalid SETUP response (no port number)."); + return; + } + } + + /* Call our callback */ + c->callback(c, c->state, c->response_headers, c->userdata); + + pa_headerlist_free(c->response_headers); + c->response_headers = NULL; +} + + +static void line_callback(pa_ioline *line, const char *s, void *userdata) { + char *delimpos; + char *s2, *s2p; + + pa_rtsp_client *c = userdata; + pa_assert(line); + pa_assert(c); + pa_assert(c->callback); + + if (!s) { + /* Keep the ioline/iochannel open as they will be freed automatically */ + c->ioline = NULL; + c->io = NULL; + c->callback(c, STATE_DISCONNECTED, NULL, c->userdata); + return; + } + + s2 = pa_xstrdup(s); + /* Trim trailing carriage returns */ + s2p = s2 + strlen(s2) - 1; + while (s2p >= s2 && '\r' == *s2p) { + *s2p = '\0'; + s2p -= 1; + } + if (c->waiting && 0 == strcmp("RTSP/1.0 200 OK", s2)) { + c->waiting = 0; + pa_assert(!c->response_headers); + c->response_headers = pa_headerlist_new(); + goto exit; + } + if (c->waiting) { + pa_log_warn("Unexpected response: %s", s2); + goto exit;; + } + if (!strlen(s2)) { + /* End of headers */ + /* We will have a header left from our looping itteration, so add it in :) */ + if (c->last_header) { + /* This is not a continuation header so let's dump it into our proplist */ + pa_headerlist_puts(c->response_headers, c->last_header, pa_strbuf_tostring_free(c->header_buffer)); + pa_xfree(c->last_header); + c->last_header = NULL; + c->header_buffer= NULL; + } + + pa_log_debug("Full response received. Dispatching"); + headers_read(c); + c->waiting = 1; + goto exit; + } + + /* Read and parse a header (we know it's not empty) */ + /* TODO: Move header reading into the headerlist. */ + + /* If the first character is a space, it's a continuation header */ + if (c->last_header && ' ' == s2[0]) { + pa_assert(c->header_buffer); + + /* Add this line to the buffer (sans the space. */ + pa_strbuf_puts(c->header_buffer, &(s2[1])); + goto exit; + } + + if (c->last_header) { + /* This is not a continuation header so let's dump the full + header/value into our proplist */ + pa_headerlist_puts(c->response_headers, c->last_header, pa_strbuf_tostring_free(c->header_buffer)); + pa_xfree(c->last_header); + c->last_header = NULL; + c->header_buffer = NULL; + } + + delimpos = strstr(s2, ":"); + if (!delimpos) { + pa_log_warn("Unexpected response when expecting header: %s", s); + goto exit; + } + + pa_assert(!c->header_buffer); + pa_assert(!c->last_header); + + c->header_buffer = pa_strbuf_new(); + if (strlen(delimpos) > 1) { + /* Cut our line off so we can copy the header name out */ + *delimpos++ = '\0'; + + /* Trim the front of any spaces */ + while (' ' == *delimpos) + ++delimpos; + + pa_strbuf_puts(c->header_buffer, delimpos); + } else { + /* Cut our line off so we can copy the header name out */ + *delimpos = '\0'; + } + + /* Save the header name */ + c->last_header = pa_xstrdup(s2); + exit: + pa_xfree(s2); +} + + +static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata) { + pa_rtsp_client *c = userdata; + union { + struct sockaddr sa; + struct sockaddr_in in; + struct sockaddr_in6 in6; + } sa; + socklen_t sa_len = sizeof(sa); + + pa_assert(sc); + pa_assert(c); + pa_assert(STATE_CONNECT == c->state); + pa_assert(c->sc == sc); + pa_socket_client_unref(c->sc); + c->sc = NULL; + + if (!io) { + pa_log("Connection failed: %s", pa_cstrerror(errno)); + return; + } + pa_assert(!c->io); + c->io = io; + + c->ioline = pa_ioline_new(io); + pa_ioline_set_callback(c->ioline, line_callback, c); + + /* Get the local IP address for use externally */ + if (0 == getsockname(pa_iochannel_get_recv_fd(io), &sa.sa, &sa_len)) { + char buf[INET6_ADDRSTRLEN]; + const char *res = NULL; + + if (AF_INET == sa.sa.sa_family) { + if ((res = inet_ntop(sa.sa.sa_family, &sa.in.sin_addr, buf, sizeof(buf)))) { + c->localip = pa_xstrdup(res); + } + } else if (AF_INET6 == sa.sa.sa_family) { + if ((res = inet_ntop(AF_INET6, &sa.in6.sin6_addr, buf, sizeof(buf)))) { + c->localip = pa_sprintf_malloc("[%s]", res); + } + } + } + pa_log_debug("Established RTSP connection from local ip %s", c->localip); + + if (c->callback) + c->callback(c, c->state, NULL, c->userdata); +} + +int pa_rtsp_connect(pa_rtsp_client *c) { + pa_assert(c); + pa_assert(!c->sc); + + pa_xfree(c->session); + c->session = NULL; + + if (!(c->sc = pa_socket_client_new_string(c->mainloop, c->hostname, c->port))) { + pa_log("failed to connect to server '%s:%d'", c->hostname, c->port); + return -1; + } + + pa_socket_client_set_callback(c->sc, on_connection, c); + c->waiting = 1; + c->state = STATE_CONNECT; + return 0; +} + +void pa_rtsp_set_callback(pa_rtsp_client *c, pa_rtsp_cb_t callback, void *userdata) { + pa_assert(c); + + c->callback = callback; + c->userdata = userdata; +} + +void pa_rtsp_disconnect(pa_rtsp_client *c) { + pa_assert(c); + + if (c->io) + pa_iochannel_free(c->io); + c->io = NULL; +} + + +const char* pa_rtsp_localip(pa_rtsp_client* c) { + pa_assert(c); + + return c->localip; +} + +uint32_t pa_rtsp_serverport(pa_rtsp_client* c) { + pa_assert(c); + + return c->rtp_port; +} + +void pa_rtsp_set_url(pa_rtsp_client* c, const char* url) { + pa_assert(c); + + c->url = pa_xstrdup(url); +} + +void pa_rtsp_add_header(pa_rtsp_client *c, const char* key, const char* value) +{ + pa_assert(c); + pa_assert(key); + pa_assert(value); + + pa_headerlist_puts(c->headers, key, value); +} + +void pa_rtsp_remove_header(pa_rtsp_client *c, const char* key) +{ + pa_assert(c); + pa_assert(key); + + pa_headerlist_remove(c->headers, key); +} + +static int rtsp_exec(pa_rtsp_client* c, const char* cmd, + const char* content_type, const char* content, + int expect_response, + pa_headerlist* headers) { + pa_strbuf* buf; + char* hdrs; + ssize_t l; + + pa_assert(c); + pa_assert(c->url); + + if (!cmd) + return -1; + + pa_log_debug("Sending command: %s", cmd); + + buf = pa_strbuf_new(); + pa_strbuf_printf(buf, "%s %s RTSP/1.0\r\nCSeq: %d\r\n", cmd, c->url, ++c->cseq); + if (c->session) + pa_strbuf_printf(buf, "Session: %s\r\n", c->session); + + /* Add the headers */ + if (headers) { + hdrs = pa_headerlist_to_string(headers); + pa_strbuf_puts(buf, hdrs); + pa_xfree(hdrs); + } + + if (content_type && content) { + pa_strbuf_printf(buf, "Content-Type: %s\r\nContent-Length: %d\r\n", + content_type, (int)strlen(content)); + } + + pa_strbuf_printf(buf, "User-Agent: %s\r\n", c->useragent); + + if (c->headers) { + hdrs = pa_headerlist_to_string(c->headers); + pa_strbuf_puts(buf, hdrs); + pa_xfree(hdrs); + } + + pa_strbuf_puts(buf, "\r\n"); + + if (content_type && content) { + pa_strbuf_puts(buf, content); + } + + /* Our packet is created... now we can send it :) */ + hdrs = pa_strbuf_tostring_free(buf); + /*pa_log_debug("Submitting request:"); + pa_log_debug(hdrs);*/ + l = pa_iochannel_write(c->io, hdrs, strlen(hdrs)); + pa_xfree(hdrs); + + return 0; +} + + +int pa_rtsp_announce(pa_rtsp_client *c, const char* sdp) { + pa_assert(c); + if (!sdp) + return -1; + + c->state = STATE_ANNOUNCE; + return rtsp_exec(c, "ANNOUNCE", "application/sdp", sdp, 1, NULL); +} + + +int pa_rtsp_setup(pa_rtsp_client* c) { + pa_headerlist* headers; + int rv; + + pa_assert(c); + + headers = pa_headerlist_new(); + pa_headerlist_puts(headers, "Transport", "RTP/AVP/TCP;unicast;interleaved=0-1;mode=record"); + + c->state = STATE_SETUP; + rv = rtsp_exec(c, "SETUP", NULL, NULL, 1, headers); + pa_headerlist_free(headers); + return rv; +} + + +int pa_rtsp_record(pa_rtsp_client* c, uint16_t* seq, uint32_t* rtptime) { + pa_headerlist* headers; + int rv; + char *info; + + pa_assert(c); + if (!c->session) { + /* No seesion in progres */ + return -1; + } + + /* Todo: Generate these values randomly as per spec */ + *seq = *rtptime = 0; + + headers = pa_headerlist_new(); + pa_headerlist_puts(headers, "Range", "npt=0-"); + info = pa_sprintf_malloc("seq=%u;rtptime=%u", *seq, *rtptime); + pa_headerlist_puts(headers, "RTP-Info", info); + pa_xfree(info); + + c->state = STATE_RECORD; + rv = rtsp_exec(c, "RECORD", NULL, NULL, 1, headers); + pa_headerlist_free(headers); + return rv; +} + + +int pa_rtsp_teardown(pa_rtsp_client *c) { + pa_assert(c); + + c->state = STATE_TEARDOWN; + return rtsp_exec(c, "TEARDOWN", NULL, NULL, 0, NULL); +} + + +int pa_rtsp_setparameter(pa_rtsp_client *c, const char* param) { + pa_assert(c); + if (!param) + return -1; + + c->state = STATE_SET_PARAMETER; + return rtsp_exec(c, "SET_PARAMETER", "text/parameters", param, 1, NULL); +} + + +int pa_rtsp_flush(pa_rtsp_client *c, uint16_t seq, uint32_t rtptime) { + pa_headerlist* headers; + int rv; + char *info; + + pa_assert(c); + + headers = pa_headerlist_new(); + info = pa_sprintf_malloc("seq=%u;rtptime=%u", seq, rtptime); + pa_headerlist_puts(headers, "RTP-Info", info); + pa_xfree(info); + + c->state = STATE_FLUSH; + rv = rtsp_exec(c, "FLUSH", NULL, NULL, 1, headers); + pa_headerlist_free(headers); + return rv; +} diff --git a/src/modules/rtp/rtsp_client.h b/src/modules/rtp/rtsp_client.h new file mode 100644 index 00000000..88fb3839 --- /dev/null +++ b/src/modules/rtp/rtsp_client.h @@ -0,0 +1,73 @@ +#ifndef foortspclienthfoo +#define foortspclienthfoo + +/*** + This file is part of PulseAudio. + + Copyright 2008 Colin Guthrie + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include <inttypes.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <netdb.h> + +#include <pulsecore/memblockq.h> +#include <pulsecore/memchunk.h> +#include <pulsecore/socket-client.h> +#include <pulse/mainloop-api.h> + +#include "headerlist.h" + +typedef struct pa_rtsp_client pa_rtsp_client; +typedef enum { + STATE_CONNECT, + STATE_ANNOUNCE, + STATE_SETUP, + STATE_RECORD, + STATE_FLUSH, + STATE_TEARDOWN, + STATE_SET_PARAMETER, + STATE_DISCONNECTED +} pa_rtsp_state; +typedef void (*pa_rtsp_cb_t)(pa_rtsp_client *c, pa_rtsp_state state, pa_headerlist* hl, void *userdata); + +pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char* hostname, uint16_t port, const char* useragent); +void pa_rtsp_client_free(pa_rtsp_client* c); + +int pa_rtsp_connect(pa_rtsp_client* c); +void pa_rtsp_set_callback(pa_rtsp_client *c, pa_rtsp_cb_t callback, void *userdata); + +void pa_rtsp_disconnect(pa_rtsp_client* c); + +const char* pa_rtsp_localip(pa_rtsp_client* c); +uint32_t pa_rtsp_serverport(pa_rtsp_client* c); +void pa_rtsp_set_url(pa_rtsp_client* c, const char* url); +void pa_rtsp_add_header(pa_rtsp_client *c, const char* key, const char* value); +void pa_rtsp_remove_header(pa_rtsp_client *c, const char* key); + +int pa_rtsp_announce(pa_rtsp_client* c, const char* sdp); + +int pa_rtsp_setup(pa_rtsp_client* c); +int pa_rtsp_record(pa_rtsp_client* c, uint16_t* seq, uint32_t* rtptime); +int pa_rtsp_teardown(pa_rtsp_client* c); + +int pa_rtsp_setparameter(pa_rtsp_client* c, const char* param); +int pa_rtsp_flush(pa_rtsp_client* c, uint16_t seq, uint32_t rtptime); + +#endif diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index 5d9b58fa..b0c95aa5 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -76,7 +76,7 @@ int pa_sap_send(pa_sap_context *c, pa_bool_t goodbye) { socklen_t salen = sizeof(sa_buf); struct iovec iov[4]; struct msghdr m; - int k; + ssize_t k; if (getsockname(c->fd, sa, &salen) < 0) { pa_log("getsockname() failed: %s\n", pa_cstrerror(errno)); @@ -94,7 +94,7 @@ int pa_sap_send(pa_sap_context *c, pa_bool_t goodbye) { iov[0].iov_len = sizeof(header); iov[1].iov_base = sa->sa_family == AF_INET ? (void*) &((struct sockaddr_in*) sa)->sin_addr : (void*) &((struct sockaddr_in6*) sa)->sin6_addr; - iov[1].iov_len = sa->sa_family == AF_INET ? 4 : 16; + iov[1].iov_len = sa->sa_family == AF_INET ? 4U : 16U; iov[2].iov_base = (char*) MIME_TYPE; iov[2].iov_len = sizeof(MIME_TYPE); @@ -113,7 +113,7 @@ int pa_sap_send(pa_sap_context *c, pa_bool_t goodbye) { if ((k = sendmsg(c->fd, &m, MSG_DONTWAIT)) < 0) pa_log_warn("sendmsg() failed: %s\n", pa_cstrerror(errno)); - return k; + return (int) k; } pa_sap_context* pa_sap_context_init_recv(pa_sap_context *c, int fd) { @@ -128,10 +128,10 @@ pa_sap_context* pa_sap_context_init_recv(pa_sap_context *c, int fd) { int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye) { struct msghdr m; struct iovec iov; - int size, k; + int size; char *buf = NULL, *e; uint32_t header; - int six, ac; + unsigned six, ac, k; ssize_t r; pa_assert(c); @@ -142,11 +142,11 @@ int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye) { goto fail; } - buf = pa_xnew(char, size+1); + buf = pa_xnew(char, (unsigned) size+1); buf[size] = 0; iov.iov_base = buf; - iov.iov_len = size; + iov.iov_len = (size_t) size; m.msg_name = NULL; m.msg_namelen = 0; @@ -184,21 +184,21 @@ int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye) { goto fail; } - six = (header >> 28) & 1; - ac = (header >> 16) & 0xFF; + six = (header >> 28) & 1U; + ac = (header >> 16) & 0xFFU; - k = 4 + (six ? 16 : 4) + ac*4; - if (size < k) { + k = 4 + (six ? 16U : 4U) + ac*4U; + if ((unsigned) size < k) { pa_log_warn("SAP packet too short (AD)."); goto fail; } e = buf + k; - size -= k; + size -= (int) k; if ((unsigned) size >= sizeof(MIME_TYPE) && !strcmp(e, MIME_TYPE)) { e += sizeof(MIME_TYPE); - size -= sizeof(MIME_TYPE); + size -= (int) sizeof(MIME_TYPE); } else if ((unsigned) size < sizeof(PA_SDP_HEADER)-1 || strncmp(e, PA_SDP_HEADER, sizeof(PA_SDP_HEADER)-1)) { pa_log_warn("Invalid SDP header."); goto fail; @@ -207,7 +207,7 @@ int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye) { if (c->sdp_data) pa_xfree(c->sdp_data); - c->sdp_data = pa_xstrndup(e, size); + c->sdp_data = pa_xstrndup(e, (unsigned) size); pa_xfree(buf); *goodbye = !!((header >> 26) & 1); diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c index cef90433..59989e1a 100644 --- a/src/modules/rtp/sdp.c +++ b/src/modules/rtp/sdp.c @@ -55,7 +55,7 @@ char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, u if (!(u = pa_get_user_name(un, sizeof(un)))) u = "-"; - ntp = time(NULL) + 2208988800U; + ntp = (uint32_t) time(NULL) + 2208988800U; pa_assert_se(a = inet_ntop(af, src, buf_src, sizeof(buf_src))); pa_assert_se(a = inet_ntop(af, dst, buf_dst, sizeof(buf_dst))); @@ -99,10 +99,10 @@ static pa_sample_spec *parse_sdp_sample_spec(pa_sample_spec *ss, char *c) { return NULL; if (sscanf(c, "%u/%u", &rate, &channels) == 2) { - ss->rate = rate; - ss->channels = channels; + ss->rate = (uint32_t) rate; + ss->channels = (uint8_t) channels; } else if (sscanf(c, "%u", &rate) == 2) { - ss->rate = rate; + ss->rate = (uint32_t) rate; ss->channels = 1; } else return NULL; diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c index db0c4b3f..fd313bd3 100644 --- a/src/pulse/channelmap.c +++ b/src/pulse/channelmap.c @@ -198,10 +198,11 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p pa_assert(m); pa_assert(channels > 0); pa_assert(channels <= PA_CHANNELS_MAX); + pa_assert(def < PA_CHANNEL_MAP_DEF_MAX); pa_channel_map_init(m); - m->channels = channels; + m->channels = (uint8_t) channels; switch (def) { case PA_CHANNEL_MAP_AIFF: @@ -287,9 +288,6 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p case PA_CHANNEL_MAP_AUX: { unsigned i; - if (channels >= PA_CHANNELS_MAX) - return NULL; - for (i = 0; i < channels; i++) m->map[i] = PA_CHANNEL_POSITION_AUX0 + i; @@ -391,7 +389,7 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p default: - return NULL; + pa_assert_not_reached(); } } @@ -401,6 +399,7 @@ pa_channel_map* pa_channel_map_init_extend(pa_channel_map *m, unsigned channels, pa_assert(m); pa_assert(channels > 0); pa_assert(channels <= PA_CHANNELS_MAX); + pa_assert(def < PA_CHANNEL_MAP_DEF_MAX); pa_channel_map_init(m); @@ -415,7 +414,7 @@ pa_channel_map* pa_channel_map_init_extend(pa_channel_map *m, unsigned channels, i++; } - m->channels = channels; + m->channels = (uint8_t) channels; return m; } @@ -460,13 +459,20 @@ int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) { char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) { unsigned channel; - int first = 1; + pa_bool_t first = TRUE; char *e; pa_assert(s); pa_assert(l > 0); pa_assert(map); + pa_init_i18n(); + + if (!pa_channel_map_valid(map)) { + pa_snprintf(s, l, _("(invalid)")); + return s; + } + *(e = s) = 0; for (channel = 0; channel < map->channels && l > 1; channel++) { @@ -475,7 +481,7 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) { pa_channel_position_to_string(map->map[channel])); e = strchr(e, 0); - first = 0; + first = FALSE; } return s; @@ -489,7 +495,7 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) { pa_assert(rmap); pa_assert(s); - memset(&map, 0, sizeof(map)); + pa_channel_map_init(&map); if (strcmp(s, "stereo") == 0) { map.channels = 2; @@ -552,11 +558,22 @@ int pa_channel_map_valid(const pa_channel_map *map) { if (map->channels <= 0 || map->channels > PA_CHANNELS_MAX) return 0; - for (c = 0; c < map->channels; c++) { - - if (map->map[c] < 0 ||map->map[c] >= PA_CHANNEL_POSITION_MAX) + for (c = 0; c < map->channels; c++) + if (map->map[c] < 0 || map->map[c] >= PA_CHANNEL_POSITION_MAX) return 0; - } return 1; } + +int pa_channel_map_compatible(const pa_channel_map *map, const pa_sample_spec *ss) { + pa_assert(map); + pa_assert(ss); + + if (!pa_channel_map_valid(map)) + return 0; + + if (!pa_sample_spec_valid(ss)) + return 0; + + return map->channels == ss->channels; +} diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h index 7c32b868..d7d19d79 100644 --- a/src/pulse/channelmap.h +++ b/src/pulse/channelmap.h @@ -142,24 +142,42 @@ typedef enum pa_channel_position { /** A list of channel mapping definitions for pa_channel_map_init_auto() */ typedef enum pa_channel_map_def { - PA_CHANNEL_MAP_AIFF, /**< The mapping from RFC3551, which is based on AIFF-C */ - PA_CHANNEL_MAP_ALSA, /**< The default mapping used by ALSA */ - PA_CHANNEL_MAP_AUX, /**< Only aux channels */ - PA_CHANNEL_MAP_WAVEEX, /**< Microsoft's WAVEFORMATEXTENSIBLE mapping */ - PA_CHANNEL_MAP_OSS, /**< The default channel mapping used by OSS as defined in the OSS 4.0 API specs */ + PA_CHANNEL_MAP_AIFF, + /**< The mapping from RFC3551, which is based on AIFF-C */ - PA_CHANNEL_MAP_DEFAULT = PA_CHANNEL_MAP_AIFF /**< The default channel map */ + PA_CHANNEL_MAP_ALSA, + /**< The default mapping used by ALSA */ + + PA_CHANNEL_MAP_AUX, + /**< Only aux channels */ + + PA_CHANNEL_MAP_WAVEEX, + /**< Microsoft's WAVEFORMATEXTENSIBLE mapping */ + + PA_CHANNEL_MAP_OSS, + /**< The default channel mapping used by OSS as defined in the OSS 4.0 API specs */ + + /**< Upper limit of valid channel mapping definitions */ + PA_CHANNEL_MAP_DEF_MAX, + + PA_CHANNEL_MAP_DEFAULT = PA_CHANNEL_MAP_AIFF + /**< The default channel map */ } pa_channel_map_def_t; /** A channel map which can be used to attach labels to specific * channels of a stream. These values are relevant for conversion and * mixing of streams */ typedef struct pa_channel_map { - uint8_t channels; /**< Number of channels */ - pa_channel_position_t map[PA_CHANNELS_MAX]; /**< Channel labels */ + uint8_t channels; + /**< Number of channels */ + + pa_channel_position_t map[PA_CHANNELS_MAX]; + /**< Channel labels */ } pa_channel_map; -/** Initialize the specified channel map and return a pointer to it */ +/** Initialize the specified channel map and return a pointer to + * it. The channel map will have a defined state but + * pa_channel_map_valid() will fail for it. */ pa_channel_map* pa_channel_map_init(pa_channel_map *m); /** Initialize the specified channel map for monoaural audio and return a pointer to it */ @@ -186,7 +204,11 @@ const char* pa_channel_position_to_string(pa_channel_position_t pos) PA_GCC_PURE /** Return a human readable text label for the specified channel position. \since 0.9.7 */ const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos); -/** The maximum length of strings returned by pa_channel_map_snprint() */ +/** The maximum length of strings returned by + * pa_channel_map_snprint(). Please note that this value can change + * with any release without warning and without being considered API + * or ABI breakage. You should not use this definition anywhere where + * it might become part of an ABI. */ #define PA_CHANNEL_MAP_SNPRINT_MAX 336 /** Make a humand readable string from the specified channel map */ @@ -198,9 +220,13 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *map, const char *s); /** Compare two channel maps. Return 1 if both match. */ int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) PA_GCC_PURE; -/** Return non-zero of the specified channel map is considered valid */ +/** Return non-zero if the specified channel map is considered valid */ int pa_channel_map_valid(const pa_channel_map *map) PA_GCC_PURE; +/** Return non-zero if the specified channel map is compatible with + * the specified sample spec. \since 0.9.12 */ +int pa_channel_map_compatible(const pa_channel_map *map, const pa_sample_spec *ss) PA_GCC_PURE; + PA_C_DECL_END #endif diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 739ef161..58d64642 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -61,6 +61,7 @@ static const pa_client_conf default_conf = { .disable_shm = FALSE, .cookie_file = NULL, .cookie_valid = FALSE, + .shm_size = 0 }; pa_client_conf *pa_client_conf_new(void) { @@ -99,6 +100,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { { "autospawn", pa_config_parse_bool, NULL }, { "cookie-file", pa_config_parse_string, NULL }, { "disable-shm", pa_config_parse_bool, NULL }, + { "shm-size-bytes", pa_config_parse_size, NULL }, { NULL, NULL, NULL }, }; @@ -110,6 +112,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { table[5].data = &c->autospawn; table[6].data = &c->cookie_file; table[7].data = &c->disable_shm; + table[8].data = &c->shm_size; if (filename) { diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h index 699279aa..4eac467e 100644 --- a/src/pulse/client-conf.h +++ b/src/pulse/client-conf.h @@ -31,6 +31,7 @@ typedef struct pa_client_conf { pa_bool_t autospawn, disable_shm; uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; pa_bool_t cookie_valid; /* non-zero, when cookie is valid */ + size_t shm_size; } pa_client_conf; /* Create a new configuration data object and reset it to defaults */ diff --git a/src/pulse/client.conf.in b/src/pulse/client.conf.in index 8339d651..579bcc20 100644 --- a/src/pulse/client.conf.in +++ b/src/pulse/client.conf.in @@ -30,3 +30,4 @@ ; cookie-file = ; disable-shm = no +; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB diff --git a/src/pulse/context.c b/src/pulse/context.c index 5be4078b..3145d9c8 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -81,8 +81,6 @@ #include "context.h" -#define AUTOSPAWN_LOCK "autospawn.lock" - void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { @@ -99,23 +97,6 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event, [PA_COMMAND_EXTENSION] = pa_command_extension }; - -static void unlock_autospawn_lock_file(pa_context *c) { - pa_assert(c); - - if (c->autospawn_lock_fd >= 0) { - char *lf; - - if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK))) - pa_log_warn(_("Cannot unlock autospawn because runtime path is no more.")); - - pa_unlock_lockfile(lf, c->autospawn_lock_fd); - pa_xfree(lf); - - c->autospawn_lock_fd = -1; - } -} - static void context_free(pa_context *c); pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { @@ -174,11 +155,12 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char * c->is_local = FALSE; c->server_list = NULL; c->server = NULL; - c->autospawn_lock_fd = -1; - memset(&c->spawn_api, 0, sizeof(c->spawn_api)); - c->do_autospawn = FALSE; + c->do_shm = FALSE; + c->do_autospawn = FALSE; + memset(&c->spawn_api, 0, sizeof(c->spawn_api)); + #ifndef MSG_NOSIGNAL #ifdef SIGPIPE pa_check_signal_is_blocked(SIGPIPE); @@ -192,10 +174,10 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char * pa_client_conf_load(c->conf, NULL); pa_client_conf_env(c->conf); - if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm))) { + if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm, c->conf->shm_size))) { if (!c->conf->disable_shm) - c->mempool = pa_mempool_new(0); + c->mempool = pa_mempool_new(FALSE, c->conf->shm_size); if (!c->mempool) { context_free(c); @@ -246,8 +228,6 @@ static void context_free(pa_context *c) { context_unlink(c); - unlock_autospawn_lock_file(c); - if (c->record_streams) pa_dynarray_free(c->record_streams, NULL, NULL); if (c->playback_streams) @@ -407,11 +387,11 @@ int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t, pa err = PA_ERR_UNKNOWN; if (fail) { - pa_context_fail(c, err); + pa_context_fail(c, (int) err); return -1; } - pa_context_set_error(c, err); + pa_context_set_error(c, (int) err); return 0; } @@ -433,7 +413,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t switch(c->state) { case PA_CONTEXT_AUTHORIZING: { pa_tagstruct *reply; - pa_bool_t shm_on_remote; + pa_bool_t shm_on_remote = FALSE; if (pa_tagstruct_getu32(t, &c->version) < 0 || !pa_tagstruct_eof(t)) { @@ -571,31 +551,89 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_context_unref(c); } -static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata); +static char *get_old_legacy_runtime_dir(void) { + char *p, u[128]; + struct stat st; -#ifndef OS_IS_WIN32 + if (!pa_get_user_name(u, sizeof(u))) + return NULL; -static int context_connect_spawn(pa_context *c) { - pid_t pid; - int status, r; - int fds[2] = { -1, -1} ; - pa_iochannel *io; + p = pa_sprintf_malloc("/tmp/pulse-%s", u); - if (getuid() == 0) - return -1; + if (stat(p, &st) < 0) { + pa_xfree(p); + return NULL; + } - pa_context_ref(c); + if (st.st_uid != getuid()) { + pa_xfree(p); + return NULL; + } - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - pa_log_error(_("socketpair(): %s"), pa_cstrerror(errno)); - pa_context_fail(c, PA_ERR_INTERNAL); - goto fail; + return p; +} + +static char *get_very_old_legacy_runtime_dir(void) { + char *p, h[128]; + struct stat st; + + if (!pa_get_home_dir(h, sizeof(h))) + return NULL; + + p = pa_sprintf_malloc("%s/.pulse", h); + + if (stat(p, &st) < 0) { + pa_xfree(p); + return NULL; + } + + if (st.st_uid != getuid()) { + pa_xfree(p); + return NULL; } - pa_make_fd_cloexec(fds[0]); + return p; +} - pa_make_socket_low_delay(fds[0]); - pa_make_socket_low_delay(fds[1]); + +static pa_strlist *prepend_per_user(pa_strlist *l) { + char *ufn; + static char *legacy_dir; + + /* The very old per-user instance path (< 0.9.11). This is supported only to ease upgrades */ + if ((legacy_dir = get_very_old_legacy_runtime_dir())) { + char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir); + l = pa_strlist_prepend(l, p); + pa_xfree(p); + pa_xfree(legacy_dir); + } + + /* The old per-user instance path (< 0.9.12). This is supported only to ease upgrades */ + if ((legacy_dir = get_old_legacy_runtime_dir())) { + char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir); + l = pa_strlist_prepend(l, p); + pa_xfree(p); + pa_xfree(legacy_dir); + } + + /* The per-user instance */ + if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) { + l = pa_strlist_prepend(l, ufn); + pa_xfree(ufn); + } + + return l; +} + +#ifndef OS_IS_WIN32 + +static int context_autospawn(pa_context *c) { + pid_t pid; + int status, r; + + pa_log_debug("Trying to autospawn..."); + + pa_context_ref(c); if (c->spawn_api.prefork) c->spawn_api.prefork(); @@ -611,31 +649,22 @@ static int context_connect_spawn(pa_context *c) { } else if (!pid) { /* Child */ - char t[128]; const char *state = NULL; #define MAX_ARGS 64 const char * argv[MAX_ARGS+1]; int n; - char *f; - - pa_close_all(fds[1], -1); - - f = pa_sprintf_malloc("%i", fds[1]); - pa_set_env("PULSE_PASSED_FD", f); - pa_xfree(f); if (c->spawn_api.atfork) c->spawn_api.atfork(); + pa_close_all(-1); + /* Setup argv */ n = 0; argv[n++] = c->conf->daemon_binary; - argv[n++] = "--daemonize=yes"; - - pa_snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); - argv[n++] = strdup(t); + argv[n++] = "--start"; while (n < MAX_ARGS) { char *a; @@ -655,14 +684,13 @@ static int context_connect_spawn(pa_context *c) { /* Parent */ - pa_assert_se(pa_close(fds[1]) == 0); - fds[1] = -1; - - r = waitpid(pid, &status, 0); - if (c->spawn_api.postfork) c->spawn_api.postfork(); + do { + r = waitpid(pid, &status, 0); + } while (r < 0 && errno == EINTR); + if (r < 0) { pa_log(_("waitpid(): %s"), pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); @@ -672,21 +700,11 @@ static int context_connect_spawn(pa_context *c) { goto fail; } - c->is_local = TRUE; - - unlock_autospawn_lock_file(c); - - io = pa_iochannel_new(c->mainloop, fds[0], fds[0]); - setup_context(c, io); - pa_context_unref(c); return 0; fail: - pa_close_pipe(fds); - - unlock_autospawn_lock_file(c); pa_context_unref(c); @@ -695,6 +713,8 @@ fail: #endif /* OS_IS_WIN32 */ +static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata); + static int try_next_connection(pa_context *c) { char *u = NULL; int r = -1; @@ -712,8 +732,18 @@ static int try_next_connection(pa_context *c) { #ifndef OS_IS_WIN32 if (c->do_autospawn) { - r = context_connect_spawn(c); - goto finish; + + if ((r = context_autospawn(c)) < 0) + goto finish; + + /* Autospawn only once */ + c->do_autospawn = FALSE; + + /* Connect only to per-user sockets this time */ + c->server_list = prepend_per_user(c->server_list); + + /* Retry connection */ + continue; } #endif @@ -768,36 +798,12 @@ static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userd goto finish; } - unlock_autospawn_lock_file(c); setup_context(c, io); finish: pa_context_unref(c); } - -static char *get_legacy_runtime_dir(void) { - char *p, u[128]; - struct stat st; - - if (!pa_get_user_name(u, sizeof(u))) - return NULL; - - p = pa_sprintf_malloc("/tmp/pulse-%s", u); - - if (stat(p, &st) < 0) { - pa_xfree(p); - return NULL; - } - - if (st.st_uid != getuid()) { - pa_xfree(p); - return NULL; - } - - return p; -} - int pa_context_connect( pa_context *c, const char *server, @@ -825,12 +831,13 @@ int pa_context_connect( pa_context_fail(c, PA_ERR_INVALIDSERVER); goto finish; } + } else { - char *d, *ufn; - static char *legacy_dir; + char *d; /* Prepend in reverse order */ + /* Follow the X display */ if ((d = getenv("DISPLAY"))) { char *e; d = pa_xstrdup(d); @@ -843,43 +850,27 @@ int pa_context_connect( pa_xfree(d); } - c->server_list = pa_strlist_prepend(c->server_list, "tcp6:localhost"); - c->server_list = pa_strlist_prepend(c->server_list, "tcp4:localhost"); + /* Add TCP/IP on the localhost */ + c->server_list = pa_strlist_prepend(c->server_list, "tcp6:[::1]"); + c->server_list = pa_strlist_prepend(c->server_list, "tcp4:127.0.0.1"); - /* The system wide instance */ + /* The system wide instance via PF_LOCAL */ c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET); - /* The old per-user instance path. This is supported only to ease upgrades */ - if ((legacy_dir = get_legacy_runtime_dir())) { - char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir); - c->server_list = pa_strlist_prepend(c->server_list, p); - pa_xfree(p); - pa_xfree(legacy_dir); - } + /* The user instance via PF_LOCAL */ + c->server_list = prepend_per_user(c->server_list); - /* The per-user instance */ - if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) { - c->server_list = pa_strlist_prepend(c->server_list, ufn); - pa_xfree(ufn); - } - - /* Wrap the connection attempts in a single transaction for sane autospawn locking */ + /* Set up autospawning */ if (!(flags & PA_CONTEXT_NOAUTOSPAWN) && c->conf->autospawn) { - char *lf; - if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK))) { - pa_context_fail(c, PA_ERR_ACCESS); - goto finish; - } + if (getuid() == 0) + pa_log_debug("Not doing autospawn since we are root."); + else { + c->do_autospawn = TRUE; - pa_assert(c->autospawn_lock_fd <= 0); - c->autospawn_lock_fd = pa_lock_lockfile(lf); - pa_xfree(lf); - - if (api) - c->spawn_api = *api; - - c->do_autospawn = TRUE; + if (api) + c->spawn_api = *api; + } } } @@ -938,11 +929,11 @@ int pa_context_is_pending(pa_context *c) { static void set_dispatch_callbacks(pa_operation *o); -static void pdispatch_drain_callback(PA_GCC_UNUSED pa_pdispatch*pd, void *userdata) { +static void pdispatch_drain_callback(pa_pdispatch*pd, void *userdata) { set_dispatch_callbacks(userdata); } -static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream *s, void *userdata) { +static void pstream_drain_callback(pa_pstream *s, void *userdata) { set_dispatch_callbacks(userdata); } @@ -994,7 +985,7 @@ pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *u return o; } -void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int success = 1; @@ -1146,7 +1137,7 @@ const char* pa_context_get_server(pa_context *c) { return c->server; } -uint32_t pa_context_get_protocol_version(PA_GCC_UNUSED pa_context *c) { +uint32_t pa_context_get_protocol_version(pa_context *c) { return PA_PROTOCOL_VERSION; } diff --git a/src/pulse/def.h b/src/pulse/def.h index aa07d1c9..ace56574 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -57,7 +57,7 @@ static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x) { /** The state of a stream */ typedef enum pa_stream_state { - PA_STREAM_UNCONNECTED, /**< The stream is not yet connected to any sink or source */ + PA_STREAM_UNCONNECTED, /**< The stream is not yet connected to any sink or source */ PA_STREAM_CREATING, /**< The stream is being created */ PA_STREAM_READY, /**< The stream is established, you may pass audio data to it now */ PA_STREAM_FAILED, /**< An error occured that made the stream invalid */ @@ -83,9 +83,15 @@ typedef enum pa_operation_state { /** Some special flags for contexts. */ typedef enum pa_context_flags { - PA_CONTEXT_NOAUTOSPAWN = 1 /**< Disabled autospawning of the PulseAudio daemon if required */ + PA_CONTEXT_NOAUTOSPAWN = 1 + /**< Disabled autospawning of the PulseAudio daemon if required */ } pa_context_flags_t; +/** \cond fulldocs */ +/* Allow clients to check with #ifdef for those flags */ +#define PA_CONTEXT_NOAUTOSPAWN PA_CONTEXT_NOAUTOSPAWN +/** \endcond */ + /** The direction of a pa_stream object */ typedef enum pa_stream_direction { PA_STREAM_NODIRECTION, /**< Invalid direction */ @@ -96,237 +102,226 @@ typedef enum pa_stream_direction { /** Some special flags for stream connections. */ typedef enum pa_stream_flags { - PA_STREAM_START_CORKED = 1, /**< Create the stream corked, requiring an explicit pa_stream_cork() call to uncork it. */ - PA_STREAM_INTERPOLATE_TIMING = 2, /**< Interpolate the latency for - * this stream. When enabled, - * pa_stream_get_latency() and - * pa_stream_get_time() will try - * to estimate the current - * record/playback time based on - * the local time that passed - * since the last timing info - * update. Using this option - * has the advantage of not - * requiring a whole roundtrip - * when the current - * playback/recording time is - * needed. Consider using this - * option when requesting - * latency information - * frequently. This is - * especially useful on long - * latency network - * connections. It makes a lot - * of sense to combine this - * option with - * PA_STREAM_AUTO_TIMING_UPDATE. */ - PA_STREAM_NOT_MONOTONIC = 4, /**< Don't force the time to - * increase monotonically. If - * this option is enabled, - * pa_stream_get_time() will not - * necessarily return always - * monotonically increasing time - * values on each call. This may - * confuse applications which - * cannot deal with time going - * 'backwards', but has the - * advantage that bad transport - * latency estimations that - * caused the time to to jump - * ahead can be corrected - * quickly, without the need to - * wait. (Please note that this - * flag was named - * PA_STREAM_NOT_MONOTONOUS in - * releases prior to 0.9.11. The - * old name is still defined too, - * for compatibility reasons. */ - PA_STREAM_AUTO_TIMING_UPDATE = 8, /**< If set timing update requests - * are issued periodically - * automatically. Combined with - * PA_STREAM_INTERPOLATE_TIMING - * you will be able to query the - * current time and latency with - * pa_stream_get_time() and - * pa_stream_get_latency() at - * all times without a packet - * round trip.*/ - PA_STREAM_NO_REMAP_CHANNELS = 16, /**< Don't remap channels by - * their name, instead map them - * simply by their - * index. Implies - * PA_STREAM_NO_REMIX_CHANNELS. Only - * supported when the server is - * at least PA 0.9.8. It is - * ignored on older - * servers.\since 0.9.8 */ - PA_STREAM_NO_REMIX_CHANNELS = 32, /**< When remapping channels by - * name, don't upmix or downmix - * them to related - * channels. Copy them into - * matching channels of the - * device 1:1. Only supported - * when the server is at least - * PA 0.9.8. It is ignored on - * older servers. \since - * 0.9.8 */ - PA_STREAM_FIX_FORMAT = 64, /**< Use the sample format of the - * sink/device this stream is being - * connected to, and possibly ignore - * the format the sample spec contains - * -- but you still have to pass a - * valid value in it as a hint to - * PulseAudio what would suit your - * stream best. If this is used you - * should query the used sample format - * after creating the stream by using - * pa_stream_get_sample_spec(). Also, - * if you specified manual buffer - * metrics it is recommended to update - * them with - * pa_stream_set_buffer_attr() to - * compensate for the changed frame - * sizes. Only supported when the - * server is at least PA 0.9.8. It is - * ignored on older servers. \since - * 0.9.8 */ - - PA_STREAM_FIX_RATE = 128, /**< Use the sample rate of the sink, - * and possibly ignore the rate the - * sample spec contains. Usage similar - * to PA_STREAM_FIX_FORMAT.Only - * supported when the server is at least - * PA 0.9.8. It is ignored on older - * servers. \since 0.9.8 */ - - PA_STREAM_FIX_CHANNELS = 256, /**< Use the number of channels and - * the channel map of the sink, and - * possibly ignore the number of - * channels and the map the sample spec - * and the passed channel map - * contains. Usage similar to - * PA_STREAM_FIX_FORMAT. Only supported - * when the server is at least PA - * 0.9.8. It is ignored on older - * servers. \since 0.9.8 */ - PA_STREAM_DONT_MOVE = 512, /**< Don't allow moving of this stream to - * another sink/device. Useful if you use - * any of the PA_STREAM_FIX_ flags and - * want to make sure that resampling - * never takes place -- which might - * happen if the stream is moved to - * another sink/source whith a different - * sample spec/channel map. Only - * supported when the server is at least - * PA 0.9.8. It is ignored on older - * servers. \since 0.9.8 */ - PA_STREAM_VARIABLE_RATE = 1024, /**< Allow dynamic changing of the - * sampling rate during playback - * with - * pa_stream_update_sample_rate(). Only - * supported when the server is at - * least PA 0.9.8. It is ignored - * on older servers. \since - * 0.9.8 */ - PA_STREAM_PEAK_DETECT = 2048, /**< Find peaks instead of - * resampling. \since 0.9.11 */ - - PA_STREAM_START_MUTED = 4096, /**< Create in muted state. \since 0.9.11 */ - - PA_STREAM_ADJUST_LATENCY = 8192, /**< Try to adjust the latency of - * the sink/source based on the - * requested buffer metrics and - * adjust buffer metrics - * accordingly. See pa_buffer_attr \since 0.9.11 */ + + PA_STREAM_START_CORKED = 0x0001U, + /**< Create the stream corked, requiring an explicit + * pa_stream_cork() call to uncork it. */ + + PA_STREAM_INTERPOLATE_TIMING = 0x0002U, + /**< Interpolate the latency for this stream. When enabled, + * pa_stream_get_latency() and pa_stream_get_time() will try to + * estimate the current record/playback time based on the local + * time that passed since the last timing info update. Using this + * option has the advantage of not requiring a whole roundtrip + * when the current playback/recording time is needed. Consider + * using this option when requesting latency information + * frequently. This is especially useful on long latency network + * connections. It makes a lot of sense to combine this option + * with PA_STREAM_AUTO_TIMING_UPDATE. */ + + PA_STREAM_NOT_MONOTONIC = 0x0004U, + /**< Don't force the time to increase monotonically. If this + * option is enabled, pa_stream_get_time() will not necessarily + * return always monotonically increasing time values on each + * call. This may confuse applications which cannot deal with time + * going 'backwards', but has the advantage that bad transport + * latency estimations that caused the time to to jump ahead can + * be corrected quickly, without the need to wait. (Please note + * that this flag was named PA_STREAM_NOT_MONOTONOUS in releases + * prior to 0.9.11. The old name is still defined too, for + * compatibility reasons. */ + + PA_STREAM_AUTO_TIMING_UPDATE = 0x0008U, + /**< If set timing update requests are issued periodically + * automatically. Combined with PA_STREAM_INTERPOLATE_TIMING you + * will be able to query the current time and latency with + * pa_stream_get_time() and pa_stream_get_latency() at all times + * without a packet round trip.*/ + + PA_STREAM_NO_REMAP_CHANNELS = 0x0010U, + /**< Don't remap channels by their name, instead map them simply + * by their index. Implies PA_STREAM_NO_REMIX_CHANNELS. Only + * supported when the server is at least PA 0.9.8. It is ignored + * on older servers.\since 0.9.8 */ + + PA_STREAM_NO_REMIX_CHANNELS = 0x0020U, + /**< When remapping channels by name, don't upmix or downmix them + * to related channels. Copy them into matching channels of the + * device 1:1. Only supported when the server is at least PA + * 0.9.8. It is ignored on older servers. \since 0.9.8 */ + + PA_STREAM_FIX_FORMAT = 0x0040U, + /**< Use the sample format of the sink/device this stream is being + * connected to, and possibly ignore the format the sample spec + * contains -- but you still have to pass a valid value in it as a + * hint to PulseAudio what would suit your stream best. If this is + * used you should query the used sample format after creating the + * stream by using pa_stream_get_sample_spec(). Also, if you + * specified manual buffer metrics it is recommended to update + * them with pa_stream_set_buffer_attr() to compensate for the + * changed frame sizes. Only supported when the server is at least + * PA 0.9.8. It is ignored on older servers. \since 0.9.8 */ + + PA_STREAM_FIX_RATE = 0x0080U, + /**< Use the sample rate of the sink, and possibly ignore the rate + * the sample spec contains. Usage similar to + * PA_STREAM_FIX_FORMAT.Only supported when the server is at least + * PA 0.9.8. It is ignored on older servers. \since 0.9.8 */ + + PA_STREAM_FIX_CHANNELS = 0x0100, + /**< Use the number of channels and the channel map of the sink, + * and possibly ignore the number of channels and the map the + * sample spec and the passed channel map contains. Usage similar + * to PA_STREAM_FIX_FORMAT. Only supported when the server is at + * least PA 0.9.8. It is ignored on older servers. \since 0.9.8 */ + + PA_STREAM_DONT_MOVE = 0x0200U, + /**< Don't allow moving of this stream to another + * sink/device. Useful if you use any of the PA_STREAM_FIX_ flags + * and want to make sure that resampling never takes place -- + * which might happen if the stream is moved to another + * sink/source whith a different sample spec/channel map. Only + * supported when the server is at least PA 0.9.8. It is ignored + * on older servers. \since 0.9.8 */ + + PA_STREAM_VARIABLE_RATE = 0x0400U, + /**< Allow dynamic changing of the sampling rate during playback + * with pa_stream_update_sample_rate(). Only supported when the + * server is at least PA 0.9.8. It is ignored on older + * servers. \since 0.9.8 */ + + PA_STREAM_PEAK_DETECT = 0x0800U, + /**< Find peaks instead of resampling. \since 0.9.11 */ + + PA_STREAM_START_MUTED = 0x1000U, + /**< Create in muted state. If neither PA_STREAM_START_UNMUTED nor + * PA_STREAM_START_MUTED it is left to the server to decide + * whether to create the stream in muted or in unmuted + * state. \since 0.9.11 */ + + PA_STREAM_ADJUST_LATENCY = 0x2000U, + /**< Try to adjust the latency of the sink/source based on the + * requested buffer metrics and adjust buffer metrics + * accordingly. Also see pa_buffer_attr. This option may not be + * specified at the same time as PA_STREAM_EARLY_REQUESTS. \since + * 0.9.11 */ + + PA_STREAM_EARLY_REQUESTS = 0x4000U, + /**< Enable compatibility mode for legacy clients that rely on a + * "classic" hardware device fragment-style playback model. If + * this option is set, the minreq value of the buffer metrics gets + * a new meaning: instead of just specifying that no requests + * asking for less new data than this value will be made to the + * client it will also guarantee that requests are generated as + * early as this limit is reached. This flag should only be set in + * very few situations where compatiblity with a fragment-based + * playback model needs to be kept and the client applications + * cannot deal with data requests that are delayed to the latest + * moment possible. (Usually these are programs that use usleep() + * or a similar call in their playback loops instead of sleeping + * on the device itself.) Also see pa_buffer_attr. This option may + * not be specified at the same time as + * PA_STREAM_ADJUST_LATENCY. \since 0.9.12 */ + + PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND = 0x8000U, + /**< If set this stream won't be taken into account when we it is + * checked whether the device this stream is connected to should + * auto-suspend. \ since 0.9.14 */ + + PA_STREAM_START_UNMUTED = 0x10000U + /**< Create in unmuted state. If neither PA_STREAM_START_UNMUTED + * nor PA_STREAM_START_MUTED it is left to the server to decide + * whether to create the stream in muted or in unmuted + * state. \since 0.9.14 */ + } pa_stream_flags_t; +/** \cond fulldocs */ -/** English is an evil language */ +/* English is an evil language */ #define PA_STREAM_NOT_MONOTONOUS PA_STREAM_NOT_MONOTONIC +/* Allow clients to check with #ifdef for those flags */ +#define PA_STREAM_START_CORKED PA_STREAM_START_CORKED +#define PA_STREAM_INTERPOLATE_TIMING PA_STREAM_INTERPOLATE_TIMING +#define PA_STREAM_NOT_MONOTONIC PA_STREAM_NOT_MONOTONIC +#define PA_STREAM_AUTO_TIMING_UPDATE PA_STREAM_AUTO_TIMING_UPDATE +#define PA_STREAM_NO_REMAP_CHANNELS PA_STREAM_NO_REMAP_CHANNELS +#define PA_STREAM_NO_REMIX_CHANNELS PA_STREAM_NO_REMIX_CHANNELS +#define PA_STREAM_FIX_FORMAT PA_STREAM_FIX_FORMAT +#define PA_STREAM_FIX_RATE PA_STREAM_FIX_RATE +#define PA_STREAM_FIX_CHANNELS PA_STREAM_FIX_CHANNELS +#define PA_STREAM_DONT_MOVE PA_STREAM_DONT_MOVE +#define PA_STREAM_VARIABLE_RATE PA_STREAM_VARIABLE_RATE +#define PA_STREAM_PEAK_DETECT PA_STREAM_PEAK_DETECT +#define PA_STREAM_START_MUTED PA_STREAM_START_MUTED +#define PA_STREAM_ADJUST_LATENCY PA_STREAM_ADJUST_LATENCY +#define PA_STREAM_EARLY_REQUESTS PA_STREAM_EARLY_REQUESTS +#define PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND +#define PA_STREAM_START_UNMUTED PA_STREAM_START_UNMUTED + +/** \endcond */ + /** Playback and record buffer metrics */ typedef struct pa_buffer_attr { - uint32_t maxlength; /**< Maximum length of the - * buffer. Setting this to (uint32_t) -1 will - * initialize this to the maximum value - * supported by server, which is - * recommended. */ - uint32_t tlength; /**< Playback only: target length of the - * buffer. The server tries to assure - * that at least tlength bytes are always - * available in the per-stream - * server-side playback buffer. It is - * recommended to set this to (uint32_t) - * -1, which will initialize this to a - * value that is deemed sensible by the - * server. However, this value will - * default to something like 2s, i.e. for - * applications that have specific - * latency requirements this value should - * be set to the maximum latency that the - * application can deal with. When - * PA_STREAM_ADJUST_LATENCY is not set - * this value will influence only the - * per-stream playback buffer size. When - * PA_STREAM_ADJUST_LATENCY is set the - * overall latency of the sink plus the - * playback buffer size is configured to - * this value. Set - * PA_STREAM_ADJUST_LATENCY if you are - * interested in adjusting the overall - * latency. Don't set it if you are - * interested in configuring the - * server-sider per-stream playback - * buffer size. */ - uint32_t prebuf; /**< Playback only: pre-buffering. The - * server does not start with playback - * before at least prebug bytes are - * available in the buffer. It is - * recommended to set this to (uint32_t) - * -1, which will initialize this to the - * same value as tlength, whatever that - * may be. Initialize to 0 to enable - * manual start/stop control of the - * stream. This means that playback will - * not stop on underrun and playback will - * not start automatically. Instead - * pa_stream_corked() needs to be called - * explicitly. If you set this value to 0 - * you should also set - * PA_STREAM_START_CORKED. */ - uint32_t minreq; /**< Playback only: minimum request. The - * server does not request less than - * minreq bytes from the client, instead - * waits until the buffer is free enough - * to request more bytes at once. It is - * recommended to set this to (uint32_t) - * -1, which will initialize this to a - * value that is deemed sensible by the - * server. This should be set to a value - * that gives PulseAudio enough time to - * move the data from the per-stream - * playback buffer into the hardware - * playback buffer. */ - uint32_t fragsize; /**< Recording only: fragment size. The - * server sends data in blocks of - * fragsize bytes size. Large values - * deminish interactivity with other - * operations on the connection context - * but decrease control overhead. It is - * recommended to set this to (uint32_t) - * -1, which will initialize this to a - * value that is deemed sensible by the - * server. However, this value will - * default to something like 2s, i.e. for - * applications that have specific - * latency requirements this value should - * be set to the maximum latency that the - * application can deal with. If - * PA_STREAM_ADJUST_LATENCY is set the - * overall source latency will be - * adjusted according to this value. If - * it is not set the source latency is - * left unmodified. */ + uint32_t maxlength; + /**< Maximum length of the buffer. Setting this to (uint32_t) -1 + * will initialize this to the maximum value supported by server, + * which is recommended. */ + + uint32_t tlength; + /**< Playback only: target length of the buffer. The server tries + * to assure that at least tlength bytes are always available in + * the per-stream server-side playback buffer. It is recommended + * to set this to (uint32_t) -1, which will initialize this to a + * value that is deemed sensible by the server. However, this + * value will default to something like 2s, i.e. for applications + * that have specific latency requirements this value should be + * set to the maximum latency that the application can deal + * with. When PA_STREAM_ADJUST_LATENCY is not set this value will + * influence only the per-stream playback buffer size. When + * PA_STREAM_ADJUST_LATENCY is set the overall latency of the sink + * plus the playback buffer size is configured to this value. Set + * PA_STREAM_ADJUST_LATENCY if you are interested in adjusting the + * overall latency. Don't set it if you are interested in + * configuring the server-sider per-stream playback buffer + * size. */ + + uint32_t prebuf; + /**< Playback only: pre-buffering. The server does not start with + * playback before at least prebug bytes are available in the + * buffer. It is recommended to set this to (uint32_t) -1, which + * will initialize this to the same value as tlength, whatever + * that may be. Initialize to 0 to enable manual start/stop + * control of the stream. This means that playback will not stop + * on underrun and playback will not start automatically. Instead + * pa_stream_corked() needs to be called explicitly. If you set + * this value to 0 you should also set PA_STREAM_START_CORKED. */ + + uint32_t minreq; + /**< Playback only: minimum request. The server does not request + * less than minreq bytes from the client, instead waits until the + * buffer is free enough to request more bytes at once. It is + * recommended to set this to (uint32_t) -1, which will initialize + * this to a value that is deemed sensible by the server. This + * should be set to a value that gives PulseAudio enough time to + * move the data from the per-stream playback buffer into the + * hardware playback buffer. */ + + uint32_t fragsize; + /**< Recording only: fragment size. The server sends data in + * blocks of fragsize bytes size. Large values deminish + * interactivity with other operations on the connection context + * but decrease control overhead. It is recommended to set this to + * (uint32_t) -1, which will initialize this to a value that is + * deemed sensible by the server. However, this value will default + * to something like 2s, i.e. for applications that have specific + * latency requirements this value should be set to the maximum + * latency that the application can deal with. If + * PA_STREAM_ADJUST_LATENCY is set the overall source latency will + * be adjusted according to this value. If it is not set the + * source latency is left unmodified. */ + } pa_buffer_attr; /** Error values as used by pa_context_errno(). Use pa_strerror() to convert these values to human readable strings */ @@ -358,36 +353,84 @@ enum { /** Subscription event mask, as used by pa_context_subscribe() */ typedef enum pa_subscription_mask { - PA_SUBSCRIPTION_MASK_NULL = 0, /**< No events */ - PA_SUBSCRIPTION_MASK_SINK = 1, /**< Sink events */ - PA_SUBSCRIPTION_MASK_SOURCE = 2, /**< Source events */ - PA_SUBSCRIPTION_MASK_SINK_INPUT = 4, /**< Sink input events */ - PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT = 8, /**< Source output events */ - PA_SUBSCRIPTION_MASK_MODULE = 16, /**< Module events */ - PA_SUBSCRIPTION_MASK_CLIENT = 32, /**< Client events */ - PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, /**< Sample cache events */ - PA_SUBSCRIPTION_MASK_SERVER = 128, /**< Other global server changes. */ - PA_SUBSCRIPTION_MASK_AUTOLOAD = 256, /**< Autoload table events. */ - PA_SUBSCRIPTION_MASK_ALL = 511 /**< Catch all events */ + PA_SUBSCRIPTION_MASK_NULL = 0x0000U, + /**< No events */ + + PA_SUBSCRIPTION_MASK_SINK = 0x0001U, + /**< Sink events */ + + PA_SUBSCRIPTION_MASK_SOURCE = 0x0002U, + /**< Source events */ + + PA_SUBSCRIPTION_MASK_SINK_INPUT = 0x0004U, + /**< Sink input events */ + + PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT = 0x0008U, + /**< Source output events */ + + PA_SUBSCRIPTION_MASK_MODULE = 0x0010U, + /**< Module events */ + + PA_SUBSCRIPTION_MASK_CLIENT = 0x0020U, + /**< Client events */ + + PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 0x0040U, + /**< Sample cache events */ + + PA_SUBSCRIPTION_MASK_SERVER = 0x0080U, + /**< Other global server changes. */ + + PA_SUBSCRIPTION_MASK_AUTOLOAD = 0x0100U, + /**< Autoload table events. */ + + PA_SUBSCRIPTION_MASK_ALL = 0x01ffU + /**< Catch all events */ } pa_subscription_mask_t; /** Subscription event types, as used by pa_context_subscribe() */ typedef enum pa_subscription_event_type { - PA_SUBSCRIPTION_EVENT_SINK = 0, /**< Event type: Sink */ - PA_SUBSCRIPTION_EVENT_SOURCE = 1, /**< Event type: Source */ - PA_SUBSCRIPTION_EVENT_SINK_INPUT = 2, /**< Event type: Sink input */ - PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT = 3, /**< Event type: Source output */ - PA_SUBSCRIPTION_EVENT_MODULE = 4, /**< Event type: Module */ - PA_SUBSCRIPTION_EVENT_CLIENT = 5, /**< Event type: Client */ - PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 6, /**< Event type: Sample cache item */ - PA_SUBSCRIPTION_EVENT_SERVER = 7, /**< Event type: Global server change, only occuring with PA_SUBSCRIPTION_EVENT_CHANGE. */ - PA_SUBSCRIPTION_EVENT_AUTOLOAD = 8, /**< Event type: Autoload table changes. */ - PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 15, /**< A mask to extract the event type from an event value */ - - PA_SUBSCRIPTION_EVENT_NEW = 0, /**< A new object was created */ - PA_SUBSCRIPTION_EVENT_CHANGE = 16, /**< A property of the object was modified */ - PA_SUBSCRIPTION_EVENT_REMOVE = 32, /**< An object was removed */ - PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32 /**< A mask to extract the event operation from an event value */ + PA_SUBSCRIPTION_EVENT_SINK = 0x0000U, + /**< Event type: Sink */ + + PA_SUBSCRIPTION_EVENT_SOURCE = 0x0001U, + /**< Event type: Source */ + + PA_SUBSCRIPTION_EVENT_SINK_INPUT = 0x0002U, + /**< Event type: Sink input */ + + PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT = 0x0003U, + /**< Event type: Source output */ + + PA_SUBSCRIPTION_EVENT_MODULE = 0x0004U, + /**< Event type: Module */ + + PA_SUBSCRIPTION_EVENT_CLIENT = 0x0005U, + /**< Event type: Client */ + + PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 0x0006U, + /**< Event type: Sample cache item */ + + PA_SUBSCRIPTION_EVENT_SERVER = 0x0007U, + /**< Event type: Global server change, only occuring with PA_SUBSCRIPTION_EVENT_CHANGE. */ + + PA_SUBSCRIPTION_EVENT_AUTOLOAD = 0x0008U, + /**< Event type: Autoload table changes. */ + + PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 0x000FU, + /**< A mask to extract the event type from an event value */ + + PA_SUBSCRIPTION_EVENT_NEW = 0x0000U, + /**< A new object was created */ + + PA_SUBSCRIPTION_EVENT_CHANGE = 0x0010U, + /**< A property of the object was modified */ + + PA_SUBSCRIPTION_EVENT_REMOVE = 0x0020U, + /**< An object was removed */ + + PA_SUBSCRIPTION_EVENT_TYPE_MASK = 0x0030U, + /**< A mask to extract the event operation from an event value */ + } pa_subscription_event_type_t; /** Return one if an event type t matches an event mask bitfield */ @@ -412,69 +455,71 @@ typedef enum pa_subscription_event_type { * note that this structure can be extended as part of evolutionary * API updates at any time in any new release.*/ typedef struct pa_timing_info { - struct timeval timestamp; /**< The time when this timing info structure was current */ - int synchronized_clocks; /**< Non-zero if the local and the - * remote machine have synchronized - * clocks. If synchronized clocks are - * detected transport_usec becomes much - * more reliable. However, the code that - * detects synchronized clocks is very - * limited und unreliable itself. */ - - pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. For playback streams and record streams connected to a monitor source. */ - pa_usec_t source_usec; /**< Time in usecs a sample takes from being recorded to being delivered to the application. Only for record streams. */ - pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to/from the daemon. For both playback and record streams. */ - - int playing; /**< Non-zero when the stream is - * currently not underrun and data is - * being passed on to the device. Only - * for playback streams. This field does - * not say whether the data is actually - * already being played. To determine - * this check whether since_underrun - * (converted to usec) is larger than - * sink_usec.*/ - - int write_index_corrupt; /**< Non-zero if write_index is not - * up-to-date because a local write - * command that corrupted it has been - * issued in the time since this latency - * info was current . Only write - * commands with SEEK_RELATIVE_ON_READ - * and SEEK_RELATIVE_END can corrupt - * write_index. */ - int64_t write_index; /**< Current write index into the - * playback buffer in bytes. Think twice before - * using this for seeking purposes: it - * might be out of date a the time you - * want to use it. Consider using - * PA_SEEK_RELATIVE instead. */ - - int read_index_corrupt; /**< Non-zero if read_index is not - * up-to-date because a local pause or - * flush request that corrupted it has - * been issued in the time since this - * latency info was current. */ - - int64_t read_index; /**< Current read index into the - * playback buffer in bytes. Think twice before - * using this for seeking purposes: it - * might be out of date a the time you - * want to use it. Consider using - * PA_SEEK_RELATIVE_ON_READ - * instead. */ - - pa_usec_t configured_sink_usec; /**< The configured latency for - * the sink. \since 0.9.11 */ - pa_usec_t configured_source_usec; /**< The configured latency for - * the source. \since 0.9.11 */ - - int64_t since_underrun; /**< Bytes that were handed to the sink - since the last underrun happened, or - since playback started again after - the last underrun. playing will tell - you which case it is. \since - 0.9.11 */ + struct timeval timestamp; + /**< The time when this timing info structure was current */ + + int synchronized_clocks; + /**< Non-zero if the local and the remote machine have + * synchronized clocks. If synchronized clocks are detected + * transport_usec becomes much more reliable. However, the code + * that detects synchronized clocks is very limited und unreliable + * itself. */ + + pa_usec_t sink_usec; + /**< Time in usecs a sample takes to be played on the sink. For + * playback streams and record streams connected to a monitor + * source. */ + + pa_usec_t source_usec; + /**< Time in usecs a sample takes from being recorded to being + * delivered to the application. Only for record streams. */ + + pa_usec_t transport_usec; + /**< Estimated time in usecs a sample takes to be transferred + * to/from the daemon. For both playback and record streams. */ + + int playing; + /**< Non-zero when the stream is currently not underrun and data + * is being passed on to the device. Only for playback + * streams. This field does not say whether the data is actually + * already being played. To determine this check whether + * since_underrun (converted to usec) is larger than sink_usec.*/ + + int write_index_corrupt; + /**< Non-zero if write_index is not up-to-date because a local + * write command that corrupted it has been issued in the time + * since this latency info was current . Only write commands with + * SEEK_RELATIVE_ON_READ and SEEK_RELATIVE_END can corrupt + * write_index. */ + + int64_t write_index; + /**< Current write index into the playback buffer in bytes. Think + * twice before using this for seeking purposes: it might be out + * of date a the time you want to use it. Consider using + * PA_SEEK_RELATIVE instead. */ + + int read_index_corrupt; + /**< Non-zero if read_index is not up-to-date because a local + * pause or flush request that corrupted it has been issued in the + * time since this latency info was current. */ + + int64_t read_index; + /**< Current read index into the playback buffer in bytes. Think + * twice before using this for seeking purposes: it might be out + * of date a the time you want to use it. Consider using + * PA_SEEK_RELATIVE_ON_READ instead. */ + + pa_usec_t configured_sink_usec; + /**< The configured latency for the sink. \since 0.9.11 */ + + pa_usec_t configured_source_usec; + /**< The configured latency for * the source. \since 0.9.11 */ + + int64_t since_underrun; + /**< Bytes that were handed to the sink since the last underrun + * happened, or since playback started again after the last + * underrun. playing will tell you which case it is. \since + * 0.9.11 */ } pa_timing_info; @@ -486,45 +531,101 @@ typedef struct pa_timing_info { * thread compatible way. You might have to do this in * prefork/postfork. */ typedef struct pa_spawn_api { - void (*prefork)(void); /**< Is called just before the fork in the parent process. May be NULL. */ - void (*postfork)(void); /**< Is called immediately after the fork in the parent process. May be NULL.*/ - void (*atfork)(void); /**< Is called immediately after the - * fork in the child process. May be - * NULL. It is not safe to close all - * file descriptors in this function - * unconditionally, since a UNIX socket - * (created using socketpair()) is - * passed to the new process. */ + void (*prefork)(void); + /**< Is called just before the fork in the parent process. May be + * NULL. */ + + void (*postfork)(void); + /**< Is called immediately after the fork in the parent + * process. May be NULL.*/ + + void (*atfork)(void); + /**< Is called immediately after the fork in the child + * process. May be NULL. It is not safe to close all file + * descriptors in this function unconditionally, since a UNIX + * socket (created using socketpair()) is passed to the new + * process. */ } pa_spawn_api; /** Seek type for pa_stream_write(). */ typedef enum pa_seek_mode { - PA_SEEK_RELATIVE = 0, /**< Seek relatively to the write index */ - PA_SEEK_ABSOLUTE = 1, /**< Seek relatively to the start of the buffer queue */ - PA_SEEK_RELATIVE_ON_READ = 2, /**< Seek relatively to the read index. */ - PA_SEEK_RELATIVE_END = 3 /**< Seek relatively to the current end of the buffer queue. */ + PA_SEEK_RELATIVE = 0, + /**< Seek relatively to the write index */ + + PA_SEEK_ABSOLUTE = 1, + /**< Seek relatively to the start of the buffer queue */ + + PA_SEEK_RELATIVE_ON_READ = 2, + /**< Seek relatively to the read index. */ + + PA_SEEK_RELATIVE_END = 3 + /**< Seek relatively to the current end of the buffer queue. */ } pa_seek_mode_t; /** Special sink flags. */ typedef enum pa_sink_flags { - PA_SINK_HW_VOLUME_CTRL = 1, /**< Supports hardware volume control */ - PA_SINK_LATENCY = 2, /**< Supports latency querying */ - PA_SINK_HARDWARE = 4, /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks \since 0.9.3 */ - PA_SINK_NETWORK = 8, /**< Is a networked sink of some kind. \since 0.9.7 */ - PA_SINK_HW_MUTE_CTRL = 16, /**< Supports hardware mute control \since 0.9.11 */ - PA_SINK_DECIBEL_VOLUME = 32 /**< Volume can be translated to dB with pa_sw_volume_to_dB() \since 0.9.11 */ + PA_SINK_HW_VOLUME_CTRL = 0x0001U, + /**< Supports hardware volume control */ + + PA_SINK_LATENCY = 0x0002U, + /**< Supports latency querying */ + + PA_SINK_HARDWARE = 0x0004U, + /**< Is a hardware sink of some kind, in contrast to + * "virtual"/software sinks \since 0.9.3 */ + + PA_SINK_NETWORK = 0x0008U, + /**< Is a networked sink of some kind. \since 0.9.7 */ + + PA_SINK_HW_MUTE_CTRL = 0x0010U, + /**< Supports hardware mute control \since 0.9.11 */ + + PA_SINK_DECIBEL_VOLUME = 0x0020U + /**< Volume can be translated to dB with pa_sw_volume_to_dB() + * \since 0.9.11 */ } pa_sink_flags_t; +/** \cond fulldocs */ +#define PA_SINK_HW_VOLUME_CTRL PA_SINK_HW_VOLUME_CTRL +#define PA_SINK_LATENCY PA_SINK_LATENCY +#define PA_SINK_HARDWARE PA_SINK_HARDWARE +#define PA_SINK_NETWORK PA_SINK_NETWORK +#define PA_SINK_HW_VOLUME_CTRL PA_SINK_HW_VOLUME_CTRL +#define PA_SINK_DECIBEL_VOLUME PA_SINK_DECIBEL_VOLUME +/** \endcond */ + /** Special source flags. */ typedef enum pa_source_flags { - PA_SOURCE_HW_VOLUME_CTRL = 1, /**< Supports hardware volume control */ - PA_SOURCE_LATENCY = 2, /**< Supports latency querying */ - PA_SOURCE_HARDWARE = 4, /**< Is a hardware source of some kind, in contrast to "virtual"/software source \since 0.9.3 */ - PA_SOURCE_NETWORK = 8, /**< Is a networked sink of some kind. \since 0.9.7 */ - PA_SOURCE_HW_MUTE_CTRL = 16, /**< Supports hardware mute control \since 0.9.11 */ - PA_SOURCE_DECIBEL_VOLUME = 32 /**< Volume can be translated to dB with pa_sw_volume_to_dB() \since 0.9.11 */ + PA_SOURCE_HW_VOLUME_CTRL = 0x0001U, + /**< Supports hardware volume control */ + + PA_SOURCE_LATENCY = 0x0002U, + /**< Supports latency querying */ + + PA_SOURCE_HARDWARE = 0x0004U, + /**< Is a hardware source of some kind, in contrast to + * "virtual"/software source \since 0.9.3 */ + + PA_SOURCE_NETWORK = 0x0008U, + /**< Is a networked sink of some kind. \since 0.9.7 */ + + PA_SOURCE_HW_MUTE_CTRL = 0x0010U, + /**< Supports hardware mute control \since 0.9.11 */ + + PA_SOURCE_DECIBEL_VOLUME = 0x0020U + /**< Volume can be translated to dB with pa_sw_volume_to_dB() + * \since 0.9.11 */ } pa_source_flags_t; +/** \cond fulldocs */ +#define PA_SOURCE_HW_VOLUME_CTRL PA_SOURCE_HW_VOLUME_CTRL +#define PA_SOURCE_LATENCY PA_SOURCE_LATENCY +#define PA_SOURCE_HARDWARE PA_SOURCE_HARDWARE +#define PA_SOURCE_NETWORK PA_SOURCE_NETWORK +#define PA_SOURCE_HW_VOLUME_CTRL PA_SOURCE_HW_VOLUME_CTRL +#define PA_SOURCE_DECIBEL_VOLUME PA_SOURCE_DECIBEL_VOLUME +/** \endcond */ + /** A generic free() like callback prototype */ typedef void (*pa_free_cb_t)(void *p); diff --git a/src/pulse/ext-stream-restore.h b/src/pulse/ext-stream-restore.h index a8eceaf1..2038eb4a 100644 --- a/src/pulse/ext-stream-restore.h +++ b/src/pulse/ext-stream-restore.h @@ -24,37 +24,49 @@ #include <pulse/context.h> +/** \file + * + * Routines for controlling module-stream-restore + */ + PA_C_DECL_BEGIN +/** Stores information about one entry in the stream database that is + * maintained by module-stream-restore. \since 0.9.12 */ typedef struct pa_ext_stream_restore_info { - const char *name; - pa_channel_map channel_map; - pa_cvolume volume; - const char *device; - int mute; + const char *name; /**< Identifier string of the stream. A string like "sink-input-by-role:" or similar followed by some arbitrary property value. */ + pa_channel_map channel_map; /**< The channel map for the volume field */ + pa_cvolume volume; /**< The volume of the stream when it was seen last, if applicable */ + const char *device; /**< The sink/source of the stream when it was last seen */ + int mute; /**< The boolean mute state of the stream when it was last seen, if applicable */ } pa_ext_stream_restore_info; +/** Callback prototype for pa_ext_stream_restore_test(). \since 0.9.12 */ typedef void (*pa_ext_stream_restore_test_cb_t)( pa_context *c, uint32_t version, void *userdata); +/** Test if this extension module is available in the server. \since 0.9.12 */ pa_operation *pa_ext_stream_restore_test( pa_context *c, pa_ext_stream_restore_test_cb_t cb, void *userdata); +/** Callback prototype for pa_ext_stream_restore_read(). \since 0.9.12 */ typedef void (*pa_ext_stream_restore_read_cb_t)( pa_context *c, const pa_ext_stream_restore_info *info, int eol, void *userdata); +/** Read all entries from the stream database. \since 0.9.12 */ pa_operation *pa_ext_stream_restore_read( pa_context *c, pa_ext_stream_restore_read_cb_t cb, void *userdata); +/** Store entries in the stream database. \since 0.9.12 */ pa_operation *pa_ext_stream_restore_write( pa_context *c, pa_update_mode_t mode, @@ -64,22 +76,27 @@ pa_operation *pa_ext_stream_restore_write( pa_context_success_cb_t cb, void *userdata); +/** Delete entries from the stream database. \since 0.9.12 */ pa_operation *pa_ext_stream_restore_delete( pa_context *c, const char *const s[], pa_context_success_cb_t cb, void *userdata); +/** Subscribe to changes in the stream database. \since 0.9.12 */ pa_operation *pa_ext_stream_restore_subscribe( pa_context *c, int enable, pa_context_success_cb_t cb, void *userdata); +/** Callback prototype for pa_ext_stream_restore_set_subscribe_cb(). \since 0.9.12 */ typedef void (*pa_ext_stream_restore_subscribe_cb_t)( pa_context *c, void *userdata); +/** Set the subscription callback that is called when + * pa_ext_stream_restore_subscribe() was called. \since 0.9.12 */ void pa_ext_stream_restore_set_subscribe_cb( pa_context *c, pa_ext_stream_restore_subscribe_cb_t cb, diff --git a/src/pulse/gccmacro.h b/src/pulse/gccmacro.h index e4062033..0533b109 100644 --- a/src/pulse/gccmacro.h +++ b/src/pulse/gccmacro.h @@ -93,4 +93,24 @@ #endif #endif +#ifndef PA_GCC_ALLOC_SIZE +#if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3) +#define PA_GCC_ALLOC_SIZE(x) __attribute__ ((__alloc_size__(x))) +#define PA_GCC_ALLOC_SIZE2(x,y) __attribute__ ((__alloc_size__(x,y))) +#else +/** Macro for usage of GCC's alloc_size attribute */ +#define PA_GCC_ALLOC_SIZE(x) +#define PA_GCC_ALLOC_SIZE2(x,y) +#endif +#endif + +#ifndef PA_GCC_MALLOC +#ifdef __GNUCC__ +#define PA_GCC_MALLOC __attribute__ ((malloc)) +#else +/** Macro for usage of GCC's malloc attribute */ +#define PA_GCC_MALLOC +#endif +#endif + #endif diff --git a/src/pulse/glib-mainloop.c b/src/pulse/glib-mainloop.c index 6ddb0faa..5f5dc494 100644 --- a/src/pulse/glib-mainloop.c +++ b/src/pulse/glib-mainloop.c @@ -195,11 +195,11 @@ static void cleanup_defer_events(pa_glib_mainloop *g, int force) { } static gushort map_flags_to_glib(pa_io_event_flags_t flags) { - return - (flags & PA_IO_EVENT_INPUT ? G_IO_IN : 0) | - (flags & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0) | - (flags & PA_IO_EVENT_ERROR ? G_IO_ERR : 0) | - (flags & PA_IO_EVENT_HANGUP ? G_IO_HUP : 0); + return (gushort) + ((flags & PA_IO_EVENT_INPUT ? G_IO_IN : 0) | + (flags & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0) | + (flags & PA_IO_EVENT_ERROR ? G_IO_ERR : 0) | + (flags & PA_IO_EVENT_HANGUP ? G_IO_HUP : 0)); } static pa_io_event_flags_t map_flags_from_glib(gushort flags) { @@ -425,7 +425,7 @@ static void glib_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_ /* quit() */ -static void glib_quit(pa_mainloop_api*a, PA_GCC_UNUSED int retval) { +static void glib_quit(pa_mainloop_api*a, int retval) { g_warning("quit() ignored"); @@ -536,7 +536,7 @@ static gboolean check_func(GSource *source) { return FALSE; } -static gboolean dispatch_func(GSource *source, PA_GCC_UNUSED GSourceFunc callback, PA_GCC_UNUSED gpointer userdata) { +static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer userdata) { pa_glib_mainloop *g = (pa_glib_mainloop*) source; pa_io_event *e; diff --git a/src/pulse/internal.h b/src/pulse/internal.h index bfe888ee..5fe4210e 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -64,7 +64,7 @@ struct pa_context { uint32_t version; uint32_t ctag; uint32_t csyncid; - uint32_t error; + int error; pa_context_state_t state; pa_context_notify_cb_t state_callback; @@ -75,9 +75,9 @@ struct pa_context { pa_mempool *mempool; pa_bool_t is_local:1; - pa_bool_t do_autospawn:1; pa_bool_t do_shm:1; - int autospawn_lock_fd; + + pa_bool_t do_autospawn:1; pa_spawn_api spawn_api; pa_strlist *server_list; diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c index 4be2c62a..38091581 100644 --- a/src/pulse/introspect.c +++ b/src/pulse/introspect.c @@ -24,6 +24,8 @@ #include <config.h> #endif +#include <string.h> + #include <pulse/context.h> #include <pulse/gccmacro.h> @@ -36,7 +38,7 @@ /*** Statistics ***/ -static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void context_stat_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; pa_stat_info i, *p = &i; @@ -79,7 +81,7 @@ pa_operation* pa_context_stat(pa_context *c, pa_stat_info_cb_t cb, void *userdat /*** Server Info ***/ -static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; pa_server_info i, *p = &i; @@ -127,7 +129,7 @@ pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, /*** Sink Info ***/ -static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int eol = 1; @@ -248,7 +250,7 @@ pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, /*** Source info ***/ -static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int eol = 1; @@ -369,7 +371,7 @@ pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name /*** Client info ***/ -static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int eol = 1; @@ -451,7 +453,7 @@ pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t /*** Module info ***/ -static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int eol = 1; @@ -530,7 +532,7 @@ pa_operation* pa_context_get_module_info_list(pa_context *c, pa_module_info_cb_t /*** Sink input info ***/ -static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int eol = 1; @@ -624,7 +626,7 @@ pa_operation* pa_context_get_sink_input_info_list(pa_context *c, void (*cb)(pa_c /*** Source output info ***/ -static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int eol = 1; @@ -954,7 +956,7 @@ pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name /** Sample Cache **/ -static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int eol = 1; @@ -1098,7 +1100,7 @@ pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_cont return command_kill(c, PA_COMMAND_KILL_SOURCE_OUTPUT, idx, cb, userdata); } -static void context_index_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void context_index_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; uint32_t idx; @@ -1159,7 +1161,7 @@ pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_s /*** Autoload stuff ***/ -static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int eol = 1; diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h index ca79f5b7..087bd9f9 100644 --- a/src/pulse/introspect.h +++ b/src/pulse/introspect.h @@ -561,7 +561,7 @@ typedef enum pa_autoload_type { typedef struct pa_autoload_info { uint32_t index; /**< Index of this autoload entry */ const char *name; /**< Name of the sink or source */ - pa_autoload_type_t type; /**< Type of the autoload entry */ + pa_autoload_type_t type; /**< Type of the autoload entry */ const char *module; /**< Module name to load */ const char *argument; /**< Argument string for module */ } pa_autoload_info; diff --git a/src/pulse/mainloop-api.c b/src/pulse/mainloop-api.c index 4e3b135a..4b862f9a 100644 --- a/src/pulse/mainloop-api.c +++ b/src/pulse/mainloop-api.c @@ -51,7 +51,7 @@ static void once_callback(pa_mainloop_api *m, pa_defer_event *e, void *userdata) m->defer_free(e); } -static void free_callback(pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event *e, void *userdata) { +static void free_callback(pa_mainloop_api *m, pa_defer_event *e, void *userdata) { struct once_info *i = userdata; pa_assert(m); diff --git a/src/pulse/mainloop-signal.c b/src/pulse/mainloop-signal.c index e95968ae..d09f4b0a 100644 --- a/src/pulse/mainloop-signal.c +++ b/src/pulse/mainloop-signal.c @@ -90,7 +90,7 @@ static void dispatch(pa_mainloop_api*a, int sig) { } } -static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t f, PA_GCC_UNUSED void *userdata) { +static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata) { ssize_t r; int sig; diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index 5823e280..60e5d1ff 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -57,7 +57,7 @@ struct pa_io_event { pa_mainloop *mainloop; - int dead; + pa_bool_t dead:1; int fd; pa_io_event_flags_t events; @@ -72,9 +72,9 @@ struct pa_io_event { struct pa_time_event { pa_mainloop *mainloop; - int dead; + pa_bool_t dead:1; - int enabled; + pa_bool_t enabled:1; struct timeval timeval; pa_time_event_cb_t callback; @@ -86,9 +86,9 @@ struct pa_time_event { struct pa_defer_event { pa_mainloop *mainloop; - int dead; + pa_bool_t dead:1; - int enabled; + pa_bool_t enabled:1; pa_defer_event_cb_t callback; void *userdata; @@ -102,22 +102,24 @@ struct pa_mainloop { PA_LLIST_HEAD(pa_time_event, time_events); PA_LLIST_HEAD(pa_defer_event, defer_events); - int n_enabled_defer_events, n_enabled_time_events, n_io_events; - int io_events_please_scan, time_events_please_scan, defer_events_please_scan; + unsigned n_enabled_defer_events, n_enabled_time_events, n_io_events; + unsigned io_events_please_scan, time_events_please_scan, defer_events_please_scan; + pa_bool_t rebuild_pollfds:1; struct pollfd *pollfds; unsigned max_pollfds, n_pollfds; - int rebuild_pollfds; int prepared_timeout; pa_time_event *cached_next_time_event; - int quit, retval; pa_mainloop_api api; + int retval; + pa_bool_t quit:1; + + pa_bool_t wakeup_requested:1; int wakeup_pipe[2]; int wakeup_pipe_type; - int wakeup_requested; enum { STATE_PASSIVE, @@ -133,11 +135,11 @@ struct pa_mainloop { }; static short map_flags_to_libc(pa_io_event_flags_t flags) { - return - (flags & PA_IO_EVENT_INPUT ? POLLIN : 0) | - (flags & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) | - (flags & PA_IO_EVENT_ERROR ? POLLERR : 0) | - (flags & PA_IO_EVENT_HANGUP ? POLLHUP : 0); + return (short) + ((flags & PA_IO_EVENT_INPUT ? POLLIN : 0) | + (flags & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) | + (flags & PA_IO_EVENT_ERROR ? POLLERR : 0) | + (flags & PA_IO_EVENT_HANGUP ? POLLHUP : 0)); } static pa_io_event_flags_t map_flags_from_libc(short flags) { @@ -169,7 +171,7 @@ static pa_io_event* mainloop_io_new( e = pa_xnew(pa_io_event, 1); e->mainloop = m; - e->dead = 0; + e->dead = FALSE; e->fd = fd; e->events = events; @@ -194,13 +196,13 @@ static pa_io_event* mainloop_io_new( SELECT_TYPE_ARG5 &tv) == -1) && (WSAGetLastError() == WSAENOTSOCK)) { pa_log_warn("Cannot monitor non-socket file descriptors."); - e->dead = 1; + e->dead = TRUE; } } #endif PA_LLIST_PREPEND(pa_io_event, m->io_events, e); - m->rebuild_pollfds = 1; + m->rebuild_pollfds = TRUE; m->n_io_events ++; pa_mainloop_wakeup(m); @@ -220,7 +222,7 @@ static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) { if (e->pollfd) e->pollfd->events = map_flags_to_libc(events); else - e->mainloop->rebuild_pollfds = 1; + e->mainloop->rebuild_pollfds = TRUE; pa_mainloop_wakeup(e->mainloop); } @@ -229,11 +231,11 @@ static void mainloop_io_free(pa_io_event *e) { pa_assert(e); pa_assert(!e->dead); - e->dead = 1; + e->dead = TRUE; e->mainloop->io_events_please_scan ++; e->mainloop->n_io_events --; - e->mainloop->rebuild_pollfds = 1; + e->mainloop->rebuild_pollfds = TRUE; pa_mainloop_wakeup(e->mainloop); } @@ -262,9 +264,9 @@ static pa_defer_event* mainloop_defer_new( e = pa_xnew(pa_defer_event, 1); e->mainloop = m; - e->dead = 0; + e->dead = FALSE; - e->enabled = 1; + e->enabled = TRUE; m->n_enabled_defer_events++; e->callback = callback; @@ -297,13 +299,13 @@ static void mainloop_defer_free(pa_defer_event *e) { pa_assert(e); pa_assert(!e->dead); - e->dead = 1; + e->dead = TRUE; e->mainloop->defer_events_please_scan ++; if (e->enabled) { pa_assert(e->mainloop->n_enabled_defer_events > 0); e->mainloop->n_enabled_defer_events--; - e->enabled = 0; + e->enabled = FALSE; } } @@ -333,7 +335,7 @@ static pa_time_event* mainloop_time_new( e = pa_xnew(pa_time_event, 1); e->mainloop = m; - e->dead = 0; + e->dead = FALSE; if ((e->enabled = !!tv)) { e->timeval = *tv; @@ -388,13 +390,13 @@ static void mainloop_time_free(pa_time_event *e) { pa_assert(e); pa_assert(!e->dead); - e->dead = 1; + e->dead = TRUE; e->mainloop->time_events_please_scan ++; if (e->enabled) { pa_assert(e->mainloop->n_enabled_time_events > 0); e->mainloop->n_enabled_time_events--; - e->enabled = 0; + e->enabled = FALSE; } if (e->mainloop->cached_next_time_event == e) @@ -462,7 +464,7 @@ pa_mainloop *pa_mainloop_new(void) { pa_make_fd_nonblock(m->wakeup_pipe[1]); pa_make_fd_cloexec(m->wakeup_pipe[0]); pa_make_fd_cloexec(m->wakeup_pipe[1]); - m->wakeup_requested = 0; + m->wakeup_requested = FALSE; PA_LLIST_HEAD_INIT(pa_io_event, m->io_events); PA_LLIST_HEAD_INIT(pa_time_event, m->time_events); @@ -476,9 +478,10 @@ pa_mainloop *pa_mainloop_new(void) { m->pollfds = NULL; m->max_pollfds = m->n_pollfds = 0; - m->rebuild_pollfds = 1; + m->rebuild_pollfds = TRUE; - m->quit = m->retval = 0; + m->quit = FALSE; + m->retval = 0; m->api = vtable; m->api.userdata = m; @@ -492,7 +495,7 @@ pa_mainloop *pa_mainloop_new(void) { return m; } -static void cleanup_io_events(pa_mainloop *m, int force) { +static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) { pa_io_event *e; e = m->io_events; @@ -515,7 +518,7 @@ static void cleanup_io_events(pa_mainloop *m, int force) { pa_xfree(e); - m->rebuild_pollfds = 1; + m->rebuild_pollfds = TRUE; } e = n; @@ -524,7 +527,7 @@ static void cleanup_io_events(pa_mainloop *m, int force) { pa_assert(m->io_events_please_scan == 0); } -static void cleanup_time_events(pa_mainloop *m, int force) { +static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) { pa_time_event *e; e = m->time_events; @@ -545,7 +548,7 @@ static void cleanup_time_events(pa_mainloop *m, int force) { if (!e->dead && e->enabled) { pa_assert(m->n_enabled_time_events > 0); m->n_enabled_time_events--; - e->enabled = 0; + e->enabled = FALSE; } if (e->destroy_callback) @@ -560,7 +563,7 @@ static void cleanup_time_events(pa_mainloop *m, int force) { pa_assert(m->time_events_please_scan == 0); } -static void cleanup_defer_events(pa_mainloop *m, int force) { +static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) { pa_defer_event *e; e = m->defer_events; @@ -581,7 +584,7 @@ static void cleanup_defer_events(pa_mainloop *m, int force) { if (!e->dead && e->enabled) { pa_assert(m->n_enabled_defer_events > 0); m->n_enabled_defer_events--; - e->enabled = 0; + e->enabled = FALSE; } if (e->destroy_callback) @@ -600,9 +603,9 @@ static void cleanup_defer_events(pa_mainloop *m, int force) { void pa_mainloop_free(pa_mainloop* m) { pa_assert(m); - cleanup_io_events(m, 1); - cleanup_defer_events(m, 1); - cleanup_time_events(m, 1); + cleanup_io_events(m, TRUE); + cleanup_defer_events(m, TRUE); + cleanup_time_events(m, TRUE); pa_xfree(m->pollfds); @@ -615,13 +618,13 @@ static void scan_dead(pa_mainloop *m) { pa_assert(m); if (m->io_events_please_scan) - cleanup_io_events(m, 0); + cleanup_io_events(m, FALSE); if (m->time_events_please_scan) - cleanup_time_events(m, 0); + cleanup_time_events(m, FALSE); if (m->defer_events_please_scan) - cleanup_defer_events(m, 0); + cleanup_defer_events(m, FALSE); } static void rebuild_pollfds(pa_mainloop *m) { @@ -662,7 +665,7 @@ static void rebuild_pollfds(pa_mainloop *m) { m->n_pollfds++; } - m->rebuild_pollfds = 0; + m->rebuild_pollfds = FALSE; } static int dispatch_pollfds(pa_mainloop *m) { @@ -948,7 +951,7 @@ int pa_mainloop_run(pa_mainloop *m, int *retval) { void pa_mainloop_quit(pa_mainloop *m, int retval) { pa_assert(m); - m->quit = 1; + m->quit = TRUE; m->retval = retval; pa_mainloop_wakeup(m); } diff --git a/src/pulse/proplist.c b/src/pulse/proplist.c index 9e0549ea..93bc0034 100644 --- a/src/pulse/proplist.c +++ b/src/pulse/proplist.c @@ -280,7 +280,7 @@ char *pa_proplist_to_string(pa_proplist *p) { char *c; pa_assert_se(pa_proplist_get(p, key, &value, &nbytes) == 0); - c = pa_xnew(char, nbytes*2+1); + c = pa_xmalloc(nbytes*2+1); pa_hexstr((const uint8_t*) value, nbytes, c, nbytes*2+1); pa_strbuf_printf(buf, "%s = hex:%s\n", key, c); diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h index 39d53303..c23ef238 100644 --- a/src/pulse/proplist.h +++ b/src/pulse/proplist.h @@ -168,9 +168,19 @@ int pa_proplist_get(pa_proplist *p, const char *key, const void **data, size_t * /** Update mode enum for pa_proplist_update(). \since 0.9.11 */ typedef enum pa_update_mode { - PA_UPDATE_SET, /*< Replace the entirey property list with the new one. Don't keep any of the old data around */ - PA_UPDATE_MERGE, /*< Merge new property list into the existing one, not replacing any old entries if they share a common key with the new property list. */ - PA_UPDATE_REPLACE /*< Merge new property list into the existing one, replacing all old entries that share a common key with the new property list. */ + PA_UPDATE_SET, + /*< Replace the entirey property list with the new one. Don't keep + * any of the old data around */ + + PA_UPDATE_MERGE, + /*< Merge new property list into the existing one, not replacing + * any old entries if they share a common key with the new + * property list. */ + + PA_UPDATE_REPLACE + /*< Merge new property list into the existing one, replacing all + * old entries that share a common key with the new property + * list. */ } pa_update_mode_t; /** Merge property list "other" into "p", adhering the merge mode as diff --git a/src/pulse/sample.c b/src/pulse/sample.c index 93da2465..29501595 100644 --- a/src/pulse/sample.c +++ b/src/pulse/sample.c @@ -80,6 +80,16 @@ size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) { return (size_t) (((t * spec->rate) / PA_USEC_PER_SEC)) * pa_frame_size(spec); } +pa_sample_spec* pa_sample_spec_init(pa_sample_spec *spec) { + pa_assert(spec); + + spec->format = PA_SAMPLE_INVALID; + spec->rate = 0; + spec->channels = 0; + + return spec; +} + int pa_sample_spec_valid(const pa_sample_spec *spec) { pa_assert(spec); @@ -131,7 +141,7 @@ char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) { pa_init_i18n(); if (!pa_sample_spec_valid(spec)) - pa_snprintf(s, l, _("Invalid")); + pa_snprintf(s, l, _("(invalid)")); else pa_snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate); diff --git a/src/pulse/sample.h b/src/pulse/sample.h index 2680cf7e..3c7dd0e7 100644 --- a/src/pulse/sample.h +++ b/src/pulse/sample.h @@ -120,17 +120,38 @@ PA_C_DECL_BEGIN /** Sample format */ typedef enum pa_sample_format { - PA_SAMPLE_U8, /**< Unsigned 8 Bit PCM */ - PA_SAMPLE_ALAW, /**< 8 Bit a-Law */ - PA_SAMPLE_ULAW, /**< 8 Bit mu-Law */ - PA_SAMPLE_S16LE, /**< Signed 16 Bit PCM, little endian (PC) */ - PA_SAMPLE_S16BE, /**< Signed 16 Bit PCM, big endian */ - PA_SAMPLE_FLOAT32LE, /**< 32 Bit IEEE floating point, little endian, range -1 to 1 */ - PA_SAMPLE_FLOAT32BE, /**< 32 Bit IEEE floating point, big endian, range -1 to 1 */ - PA_SAMPLE_S32LE, /**< Signed 32 Bit PCM, little endian (PC) */ - PA_SAMPLE_S32BE, /**< Signed 32 Bit PCM, big endian (PC) */ - PA_SAMPLE_MAX, /**< Upper limit of valid sample types */ - PA_SAMPLE_INVALID = -1 /**< An invalid value */ + PA_SAMPLE_U8, + /**< Unsigned 8 Bit PCM */ + + PA_SAMPLE_ALAW, + /**< 8 Bit a-Law */ + + PA_SAMPLE_ULAW, + /**< 8 Bit mu-Law */ + + PA_SAMPLE_S16LE, + /**< Signed 16 Bit PCM, little endian (PC) */ + + PA_SAMPLE_S16BE, + /**< Signed 16 Bit PCM, big endian */ + + PA_SAMPLE_FLOAT32LE, + /**< 32 Bit IEEE floating point, little endian, range -1 to 1 */ + + PA_SAMPLE_FLOAT32BE, + /**< 32 Bit IEEE floating point, big endian, range -1 to 1 */ + + PA_SAMPLE_S32LE, + /**< Signed 32 Bit PCM, little endian (PC) */ + + PA_SAMPLE_S32BE, + /**< Signed 32 Bit PCM, big endian (PC) */ + + PA_SAMPLE_MAX, + /**< Upper limit of valid sample types */ + + PA_SAMPLE_INVALID = -1 + /**< An invalid value */ } pa_sample_format_t; #ifdef WORDS_BIGENDIAN @@ -164,11 +185,29 @@ typedef enum pa_sample_format { /** A Shortcut for PA_SAMPLE_FLOAT32NE */ #define PA_SAMPLE_FLOAT32 PA_SAMPLE_FLOAT32NE +/** \cond fulldocs */ +/* Allow clients to check with #ifdef for thse sample formats */ +#define PA_SAMPLE_U8 PA_SAMPLE_U8 +#define PA_SAMPLE_ALAW PA_SAMPLE_ALAW +#define PA_SAMPLE_ULAW PA_SAMPLE_ULAW +#define PA_SAMPLE_S16LE PA_SAMPLE_S16LE +#define PA_SAMPLE_S16BE PA_SAMPLE_S16BE +#define PA_SAMPLE_FLOAT32LE PA_SAMPLE_FLOAT32LE +#define PA_SAMPLE_FLOAT32BE PA_SAMPLE_FLOAT32BE +#define PA_SAMPLE_S32LE PA_SAMPLE_S32LE +#define PA_SAMPLE_S32BE PA_SAMPLE_S32BE +/** \endcond */ + /** A sample format and attribute specification */ typedef struct pa_sample_spec { - pa_sample_format_t format; /**< The sample format */ - uint32_t rate; /**< The sample rate. (e.g. 44100) */ - uint8_t channels; /**< Audio channels. (1 for mono, 2 for stereo, ...) */ + pa_sample_format_t format; + /**< The sample format */ + + uint32_t rate; + /**< The sample rate. (e.g. 44100) */ + + uint8_t channels; + /**< Audio channels. (1 for mono, 2 for stereo, ...) */ } pa_sample_spec; /** Type for usec specifications (unsigned). Always 64 bit. */ @@ -183,12 +222,21 @@ size_t pa_frame_size(const pa_sample_spec *spec) PA_GCC_PURE; /** Return the size of a sample with the specific sample type */ size_t pa_sample_size(const pa_sample_spec *spec) PA_GCC_PURE; -/** Calculate the time the specified bytes take to play with the specified sample type */ +/** Calculate the time the specified bytes take to play with the + * specified sample type. The return value will always be rounded + * down for non-integral return values. */ pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) PA_GCC_PURE; -/** Calculates the number of bytes that are required for the specified time. \since 0.9 */ +/** Calculates the number of bytes that are required for the specified + * time. The return value will always be rounded down for non-integral + * return values. \since 0.9 */ size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) PA_GCC_PURE; +/** Initialize the specified sample spec and return a pointer to + * it. The sample spec will have a defined state but + * pa_sample_spec_valid() will fail for it. \since 0.9.13 */ +pa_sample_spec* pa_sample_spec_init(pa_sample_spec *spec); + /** Return non-zero when the sample type specification is valid */ int pa_sample_spec_valid(const pa_sample_spec *spec) PA_GCC_PURE; @@ -201,7 +249,11 @@ const char *pa_sample_format_to_string(pa_sample_format_t f) PA_GCC_PURE; /** Parse a sample format text. Inverse of pa_sample_format_to_string() */ pa_sample_format_t pa_parse_sample_format(const char *format) PA_GCC_PURE; -/** Maximum required string length for pa_sample_spec_snprint() */ +/** Maximum required string length for + * pa_sample_spec_snprint(). Please note that this value can change + * with any release without warning and without being considered API + * or ABI breakage. You should not use this definition anywhere where + * it might become part of an ABI. */ #define PA_SAMPLE_SPEC_SNPRINT_MAX 32 /** Pretty print a sample type specification to a string */ diff --git a/src/pulse/scache.c b/src/pulse/scache.c index 5e31e7af..fd3b9876 100644 --- a/src/pulse/scache.c +++ b/src/pulse/scache.c @@ -47,6 +47,7 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) { PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, length > 0, PA_ERR_INVALID); + PA_CHECK_VALIDITY(s->context, length == (size_t) (uint32_t) length, PA_ERR_INVALID); if (!(name = pa_proplist_gets(s->proplist, PA_PROP_EVENT_ID))) name = pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME); @@ -63,7 +64,7 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) { pa_tagstruct_puts(t, name); pa_tagstruct_put_sample_spec(t, &s->sample_spec); pa_tagstruct_put_channel_map(t, &s->channel_map); - pa_tagstruct_putu32(t, length); + pa_tagstruct_putu32(t, (uint32_t) length); if (s->context->version >= 13) { pa_init_proplist(s->proplist); diff --git a/src/pulse/simple.c b/src/pulse/simple.c index 51160ad7..79e39ebb 100644 --- a/src/pulse/simple.c +++ b/src/pulse/simple.c @@ -272,7 +272,7 @@ int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) { if (l > length) l = length; - r = pa_stream_write(p->stream, data, l, NULL, 0, PA_SEEK_RELATIVE); + r = pa_stream_write(p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE); CHECK_SUCCESS_GOTO(p, rerror, r >= 0, unlock_and_fail); data = (const uint8_t*) data + l; diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 585518f0..c0ae4ac2 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -86,7 +86,7 @@ pa_stream *pa_stream_new_with_proplist( pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID); - PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE || ss->format != PA_SAMPLE_S32NE), PA_ERR_NOTSUPPORTED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE && ss->format != PA_SAMPLE_S32BE), PA_ERR_NOTSUPPORTED); PA_CHECK_VALIDITY_RETURN_NULL(c, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID); PA_CHECK_VALIDITY_RETURN_NULL(c, name || (p && pa_proplist_contains(p, PA_PROP_MEDIA_NAME)), PA_ERR_INVALID); @@ -124,7 +124,7 @@ pa_stream *pa_stream_new_with_proplist( * what older PA versions provided. */ s->buffer_attr.maxlength = (uint32_t) -1; - s->buffer_attr.tlength = pa_usec_to_bytes(250*PA_USEC_PER_MSEC, ss); /* 250ms of buffering */ + s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes(250*PA_USEC_PER_MSEC, ss); /* 250ms of buffering */ s->buffer_attr.minreq = (uint32_t) -1; s->buffer_attr.prebuf = (uint32_t) -1; s->buffer_attr.fragsize = (uint32_t) -1; @@ -315,7 +315,7 @@ static void request_auto_timing_update(pa_stream *s, pa_bool_t force) { } } -void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; pa_stream *s; uint32_t channel; @@ -382,7 +382,7 @@ static void check_smoother_status(pa_stream *s, pa_bool_t aposteriori, pa_bool_t * if prebuf is non-zero! */ } -void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; pa_stream *s; uint32_t channel; @@ -479,7 +479,7 @@ finish: pa_context_unref(c); } -void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; pa_stream *s; uint32_t channel; @@ -557,13 +557,13 @@ void pa_command_stream_started(pa_pdispatch *pd, uint32_t command, uint32_t tag, request_auto_timing_update(s, TRUE); if (s->started_callback) - s->started_callback(s, s->suspended_userdata); + s->started_callback(s, s->started_userdata); finish: pa_context_unref(c); } -void pa_command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +void pa_command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_stream *s; pa_context *c = userdata; uint32_t bytes, channel; @@ -598,7 +598,7 @@ finish: pa_context_unref(c); } -void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_stream *s; pa_context *c = userdata; uint32_t channel; @@ -670,7 +670,7 @@ static void invalidate_indexes(pa_stream *s, pa_bool_t r, pa_bool_t w) { request_auto_timing_update(s, TRUE); } -static void auto_timing_update_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC_UNUSED pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { +static void auto_timing_update_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *tv, void *userdata) { pa_stream *s = userdata; pa_assert(s); @@ -694,7 +694,7 @@ static void create_stream_complete(pa_stream *s) { if (s->flags & PA_STREAM_AUTO_TIMING_UPDATE) { struct timeval tv; pa_gettimeofday(&tv); - tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */ + tv.tv_usec += (suseconds_t) LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */ pa_assert(!s->auto_timing_update_event); s->auto_timing_update_event = s->mainloop->time_new(s->mainloop, &tv, &auto_timing_update_callback, s); @@ -722,7 +722,7 @@ static void automatic_buffer_attr(pa_stream *s, pa_buffer_attr *attr, const pa_s attr->maxlength = 4*1024*1024; /* 4MB is the maximum queue length PulseAudio <= 0.9.9 supported. */ if (attr->tlength == (uint32_t) -1) - attr->tlength = pa_usec_to_bytes(250*PA_USEC_PER_MSEC, ss); /* 250ms of buffering */ + attr->tlength = (uint32_t) pa_usec_to_bytes(250*PA_USEC_PER_MSEC, ss); /* 250ms of buffering */ if (attr->minreq == (uint32_t) -1) attr->minreq = (attr->tlength)/5; /* Ask for more data when there are only 200ms left in the playback buffer */ @@ -734,7 +734,7 @@ static void automatic_buffer_attr(pa_stream *s, pa_buffer_attr *attr, const pa_s attr->fragsize = attr->tlength; /* Pass data to the app only when the buffer is filled up once */ } -void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_stream *s = userdata; pa_assert(pd); @@ -865,6 +865,7 @@ static int create_stream( pa_tagstruct *t; uint32_t tag; + pa_bool_t volume_set = FALSE; pa_assert(s); pa_assert(PA_REFCNT_VALUE(s) >= 1); @@ -885,7 +886,10 @@ static int create_stream( PA_STREAM_VARIABLE_RATE| PA_STREAM_PEAK_DETECT| PA_STREAM_START_MUTED| - PA_STREAM_ADJUST_LATENCY)), PA_ERR_INVALID); + PA_STREAM_ADJUST_LATENCY| + PA_STREAM_EARLY_REQUESTS| + PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND| + PA_STREAM_START_UNMUTED)), PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, s->context->version >= 12 || !(flags & PA_STREAM_VARIABLE_RATE), PA_ERR_NOTSUPPORTED); PA_CHECK_VALIDITY(s->context, s->context->version >= 13 || !(flags & PA_STREAM_PEAK_DETECT), PA_ERR_NOTSUPPORTED); @@ -898,6 +902,7 @@ static int create_stream( PA_CHECK_VALIDITY(s->context, direction == PA_STREAM_RECORD || !(flags & (PA_STREAM_PEAK_DETECT)), PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, !volume || volume->channels == s->sample_spec.channels, PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID); + PA_CHECK_VALIDITY(s->context, (flags & (PA_STREAM_ADJUST_LATENCY|PA_STREAM_EARLY_REQUESTS)) != (PA_STREAM_ADJUST_LATENCY|PA_STREAM_EARLY_REQUESTS), PA_ERR_INVALID); pa_stream_ref(s); @@ -930,7 +935,7 @@ static int create_stream( t = pa_tagstruct_command( s->context, - s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM, + (uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM), &tag); if (s->context->version < 13) @@ -957,6 +962,8 @@ static int create_stream( PA_TAG_U32, s->syncid, PA_TAG_INVALID); + volume_set = !!volume; + if (!volume) volume = pa_cvolume_reset(&cv, s->sample_spec.channels); @@ -994,6 +1001,22 @@ static int create_stream( pa_tagstruct_putu32(t, s->direct_on_input); } + if (s->context->version >= 14) { + + if (s->direction == PA_STREAM_PLAYBACK) + pa_tagstruct_put_boolean(t, volume_set); + + pa_tagstruct_put_boolean(t, flags & PA_STREAM_EARLY_REQUESTS); + } + + if (s->context->version >= 15) { + + if (s->direction == PA_STREAM_PLAYBACK) + pa_tagstruct_put_boolean(t, flags & (PA_STREAM_START_MUTED|PA_STREAM_START_UNMUTED)); + + pa_tagstruct_put_boolean(t, flags & PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND); + } + pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL); @@ -1093,7 +1116,7 @@ int pa_stream_write( free_cb((void*) data); if (length < s->requested_bytes) - s->requested_bytes -= length; + s->requested_bytes -= (uint32_t) length; else s->requested_bytes = 0; @@ -1107,10 +1130,10 @@ int pa_stream_write( if (seek == PA_SEEK_ABSOLUTE) { s->write_index_corrections[s->current_write_index_correction].corrupt = FALSE; s->write_index_corrections[s->current_write_index_correction].absolute = TRUE; - s->write_index_corrections[s->current_write_index_correction].value = offset + length; + s->write_index_corrections[s->current_write_index_correction].value = offset + (int64_t) length; } else if (seek == PA_SEEK_RELATIVE) { if (!s->write_index_corrections[s->current_write_index_correction].corrupt) - s->write_index_corrections[s->current_write_index_correction].value += offset + length; + s->write_index_corrections[s->current_write_index_correction].value += offset + (int64_t) length; } else s->write_index_corrections[s->current_write_index_correction].corrupt = TRUE; } @@ -1120,10 +1143,10 @@ int pa_stream_write( if (seek == PA_SEEK_ABSOLUTE) { s->timing_info.write_index_corrupt = FALSE; - s->timing_info.write_index = offset + length; + s->timing_info.write_index = offset + (int64_t) length; } else if (seek == PA_SEEK_RELATIVE) { if (!s->timing_info.write_index_corrupt) - s->timing_info.write_index += offset + length; + s->timing_info.write_index += offset + (int64_t) length; } else s->timing_info.write_index_corrupt = TRUE; } @@ -1173,7 +1196,7 @@ int pa_stream_drop(pa_stream *s) { /* Fix the simulated local read index */ if (s->timing_info_valid && !s->timing_info.read_index_corrupt) - s->timing_info.read_index += s->peek_memchunk.length; + s->timing_info.read_index += (int64_t) s->peek_memchunk.length; pa_assert(s->peek_data); pa_memblock_release(s->peek_memchunk.memblock); @@ -1257,7 +1280,9 @@ static pa_usec_t calc_time(pa_stream *s, pa_bool_t ignore_transport) { usec -= s->timing_info.sink_usec; } - } else if (s->direction == PA_STREAM_RECORD) { + } else { + pa_assert(s->direction == PA_STREAM_RECORD); + /* The last byte written into the server side queue had * this time value associated */ usec = pa_bytes_to_usec(s->timing_info.write_index < 0 ? 0 : (uint64_t) s->timing_info.write_index, &s->sample_spec); @@ -1340,7 +1365,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, i->read_index_corrupt = FALSE; i->playing = (int) playing; - i->since_underrun = playing ? playing_for : underrun_for; + i->since_underrun = (int64_t) (playing ? playing_for : underrun_for); pa_gettimeofday(&now); @@ -1418,7 +1443,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, /* Read index correction */ if (!i->read_index_corrupt) - i->read_index -= pa_memblockq_get_length(o->stream->record_memblockq); + i->read_index -= (int64_t) pa_memblockq_get_length(o->stream->record_memblockq); } /* Update smoother */ @@ -1435,7 +1460,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, * speakers. Since we follow that timing here, we need * to try to fix this up */ - su = pa_bytes_to_usec(i->since_underrun, &o->stream->sample_spec); + su = pa_bytes_to_usec((uint64_t) i->since_underrun, &o->stream->sample_spec); if (su < i->sink_usec) x += i->sink_usec - su; @@ -1494,7 +1519,7 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t t = pa_tagstruct_command( s->context, - s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_GET_PLAYBACK_LATENCY : PA_COMMAND_GET_RECORD_LATENCY, + (uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_GET_PLAYBACK_LATENCY : PA_COMMAND_GET_RECORD_LATENCY), &tag); pa_tagstruct_putu32(t, s->channel); pa_tagstruct_put_timeval(t, pa_gettimeofday(&now)); @@ -1517,7 +1542,7 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t return o; } -void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_stream *s = userdata; pa_assert(pd); @@ -1557,8 +1582,8 @@ int pa_stream_disconnect(pa_stream *s) { t = pa_tagstruct_command( s->context, - s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : - (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM), + (uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : + (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)), &tag); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); @@ -1667,7 +1692,7 @@ void pa_stream_set_started_callback(pa_stream *s, pa_stream_notify_cb_t cb, void s->started_userdata = userdata; } -void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int success = 1; @@ -1715,7 +1740,7 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi t = pa_tagstruct_command( s->context, - s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CORK_PLAYBACK_STREAM : PA_COMMAND_CORK_RECORD_STREAM, + (uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CORK_PLAYBACK_STREAM : PA_COMMAND_CORK_RECORD_STREAM), &tag); pa_tagstruct_putu32(t, s->channel); pa_tagstruct_put_boolean(t, !!b); @@ -1760,7 +1785,7 @@ pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *use PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - if (!(o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata))) + if (!(o = stream_send_simple_command(s, (uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM), cb, userdata))) return NULL; if (s->direction == PA_STREAM_PLAYBACK) { @@ -1836,7 +1861,7 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe if (s->context->version >= 13) { pa_proplist *p = pa_proplist_new(); - pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name); + pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name); o = pa_stream_proplist_update(s, PA_UPDATE_REPLACE, p, cb, userdata); pa_proplist_free(p); } else { @@ -1846,7 +1871,7 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command( s->context, - s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_NAME : PA_COMMAND_SET_PLAYBACK_STREAM_NAME, + (uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_NAME : PA_COMMAND_SET_PLAYBACK_STREAM_NAME), &tag); pa_tagstruct_putu32(t, s->channel); pa_tagstruct_puts(t, name); @@ -1932,7 +1957,7 @@ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) { if (cindex < 0) cindex = 0; - c = pa_bytes_to_usec(cindex, &s->sample_spec); + c = pa_bytes_to_usec((uint64_t) cindex, &s->sample_spec); if (s->direction == PA_STREAM_PLAYBACK) *r_usec = time_counter_diff(s, c, t, negative); @@ -1948,7 +1973,7 @@ const pa_timing_info* pa_stream_get_timing_info(pa_stream *s) { 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); - PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->timing_info_valid, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->timing_info_valid, PA_ERR_NODATA); return &s->timing_info; } @@ -1978,7 +2003,7 @@ const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s) { return &s->buffer_attr; } -static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int success = 1; @@ -1995,7 +2020,6 @@ static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command, success = 0; } else { - if (o->stream->direction == PA_STREAM_PLAYBACK) { if (pa_tagstruct_getu32(t, &o->stream->buffer_attr.maxlength) < 0 || pa_tagstruct_getu32(t, &o->stream->buffer_attr.tlength) < 0 || @@ -2012,6 +2036,20 @@ static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command, } } + if (o->stream->context->version >= 13) { + pa_usec_t usec; + + if (pa_tagstruct_get_usec(t, &usec) < 0) { + pa_context_fail(o->context, PA_ERR_PROTOCOL); + goto finish; + } + + if (o->stream->direction == PA_STREAM_RECORD) + o->stream->timing_info.configured_source_usec = usec; + else + o->stream->timing_info.configured_sink_usec = usec; + } + if (!pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; @@ -2046,7 +2084,7 @@ pa_operation* pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr t = pa_tagstruct_command( s->context, - s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR : PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR, + (uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR : PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR), &tag); pa_tagstruct_putu32(t, s->channel); @@ -2065,6 +2103,9 @@ pa_operation* pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr if (s->context->version >= 13) pa_tagstruct_put_boolean(t, !!(s->flags & PA_STREAM_ADJUST_LATENCY)); + if (s->context->version >= 14) + pa_tagstruct_put_boolean(t, !!(s->flags & PA_STREAM_EARLY_REQUESTS)); + pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_set_buffer_attr_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); @@ -2120,7 +2161,7 @@ int pa_stream_is_corked(pa_stream *s) { return s->corked; } -static void stream_update_sample_rate_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void stream_update_sample_rate_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int success = 1; @@ -2177,7 +2218,7 @@ pa_operation *pa_stream_update_sample_rate(pa_stream *s, uint32_t rate, pa_strea t = pa_tagstruct_command( s->context, - s->direction == PA_STREAM_RECORD ? PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE : PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE, + (uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE : PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE), &tag); pa_tagstruct_putu32(t, s->channel); pa_tagstruct_putu32(t, rate); @@ -2205,7 +2246,7 @@ pa_operation *pa_stream_proplist_update(pa_stream *s, pa_update_mode_t mode, pa_ t = pa_tagstruct_command( s->context, - s->direction == PA_STREAM_RECORD ? PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST : PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST, + (uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST : PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST), &tag); pa_tagstruct_putu32(t, s->channel); pa_tagstruct_putu32(t, (uint32_t) mode); @@ -2238,7 +2279,7 @@ pa_operation *pa_stream_proplist_remove(pa_stream *s, const char *const keys[], t = pa_tagstruct_command( s->context, - s->direction == PA_STREAM_RECORD ? PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST : PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST, + (uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST : PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST), &tag); pa_tagstruct_putu32(t, s->channel); diff --git a/src/pulse/stream.h b/src/pulse/stream.h index 2a8f7a8b..6cb363c8 100644 --- a/src/pulse/stream.h +++ b/src/pulse/stream.h @@ -473,7 +473,7 @@ void pa_stream_set_underflow_callback(pa_stream *p, pa_stream_notify_cb_t cb, vo /** Set the callback function that is called when a the server starts * playback after an underrun or on initial startup. This only informs - * that audio is flowing again, it is no indication that audio startet + * that audio is flowing again, it is no indication that audio started * to reach the speakers already. (Only for playback streams). \since * 0.9.11 */ void pa_stream_set_started_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata); diff --git a/src/pulse/subscribe.c b/src/pulse/subscribe.c index b8d3be89..e12d1446 100644 --- a/src/pulse/subscribe.c +++ b/src/pulse/subscribe.c @@ -34,7 +34,7 @@ #include "subscribe.h" -void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; pa_subscription_event_type_t e; uint32_t idx; diff --git a/src/pulse/timeval.c b/src/pulse/timeval.c index 9708a735..376cf13c 100644 --- a/src/pulse/timeval.c +++ b/src/pulse/timeval.c @@ -90,13 +90,13 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { } /* Calculate the second difference*/ - r = ((pa_usec_t) a->tv_sec - b->tv_sec) * PA_USEC_PER_SEC; + r = ((pa_usec_t) a->tv_sec - (pa_usec_t) b->tv_sec) * PA_USEC_PER_SEC; /* Calculate the microsecond difference */ if (a->tv_usec > b->tv_usec) - r += ((pa_usec_t) a->tv_usec - b->tv_usec); + r += ((pa_usec_t) a->tv_usec - (pa_usec_t) b->tv_usec); else if (a->tv_usec < b->tv_usec) - r -= ((pa_usec_t) b->tv_usec - a->tv_usec); + r -= ((pa_usec_t) b->tv_usec - (pa_usec_t) a->tv_usec); return r; } @@ -132,7 +132,7 @@ struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) { pa_assert(tv); secs = (unsigned long) (v/PA_USEC_PER_SEC); - tv->tv_sec += secs; + tv->tv_sec += (time_t) secs; v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC; tv->tv_usec += (suseconds_t) v; @@ -140,7 +140,7 @@ struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) { /* Normalize */ while ((unsigned) tv->tv_usec >= PA_USEC_PER_SEC) { tv->tv_sec++; - tv->tv_usec -= PA_USEC_PER_SEC; + tv->tv_usec -= (suseconds_t) PA_USEC_PER_SEC; } return tv; @@ -151,14 +151,14 @@ struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) { pa_assert(tv); secs = (unsigned long) (v/PA_USEC_PER_SEC); - tv->tv_sec -= secs; + tv->tv_sec -= (time_t) secs; v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC; if (tv->tv_usec >= (suseconds_t) v) tv->tv_usec -= (suseconds_t) v; else { tv->tv_sec --; - tv->tv_usec = tv->tv_usec + PA_USEC_PER_SEC - v; + tv->tv_usec += (suseconds_t) (PA_USEC_PER_SEC - v); } return tv; @@ -167,8 +167,8 @@ struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) { struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) { pa_assert(tv); - tv->tv_sec = v / PA_USEC_PER_SEC; - tv->tv_usec = v % PA_USEC_PER_SEC; + tv->tv_sec = (time_t) (v / PA_USEC_PER_SEC); + tv->tv_usec = (suseconds_t) (v % PA_USEC_PER_SEC); return tv; } diff --git a/src/pulse/utf8.c b/src/pulse/utf8.c index 119be542..7671be46 100644 --- a/src/pulse/utf8.c +++ b/src/pulse/utf8.c @@ -64,24 +64,24 @@ #define FILTER_CHAR '_' -static inline int is_unicode_valid(uint32_t ch) { +static inline pa_bool_t is_unicode_valid(uint32_t ch) { if (ch >= 0x110000) /* End of unicode space */ - return 0; + return FALSE; if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */ - return 0; + return FALSE; if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */ - return 0; + return FALSE; if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */ - return 0; + return FALSE; - return 1; + return TRUE; } -static inline int is_continuation_char(uint8_t ch) { +static inline pa_bool_t is_continuation_char(uint8_t ch) { if ((ch & 0xc0) != 0x80) /* 10xxxxxx */ - return 0; - return 1; + return FALSE; + return TRUE; } static inline void merge_continuation_char(uint32_t *u_ch, uint8_t ch) { @@ -109,17 +109,17 @@ static char* utf8_validate(const char *str, char *output) { if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */ size = 2; min = 128; - val = *p & 0x1e; + val = (uint32_t) (*p & 0x1e); goto ONE_REMAINING; } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/ size = 3; min = (1 << 11); - val = *p & 0x0f; + val = (uint32_t) (*p & 0x0f); goto TWO_REMAINING; } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */ size = 4; min = (1 << 16); - val = *p & 0x07; + val = (uint32_t) (*p & 0x07); } else { size = 1; goto error; @@ -149,7 +149,7 @@ ONE_REMAINING: goto error; if (o) { - memcpy(o, last, size); + memcpy(o, last, (size_t) size); o += size - 1; } @@ -189,7 +189,7 @@ char* pa_utf8_filter (const char *str) { char *new_str; pa_assert(str); - new_str = pa_xnew(char, strlen(str) + 1); + new_str = pa_xmalloc(strlen(str) + 1); return utf8_validate(str, new_str); } @@ -212,7 +212,7 @@ static char* iconv_simple(const char *str, const char *to, const char *from) { return NULL; inlen = len = strlen(str) + 1; - new_str = pa_xnew(char, len); + new_str = pa_xmalloc(len); for (;;) { inbuf = (ICONV_CONST char*) str; /* Brain dead prototype for iconv() */ diff --git a/src/pulse/util.c b/src/pulse/util.c index f785a2e9..b20ea46a 100644 --- a/src/pulse/util.c +++ b/src/pulse/util.c @@ -95,12 +95,15 @@ char *pa_get_user_name(char *s, size_t l) { #elif defined(OS_IS_WIN32) /* HAVE_PWD_H */ DWORD size = sizeof(buf); - if (!GetUserName(buf, &size)) + if (!GetUserName(buf, &size)) { + errno = ENOENT; return NULL; + } p = buf; #else /* HAVE_PWD_H */ + return NULL; #endif /* HAVE_PWD_H */ } @@ -138,6 +141,8 @@ char *pa_get_home_dir(char *s, size_t l) { return pa_strlcpy(s, e, l); #ifdef HAVE_PWD_H + + errno = 0; #ifdef HAVE_GETPWUID_R if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { #else @@ -145,11 +150,16 @@ char *pa_get_home_dir(char *s, size_t l) { * that do not support getpwuid_r. */ if ((r = getpwuid(getuid())) == NULL) { #endif + if (!errno) + errno = ENOENT; + return NULL; } return pa_strlcpy(s, r->pw_dir, l); #else /* HAVE_PWD_H */ + + errno = ENOENT; return NULL; #endif } @@ -200,6 +210,7 @@ char *pa_get_binary_name(char *s, size_t l) { } #endif + errno = ENOENT; return NULL; } @@ -249,8 +260,8 @@ int pa_msleep(unsigned long t) { #elif defined(HAVE_NANOSLEEP) struct timespec ts; - ts.tv_sec = t/1000; - ts.tv_nsec = (t % 1000) * 1000000; + ts.tv_sec = (time_t) (t/1000UL); + ts.tv_nsec = (long) ((t % 1000UL) * 1000000UL); return nanosleep(&ts, NULL); #else diff --git a/src/pulse/volume.c b/src/pulse/volume.c index 625eb19a..99a85f44 100644 --- a/src/pulse/volume.c +++ b/src/pulse/volume.c @@ -26,6 +26,7 @@ #include <stdio.h> #include <string.h> +#include <pulse/i18n.h> #include <pulsecore/core-util.h> #include <pulsecore/macro.h> @@ -46,6 +47,19 @@ int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) { return 1; } +pa_cvolume* pa_cvolume_init(pa_cvolume *a) { + unsigned c; + + pa_assert(a); + + a->channels = 0; + + for (c = 0; c < PA_CHANNELS_MAX; c++) + a->values[c] = (pa_volume_t) -1; + + return a; +} + pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) { int i; @@ -53,7 +67,7 @@ pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) { pa_assert(channels > 0); pa_assert(channels <= PA_CHANNELS_MAX); - a->channels = channels; + a->channels = (uint8_t) channels; for (i = 0; i < a->channels; i++) a->values[i] = v; @@ -74,8 +88,29 @@ pa_volume_t pa_cvolume_avg(const pa_cvolume *a) { return (pa_volume_t) sum; } +pa_volume_t pa_cvolume_max(const pa_cvolume *a) { + pa_volume_t m = 0; + int i; + pa_assert(a); + + for (i = 0; i < a->channels; i++) + if (a->values[i] > m) + m = a->values[i]; + + return m; +} + pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) { - return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a)* pa_sw_volume_to_linear(b)); + return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a) * pa_sw_volume_to_linear(b)); +} + +pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) { + double v = pa_sw_volume_to_linear(b); + + if (v <= 0) + return 0; + + return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a) / v); } #define USER_DECIBEL_RANGE 60 @@ -84,7 +119,7 @@ pa_volume_t pa_sw_volume_from_dB(double dB) { if (isinf(dB) < 0 || dB <= -USER_DECIBEL_RANGE) return PA_VOLUME_MUTED; - return (pa_volume_t) ((dB/USER_DECIBEL_RANGE+1)*PA_VOLUME_NORM); + return (pa_volume_t) lrint((dB/USER_DECIBEL_RANGE+1)*PA_VOLUME_NORM); } double pa_sw_volume_to_dB(pa_volume_t v) { @@ -110,18 +145,25 @@ double pa_sw_volume_to_linear(pa_volume_t v) { if (v == PA_VOLUME_MUTED) return 0; - return pow(10, pa_sw_volume_to_dB(v)/20); + return pow(10.0, pa_sw_volume_to_dB(v)/20.0); } char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) { unsigned channel; - int first = 1; + pa_bool_t first = TRUE; char *e; pa_assert(s); pa_assert(l > 0); pa_assert(c); + pa_init_i18n(); + + if (!pa_cvolume_valid(c)) { + pa_snprintf(s, l, _("(invalid)")); + return s; + } + *(e = s) = 0; for (channel = 0; channel < c->channels && l > 1; channel++) { @@ -131,7 +173,38 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) { (c->values[channel]*100)/PA_VOLUME_NORM); e = strchr(e, 0); - first = 0; + first = FALSE; + } + + return s; +} + +char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) { + unsigned channel; + pa_bool_t first = TRUE; + char *e; + + pa_assert(s); + pa_assert(l > 0); + pa_assert(c); + + pa_init_i18n(); + + if (!pa_cvolume_valid(c)) { + pa_snprintf(s, l, _("(invalid)")); + return s; + } + + *(e = s) = 0; + + for (channel = 0; channel < c->channels && l > 1; channel++) { + l -= pa_snprintf(e, l, "%s%u: %0.2f dB", + first ? "" : " ", + channel, + pa_sw_volume_to_dB(c->values[channel])); + + e = strchr(e, 0); + first = FALSE; } return s; @@ -156,24 +229,41 @@ pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_assert(a); pa_assert(b); - for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++) { + for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++) + dest->values[i] = pa_sw_volume_multiply(a->values[i], b->values[i]); - dest->values[i] = pa_sw_volume_multiply( - i < a->channels ? a->values[i] : PA_VOLUME_NORM, - i < b->channels ? b->values[i] : PA_VOLUME_NORM); - } + dest->channels = (uint8_t) i; - dest->channels = i; + return dest; +} + +pa_cvolume *pa_sw_cvolume_divide(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) { + unsigned i; + + pa_assert(dest); + pa_assert(a); + pa_assert(b); + + for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++) + dest->values[i] = pa_sw_volume_divide(a->values[i], b->values[i]); + + dest->channels = (uint8_t) i; return dest; } int pa_cvolume_valid(const pa_cvolume *v) { + unsigned c; + pa_assert(v); if (v->channels <= 0 || v->channels > PA_CHANNELS_MAX) return 0; + for (c = 0; c < v->channels; c++) + if (v->values[c] == (pa_volume_t) -1) + return 0; + return 1; } @@ -261,3 +351,17 @@ pa_cvolume *pa_cvolume_remap(pa_cvolume *v, pa_channel_map *from, pa_channel_map *v = result; return v; } + +int pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) { + + pa_assert(v); + pa_assert(ss); + + if (!pa_cvolume_valid(v)) + return 0; + + if (!pa_sample_spec_valid(ss)) + return 0; + + return v->channels == ss->channels; +} diff --git a/src/pulse/volume.h b/src/pulse/volume.h index 4fdbf658..75051af5 100644 --- a/src/pulse/volume.h +++ b/src/pulse/volume.h @@ -62,7 +62,7 @@ * * The functions described above are only valid when used with * software volumes. Hence it is usually a better idea to treat all - * volume values as opaque with a range from PA_VOLUME_MUTE (0%) to + * volume values as opaque with a range from PA_VOLUME_MUTED (0%) to * PA_VOLUME_NORM (100%) and to refrain from any calculations with * them. * @@ -116,6 +116,11 @@ typedef struct pa_cvolume { /** Return non-zero when *a == *b */ int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) PA_GCC_PURE; +/** Initialize the specified volume and return a pointer to + * it. The sample spec will have a defined state but + * pa_cvolume_valid() will fail for it. \since 0.9.13 */ +pa_cvolume* pa_cvolume_init(pa_cvolume *a); + /** Set the volume of all channels to PA_VOLUME_NORM */ #define pa_cvolume_reset(a, n) pa_cvolume_set((a), (n), PA_VOLUME_NORM) @@ -125,15 +130,32 @@ int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) PA_GCC_PURE; /** Set the volume of all channels to the specified parameter */ pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v); -/** Maximum length of the strings returned by pa_cvolume_snprint() */ -#define PA_CVOLUME_SNPRINT_MAX 64 +/** Maximum length of the strings returned by + * pa_cvolume_snprint(). Please note that this value can change with + * any release without warning and without being considered API or ABI + * breakage. You should not use this definition anywhere where it + * might become part of an ABI.*/ +#define PA_CVOLUME_SNPRINT_MAX 320 /** Pretty print a volume structure */ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c); +/** Maximum length of the strings returned by + * pa_cvolume_snprint_dB(). Please note that this value can change with + * any release without warning and without being considered API or ABI + * breakage. You should not use this definition anywhere where it + * might become part of an ABI. \since 0.9.13 */ +#define PA_SW_CVOLUME_SNPRINT_DB_MAX 448 + +/** Pretty print a volume structure but show dB values. \since 0.9.13 */ +char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c); + /** Return the average volume of all channels */ pa_volume_t pa_cvolume_avg(const pa_cvolume *a) PA_GCC_PURE; +/** Return the maximum volume of all channels. \since 0.9.12 */ +pa_volume_t pa_cvolume_max(const pa_cvolume *a) PA_GCC_PURE; + /** Return TRUE when the passed cvolume structure is valid, FALSE otherwise */ int pa_cvolume_valid(const pa_cvolume *v) PA_GCC_PURE; @@ -146,12 +168,25 @@ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) PA_GCC_PURE /** Return 1 if the specified volume has all channels on normal level */ #define pa_cvolume_is_norm(a) pa_cvolume_channels_equal_to((a), PA_VOLUME_NORM) -/** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. This is only valid for software volumes! */ +/** Multiply two volume specifications, return the result. This uses + * PA_VOLUME_NORM as neutral element of multiplication. This is only + * valid for software volumes! */ pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) PA_GCC_CONST; -/** Multiply to per-channel volumes and return the result in *dest. This is only valid for software volumes! */ +/** Multiply two per-channel volumes and return the result in + * *dest. This is only valid for software volumes! */ pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b); +/** Divide two volume specifications, return the result. This uses + * PA_VOLUME_NORM as neutral element of division. This is only valid + * for software volumes! If a division by zero is tried the result + * will be 0. \since 0.9.13 */ +pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) PA_GCC_CONST; + +/** Multiply to per-channel volumes and return the result in + * *dest. This is only valid for software volumes! \since 0.9.13 */ +pa_cvolume *pa_sw_cvolume_divide(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b); + /** Convert a decibel value to a volume. This is only valid for software volumes! */ pa_volume_t pa_sw_volume_from_dB(double f) PA_GCC_CONST; @@ -174,6 +209,10 @@ double pa_sw_volume_to_linear(pa_volume_t v) PA_GCC_CONST; /** Remap a volume from one channel mapping to a different channel mapping. \since 0.9.12 */ pa_cvolume *pa_cvolume_remap(pa_cvolume *v, pa_channel_map *from, pa_channel_map *to); +/** Return non-zero if the specified volume is compatible with + * the specified sample spec. \since 0.9.13 */ +int pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) PA_GCC_PURE; + PA_C_DECL_END #endif diff --git a/src/pulse/xmalloc.c b/src/pulse/xmalloc.c index 90237013..c570e40f 100644 --- a/src/pulse/xmalloc.c +++ b/src/pulse/xmalloc.c @@ -36,7 +36,7 @@ #include "xmalloc.h" /* Make sure not to allocate more than this much memory. */ -#define MAX_ALLOC_SIZE (1024*1024*20) /* 20MB */ +#define MAX_ALLOC_SIZE (1024*1024*96) /* 96MB */ /* #undef malloc */ /* #undef free */ @@ -46,7 +46,7 @@ static void oom(void) PA_GCC_NORETURN; -/** called in case of an OOM situation. Prints an error message and +/* called in case of an OOM situation. Prints an error message and * exits */ static void oom(void) { static const char e[] = "Not enough memory\n"; @@ -113,7 +113,7 @@ char *pa_xstrndup(const char *s, size_t l) { return NULL; if ((e = memchr(s, 0, l))) - return pa_xmemdup(s, e-s+1); + return pa_xmemdup(s, (size_t) (e-s+1)); r = pa_xmalloc(l+1); memcpy(r, s, l); diff --git a/src/pulse/xmalloc.h b/src/pulse/xmalloc.h index c453138b..b2643588 100644 --- a/src/pulse/xmalloc.h +++ b/src/pulse/xmalloc.h @@ -26,7 +26,9 @@ #include <stdlib.h> #include <limits.h> #include <assert.h> + #include <pulse/cdecl.h> +#include <pulse/gccmacro.h> /** \file * Memory allocation functions. @@ -35,52 +37,58 @@ PA_C_DECL_BEGIN /** Allocate the specified number of bytes, just like malloc() does. However, in case of OOM, terminate */ -void* pa_xmalloc(size_t l); +void* pa_xmalloc(size_t l) PA_GCC_MALLOC PA_GCC_ALLOC_SIZE(1); /** Same as pa_xmalloc(), but initialize allocated memory to 0 */ -void *pa_xmalloc0(size_t l); +void *pa_xmalloc0(size_t l) PA_GCC_MALLOC PA_GCC_ALLOC_SIZE(1); /** The combination of pa_xmalloc() and realloc() */ -void *pa_xrealloc(void *ptr, size_t size); +void *pa_xrealloc(void *ptr, size_t size) PA_GCC_ALLOC_SIZE(2); /** Free allocated memory */ void pa_xfree(void *p); /** Duplicate the specified string, allocating memory with pa_xmalloc() */ -char *pa_xstrdup(const char *s); +char *pa_xstrdup(const char *s) PA_GCC_MALLOC; /** Duplicate the specified string, but truncate after l characters */ -char *pa_xstrndup(const char *s, size_t l); +char *pa_xstrndup(const char *s, size_t l) PA_GCC_MALLOC; /** Duplicate the specified memory block */ -void* pa_xmemdup(const void *p, size_t l); +void* pa_xmemdup(const void *p, size_t l) PA_GCC_MALLOC PA_GCC_ALLOC_SIZE(2); /** Internal helper for pa_xnew() */ -static inline void* pa_xnew_internal(unsigned n, size_t k) { +static void* _pa_xnew_internal(size_t n, size_t k) PA_GCC_MALLOC PA_GCC_ALLOC_SIZE2(1,2); + +static inline void* _pa_xnew_internal(size_t n, size_t k) { assert(n < INT_MAX/k); return pa_xmalloc(n*k); } /** Allocate n new structures of the specified type. */ -#define pa_xnew(type, n) ((type*) pa_xnew_internal((n), sizeof(type))) +#define pa_xnew(type, n) ((type*) _pa_xnew_internal((n), sizeof(type))) /** Internal helper for pa_xnew0() */ -static inline void* pa_xnew0_internal(unsigned n, size_t k) { +static void* _pa_xnew0_internal(size_t n, size_t k) PA_GCC_MALLOC PA_GCC_ALLOC_SIZE2(1,2); + +static inline void* _pa_xnew0_internal(size_t n, size_t k) { assert(n < INT_MAX/k); return pa_xmalloc0(n*k); } /** Same as pa_xnew() but set the memory to zero */ -#define pa_xnew0(type, n) ((type*) pa_xnew0_internal((n), sizeof(type))) +#define pa_xnew0(type, n) ((type*) _pa_xnew0_internal((n), sizeof(type))) /** Internal helper for pa_xnew0() */ -static inline void* pa_xnewdup_internal(const void *p, unsigned n, size_t k) { +static void* _pa_xnewdup_internal(const void *p, size_t n, size_t k) PA_GCC_MALLOC PA_GCC_ALLOC_SIZE2(2,3); + +static inline void* _pa_xnewdup_internal(const void *p, size_t n, size_t k) { assert(n < INT_MAX/k); return pa_xmemdup(p, n*k); } /** Same as pa_xnew() but set the memory to zero */ -#define pa_xnewdup(type, p, n) ((type*) pa_xnewdup_internal((p), (n), sizeof(type))) +#define pa_xnewdup(type, p, n) ((type*) _pa_xnewdup_internal((p), (n), sizeof(type))) PA_C_DECL_END diff --git a/src/pulsecore/asyncq.c b/src/pulsecore/asyncq.c index 03e9f0df..f64931a5 100644 --- a/src/pulsecore/asyncq.c +++ b/src/pulsecore/asyncq.c @@ -71,7 +71,7 @@ PA_STATIC_FLIST_DECLARE(localq, 0, pa_xfree); #define PA_ASYNCQ_CELLS(x) ((pa_atomic_ptr_t*) ((uint8_t*) (x) + PA_ALIGN(sizeof(struct pa_asyncq)))) -static int reduce(pa_asyncq *l, int value) { +static unsigned reduce(pa_asyncq *l, unsigned value) { return value & (unsigned) (l->size - 1); } @@ -132,7 +132,7 @@ void pa_asyncq_free(pa_asyncq *l, pa_free_cb_t free_cb) { } static int push(pa_asyncq*l, void *p, pa_bool_t wait) { - int idx; + unsigned idx; pa_atomic_ptr_t *cells; pa_assert(l); @@ -220,7 +220,7 @@ void pa_asyncq_post(pa_asyncq*l, void *p) { } void* pa_asyncq_pop(pa_asyncq*l, pa_bool_t wait) { - int idx; + unsigned idx; void *ret; pa_atomic_ptr_t *cells; @@ -263,7 +263,7 @@ int pa_asyncq_read_fd(pa_asyncq *q) { } int pa_asyncq_read_before_poll(pa_asyncq *l) { - int idx; + unsigned idx; pa_atomic_ptr_t *cells; pa_assert(l); @@ -280,8 +280,6 @@ int pa_asyncq_read_before_poll(pa_asyncq *l) { if (pa_fdsem_before_poll(l->write_fdsem) >= 0) return 0; } - - return 0; } void pa_asyncq_read_after_poll(pa_asyncq *l) { diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h index a91c4d56..9c58c661 100644 --- a/src/pulsecore/atomic.h +++ b/src/pulsecore/atomic.h @@ -23,6 +23,8 @@ USA. ***/ +#include <pulsecore/macro.h> + /* * atomic_ops guarantees us that sizeof(AO_t) == sizeof(void*). It is * not guaranteed however, that sizeof(AO_t) == sizeof(size_t). @@ -35,7 +37,7 @@ * On gcc >= 4.1 we use the builtin atomic functions. otherwise we use * libatomic_ops */ -# + #ifndef PACKAGE #error "Please include config.h before including this file!" #endif @@ -80,8 +82,8 @@ static inline int pa_atomic_dec(pa_atomic_t *a) { return pa_atomic_sub(a, 1); } -/* Returns non-zero when the operation was successful. */ -static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { +/* Returns TRUE when the operation was successful. */ +static inline pa_bool_t pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { return __sync_bool_compare_and_swap(&a->value, old_i, new_i); } @@ -101,13 +103,13 @@ static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { __sync_synchronize(); } -static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { +static inline pa_bool_t pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { return __sync_bool_compare_and_swap(&a->value, (long) old_p, (long) new_p); } #elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__)) -#error "The native atomic operations implementation for AMD64 has not been tested. 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: make the native atomic operations implementation for AMD64 work, fix libatomic_ops, or upgrade your GCC." +#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." /* Addapted from glibc */ @@ -147,14 +149,14 @@ static inline int pa_atomic_dec(pa_atomic_t *a) { return pa_atomic_sub(a, 1); } -static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { +static inline pa_bool_t pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { int result; __asm__ __volatile__ ("lock; cmpxchgl %2, %1" : "=a" (result), "=m" (a->value) : "r" (new_i), "m" (a->value), "0" (old_i)); - return result == oldval; + return result == old_i; } typedef struct pa_atomic_ptr { @@ -171,14 +173,14 @@ static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { a->value = (unsigned long) p; } -static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { +static inline pa_bool_t pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { void *result; __asm__ __volatile__ ("lock; cmpxchgq %q2, %1" : "=a" (result), "=m" (a->value) : "r" (new_p), "m" (a->value), "0" (old_p)); - return result; + return result == old_p; } #elif defined(ATOMIC_ARM_INLINE_ASM) @@ -255,7 +257,7 @@ static inline int pa_atomic_dec(pa_atomic_t *a) { return pa_atomic_sub(a, 1); } -static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { +static inline pa_bool_t pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { unsigned long not_equal, not_exclusive; pa_memory_barrier(); @@ -289,7 +291,7 @@ static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { pa_memory_barrier(); } -static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { +static inline pa_bool_t pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { unsigned long not_equal, not_exclusive; pa_memory_barrier(); @@ -377,8 +379,8 @@ static inline int pa_atomic_dec(pa_atomic_t *a) { return pa_atomic_sub(a, 1); } -/* Returns non-zero when the operation was successful. */ -static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { +/* Returns TRUE when the operation was successful. */ +static inline pa_bool_t pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { pa_bool_t failed; do { failed = !!__kernel_cmpxchg(old_i, new_i, &a->value); @@ -402,7 +404,7 @@ static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { pa_memory_barrier(); } -static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { +static inline pa_bool_t pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { pa_bool_t failed; do { failed = !!__kernel_cmpxchg_u((unsigned long) old_p, (unsigned long) new_p, &a->value); @@ -420,7 +422,7 @@ typedef struct pa_atomic { volatile AO_t value; } pa_atomic_t; -#define PA_ATOMIC_INIT(v) { .value = (v) } +#define PA_ATOMIC_INIT(v) { .value = (AO_t) (v) } static inline int pa_atomic_load(const pa_atomic_t *a) { return (int) AO_load_full((AO_t*) &a->value); @@ -431,23 +433,23 @@ static inline void pa_atomic_store(pa_atomic_t *a, int i) { } static inline int pa_atomic_add(pa_atomic_t *a, int i) { - return AO_fetch_and_add_full(&a->value, (AO_t) i); + return (int) AO_fetch_and_add_full(&a->value, (AO_t) i); } static inline int pa_atomic_sub(pa_atomic_t *a, int i) { - return AO_fetch_and_add_full(&a->value, (AO_t) -i); + return (int) AO_fetch_and_add_full(&a->value, (AO_t) -i); } static inline int pa_atomic_inc(pa_atomic_t *a) { - return AO_fetch_and_add1_full(&a->value); + return (int) AO_fetch_and_add1_full(&a->value); } static inline int pa_atomic_dec(pa_atomic_t *a) { - return AO_fetch_and_sub1_full(&a->value); + return (int) AO_fetch_and_sub1_full(&a->value); } -static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { - return AO_compare_and_swap_full(&a->value, old_i, new_i); +static inline pa_bool_t pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { + return AO_compare_and_swap_full(&a->value, (unsigned long) old_i, (unsigned long) new_i); } typedef struct pa_atomic_ptr { @@ -464,7 +466,7 @@ static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { AO_store_full(&a->value, (AO_t) p); } -static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { +static inline pa_bool_t pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { return AO_compare_and_swap_full(&a->value, (AO_t) old_p, (AO_t) new_p); } diff --git a/src/pulsecore/authkey.c b/src/pulsecore/authkey.c index f3f40f80..b122feee 100644 --- a/src/pulsecore/authkey.c +++ b/src/pulsecore/authkey.c @@ -54,8 +54,8 @@ static int generate(int fd, void *ret_data, size_t length) { pa_random(ret_data, length); - lseek(fd, 0, SEEK_SET); - (void) ftruncate(fd, 0); + lseek(fd, (off_t) 0, SEEK_SET); + (void) ftruncate(fd, (off_t) 0); if ((r = pa_loop_write(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) { pa_log("Failed to write cookie file: %s", pa_cstrerror(errno)); @@ -88,7 +88,7 @@ static int load(const char *fn, void *data, size_t length) { if ((fd = open(fn, O_RDWR|O_CREAT|O_BINARY|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) { if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY|O_NOCTTY)) < 0) { - pa_log("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); + pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } else writable = 0; @@ -105,7 +105,7 @@ static int load(const char *fn, void *data, size_t length) { pa_log_debug("Got %d bytes from cookie file '%s', expected %d", (int) r, fn, (int) length); if (!writable) { - pa_log("Unable to write cookie to read only file"); + pa_log_warn("Unable to write cookie to read-only file"); goto finish; } @@ -140,7 +140,7 @@ int pa_authkey_load(const char *path, void *data, size_t length) { pa_assert(length > 0); if ((ret = load(path, data, length)) < 0) - pa_log("Failed to load authorization key '%s': %s", path, (ret < 0) ? pa_cstrerror(errno) : "File corrupt"); + pa_log_warn("Failed to load authorization key '%s': %s", path, (ret < 0) ? pa_cstrerror(errno) : "File corrupt"); return ret; } @@ -206,7 +206,7 @@ int pa_authkey_save(const char *fn, const void *data, size_t length) { return -2; if ((fd = open(p, O_RDWR|O_CREAT|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) { - pa_log("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); + pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } diff --git a/src/pulsecore/autoload.c b/src/pulsecore/autoload.c index 26c294b2..8c84cee5 100644 --- a/src/pulsecore/autoload.c +++ b/src/pulsecore/autoload.c @@ -158,7 +158,7 @@ void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type_t type) { e->in_action = 0; } -static void free_func(void *p, PA_GCC_UNUSED void *userdata) { +static void free_func(void *p, void *userdata) { pa_autoload_entry *e = p; pa_idxset_remove_by_data(e->core->autoload_idxset, e, NULL); entry_free(e); diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index a80933fa..b5ff98db 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -117,6 +117,10 @@ static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); /* A method table for all available commands */ @@ -167,6 +171,10 @@ static const struct command commands[] = { { "suspend-sink", pa_cli_command_suspend_sink, "Suspend sink (args: index|name, bool)", 3}, { "suspend-source", pa_cli_command_suspend_source, "Suspend source (args: index|name, bool)", 3}, { "suspend", pa_cli_command_suspend, "Suspend all sinks and all sources (args: bool)", 2}, + { "set-log-level", pa_cli_command_log_level, "Change the log level (args: numeric level)", 2}, + { "set-log-meta", pa_cli_command_log_meta, "Show source code location in log messages (args: bool)", 2}, + { "set-log-time", pa_cli_command_log_time, "Show timestamps in log messages (args: bool)", 2}, + { "set-log-backtrace", pa_cli_command_log_backtrace, "Show bakctrace in log messages (args: frames)", 2}, { NULL, NULL, NULL, 0 } }; @@ -318,22 +326,22 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n", (unsigned) pa_atomic_load(&stat->n_allocated), - pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->allocated_size))); + pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->allocated_size))); pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n", (unsigned) pa_atomic_load(&stat->n_accumulated), - pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->accumulated_size))); + pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->accumulated_size))); pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n", (unsigned) pa_atomic_load(&stat->n_imported), - pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->imported_size))); + pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->imported_size))); pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n", (unsigned) pa_atomic_load(&stat->n_exported), - pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->exported_size))); + pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->exported_size))); pa_strbuf_printf(buf, "Total sample cache size: %s.\n", - pa_bytes_snprint(s, sizeof(s), pa_scache_total_size(c))); + pa_bytes_snprint(s, sizeof(s), (unsigned) pa_scache_total_size(c))); pa_strbuf_printf(buf, "Default sample spec: %s\n", pa_sample_spec_snprint(s, sizeof(s), &c->default_sample_spec)); @@ -1203,6 +1211,102 @@ static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, p return 0; } +static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { + const char *m; + uint32_t level; + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + if (!(m = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a log level (0..4).\n"); + return -1; + } + + if (pa_atou(m, &level) < 0 || level >= PA_LOG_LEVEL_MAX) { + pa_strbuf_puts(buf, "Failed to parse log level.\n"); + return -1; + } + + pa_log_set_maximal_level(level); + + return 0; +} + +static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { + const char *m; + pa_bool_t b; + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + if (!(m = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a boolean.\n"); + return -1; + } + + if ((b = pa_parse_boolean(m)) < 0) { + pa_strbuf_puts(buf, "Failed to parse log meta switch.\n"); + return -1; + } + + pa_log_set_show_meta(b); + + return 0; +} + +static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { + const char *m; + pa_bool_t b; + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + if (!(m = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a boolean.\n"); + return -1; + } + + if ((b = pa_parse_boolean(m)) < 0) { + pa_strbuf_puts(buf, "Failed to parse log meta switch.\n"); + return -1; + } + + pa_log_set_show_time(b); + + return 0; +} + +static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { + const char *m; + uint32_t nframes; + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + if (!(m = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a backtrace level.\n"); + return -1; + } + + if (pa_atou(m, &nframes) < 0 || nframes >= 1000) { + pa_strbuf_puts(buf, "Failed to parse backtrace level.\n"); + return -1; + } + + pa_log_set_show_backtrace(nframes); + + return 0; +} + static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { pa_module *m; pa_sink *sink; @@ -1251,8 +1355,8 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b nl = 1; } - pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink))); - pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink))); + pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink, FALSE))); + pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink, FALSE))); pa_strbuf_printf(buf, "suspend-sink %s %s\n", sink->name, pa_yes_no(pa_sink_get_state(sink) == PA_SINK_SUSPENDED)); } @@ -1265,8 +1369,8 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b nl = 1; } - pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_avg(pa_source_get_volume(source))); - pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source))); + pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_avg(pa_source_get_volume(source, FALSE))); + pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source, FALSE))); pa_strbuf_printf(buf, "suspend-source %s %s\n", source->name, pa_yes_no(pa_source_get_state(source) == PA_SOURCE_SUSPENDED)); } diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index c92fca20..7bbc2660 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -149,10 +149,12 @@ char *pa_sink_list_to_string(pa_core *c) { sink->flags & PA_SINK_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "", sink->flags & PA_SINK_LATENCY ? "LATENCY " : "", state_table[pa_sink_get_state(sink)], - pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink)), - pa_yes_no(pa_sink_get_mute(sink)), - (double) pa_sink_get_latency(sink) / PA_USEC_PER_MSEC, - (double) pa_sink_get_requested_latency(sink) / PA_USEC_PER_MSEC, (double) min_latency / PA_USEC_PER_MSEC, (double) max_latency / PA_USEC_PER_MSEC, + pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, FALSE)), + pa_yes_no(pa_sink_get_mute(sink, FALSE)), + (double) pa_sink_get_latency(sink) / (double) PA_USEC_PER_MSEC, + (double) pa_sink_get_requested_latency(sink) / (double) PA_USEC_PER_MSEC, + (double) min_latency / PA_USEC_PER_MSEC, + (double) max_latency / PA_USEC_PER_MSEC, (unsigned long) pa_sink_get_max_request(sink) / 1024, (unsigned long) pa_sink_get_max_rewind(sink) / 1024, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX, @@ -222,10 +224,12 @@ char *pa_source_list_to_string(pa_core *c) { source->flags & PA_SOURCE_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "", source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "", state_table[pa_source_get_state(source)], - pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source)), - pa_yes_no(pa_source_get_mute(source)), + pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source, FALSE)), + pa_yes_no(pa_source_get_mute(source, FALSE)), (double) pa_source_get_latency(source) / PA_USEC_PER_MSEC, - (double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC, (double) min_latency / PA_USEC_PER_MSEC, (double) max_latency / PA_USEC_PER_MSEC, + (double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC, + (double) min_latency / PA_USEC_PER_MSEC, + (double) max_latency / PA_USEC_PER_MSEC, (unsigned long) pa_source_get_max_rewind(source) / 1024, pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map), @@ -411,7 +415,7 @@ char *pa_scache_list_to_string(pa_core *c) { if (e->memchunk.memblock) { pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec); pa_channel_map_snprint(cm, sizeof(cm), &e->channel_map); - l = (double) e->memchunk.length / pa_bytes_per_second(&e->sample_spec); + l = (double) e->memchunk.length / (double) pa_bytes_per_second(&e->sample_spec); } pa_strbuf_printf( diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c index 4aec45d7..ef6d6bb6 100644 --- a/src/pulsecore/conf-parser.c +++ b/src/pulsecore/conf-parser.c @@ -148,7 +148,7 @@ finish: return r; } -int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { int *i = data; int32_t k; @@ -166,7 +166,43 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, return 0; } -int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +int pa_config_parse_unsigned(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { + unsigned *u = data; + uint32_t k; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atou(rvalue, &k) < 0) { + pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); + return -1; + } + + *u = (unsigned) k; + return 0; +} + +int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { + size_t *i = data; + uint32_t k; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atou(rvalue, &k) < 0) { + pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); + return -1; + } + + *i = (size_t) k; + return 0; +} + +int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { int k; pa_bool_t *b = data; @@ -185,7 +221,7 @@ int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue return 0; } -int pa_config_parse_string(const char *filename, PA_GCC_UNUSED unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { char **s = data; pa_assert(filename); diff --git a/src/pulsecore/conf-parser.h b/src/pulsecore/conf-parser.h index 7eb1fae2..48a0fd26 100644 --- a/src/pulsecore/conf-parser.h +++ b/src/pulsecore/conf-parser.h @@ -39,8 +39,10 @@ typedef struct pa_config_item { * NULL */ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void *userdata); -/* Generic parsers for integers, booleans and strings */ +/* Generic parsers for integers, size_t, booleans and strings */ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); +int pa_config_parse_unsigned(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); +int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c index 75fa2ff1..1d080e11 100644 --- a/src/pulsecore/core-scache.c +++ b/src/pulsecore/core-scache.c @@ -63,7 +63,7 @@ #define UNLOAD_POLL_TIME 60 -static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { +static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, const struct timeval *tv, void *userdata) { pa_core *c = userdata; struct timeval ntv; @@ -98,7 +98,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { pa_assert(c); pa_assert(name); - if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) { + if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, FALSE))) { if (e->memchunk.memblock) pa_memblock_unref(e->memchunk.memblock); @@ -111,7 +111,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { } else { e = pa_xnew(pa_scache_entry, 1); - if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, 1)) { + if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, TRUE)) { pa_xfree(e); return NULL; } @@ -134,9 +134,9 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { e->lazy = FALSE; e->last_used_time = 0; - memset(&e->sample_spec, 0, sizeof(e->sample_spec)); + pa_sample_spec_init(&e->sample_spec); pa_channel_map_init(&e->channel_map); - pa_cvolume_reset(&e->volume, PA_CHANNELS_MAX); + pa_cvolume_init(&e->volume); pa_proplist_sets(e->proplist, PA_PROP_MEDIA_ROLE, "event"); @@ -159,10 +159,12 @@ int pa_scache_add_item( pa_assert(c); pa_assert(name); pa_assert(!ss || pa_sample_spec_valid(ss)); - pa_assert(!map || (pa_channel_map_valid(map) && ss && ss->channels == map->channels)); + pa_assert(!map || (pa_channel_map_valid(map) && ss && pa_channel_map_compatible(map, ss))); - if (ss && !map) + if (ss && !map) { pa_channel_map_init_extend(&tmap, ss->channels, PA_CHANNEL_MAP_DEFAULT); + map = &tmap; + } if (chunk && chunk->length > PA_SCACHE_ENTRY_SIZE_MAX) return -1; @@ -170,12 +172,13 @@ int pa_scache_add_item( if (!(e = scache_add_item(c, name))) return -1; - memset(&e->sample_spec, 0, sizeof(e->sample_spec)); + pa_sample_spec_init(&e->sample_spec); pa_channel_map_init(&e->channel_map); + pa_cvolume_init(&e->volume); if (ss) { e->sample_spec = *ss; - e->volume.channels = e->sample_spec.channels; + pa_cvolume_reset(&e->volume, ss->channels); } if (map) @@ -282,7 +285,7 @@ int pa_scache_remove_item(pa_core *c, const char *name) { return 0; } -static void free_cb(void *p, PA_GCC_UNUSED void *userdata) { +static void free_cb(void *p, void *userdata) { pa_scache_entry *e = p; pa_assert(e); @@ -310,17 +313,21 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t pa_assert(name); pa_assert(sink); - if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1))) + if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, FALSE))) return -1; if (e->lazy && !e->memchunk.memblock) { + pa_channel_map old_channel_map = e->channel_map; + if (pa_sound_file_load(c->mempool, e->filename, &e->sample_spec, &e->channel_map, &e->memchunk) < 0) return -1; pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); - if (e->volume.channels > e->sample_spec.channels) - e->volume.channels = e->sample_spec.channels; + if (pa_cvolume_valid(&e->volume)) + pa_cvolume_remap(&e->volume, &old_channel_map, &e->channel_map); + else + pa_cvolume_reset(&e->volume, e->sample_spec.channels); } if (!e->memchunk.memblock) @@ -383,7 +390,7 @@ uint32_t pa_scache_get_id_by_name(pa_core *c, const char *name) { pa_assert(c); pa_assert(name); - if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) + if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, FALSE))) return PA_IDXSET_INVALID; return e->index; diff --git a/src/pulsecore/core-subscribe.c b/src/pulsecore/core-subscribe.c index 6107002b..c70d8adc 100644 --- a/src/pulsecore/core-subscribe.c +++ b/src/pulsecore/core-subscribe.c @@ -42,7 +42,7 @@ struct pa_subscription { pa_core *core; - int dead; + pa_bool_t dead; pa_subscription_cb_t callback; void *userdata; @@ -72,7 +72,7 @@ pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, pa_su s = pa_xnew(pa_subscription, 1); s->core = c; - s->dead = 0; + s->dead = FALSE; s->callback = callback; s->userdata = userdata; s->mask = m; @@ -86,7 +86,7 @@ void pa_subscription_free(pa_subscription*s) { pa_assert(s); pa_assert(!s->dead); - s->dead = 1; + s->dead = TRUE; sched_event(s->core); } @@ -145,7 +145,7 @@ static void dump_event(const char * prefix, pa_subscription_event*e) { [PA_SUBSCRIPTION_EVENT_REMOVE] = "REMOVE" }; - pa_log("%s event (%s|%s|%u)", + pa_log_debug("%s event (%s|%s|%u)", prefix, fac_table[e->type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK], type_table[e->type & PA_SUBSCRIPTION_EVENT_TYPE_MASK], @@ -234,7 +234,7 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i * entry in the queue. */ free_event(i); - pa_log_debug("dropped redundant event."); + pa_log_debug("Dropped redundant event due to remove event."); continue; } @@ -242,7 +242,7 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i /* This object has changed. If a "new" or "change" event for * this object is still in the queue we can exit. */ - pa_log_debug("dropped redundant event."); + pa_log_debug("Dropped redundant event due to change event."); return; } } diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index b2c91e45..dde34d7b 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -40,6 +40,9 @@ #include <sys/stat.h> #include <sys/time.h> #include <dirent.h> +#include <regex.h> +#include <langinfo.h> +#include <sys/utsname.h> #ifdef HAVE_STRTOF_L #include <locale.h> @@ -111,6 +114,8 @@ int pa_set_root(HANDLE handle) { strcpy(library_path, PULSE_ROOTENV "="); + /* FIXME: Needs to set errno */ + if (!GetModuleFileName(handle, library_path + sizeof(PULSE_ROOTENV), MAX_PATH)) return 0; @@ -168,7 +173,7 @@ void pa_make_fd_cloexec(int fd) { /** Creates a directory securely */ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) { struct stat st; - int r; + int r, saved_errno; pa_assert(dir); @@ -220,7 +225,10 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) { return 0; fail: + saved_errno = errno; rmdir(dir); + errno = saved_errno; + return -1; } @@ -230,6 +238,7 @@ char *pa_parent_dir(const char *fn) { if ((slash = (char*) pa_path_get_filename(dir)) == dir) { pa_xfree(dir); + errno = ENOENT; return NULL; } @@ -337,7 +346,7 @@ ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) { ret += r; data = (uint8_t*) data + r; - size -= r; + size -= (size_t) r; } return ret; @@ -368,7 +377,7 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) { ret += r; data = (const uint8_t*) data + r; - size -= r; + size -= (size_t) r; } return ret; @@ -390,7 +399,15 @@ int pa_close(int fd) { } #endif - return close(fd); + for (;;) { + int r; + + if ((r = close(fd)) >= 0) + return r; + + if (errno != EINTR) + return r; + } } /* Print a warning messages in case that the given signal is not @@ -437,7 +454,7 @@ void pa_check_signal_is_blocked(int sig) { /* The following function is based on an example from the GNU libc * documentation. This function is similar to GNU's asprintf(). */ char *pa_sprintf_malloc(const char *format, ...) { - int size = 100; + size_t size = 100; char *c = NULL; pa_assert(format); @@ -454,11 +471,11 @@ char *pa_sprintf_malloc(const char *format, ...) { c[size-1] = 0; - if (r > -1 && r < size) + if (r > -1 && (size_t) r < size) return c; if (r > -1) /* glibc 2.1 */ - size = r+1; + size = (size_t) r+1; else /* glibc 2.0 */ size *= 2; } @@ -467,7 +484,7 @@ char *pa_sprintf_malloc(const char *format, ...) { /* Same as the previous function, but use a va_list instead of an * ellipsis */ char *pa_vsprintf_malloc(const char *format, va_list ap) { - int size = 100; + size_t size = 100; char *c = NULL; pa_assert(format); @@ -484,11 +501,11 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) { c[size-1] = 0; - if (r > -1 && r < size) + if (r > -1 && (size_t) r < size) return c; if (r > -1) /* glibc 2.1 */ - size = r+1; + size = (size_t) r+1; else /* glibc 2.0 */ size *= 2; } @@ -546,6 +563,8 @@ int pa_make_realtime(int rtprio) { pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i.", sp.sched_priority); return 0; #else + + errno = ENOTSUP; return -1; #endif } @@ -653,6 +672,7 @@ int pa_raise_priority(int nice_level) { if (nice_level < 0) { if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) { pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError()); + errno = EPERM; return .-1; } else pa_log_info("Successfully gained high priority class."); @@ -679,15 +699,55 @@ void pa_reset_priority(void) { #endif } +static int match(const char *expr, const char *v) { + int k; + regex_t re; + int r; + + if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) { + errno = EINVAL; + return -1; + } + + if ((k = regexec(&re, v, 0, NULL, 0)) == 0) + r = 1; + else if (k == REG_NOMATCH) + r = 0; + else + r = -1; + + regfree(&re); + + if (r < 0) + errno = EINVAL; + + return r; +} + /* Try to parse a boolean string value.*/ int pa_parse_boolean(const char *v) { + const char *expr; + int r; pa_assert(v); + /* First we check language independant */ if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on")) return 1; else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off")) return 0; + /* And then we check language dependant */ + if ((expr = nl_langinfo(YESEXPR))) + if (expr[0]) + if ((r = match(expr, v)) > 0) + return 1; + + if ((expr = nl_langinfo(NOEXPR))) + if (expr[0]) + if ((r = match(expr, v)) > 0) + return 0; + + errno = EINVAL; return -1; } @@ -875,11 +935,18 @@ static int is_group(gid_t gid, const char *name) { #else n = -1; #endif - if (n < 0) n = 512; - data = pa_xmalloc(n); + if (n < 0) + n = 512; + + data = pa_xmalloc((size_t) n); + + errno = 0; + if (getgrgid_r(gid, &group, data, (size_t) n, &result) < 0 || !result) { + pa_log("getgrgid_r(%u): %s", (unsigned) gid, pa_cstrerror(errno)); + + if (!errno) + errno = ENOENT; - if (getgrgid_r(gid, &group, data, n, &result) < 0 || !result) { - pa_log("getgrgid_r(%u): %s", (unsigned)gid, pa_cstrerror(errno)); goto finish; } @@ -890,8 +957,14 @@ finish: #else /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not * support getgrgid_r. */ + + errno = 0; if ((result = getgrgid(gid)) == NULL) { pa_log("getgrgid(%u): %s", gid, pa_cstrerror(errno)); + + if (!errno) + errno = ENOENT; + goto finish; } @@ -906,27 +979,32 @@ finish: /* Check the current user is member of the specified group */ int pa_own_uid_in_group(const char *name, gid_t *gid) { GETGROUPS_T *gids, tgid; - int n = sysconf(_SC_NGROUPS_MAX); - int r = -1, i; + long n = sysconf(_SC_NGROUPS_MAX); + int r = -1, i, k; pa_assert(n > 0); - gids = pa_xmalloc(sizeof(GETGROUPS_T)*n); + gids = pa_xmalloc(sizeof(GETGROUPS_T) * (size_t) n); - if ((n = getgroups(n, gids)) < 0) { + if ((n = getgroups((int) n, gids)) < 0) { pa_log("getgroups(): %s", pa_cstrerror(errno)); goto finish; } for (i = 0; i < n; i++) { - if (is_group(gids[i], name) > 0) { + + if ((k = is_group(gids[i], name)) < 0) + goto finish; + else if (k > 0) { *gid = gids[i]; r = 1; goto finish; } } - if (is_group(tgid = getgid(), name) > 0) { + if ((k = is_group(tgid = getgid(), name)) < 0) + goto finish; + else if (k > 0) { *gid = tgid; r = 1; goto finish; @@ -949,18 +1027,25 @@ int pa_uid_in_group(uid_t uid, const char *name) { int r = -1; g_n = sysconf(_SC_GETGR_R_SIZE_MAX); - g_buf = pa_xmalloc(g_n); + g_buf = pa_xmalloc((size_t) g_n); p_n = sysconf(_SC_GETPW_R_SIZE_MAX); - p_buf = pa_xmalloc(p_n); + p_buf = pa_xmalloc((size_t) p_n); + + errno = 0; + if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) { + + if (!errno) + errno = ENOENT; - if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) goto finish; + } r = 0; for (i = gr->gr_mem; *i; i++) { struct passwd pwbuf, *pw; + errno = 0; if (getpwnam_r(*i, &pwbuf, p_buf, (size_t) p_n, &pw) != 0 || !pw) continue; @@ -985,10 +1070,16 @@ gid_t pa_get_gid_of_group(const char *name) { struct group grbuf, *gr; g_n = sysconf(_SC_GETGR_R_SIZE_MAX); - g_buf = pa_xmalloc(g_n); + g_buf = pa_xmalloc((size_t) g_n); + + errno = 0; + if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) { + + if (!errno) + errno = ENOENT; - if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) goto finish; + } ret = gr->gr_gid; @@ -1014,19 +1105,23 @@ int pa_check_in_group(gid_t g) { #else /* HAVE_GRP_H */ int pa_own_uid_in_group(const char *name, gid_t *gid) { + errno = ENOSUP; return -1; } int pa_uid_in_group(uid_t uid, const char *name) { + errno = ENOSUP; return -1; } gid_t pa_get_gid_of_group(const char *name) { + errno = ENOSUP; return (gid_t) -1; } int pa_check_in_group(gid_t g) { + errno = ENOSUP; return -1; } @@ -1040,7 +1135,7 @@ int pa_lock_fd(int fd, int b) { /* Try a R/W lock first */ - flock.l_type = b ? F_WRLCK : F_UNLCK; + flock.l_type = (short) (b ? F_WRLCK : F_UNLCK); flock.l_whence = SEEK_SET; flock.l_start = 0; flock.l_len = 0; @@ -1067,6 +1162,8 @@ int pa_lock_fd(int fd, int b) { return 0; pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError()); + + /* FIXME: Needs to set errno! */ #endif return -1; @@ -1133,8 +1230,11 @@ int pa_lock_lockfile(const char *fn) { fail: - if (fd >= 0) + if (fd >= 0) { + int saved_errno = errno; pa_close(fd); + errno = saved_errno; + } return -1; } @@ -1180,6 +1280,7 @@ static char *get_pulse_home(void) { if (st.st_uid != getuid()) { pa_log_error("Home directory %s not ours.", h); + errno = EACCES; return NULL; } @@ -1199,7 +1300,7 @@ char *pa_get_state_dir(void) { /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same * dir then this will break. */ - if (pa_make_secure_dir(d, 0700, (pid_t) -1, (pid_t) -1) < 0) { + if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) { pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno)); pa_xfree(d); return NULL; @@ -1214,31 +1315,43 @@ static char* make_random_dir(mode_t m) { "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; - char fn[24] = "/tmp/pulse-"; + const char *tmpdir; + char *fn; + size_t pathlen; + + if (!(tmpdir = getenv("TMPDIR"))) + if (!(tmpdir = getenv("TMP"))) + if (!(tmpdir = getenv("TEMP"))) + tmpdir = getenv("TEMPDIR"); + + if (!tmpdir || !pa_is_path_absolute(tmpdir)) + tmpdir = "/tmp"; - fn[sizeof(fn)-1] = 0; + fn = pa_sprintf_malloc("%s/pulse-XXXXXXXXXXXX", tmpdir); + pathlen = strlen(fn); for (;;) { - unsigned i; + size_t i; int r; mode_t u; int saved_errno; - for (i = 11; i < sizeof(fn)-1; i++) + for (i = pathlen - 12; i < pathlen; i++) fn[i] = table[rand() % (sizeof(table)-1)]; u = umask((~m) & 0777); r = mkdir(fn, m); + saved_errno = errno; umask(u); + errno = saved_errno; if (r >= 0) - return pa_xstrdup(fn); - - errno = saved_errno; + return fn; if (errno != EEXIST) { pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno)); + pa_xfree(fn); return NULL; } } @@ -1269,6 +1382,7 @@ static int make_random_dir_and_link(mode_t m, const char *k) { char *pa_get_runtime_dir(void) { char *d, *k = NULL, *p = NULL, *t = NULL, *mid; struct stat st; + mode_t m; /* The runtime directory shall contain dynamic data that needs NOT * to be kept accross reboots and is usuallly private to the user, @@ -1277,12 +1391,11 @@ char *pa_get_runtime_dir(void) { * this directory, we link it to a random subdir in /tmp, if it * was not explicitly configured. */ - if ((d = getenv("PULSE_RUNTIME_PATH"))) { - mode_t m; + m = pa_in_system_mode() ? 0755U : 0700U; - m = pa_in_system_mode() ? 0755 : 0700; + if ((d = getenv("PULSE_RUNTIME_PATH"))) { - if (pa_make_secure_dir(d, m, (pid_t) -1, (pid_t) -1) < 0) { + if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) { pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno)); goto fail; } @@ -1293,6 +1406,11 @@ char *pa_get_runtime_dir(void) { if (!(d = get_pulse_home())) goto fail; + if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) { + pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno)); + goto fail; + } + if (!(mid = pa_machine_id())) { pa_xfree(d); goto fail; @@ -1332,6 +1450,7 @@ char *pa_get_runtime_dir(void) { /* Make sure that this actually makes sense */ if (!pa_is_path_absolute(p)) { pa_log_error("Path %s in link %s is not absolute.", p, k); + errno = ENOENT; goto fail; } @@ -1423,6 +1542,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env #ifdef OS_IS_WIN32 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX)) + /* FIXME: Needs to set errno! */ return NULL; fn = buf; #endif @@ -1453,6 +1573,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env #ifdef OS_IS_WIN32 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) { + /* FIXME: Needs to set errno! */ pa_xfree(lfn); return NULL; } @@ -1481,6 +1602,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env #ifdef OS_IS_WIN32 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX)) + /* FIXME: Needs to set errno! */ return NULL; global = buf; #endif @@ -1492,9 +1614,9 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env return f; } - } else - errno = ENOENT; + } + errno = ENOENT; return NULL; } @@ -1511,6 +1633,7 @@ char *pa_find_config_file(const char *global, const char *local, const char *env #ifdef OS_IS_WIN32 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX)) + /* FIXME: Needs to set errno! */ return NULL; fn = buf; #endif @@ -1536,6 +1659,7 @@ char *pa_find_config_file(const char *global, const char *local, const char *env #ifdef OS_IS_WIN32 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) { + /* FIXME: Needs to set errno! */ pa_xfree(lfn); return NULL; } @@ -1560,14 +1684,16 @@ char *pa_find_config_file(const char *global, const char *local, const char *env if (global) { #ifdef OS_IS_WIN32 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX)) + /* FIXME: Needs to set errno! */ return NULL; global = buf; #endif if (access(global, R_OK) == 0) return pa_xstrdup(global); - } else - errno = ENOENT; + } + + errno = ENOENT; return NULL; } @@ -1604,6 +1730,7 @@ static int hexc(char c) { if (c >= 'a' && c <= 'f') return c - 'a' + 10; + errno = EINVAL; return -1; } @@ -1742,11 +1869,16 @@ int pa_atoi(const char *s, int32_t *ret_i) { errno = 0; l = strtol(s, &x, 0); - if (!x || *x || errno != 0) + if (!x || *x || errno) { + if (!errno) + errno = EINVAL; return -1; + } - if ((int32_t) l != l) + if ((int32_t) l != l) { + errno = ERANGE; return -1; + } *ret_i = (int32_t) l; @@ -1764,11 +1896,16 @@ int pa_atou(const char *s, uint32_t *ret_u) { errno = 0; l = strtoul(s, &x, 0); - if (!x || *x || errno != 0) + if (!x || *x || errno) { + if (!errno) + errno = EINVAL; return -1; + } - if ((uint32_t) l != l) + if ((uint32_t) l != l) { + errno = ERANGE; return -1; + } *ret_u = (uint32_t) l; @@ -1786,7 +1923,6 @@ static void c_locale_destroy(void) { int pa_atod(const char *s, double *ret_d) { char *x = NULL; double f; - int r = 0; pa_assert(s); pa_assert(ret_d); @@ -1812,17 +1948,20 @@ int pa_atod(const char *s, double *ret_d) { f = strtod(s, &x); } - if (!x || *x || errno != 0) - r = -1; - else - *ret_d = f; + if (!x || *x || errno) { + if (!errno) + errno = EINVAL; + return -1; + } - return r; + *ret_d = f; + + return 0; } /* Same as snprintf, but guarantees NUL-termination on every platform */ -int pa_snprintf(char *str, size_t size, const char *format, ...) { - int ret; +size_t pa_snprintf(char *str, size_t size, const char *format, ...) { + size_t ret; va_list ap; pa_assert(str); @@ -1837,7 +1976,7 @@ int pa_snprintf(char *str, size_t size, const char *format, ...) { } /* Same as vsnprintf, but guarantees NUL-termination on every platform */ -int pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) { +size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) { int ret; pa_assert(str); @@ -1849,9 +1988,12 @@ int pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) { str[size-1] = 0; if (ret < 0) - ret = strlen(str); + return strlen(str); - return PA_MIN((int) size-1, ret); + if ((size_t) ret > size-1) + return size-1; + + return (size_t) ret; } /* Truncate the specified string, but guarantee that the string @@ -1875,7 +2017,7 @@ char *pa_getcwd(void) { size_t l = 128; for (;;) { - char *p = pa_xnew(char, l); + char *p = pa_xmalloc(l); if (getcwd(p, l)) return p; @@ -1900,7 +2042,7 @@ void *pa_will_need(const void *p, size_t l) { pa_assert(l > 0); a = PA_PAGE_ALIGN_PTR(p); - size = (const uint8_t*) p + l - (const uint8_t*) a; + size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a); #ifdef HAVE_POSIX_MADVISE if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) { @@ -1921,10 +2063,11 @@ void *pa_will_need(const void *p, size_t l) { if (rlim.rlim_cur < PA_PAGE_SIZE) { pa_log_debug("posix_madvise() failed (or doesn't exist), resource limits don't allow mlock(), can't page in data: %s", pa_cstrerror(r)); + errno = EPERM; return (void*) p; } - bs = PA_PAGE_ALIGN(rlim.rlim_cur); + bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur); #else bs = PA_PAGE_SIZE*4; #endif @@ -1976,7 +2119,7 @@ char *pa_readlink(const char *p) { char *c; ssize_t n; - c = pa_xnew(char, l); + c = pa_xmalloc(l); if ((n = readlink(p, c, l-1)) < 0) { pa_xfree(c); @@ -1995,8 +2138,8 @@ char *pa_readlink(const char *p) { int pa_close_all(int except_fd, ...) { va_list ap; - int n = 0, i, r; - int *p; + unsigned n = 0, i; + int r, *p; va_start(ap, except_fd); @@ -2123,8 +2266,8 @@ int pa_close_allv(const int except_fds[]) { int pa_unblock_sigs(int except, ...) { va_list ap; - int n = 0, i, r; - int *p; + unsigned n = 0, i; + int r, *p; va_start(ap, except); @@ -2172,8 +2315,8 @@ int pa_unblock_sigsv(const int except[]) { int pa_reset_sigs(int except, ...) { va_list ap; - int n = 0, i, r; - int *p; + unsigned n = 0, i; + int *p, r; va_start(ap, except); @@ -2208,7 +2351,7 @@ int pa_reset_sigs(int except, ...) { int pa_reset_sigsv(const int except[]) { int sig; - for (sig = 1; sig < _NSIG; sig++) { + for (sig = 1; sig < NSIG; sig++) { pa_bool_t reset = TRUE; switch (sig) { @@ -2266,36 +2409,48 @@ char *pa_machine_id(void) { FILE *f; size_t l; + /* The returned value is supposed be some kind of ascii identifier + * that is unique and stable across reboots. */ + + /* First we try the D-Bus UUID, which is the best option we have, + * since it fits perfectly our needs and is not as volatile as the + * hostname which might be set from dhcp. */ + if ((f = fopen(PA_MACHINE_ID, "r"))) { char ln[34] = "", *r; r = fgets(ln, sizeof(ln)-1, f); fclose(f); - if (r) - return pa_xstrdup(pa_strip_nl(ln)); + pa_strip_nl(ln); + + if (ln[0]) + return pa_xstrdup(ln); } - l = 100; + /* The we fall back to the host name. It supposed to be somewhat + * unique, at least in a network, but may change. */ + l = 100; for (;;) { char *c; - c = pa_xnew(char, l); + c = pa_xmalloc(l); if (!pa_get_host_name(c, l)) { - if (errno == EINVAL || errno == ENAMETOOLONG) { + if (errno != EINVAL && errno != ENAMETOOLONG) + break; + + } else if (strlen(c) < l-1) { + + if (*c == 0) { pa_xfree(c); - l *= 2; - continue; + break; } - return NULL; - } - - if (strlen(c) < l-1) return c; + } /* Hmm, the hostname is as long the space we offered the * function, we cannot know if it fully fit in, so let's play @@ -2304,4 +2459,31 @@ char *pa_machine_id(void) { pa_xfree(c); l *= 2; } + + /* If no hostname was set we use the POSIX hostid. It's usually + * the IPv4 address. Mit not be that stable. */ + return pa_sprintf_malloc("%08lx", (unsigned long) gethostid); +} + +char *pa_uname_string(void) { + struct utsname u; + + pa_assert_se(uname(&u) == 0); + + return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version); } + +#ifdef HAVE_VALGRIND_MEMCHECK_H +pa_bool_t pa_in_valgrind(void) { + static int b = 0; + + /* To make heisenbugs a bit simpler to find we check for $VALGRIND + * here instead of really checking whether we run in valgrind or + * not. */ + + if (b < 1) + b = getenv("VALGRIND") ? 2 : 1; + + return b > 1; +} +#endif diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 838e4ad3..fd6ee896 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -35,6 +35,10 @@ #include <pulse/gccmacro.h> #include <pulsecore/macro.h> +#ifndef PACKAGE +#error "Please include config.h before including this file!" +#endif + struct timeval; /* These resource limits are pretty new on Linux, let's define them @@ -127,8 +131,8 @@ int pa_atoi(const char *s, int32_t *ret_i); int pa_atou(const char *s, uint32_t *ret_u); int pa_atod(const char *s, double *ret_d); -int pa_snprintf(char *str, size_t size, const char *format, ...); -int pa_vsnprintf(char *str, size_t size, const char *format, va_list ap); +size_t pa_snprintf(char *str, size_t size, const char *format, ...); +size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap); char *pa_truncate_utf8(char *c, size_t l); @@ -142,29 +146,35 @@ static inline int pa_is_power_of_two(unsigned n) { return !(n & (n - 1)); } -static inline unsigned pa_make_power_of_two(unsigned n) { - unsigned j = n; +static inline unsigned pa_ulog2(unsigned n) { - if (pa_is_power_of_two(n)) - return n; + if (n <= 1) + return 0; - while (j) { - j = j >> 1; - n = n | j; - } +#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + return 8U * (unsigned) sizeof(unsigned) - (unsigned) __builtin_clz(n) - 1; +#else +{ + unsigned r = 0; - return n + 1; -} + for (;;) { + n = n >> 1; -static inline unsigned pa_ulog2(unsigned n) { - unsigned r = 0; + if (!n) + return r; - while (n) { r++; - n = n >> 1; } +} +#endif +} + +static inline unsigned pa_make_power_of_two(unsigned n) { + + if (pa_is_power_of_two(n)) + return n; - return r; + return 1U << (pa_ulog2(n) + 1); } void pa_close_pipe(int fds[2]); @@ -185,5 +195,15 @@ pa_bool_t pa_in_system_mode(void); #define pa_streq(a,b) (!strcmp((a),(b))) char *pa_machine_id(void); +char *pa_uname_string(void); + + +#ifdef HAVE_VALGRIND_MEMCHECK_H +pa_bool_t pa_in_valgrind(void); +#else +static inline pa_bool_t pa_in_valgrind(void) { + return FALSE; +} +#endif #endif diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 5c594b02..5761bbc7 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -66,7 +66,7 @@ static int core_process_msg(pa_msgobject *o, int code, void *userdata, int64_t o static void core_free(pa_object *o); -pa_core* pa_core_new(pa_mainloop_api *m, int shared) { +pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size) { pa_core* c; pa_mempool *pool; int j; @@ -74,14 +74,14 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { pa_assert(m); if (shared) { - if (!(pool = pa_mempool_new(shared))) { + if (!(pool = pa_mempool_new(shared, shm_size))) { pa_log_warn("failed to allocate shared memory pool. Falling back to a normal memory pool."); - shared = 0; + shared = FALSE; } } if (!shared) { - if (!(pool = pa_mempool_new(shared))) { + if (!(pool = pa_mempool_new(shared, shm_size))) { pa_log("pa_mempool_new() failed."); return NULL; } @@ -138,6 +138,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { c->realtime_scheduling = FALSE; c->realtime_priority = 5; c->disable_remixing = FALSE; + c->disable_lfe_remixing = FALSE; for (j = 0; j < PA_CORE_HOOK_MAX; j++) pa_hook_init(&c->hooks[j], c); @@ -200,10 +201,11 @@ static void core_free(pa_object *o) { pa_xfree(c); } -static void exit_callback(pa_mainloop_api*m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { +static void exit_callback(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { pa_core *c = userdata; pa_assert(c->exit_event == e); + pa_log_info("We are idle, quitting..."); pa_core_exit(c, TRUE, 0); } diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index eb768418..f796fb93 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -49,6 +49,7 @@ typedef enum pa_core_hook { PA_CORE_HOOK_SINK_UNLINK_POST, PA_CORE_HOOK_SINK_STATE_CHANGED, PA_CORE_HOOK_SINK_PROPLIST_CHANGED, + PA_CORE_HOOK_SINK_SET_VOLUME, PA_CORE_HOOK_SOURCE_NEW, PA_CORE_HOOK_SOURCE_FIXATE, PA_CORE_HOOK_SOURCE_PUT, @@ -65,6 +66,7 @@ typedef enum pa_core_hook { PA_CORE_HOOK_SINK_INPUT_MOVE_POST, PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED, PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED, + PA_CORE_HOOK_SINK_INPUT_SET_VOLUME, PA_CORE_HOOK_SOURCE_OUTPUT_NEW, PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE, PA_CORE_HOOK_SOURCE_OUTPUT_PUT, @@ -124,6 +126,7 @@ struct pa_core { pa_bool_t running_as_daemon:1; pa_bool_t realtime_scheduling:1; pa_bool_t disable_remixing:1; + pa_bool_t disable_lfe_remixing:1; pa_resample_method_t resample_method; int realtime_priority; @@ -140,7 +143,7 @@ enum { PA_CORE_MESSAGE_MAX }; -pa_core* pa_core_new(pa_mainloop_api *m, int shared); +pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size); /* Check whether noone is connected to this core */ void pa_core_check_idle(pa_core *c); diff --git a/src/pulsecore/endianmacros.h b/src/pulsecore/endianmacros.h index 26336918..1b94de17 100644 --- a/src/pulsecore/endianmacros.h +++ b/src/pulsecore/endianmacros.h @@ -46,9 +46,14 @@ #endif static inline float PA_FLOAT32_SWAP(float x) { - uint32_t i = *(uint32_t*) &x; - i = PA_UINT32_SWAP(i); - return *(float*) &i; + union { + float f; + uint32_t u; + } t; + + t.f = x; + t.u = PA_UINT32_SWAP(t.u); + return t.f; } #define PA_MAYBE_INT16_SWAP(c,x) ((c) ? PA_INT32_SWAP(x) : x) diff --git a/src/pulsecore/envelope.c b/src/pulsecore/envelope.c index e2691611..7f2252e9 100644 --- a/src/pulsecore/envelope.c +++ b/src/pulsecore/envelope.c @@ -153,11 +153,11 @@ void pa_envelope_free(pa_envelope *e) { } static int32_t linear_interpolate_int(pa_usec_t x1, int32_t _y1, pa_usec_t x2, int32_t y2, pa_usec_t x3) { - return (int32_t) (_y1 + (x3 - x1) * (float) (y2 - _y1) / (float) (x2 - x1)); + return (int32_t) ((double) _y1 + (double) (x3 - x1) * (double) (y2 - _y1) / (double) (x2 - x1)); } static float linear_interpolate_float(pa_usec_t x1, float _y1, pa_usec_t x2, float y2, pa_usec_t x3) { - return _y1 + (x3 - x1) * (y2 - _y1) / (x2 - x1); + return _y1 + ((float) x3 - (float) x1) * (y2 - _y1) / ((float) x2 - (float) x1); } static int32_t item_get_int(pa_envelope_item *i, pa_usec_t x) { @@ -573,11 +573,11 @@ static float linear_get_float(pa_envelope *e, int v) { if (!e->points[v].cached_valid) { e->points[v].cached_dy_dx = (e->points[v].y.f[e->points[v].n_current+1] - e->points[v].y.f[e->points[v].n_current]) / - (e->points[v].x[e->points[v].n_current+1] - e->points[v].x[e->points[v].n_current]); + ((float) e->points[v].x[e->points[v].n_current+1] - (float) e->points[v].x[e->points[v].n_current]); e->points[v].cached_valid = TRUE; } - return e->points[v].y.f[e->points[v].n_current] + (e->x - e->points[v].x[e->points[v].n_current]) * e->points[v].cached_dy_dx; + return e->points[v].y.f[e->points[v].n_current] + (float) (e->x - e->points[v].x[e->points[v].n_current]) * e->points[v].cached_dy_dx; } void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) { @@ -605,7 +605,7 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) { uint8_t *t; for (t = p; n > 0; n -= fs) { - int16_t factor = linear_get_int(e, v); + int32_t factor = linear_get_int(e, v); unsigned c; e->x += fs; @@ -620,13 +620,13 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) { uint8_t *t; for (t = p; n > 0; n -= fs) { - int16_t factor = linear_get_int(e, v); + 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(((factor * k) / 0x10000) >> 2); + *t = (uint8_t) st_14linear2ulaw((int16_t) (((factor * k) / 0x10000) >> 2)); } } @@ -637,13 +637,13 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) { uint8_t *t; for (t = p; n > 0; n -= fs) { - int16_t factor = linear_get_int(e, v); + 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(((factor * k) / 0x10000) >> 3); + *t = (uint8_t) st_13linear2alaw((int16_t) (((factor * k) / 0x10000) >> 3)); } } @@ -659,7 +659,7 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) { e->x += fs; for (c = 0; c < e->sample_spec.channels; c++, t++) - *t = (factor * *t) / 0x10000; + *t = (int16_t) ((factor * *t) / 0x10000); } break; @@ -674,7 +674,7 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) { e->x += fs; for (c = 0; c < e->sample_spec.channels; c++, t++) { - int16_t r = (factor * PA_INT16_SWAP(*t)) / 0x10000; + int16_t r = (int16_t) ((factor * PA_INT16_SWAP(*t)) / 0x10000); *t = PA_INT16_SWAP(r); } } diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c index 1531e3db..380f34f5 100644 --- a/src/pulsecore/fdsem.c +++ b/src/pulsecore/fdsem.c @@ -41,39 +41,15 @@ #include <pulsecore/pipe.h> #endif -#ifdef __linux__ - -#if !defined(__NR_eventfd) && defined(__i386__) -#define __NR_eventfd 323 -#endif - -#if !defined(__NR_eventfd) && defined(__x86_64__) -#define __NR_eventfd 284 -#endif - -#if !defined(__NR_eventfd) && defined(__arm__) -#define __NR_eventfd (__NR_SYSCALL_BASE+351) -#endif - -#if !defined(SYS_eventfd) && defined(__NR_eventfd) -#define SYS_eventfd __NR_eventfd -#endif - -#ifdef SYS_eventfd -#define HAVE_EVENTFD - -static inline long eventfd(unsigned count) { - return syscall(SYS_eventfd, count); -} - -#endif +#ifdef HAVE_SYS_EVENTFD_H +#include <sys/eventfd.h> #endif #include "fdsem.h" struct pa_fdsem { int fds[2]; -#ifdef HAVE_EVENTFD +#ifdef HAVE_SYS_EVENTFD_H int efd; #endif @@ -85,8 +61,8 @@ pa_fdsem *pa_fdsem_new(void) { f = pa_xmalloc(PA_ALIGN(sizeof(pa_fdsem)) + PA_ALIGN(sizeof(pa_fdsem_data))); -#ifdef HAVE_EVENTFD - if ((f->efd = eventfd(0)) >= 0) { +#ifdef HAVE_SYS_EVENTFD_H + if ((f->efd = eventfd(0, 0)) >= 0) { pa_make_fd_cloexec(f->efd); f->fds[0] = f->fds[1] = -1; } else @@ -116,7 +92,7 @@ pa_fdsem *pa_fdsem_open_shm(pa_fdsem_data *data, int event_fd) { pa_assert(data); pa_assert(event_fd >= 0); -#ifdef HAVE_EVENTFD +#ifdef HAVE_SYS_EVENTFD_H f = pa_xnew(pa_fdsem, 1); f->efd = event_fd; @@ -134,11 +110,11 @@ pa_fdsem *pa_fdsem_new_shm(pa_fdsem_data *data, int* event_fd) { pa_assert(data); pa_assert(event_fd); -#ifdef HAVE_EVENTFD +#ifdef HAVE_SYS_EVENTFD_H f = pa_xnew(pa_fdsem, 1); - if ((f->efd = eventfd(0)) < 0) { + if ((f->efd = eventfd(0, 0)) < 0) { pa_xfree(f); return NULL; } @@ -159,7 +135,7 @@ pa_fdsem *pa_fdsem_new_shm(pa_fdsem_data *data, int* event_fd) { void pa_fdsem_free(pa_fdsem *f) { pa_assert(f); -#ifdef HAVE_EVENTFD +#ifdef HAVE_SYS_EVENTFD_H if (f->efd >= 0) pa_close(f->efd); #endif @@ -178,7 +154,7 @@ static void flush(pa_fdsem *f) { do { char x[10]; -#ifdef HAVE_EVENTFD +#ifdef HAVE_SYS_EVENTFD_H if (f->efd >= 0) { uint64_t u; @@ -195,7 +171,7 @@ static void flush(pa_fdsem *f) { continue; } - } while (pa_atomic_sub(&f->data->in_pipe, r) > r); + } while (pa_atomic_sub(&f->data->in_pipe, (int) r) > (int) r); } void pa_fdsem_post(pa_fdsem *f) { @@ -211,7 +187,7 @@ void pa_fdsem_post(pa_fdsem *f) { for (;;) { -#ifdef HAVE_EVENTFD +#ifdef HAVE_SYS_EVENTFD_H if (f->efd >= 0) { uint64_t u = 1; @@ -247,7 +223,7 @@ void pa_fdsem_wait(pa_fdsem *f) { char x[10]; ssize_t r; -#ifdef HAVE_EVENTFD +#ifdef HAVE_SYS_EVENTFD_H if (f->efd >= 0) { uint64_t u; @@ -265,7 +241,7 @@ void pa_fdsem_wait(pa_fdsem *f) { continue; } - pa_atomic_sub(&f->data->in_pipe, r); + pa_atomic_sub(&f->data->in_pipe, (int) r); } pa_assert_se(pa_atomic_dec(&f->data->waiting) >= 1); @@ -285,7 +261,7 @@ int pa_fdsem_try(pa_fdsem *f) { int pa_fdsem_get(pa_fdsem *f) { pa_assert(f); -#ifdef HAVE_EVENTFD +#ifdef HAVE_SYS_EVENTFD_H if (f->efd >= 0) return f->efd; #endif diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h index 2d8422f9..512dd357 100644 --- a/src/pulsecore/flist.h +++ b/src/pulsecore/flist.h @@ -26,6 +26,7 @@ #include <pulse/gccmacro.h> #include <pulsecore/once.h> +#include <pulsecore/core-util.h> /* A multiple-reader multipler-write lock-free free list implementation */ @@ -56,6 +57,8 @@ void* pa_flist_pop(pa_flist*l); } \ static void name##_flist_destructor(void) PA_GCC_DESTRUCTOR; \ static void name##_flist_destructor(void) { \ + if (!pa_in_valgrind()) \ + return; \ if (name##_flist.flist) \ pa_flist_free(name##_flist.flist, (free_cb)); \ } \ diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c index fb4497b8..24a28db7 100644 --- a/src/pulsecore/idxset.c +++ b/src/pulsecore/idxset.c @@ -66,7 +66,7 @@ unsigned pa_idxset_string_hash_func(const void *p) { const char *c; for (c = p; *c; c++) - hash = 31 * hash + *c; + hash = 31 * hash + (unsigned) *c; return hash; } @@ -80,7 +80,7 @@ unsigned pa_idxset_trivial_hash_func(const void *p) { } int pa_idxset_trivial_compare_func(const void *a, const void *b) { - return a != b; + return a < b ? -1 : (a > b ? 1 : 0); } pa_idxset* pa_idxset_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) { @@ -318,8 +318,7 @@ void* pa_idxset_rrobin(pa_idxset *s, uint32_t *idx) { hash = *idx % NBUCKETS; - if (!(e = index_scan(s, hash, *idx))) - return NULL; + e = index_scan(s, hash, *idx); if (e && e->iterate_next) e = e->iterate_next; diff --git a/src/pulsecore/ioline.c b/src/pulsecore/ioline.c index 90afaafd..88174c05 100644 --- a/src/pulsecore/ioline.c +++ b/src/pulsecore/ioline.c @@ -164,7 +164,7 @@ void pa_ioline_puts(pa_ioline *l, const char *c) { /* In case the allocated buffer is too small, enlarge it. */ if (l->wbuf_valid_length + len > l->wbuf_length) { size_t n = l->wbuf_valid_length+len; - char *new = pa_xnew(char, n); + char *new = pa_xnew(char, (unsigned) n); if (l->wbuf) { memcpy(new, l->wbuf+l->wbuf_index, l->wbuf_valid_length); @@ -285,7 +285,7 @@ static int do_read(pa_ioline *l) { memmove(l->rbuf, l->rbuf+l->rbuf_index, l->rbuf_valid_length); } else { /* Enlarge the buffer */ - char *new = pa_xnew(char, n); + char *new = pa_xnew(char, (unsigned) n); if (l->rbuf_valid_length) memcpy(new, l->rbuf+l->rbuf_index, l->rbuf_valid_length); pa_xfree(l->rbuf); @@ -315,10 +315,10 @@ static int do_read(pa_ioline *l) { return -1; } - l->rbuf_valid_length += r; + l->rbuf_valid_length += (size_t) r; /* Look if a line has been terminated in the newly read data */ - scan_for_lines(l, l->rbuf_valid_length - r); + scan_for_lines(l, l->rbuf_valid_length - (size_t) r); } return 0; @@ -346,8 +346,8 @@ static int do_write(pa_ioline *l) { return -1; } - l->wbuf_index += r; - l->wbuf_valid_length -= r; + l->wbuf_index += (size_t) r; + l->wbuf_valid_length -= (size_t) r; /* A shortcut for the next time */ if (l->wbuf_valid_length == 0) diff --git a/src/pulsecore/ipacl.c b/src/pulsecore/ipacl.c index 7b5f865b..6d5080fb 100644 --- a/src/pulsecore/ipacl.c +++ b/src/pulsecore/ipacl.c @@ -122,7 +122,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { if (e.bits < 128) { int t = 0, i; - for (i = 0, bits = e.bits; i < 16; i++) { + for (i = 0, bits = (uint32_t) e.bits; i < 16; i++) { if (bits >= 8) bits -= 8; diff --git a/src/pulsecore/lock-autospawn.c b/src/pulsecore/lock-autospawn.c new file mode 100644 index 00000000..d36b669e --- /dev/null +++ b/src/pulsecore/lock-autospawn.c @@ -0,0 +1,330 @@ +/*** + This file is part of PulseAudio. + + Copyright 2008 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <sys/poll.h> +#include <signal.h> +#include <pthread.h> + +#include <pulse/i18n.h> +#include <pulse/xmalloc.h> + +#include <pulsecore/mutex.h> +#include <pulsecore/thread.h> +#include <pulsecore/core-util.h> + +#include "lock-autospawn.h" + +/* So, why do we have this complex code here with threads and pipes + * and stuff? For two reasons: POSIX file locks are per-process, not + * per-file descriptor. That means that two contexts within the same + * process that try to create the autospawn lock might end up assuming + * they both managed to lock the file. And then, POSIX locking + * operations are synchronous. If two contexts run from the same event + * loop it must be made sure that they do not block each other, but + * that the locking operation can happen asynchronously. */ + +#define AUTOSPAWN_LOCK "autospawn.lock" + +static pa_mutex *mutex; + +static unsigned n_ref = 0; +static int lock_fd = -1; +static pa_mutex *lock_fd_mutex = NULL; +static pa_bool_t taken = FALSE; +static pa_thread *thread; +static int pipe_fd[2] = { -1, -1 }; + +static void destroy_mutex(void) PA_GCC_DESTRUCTOR; + +static int ref(void) { + + if (n_ref > 0) { + + pa_assert(pipe_fd[0] >= 0); + pa_assert(pipe_fd[1] >= 0); + + n_ref++; + + return 0; + } + + pa_assert(lock_fd < 0); + pa_assert(!lock_fd_mutex); + pa_assert(!taken); + pa_assert(!thread); + pa_assert(pipe_fd[0] < 0); + pa_assert(pipe_fd[1] < 0); + + if (pipe(pipe_fd) < 0) + return -1; + + lock_fd_mutex = pa_mutex_new(FALSE, FALSE); + + pa_make_fd_cloexec(pipe_fd[0]); + pa_make_fd_cloexec(pipe_fd[1]); + + pa_make_fd_nonblock(pipe_fd[1]); + pa_make_fd_nonblock(pipe_fd[0]); + + n_ref = 1; + return 0; +} + +static void unref(pa_bool_t after_fork) { + + pa_assert(n_ref > 0); + pa_assert(pipe_fd[0] >= 0); + pa_assert(pipe_fd[1] >= 0); + pa_assert(lock_fd_mutex); + + n_ref--; + + if (n_ref > 0) + return; + + pa_assert(!taken); + + if (thread) { + pa_thread_free(thread); + thread = NULL; + } + + pa_mutex_lock(lock_fd_mutex); + if (lock_fd >= 0) { + + if (after_fork) + pa_close(lock_fd); + else { + char *lf; + + if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK))) + pa_log_warn(_("Cannot access autospawn lock.")); + + pa_unlock_lockfile(lf, lock_fd); + pa_xfree(lf); + + lock_fd = -1; + } + } + pa_mutex_unlock(lock_fd_mutex); + + pa_mutex_free(lock_fd_mutex); + lock_fd_mutex = NULL; + + pa_close(pipe_fd[0]); + pa_close(pipe_fd[1]); + pipe_fd[0] = pipe_fd[1] = -1; +} + +static void ping(void) { + ssize_t s; + + pa_assert(pipe_fd[1] >= 0); + + for (;;) { + char x = 'x'; + + if ((s = write(pipe_fd[1], &x, 1)) == 1) + break; + + pa_assert(s < 0); + + if (errno == EAGAIN) + break; + + pa_assert(errno == EINTR); + } +} + +static void wait_for_ping(void) { + ssize_t s; + char x; + struct pollfd pfd; + int k; + + pa_assert(pipe_fd[0] >= 0); + + memset(&pfd, 0, sizeof(pfd)); + pfd.fd = pipe_fd[0]; + pfd.events = POLLIN; + + if ((k = poll(&pfd, 1, -1)) != 1) { + pa_assert(k < 0); + pa_assert(errno == EINTR); + } else if ((s = read(pipe_fd[0], &x, 1)) != 1) { + pa_assert(s < 0); + pa_assert(errno == EAGAIN); + } +} + +static void empty_pipe(void) { + char x[16]; + ssize_t s; + + pa_assert(pipe_fd[0] >= 0); + + if ((s = read(pipe_fd[0], &x, sizeof(x))) < 1) { + pa_assert(s < 0); + pa_assert(errno == EAGAIN); + } +} + +static void thread_func(void *u) { + int fd; + char *lf; + sigset_t fullset; + + /* No signals in this thread please */ + sigfillset(&fullset); + pthread_sigmask(SIG_BLOCK, &fullset, NULL); + + if (!(lf = pa_runtime_path(AUTOSPAWN_LOCK))) { + pa_log_warn(_("Cannot access autospawn lock.")); + goto finish; + } + + if ((fd = pa_lock_lockfile(lf)) < 0) + goto finish; + + pa_mutex_lock(lock_fd_mutex); + pa_assert(lock_fd < 0); + lock_fd = fd; + pa_mutex_unlock(lock_fd_mutex); + +finish: + pa_xfree(lf); + + ping(); +} + +static int start_thread(void) { + + if (!thread) + if (!(thread = pa_thread_new(thread_func, NULL))) + return -1; + + return 0; +} + +static void create_mutex(void) { + PA_ONCE_BEGIN { + mutex = pa_mutex_new(FALSE, FALSE); + } PA_ONCE_END; +} + +static void destroy_mutex(void) { + + if (mutex) + pa_mutex_free(mutex); +} + + +int pa_autospawn_lock_init(void) { + int ret = -1; + + create_mutex(); + pa_mutex_lock(mutex); + + if (ref() < 0) + ret = -1; + else + ret = pipe_fd[0]; + + pa_mutex_unlock(mutex); + + return ret; +} + +int pa_autospawn_lock_acquire(pa_bool_t block) { + int ret = -1; + + create_mutex(); + pa_mutex_lock(mutex); + pa_assert(n_ref >= 1); + + pa_mutex_lock(lock_fd_mutex); + + for (;;) { + + empty_pipe(); + + if (lock_fd >= 0 && !taken) { + taken = TRUE; + ret = 1; + break; + } + + if (lock_fd < 0) + if (start_thread() < 0) + break; + + if (!block) { + ret = 0; + break; + } + + pa_mutex_unlock(lock_fd_mutex); + pa_mutex_unlock(mutex); + + wait_for_ping(); + + pa_mutex_lock(mutex); + pa_mutex_lock(lock_fd_mutex); + } + + pa_mutex_unlock(lock_fd_mutex); + + pa_mutex_unlock(mutex); + + return ret; +} + +void pa_autospawn_lock_release(void) { + + create_mutex(); + pa_mutex_lock(mutex); + pa_assert(n_ref >= 1); + + pa_assert(taken); + taken = FALSE; + + ping(); + + pa_mutex_unlock(mutex); +} + +void pa_autospawn_lock_done(pa_bool_t after_fork) { + + create_mutex(); + pa_mutex_lock(mutex); + pa_assert(n_ref >= 1); + + unref(after_fork); + + pa_mutex_unlock(mutex); +} diff --git a/src/pulsecore/lock-autospawn.h b/src/pulsecore/lock-autospawn.h new file mode 100644 index 00000000..c04c4bd1 --- /dev/null +++ b/src/pulsecore/lock-autospawn.h @@ -0,0 +1,32 @@ +#ifndef foopulselockautospawnhfoo +#define foopulselockautospawnhfoo + +/*** + This file is part of PulseAudio. + + Copyright 2008 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include <pulsecore/macro.h> + +int pa_autospawn_lock_init(void); +int pa_autospawn_lock_acquire(pa_bool_t block); +void pa_autospawn_lock_release(void); +void pa_autospawn_lock_done(pa_bool_t after_fork); + +#endif diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index 5eda4f65..adf2f112 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -30,6 +30,10 @@ #include <string.h> #include <errno.h> +#ifdef HAVE_EXECINFO_H +#include <execinfo.h> +#endif + #ifdef HAVE_SYSLOG_H #include <syslog.h> #endif @@ -37,19 +41,27 @@ #include <pulse/utf8.h> #include <pulse/xmalloc.h> #include <pulse/util.h> +#include <pulse/timeval.h> #include <pulsecore/macro.h> #include <pulsecore/core-util.h> +#include <pulsecore/rtclock.h> +#include <pulsecore/once.h> #include "log.h" #define ENV_LOGLEVEL "PULSE_LOG" #define ENV_LOGMETA "PULSE_LOG_META" +#define ENV_LOGTIME "PULSE_LOG_TIME" +#define ENV_LOGBACKTRACE "PULSE_LOG_BACKTRACE" static char *log_ident = NULL, *log_ident_local = NULL; static pa_log_target_t log_target = PA_LOG_STDERR; -static void (*user_log_func)(pa_log_level_t l, const char *s) = NULL; -static pa_log_level_t maximal_level = PA_LOG_NOTICE; +static pa_log_func_t user_log_func = NULL; +static pa_log_level_t maximal_level = PA_LOG_ERROR; +static unsigned show_backtrace = 0; +static pa_bool_t show_meta = FALSE; +static pa_bool_t show_time = FALSE; #ifdef HAVE_SYSLOG_H static const int level_to_syslog[] = { @@ -81,6 +93,9 @@ void pa_log_set_ident(const char *p) { /* To make valgrind shut up. */ static void ident_destructor(void) PA_GCC_DESTRUCTOR; static void ident_destructor(void) { + if (!pa_in_valgrind()) + return; + pa_xfree(log_ident); pa_xfree(log_ident_local); } @@ -91,13 +106,81 @@ void pa_log_set_maximal_level(pa_log_level_t l) { maximal_level = l; } -void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t l, const char*s)) { +void pa_log_set_target(pa_log_target_t t, pa_log_func_t func) { pa_assert(t == PA_LOG_USER || !func); log_target = t; user_log_func = func; } +void pa_log_set_show_meta(pa_bool_t b) { + show_meta = b; +} + +void pa_log_set_show_time(pa_bool_t b) { + show_time = b; +} + +void pa_log_set_show_backtrace(unsigned nlevels) { + show_backtrace = nlevels; +} + +#ifdef HAVE_EXECINFO_H + +static char* get_backtrace(unsigned show_nframes) { + void* trace[32]; + int n_frames; + char **symbols, *e, *r; + unsigned j, n; + size_t a; + + if (show_nframes <= 0) + return NULL; + + n_frames = backtrace(trace, PA_ELEMENTSOF(trace)); + + if (n_frames <= 0) + return NULL; + + symbols = backtrace_symbols(trace, n_frames); + + if (!symbols) + return NULL; + + n = PA_MIN((unsigned) n_frames, show_nframes); + + a = 4; + + for (j = 0; j < n; j++) { + if (j > 0) + a += 2; + a += strlen(symbols[j]); + } + + r = pa_xnew(char, a); + + strcpy(r, " ("); + e = r + 2; + + for (j = 0; j < n; j++) { + if (j > 0) { + strcpy(e, "<<"); + e += 2; + } + + strcpy(e, symbols[j]); + e += strlen(symbols[j]); + } + + strcpy(e, ")"); + + free(symbols); + + return r; +} + +#endif + void pa_log_levelv_meta( pa_log_level_t level, const char*file, @@ -109,31 +192,82 @@ void pa_log_levelv_meta( const char *e; char *t, *n; int saved_errno = errno; + char *bt = NULL; + pa_log_level_t ml; +#ifdef HAVE_EXECINFO_H + unsigned show_bt; +#endif /* We don't use dynamic memory allocation here to minimize the hit * in RT threads */ - char text[1024], location[128]; + char text[4096], location[128], timestamp[32]; pa_assert(level < PA_LOG_LEVEL_MAX); pa_assert(format); - if ((e = getenv(ENV_LOGLEVEL))) - maximal_level = atoi(e); + ml = maximal_level; - if (level > maximal_level) { + if (PA_UNLIKELY((e = getenv(ENV_LOGLEVEL)))) { + pa_log_level_t eml = (pa_log_level_t) atoi(e); + + if (eml > ml) + ml = eml; + } + + if (PA_LIKELY(level > ml)) { errno = saved_errno; return; } pa_vsnprintf(text, sizeof(text), format, ap); - if (getenv(ENV_LOGMETA) && file && line > 0 && func) + if ((show_meta || getenv(ENV_LOGMETA)) && file && line > 0 && func) pa_snprintf(location, sizeof(location), "[%s:%i %s()] ", file, line, func); else if (file) pa_snprintf(location, sizeof(location), "%s: ", pa_path_get_filename(file)); else location[0] = 0; + if (show_time || getenv(ENV_LOGTIME)) { + static pa_usec_t start, last; + pa_usec_t u, a, r; + + u = pa_rtclock_usec(); + + PA_ONCE_BEGIN { + start = u; + last = u; + } PA_ONCE_END; + + r = u - last; + a = u - start; + + /* This is not thread safe, but this is a debugging tool only + * anyway. */ + last = u; + + pa_snprintf(timestamp, sizeof(timestamp), "(%4llu.%03llu|%4llu.%03llu) ", + (unsigned long long) (a / PA_USEC_PER_SEC), + (unsigned long long) (((a / PA_USEC_PER_MSEC)) % 1000), + (unsigned long long) (r / PA_USEC_PER_SEC), + (unsigned long long) (((r / PA_USEC_PER_MSEC)) % 1000)); + + } else + timestamp[0] = 0; + +#ifdef HAVE_EXECINFO_H + show_bt = show_backtrace; + + if ((e = getenv(ENV_LOGBACKTRACE))) { + unsigned ebt = (unsigned) atoi(e); + + if (ebt > show_bt) + show_bt = ebt; + } + + bt = get_backtrace(show_bt); +#endif + if (!pa_utf8_valid(text)) pa_log_level(level, __FILE__": invalid UTF-8 string following below:"); @@ -148,19 +282,22 @@ void pa_log_levelv_meta( switch (log_target) { case PA_LOG_STDERR: { - const char *prefix = "", *suffix = ""; + const char *prefix = "", *suffix = "", *grey = ""; char *local_t; #ifndef OS_IS_WIN32 /* Yes indeed. Useless, but fun! */ if (isatty(STDERR_FILENO)) { - if (level <= PA_LOG_ERROR) { + if (level <= PA_LOG_ERROR) prefix = "\x1B[1;31m"; - suffix = "\x1B[0m"; - } else if (level <= PA_LOG_WARN) { + else if (level <= PA_LOG_WARN) prefix = "\x1B[1m"; + + if (bt) + grey = "\x1B[2m"; + + if (grey[0] || prefix[0]) suffix = "\x1B[0m"; - } } #endif @@ -168,9 +305,9 @@ void pa_log_levelv_meta( * minimize the hit in RT threads */ local_t = pa_utf8_to_locale(t); if (!local_t) - fprintf(stderr, "%c: %s%s%s%s\n", level_to_char[level], location, prefix, t, suffix); + fprintf(stderr, "%s%c: %s%s%s%s%s%s\n", timestamp, level_to_char[level], location, prefix, t, grey, pa_strempty(bt), suffix); else { - fprintf(stderr, "%c: %s%s%s%s\n", level_to_char[level], location, prefix, local_t, suffix); + fprintf(stderr, "%s%c: %s%s%s%s%s%s\n", timestamp, level_to_char[level], location, prefix, local_t, grey, pa_strempty(bt), suffix); pa_xfree(local_t); } @@ -185,9 +322,9 @@ void pa_log_levelv_meta( local_t = pa_utf8_to_locale(t); if (!local_t) - syslog(level_to_syslog[level], "%s%s", location, t); + syslog(level_to_syslog[level], "%s%s%s%s", timestamp, location, t, pa_strempty(bt)); else { - syslog(level_to_syslog[level], "%s%s", location, local_t); + syslog(level_to_syslog[level], "%s%s%s%s", timestamp, location, local_t, pa_strempty(bt)); pa_xfree(local_t); } @@ -199,7 +336,7 @@ void pa_log_levelv_meta( case PA_LOG_USER: { char x[1024]; - pa_snprintf(x, sizeof(x), "%s%s", location, t); + pa_snprintf(x, sizeof(x), "%s%s%s", timestamp, location, t); user_log_func(level, x); break; diff --git a/src/pulsecore/log.h b/src/pulsecore/log.h index 2047696e..3d66e903 100644 --- a/src/pulsecore/log.h +++ b/src/pulsecore/log.h @@ -25,6 +25,8 @@ #include <stdarg.h> #include <stdlib.h> + +#include <pulsecore/macro.h> #include <pulse/gccmacro.h> /* A simple logging subsystem */ @@ -49,11 +51,16 @@ typedef enum pa_log_level { /* Set an identification for the current daemon. Used when logging to syslog. */ void pa_log_set_ident(const char *p); +typedef void (*pa_log_func_t)(pa_log_level_t t, const char*s); + /* Set another log target. If t is PA_LOG_USER you may specify a function that is called every log string */ -void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t t, const char*s)); +void pa_log_set_target(pa_log_target_t t, pa_log_func_t func); -/* Minimal log level */ +/* Maximal log level */ void pa_log_set_maximal_level(pa_log_level_t l); +void pa_log_set_show_meta(pa_bool_t b); +void pa_log_set_show_time(pa_bool_t b); +void pa_log_set_show_backtrace(unsigned nlevels); void pa_log_level_meta( pa_log_level_t level, diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h index fd33b7bb..f9ce949a 100644 --- a/src/pulsecore/macro.h +++ b/src/pulsecore/macro.h @@ -30,7 +30,6 @@ #include <stdio.h> #include <stdlib.h> -#include <pulsecore/log.h> #include <pulse/gccmacro.h> #ifndef PACKAGE @@ -40,7 +39,7 @@ #ifndef PA_LIKELY #ifdef __GNUC__ #define PA_LIKELY(x) (__builtin_expect(!!(x),1)) -#define PA_UNLIKELY(x) (__builtin_expect((x),0)) +#define PA_UNLIKELY(x) (__builtin_expect(!!(x),0)) #else #define PA_LIKELY(x) (x) #define PA_UNLIKELY(x) (x) @@ -208,7 +207,7 @@ typedef int pa_bool_t; #define PA_PATH_SEP_CHAR '/' #endif -#ifdef __GNUC__ +#if defined(__GNUC__) && defined(__ELF__) #define PA_WARN_REFERENCE(sym, msg) \ __asm__(".section .gnu.warning." #sym); \ @@ -221,4 +220,13 @@ typedef int pa_bool_t; #endif +#if defined(__i386__) || defined(__x86_64__) +#define PA_DEBUG_TRAP __asm__("int $3") +#else +#define PA_DEBUG_TRAP raise(SIGTRAP) +#endif + +/* We include this at the very last place */ +#include <pulsecore/log.h> + #endif diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index b43113d6..d9e1bf1c 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -31,6 +31,10 @@ #include <signal.h> #include <errno.h> +#ifdef HAVE_VALGRIND_MEMCHECK_H +#include <valgrind/memcheck.h> +#endif + #include <pulse/xmalloc.h> #include <pulse/def.h> @@ -158,14 +162,14 @@ static void stat_add(pa_memblock*b) { pa_assert(b->pool); pa_atomic_inc(&b->pool->stat.n_allocated); - pa_atomic_add(&b->pool->stat.allocated_size, b->length); + pa_atomic_add(&b->pool->stat.allocated_size, (int) b->length); pa_atomic_inc(&b->pool->stat.n_accumulated); - pa_atomic_add(&b->pool->stat.accumulated_size, b->length); + pa_atomic_add(&b->pool->stat.accumulated_size, (int) b->length); if (b->type == PA_MEMBLOCK_IMPORTED) { pa_atomic_inc(&b->pool->stat.n_imported); - pa_atomic_add(&b->pool->stat.imported_size, b->length); + pa_atomic_add(&b->pool->stat.imported_size, (int) b->length); } pa_atomic_inc(&b->pool->stat.n_allocated_by_type[b->type]); @@ -181,14 +185,14 @@ static void stat_remove(pa_memblock *b) { pa_assert(pa_atomic_load(&b->pool->stat.allocated_size) >= (int) b->length); pa_atomic_dec(&b->pool->stat.n_allocated); - pa_atomic_sub(&b->pool->stat.allocated_size, b->length); + pa_atomic_sub(&b->pool->stat.allocated_size, (int) b->length); if (b->type == PA_MEMBLOCK_IMPORTED) { pa_assert(pa_atomic_load(&b->pool->stat.n_imported) > 0); pa_assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length); pa_atomic_dec(&b->pool->stat.n_imported); - pa_atomic_sub(&b->pool->stat.imported_size, b->length); + pa_atomic_sub(&b->pool->stat.imported_size, (int) b->length); } pa_atomic_dec(&b->pool->stat.n_allocated_by_type[b->type]); @@ -248,7 +252,7 @@ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) { if ((unsigned) (idx = pa_atomic_inc(&p->n_init)) >= p->n_blocks) pa_atomic_dec(&p->n_init); else - slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * idx)); + slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * (size_t) idx)); if (!slot) { pa_log_info("Pool full"); @@ -257,6 +261,12 @@ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) { } } +/* #ifdef HAVE_VALGRIND_MEMCHECK_H */ +/* if (PA_UNLIKELY(pa_in_valgrind())) { */ +/* VALGRIND_MALLOCLIKE_BLOCK(slot, p->block_size, 0, 0); */ +/* } */ +/* #endif */ + return slot; } @@ -272,7 +282,7 @@ static unsigned mempool_slot_idx(pa_mempool *p, void *ptr) { pa_assert((uint8_t*) ptr >= (uint8_t*) p->memory.ptr); pa_assert((uint8_t*) ptr < (uint8_t*) p->memory.ptr + p->memory.size); - return ((uint8_t*) ptr - (uint8_t*) p->memory.ptr) / p->block_size; + return (unsigned) ((size_t) ((uint8_t*) ptr - (uint8_t*) p->memory.ptr) / p->block_size); } /* No lock necessary */ @@ -519,13 +529,19 @@ static void memblock_free(pa_memblock *b) { case PA_MEMBLOCK_POOL_EXTERNAL: case PA_MEMBLOCK_POOL: { struct mempool_slot *slot; - int call_free; + pa_bool_t call_free; slot = mempool_slot_by_ptr(b->pool, pa_atomic_ptr_load(&b->data)); pa_assert(slot); call_free = b->type == PA_MEMBLOCK_POOL_EXTERNAL; +/* #ifdef HAVE_VALGRIND_MEMCHECK_H */ +/* if (PA_UNLIKELY(pa_in_valgrind())) { */ +/* VALGRIND_FREELIKE_BLOCK(slot, b->pool->block_size); */ +/* } */ +/* #endif */ + /* The free list dimensions should easily allow all slots * to fit in, hence try harder if pushing this slot into * the free list fails */ @@ -647,7 +663,7 @@ static void memblock_replace_import(pa_memblock *b) { pa_assert(pa_atomic_load(&b->pool->stat.n_imported) > 0); pa_assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length); pa_atomic_dec(&b->pool->stat.n_imported); - pa_atomic_sub(&b->pool->stat.imported_size, b->length); + pa_atomic_sub(&b->pool->stat.imported_size, (int) b->length); seg = b->per_type.imported.segment; pa_assert(seg); @@ -668,8 +684,9 @@ static void memblock_replace_import(pa_memblock *b) { pa_mutex_unlock(seg->import->mutex); } -pa_mempool* pa_mempool_new(pa_bool_t shared) { +pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size) { pa_mempool *p; + char t1[64], t2[64]; p = pa_xnew(pa_mempool, 1); @@ -680,13 +697,26 @@ pa_mempool* pa_mempool_new(pa_bool_t shared) { if (p->block_size < PA_PAGE_SIZE) p->block_size = PA_PAGE_SIZE; - p->n_blocks = PA_MEMPOOL_SLOTS_MAX; + if (size <= 0) + p->n_blocks = PA_MEMPOOL_SLOTS_MAX; + else { + p->n_blocks = (unsigned) (size / p->block_size); + + if (p->n_blocks < 2) + p->n_blocks = 2; + } if (pa_shm_create_rw(&p->memory, p->n_blocks * p->block_size, shared, 0700) < 0) { pa_xfree(p); return NULL; } + pa_log_debug("Using %s memory pool with %u slots of size %s each, total size is %s", + p->memory.shared ? "shared" : "private", + p->n_blocks, + pa_bytes_snprint(t1, sizeof(t1), (unsigned) p->block_size), + pa_bytes_snprint(t2, sizeof(t2), (unsigned) (p->n_blocks * p->block_size))); + memset(&p->stat, 0, sizeof(p->stat)); pa_atomic_store(&p->n_init, 0); @@ -754,7 +784,7 @@ void pa_mempool_vacuum(pa_mempool *p) { ; while ((slot = pa_flist_pop(list))) { - pa_shm_punch(&p->memory, (uint8_t*) slot - (uint8_t*) p->memory.ptr, p->block_size); + pa_shm_punch(&p->memory, (size_t) ((uint8_t*) slot - (uint8_t*) p->memory.ptr), p->block_size); while (pa_flist_push(p->free_slots, slot)) ; @@ -967,7 +997,7 @@ void pa_memexport_free(pa_memexport *e) { pa_mutex_lock(e->mutex); while (e->used_slots) - pa_memexport_process_release(e, e->used_slots - e->slots); + pa_memexport_process_release(e, (uint32_t) (e->used_slots - e->slots)); pa_mutex_unlock(e->mutex); pa_mutex_lock(e->pool->mutex); @@ -1006,7 +1036,7 @@ int pa_memexport_process_release(pa_memexport *e, uint32_t id) { pa_assert(pa_atomic_load(&e->pool->stat.exported_size) >= (int) b->length); pa_atomic_dec(&e->pool->stat.n_exported); - pa_atomic_sub(&e->pool->stat.exported_size, b->length); + pa_atomic_sub(&e->pool->stat.exported_size, (int) b->length); pa_memblock_unref(b); @@ -1034,7 +1064,7 @@ static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i) { slot->block->per_type.imported.segment->import != i) continue; - idx = slot - e->slots; + idx = (uint32_t) (slot - e->slots); e->revoke_cb(e, idx, e->userdata); pa_memexport_process_release(e, idx); } @@ -1095,7 +1125,7 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32 PA_LLIST_PREPEND(struct memexport_slot, e->used_slots, slot); slot->block = b; - *block_id = slot - e->slots; + *block_id = (uint32_t) (slot - e->slots); pa_mutex_unlock(e->mutex); /* pa_log("Got block id %u", *block_id); */ @@ -1115,13 +1145,13 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32 pa_assert((uint8_t*) data + b->length <= (uint8_t*) memory->ptr + memory->size); *shm_id = memory->id; - *offset = (uint8_t*) data - (uint8_t*) memory->ptr; + *offset = (size_t) ((uint8_t*) data - (uint8_t*) memory->ptr); *size = b->length; pa_memblock_release(b); pa_atomic_inc(&e->pool->stat.n_exported); - pa_atomic_add(&e->pool->stat.exported_size, b->length); + pa_atomic_add(&e->pool->stat.exported_size, (int) b->length); return 0; } diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index efe55b02..b1eab2a9 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -117,7 +117,7 @@ pa_mempool * pa_memblock_get_pool(pa_memblock *b); pa_memblock *pa_memblock_will_need(pa_memblock *b); /* The memory block manager */ -pa_mempool* pa_mempool_new(pa_bool_t shared); +pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size); void pa_mempool_free(pa_mempool *p); const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p); void pa_mempool_vacuum(pa_mempool *p); diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c index 841b9075..265da37f 100644 --- a/src/pulsecore/memblockq.c +++ b/src/pulsecore/memblockq.c @@ -84,7 +84,8 @@ pa_memblockq* pa_memblockq_new( pa_log_debug("memblockq requested: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu maxrewind=%lu", (unsigned long) maxlength, (unsigned long) tlength, (unsigned long) base, (unsigned long) prebuf, (unsigned long) minreq, (unsigned long) maxrewind); - bq->missing = bq->requested = bq->maxlength = bq->tlength = bq->prebuf = bq->minreq = bq->maxrewind = 0; + bq->missing = 0; + bq->requested = bq->maxlength = bq->tlength = bq->prebuf = bq->minreq = bq->maxrewind = 0; bq->in_prebuf = TRUE; pa_memblockq_set_maxlength(bq, maxlength); @@ -215,7 +216,7 @@ static void drop_backlog(pa_memblockq *bq) { int64_t boundary; pa_assert(bq); - boundary = bq->read_index - bq->maxrewind; + boundary = bq->read_index - (int64_t) bq->maxrewind; while (bq->blocks && (bq->blocks->index + (int64_t) bq->blocks->chunk.length <= boundary)) drop_block(bq, bq->blocks); @@ -227,10 +228,10 @@ static pa_bool_t can_push(pa_memblockq *bq, size_t l) { pa_assert(bq); if (bq->read_index > bq->write_index) { - size_t d = bq->read_index - bq->write_index; + int64_t d = bq->read_index - bq->write_index; - if (l > d) - l -= d; + if ((int64_t) l > d) + l -= (size_t) d; else return TRUE; } @@ -239,7 +240,7 @@ static pa_bool_t can_push(pa_memblockq *bq, size_t l) { /* Make sure that the list doesn't get too long */ if (bq->write_index + (int64_t) l > end) - if (bq->write_index + l - bq->read_index > bq->maxlength) + if (bq->write_index + (int64_t) l - bq->read_index > (int64_t) bq->maxlength) return FALSE; return TRUE; @@ -294,7 +295,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { /* This entry isn't touched at all, let's skip it */ q = q->prev; } else if (bq->write_index <= q->index && - bq->write_index + chunk.length >= q->index + q->chunk.length) { + bq->write_index + (int64_t) chunk.length >= q->index + (int64_t) q->chunk.length) { /* This entry is fully replaced by the new entry, so let's drop it */ @@ -306,7 +307,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { /* The write index points into this memblock, so let's * truncate or split it */ - if (bq->write_index + chunk.length < q->index + q->chunk.length) { + if (bq->write_index + (int64_t) chunk.length < q->index + (int64_t) q->chunk.length) { /* We need to save the end of this memchunk */ struct list_item *p; @@ -320,11 +321,11 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { pa_memblock_ref(p->chunk.memblock); /* Calculate offset */ - d = bq->write_index + chunk.length - q->index; + d = (size_t) (bq->write_index + (int64_t) chunk.length - q->index); pa_assert(d > 0); /* Drop it from the new entry */ - p->index = q->index + d; + p->index = q->index + (int64_t) d; p->chunk.length -= d; /* Add it to the list */ @@ -339,7 +340,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { } /* Truncate the chunk */ - if (!(q->chunk.length = bq->write_index - q->index)) { + if (!(q->chunk.length = (size_t) (bq->write_index - q->index))) { struct list_item *p; p = q; q = q->prev; @@ -357,8 +358,8 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { /* The job overwrites the current entry at the end, so let's drop the beginning of this entry */ - d = bq->write_index + chunk.length - q->index; - q->index += d; + d = (size_t) (bq->write_index + (int64_t) chunk.length - q->index); + q->index += (int64_t) d; q->chunk.index += d; q->chunk.length -= d; @@ -373,11 +374,11 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { /* Try to merge memory blocks */ if (q->chunk.memblock == chunk.memblock && - q->chunk.index + (int64_t)q->chunk.length == chunk.index && - bq->write_index == q->index + (int64_t)q->chunk.length) { + q->chunk.index + q->chunk.length == chunk.index && + bq->write_index == q->index + (int64_t) q->chunk.length) { q->chunk.length += chunk.length; - bq->write_index += chunk.length; + bq->write_index += (int64_t) chunk.length; goto finish; } } else @@ -389,7 +390,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { n->chunk = chunk; pa_memblock_ref(n->chunk.memblock); n->index = bq->write_index; - bq->write_index += n->chunk.length; + bq->write_index += (int64_t) n->chunk.length; n->next = q ? q->next : bq->blocks; n->prev = q; @@ -411,10 +412,10 @@ finish: delta = bq->write_index - old; if (delta >= (int64_t) bq->requested) { - delta -= bq->requested; + delta -= (int64_t) bq->requested; bq->requested = 0; } else { - bq->requested -= delta; + bq->requested -= (size_t) delta; delta = 0; } @@ -471,7 +472,7 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { /* How much silence shall we return? */ if (bq->current_read) - length = bq->current_read->index - bq->read_index; + length = (size_t) (bq->current_read->index - bq->read_index); else if (bq->write_index > bq->read_index) length = (size_t) (bq->write_index - bq->read_index); else @@ -506,8 +507,8 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { pa_assert(bq->read_index >= bq->current_read->index); d = bq->read_index - bq->current_read->index; - chunk->index += d; - chunk->length -= d; + chunk->index += (size_t) d; + chunk->length -= (size_t) d; return 0; } @@ -533,20 +534,20 @@ void pa_memblockq_drop(pa_memblockq *bq, size_t length) { /* We go through this piece by piece to make sure we don't * drop more than allowed by prebuf */ - p = bq->current_read->index + bq->current_read->chunk.length; + p = bq->current_read->index + (int64_t) bq->current_read->chunk.length; pa_assert(p >= bq->read_index); d = p - bq->read_index; if (d > (int64_t) length) - d = length; + d = (int64_t) length; bq->read_index += d; - length -= d; + length -= (size_t) d; } else { /* The list is empty, there's nothing we could drop */ - bq->read_index += length; + bq->read_index += (int64_t) length; break; } } @@ -563,8 +564,8 @@ void pa_memblockq_rewind(pa_memblockq *bq, size_t length) { /* This is kind of the inverse of pa_memblockq_drop() */ - bq->read_index -= length; - bq->missing -= length; + bq->read_index -= (int64_t) length; + bq->missing -= (int64_t) length; } pa_bool_t pa_memblockq_is_readable(pa_memblockq *bq) { @@ -628,10 +629,10 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) { delta = bq->write_index - old; if (delta >= (int64_t) bq->requested) { - delta -= bq->requested; + delta -= (int64_t) bq->requested; bq->requested = 0; } else if (delta >= 0) { - bq->requested -= delta; + bq->requested -= (size_t) delta; delta = 0; } @@ -652,10 +653,10 @@ void pa_memblockq_flush_write(pa_memblockq *bq) { delta = bq->write_index - old; if (delta >= (int64_t) bq->requested) { - delta -= bq->requested; + delta -= (int64_t) bq->requested; bq->requested = 0; } else if (delta >= 0) { - bq->requested -= delta; + bq->requested -= (size_t) delta; delta = 0; } @@ -874,7 +875,7 @@ int pa_memblockq_splice(pa_memblockq *bq, pa_memblockq *source) { pa_memblock_unref(chunk.memblock); } else - pa_memblockq_seek(bq, chunk.length, PA_SEEK_RELATIVE); + pa_memblockq_seek(bq, (int64_t) chunk.length, PA_SEEK_RELATIVE); pa_memblockq_drop(bq, chunk.length); } diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h index 4b9450f6..31f908df 100644 --- a/src/pulsecore/memblockq.h +++ b/src/pulsecore/memblockq.h @@ -155,7 +155,7 @@ void pa_memblockq_set_maxlength(pa_memblockq *memblockq, size_t maxlength); /* m void pa_memblockq_set_tlength(pa_memblockq *memblockq, size_t tlength); /* might modify minreq, too */ void pa_memblockq_set_prebuf(pa_memblockq *memblockq, size_t prebuf); /* might modify minreq, too */ void pa_memblockq_set_minreq(pa_memblockq *memblockq, size_t minreq); -void pa_memblockq_set_maxrewind(pa_memblockq *memblockq, size_t rewind); /* Set the maximum history size */ +void pa_memblockq_set_maxrewind(pa_memblockq *memblockq, size_t maxrewind); /* Set the maximum history size */ void pa_memblockq_set_silence(pa_memblockq *memblockq, pa_memchunk *silence); /* Call pa_memchunk_willneed() for every chunk in the queue from the current read pointer to the end */ diff --git a/src/pulsecore/modargs.c b/src/pulsecore/modargs.c index d257b4ce..9e60125e 100644 --- a/src/pulsecore/modargs.c +++ b/src/pulsecore/modargs.c @@ -183,7 +183,7 @@ fail: return NULL; } -static void free_func(void *p, PA_GCC_UNUSED void*userdata) { +static void free_func(void *p, void*userdata) { struct entry *e = p; pa_assert(e); diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c index dbafa8c9..9b17cb91 100644 --- a/src/pulsecore/module.c +++ b/src/pulsecore/module.c @@ -48,7 +48,7 @@ #define UNLOAD_POLL_TIME 2 -static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { +static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, const struct timeval *tv, void *userdata) { pa_core *c = PA_CORE(userdata); struct timeval ntv; @@ -59,7 +59,7 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED pa_module_unload_unused(c); pa_gettimeofday(&ntv); - pa_timeval_add(&ntv, UNLOAD_POLL_TIME*1000000); + pa_timeval_add(&ntv, UNLOAD_POLL_TIME*PA_USEC_PER_SEC); m->time_restart(e, &ntv); } @@ -124,7 +124,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { if (m->auto_unload && !c->module_auto_unload_event) { struct timeval ntv; pa_gettimeofday(&ntv); - pa_timeval_add(&ntv, UNLOAD_POLL_TIME*1000000); + pa_timeval_add(&ntv, UNLOAD_POLL_TIME*PA_USEC_PER_SEC); c->module_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); } @@ -190,7 +190,7 @@ void pa_module_unload_by_index(pa_core *c, uint32_t idx, pa_bool_t force) { pa_assert(c); pa_assert(idx != PA_IDXSET_INVALID); - if (m->core->disallow_module_loading && !force) + if (c->disallow_module_loading && !force) return; if (!(m = pa_idxset_remove_by_index(c->modules, idx))) diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c index 30420546..ecd8def8 100644 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@ -45,12 +45,13 @@ struct namereg_entry { void *data; }; -static int is_valid_char(char c) { +static pa_bool_t is_valid_char(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.' || + c == '-' || c == '_'; } @@ -77,10 +78,10 @@ char* pa_namereg_make_valid_name(const char *name) { if (*name == 0) return NULL; - n = pa_xnew(char, strlen(name)+1); + n = pa_xmalloc(strlen(name)+1); for (a = name, b = n; *a && (a-name < PA_NAME_MAX); a++, b++) - *b = is_valid_char(*a) ? *a : '_'; + *b = (char) (is_valid_char(*a) ? *a : '_'); *b = 0; @@ -97,7 +98,7 @@ void pa_namereg_free(pa_core *c) { pa_hashmap_free(c->namereg, NULL, NULL); } -const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail) { +const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, pa_bool_t fail) { struct namereg_entry *e; char *n = NULL; @@ -136,7 +137,7 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t return NULL; } - k = pa_xnew(char, l+4); + k = pa_xmalloc(l+4); for (i = 2; i <= 99; i++) { pa_snprintf(k, l+4, "%s.%u", name, i); diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h index 3c1de8e7..f4581006 100644 --- a/src/pulsecore/namereg.h +++ b/src/pulsecore/namereg.h @@ -35,7 +35,7 @@ typedef enum pa_namereg_type { void pa_namereg_free(pa_core *c); -const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail); +const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, pa_bool_t fail); void pa_namereg_unregister(pa_core *c, const char *name); void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, pa_bool_t autoload); int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type); diff --git a/src/pulsecore/object.h b/src/pulsecore/object.h index 7dcfa2eb..2ee4fc31 100644 --- a/src/pulsecore/object.h +++ b/src/pulsecore/object.h @@ -42,7 +42,7 @@ struct pa_object { pa_object *pa_object_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name)); #define pa_object_new(type) ((type*) pa_object_new_internal(sizeof(type), #type, type##_check_type) -#define pa_object_free ((void (*) (pa_object* o)) pa_xfree) +#define pa_object_free ((void (*) (pa_object* _obj)) pa_xfree) int pa_object_check_type(const char *type); diff --git a/src/pulsecore/once.c b/src/pulsecore/once.c index 989741dc..3d4543cb 100644 --- a/src/pulsecore/once.c +++ b/src/pulsecore/once.c @@ -28,13 +28,13 @@ #include "once.h" -int pa_once_begin(pa_once *control) { +pa_bool_t pa_once_begin(pa_once *control) { pa_mutex *m; pa_assert(control); if (pa_atomic_load(&control->done)) - return 0; + return FALSE; pa_atomic_inc(&control->ref); @@ -50,15 +50,17 @@ int pa_once_begin(pa_once *control) { * wait until it is unlocked */ pa_mutex_lock(m); + pa_assert(pa_atomic_load(&control->done)); + pa_once_end(control); - return 0; + return FALSE; } pa_assert_se(m = pa_mutex_new(FALSE, FALSE)); pa_mutex_lock(m); if (pa_atomic_ptr_cmpxchg(&control->mutex, NULL, m)) - return 1; + return TRUE; pa_mutex_unlock(m); pa_mutex_free(m); @@ -91,4 +93,3 @@ void pa_run_once(pa_once *control, pa_once_func_t func) { pa_once_end(control); } } - diff --git a/src/pulsecore/once.h b/src/pulsecore/once.h index 576d40fa..c0191ef0 100644 --- a/src/pulsecore/once.h +++ b/src/pulsecore/once.h @@ -38,7 +38,7 @@ typedef struct pa_once { } /* Not to be called directly, use the macros defined below instead */ -int pa_once_begin(pa_once *o); +pa_bool_t pa_once_begin(pa_once *o); void pa_once_end(pa_once *o); #define PA_ONCE_BEGIN \ diff --git a/src/pulsecore/parseaddr.c b/src/pulsecore/parseaddr.c index f2b6b2cf..c5cd7fe7 100644 --- a/src/pulsecore/parseaddr.c +++ b/src/pulsecore/parseaddr.c @@ -51,20 +51,29 @@ static char *parse_host(const char *s, uint16_t *ret_port) { if (!(e = strchr(s+1, ']'))) return NULL; - if (e[1] == ':') - *ret_port = atoi(e+2); - else if (e[1] != 0) + if (e[1] == ':') { + uint32_t p; + + if (pa_atou(e+2, &p) < 0) + return NULL; + + *ret_port = (uint16_t) p; + } else if (e[1] != 0) return NULL; - return pa_xstrndup(s+1, e-s-1); + return pa_xstrndup(s+1, (size_t) (e-s-1)); } else { char *e; + uint32_t p; if (!(e = strrchr(s, ':'))) return pa_xstrdup(s); - *ret_port = atoi(e+1); - return pa_xstrndup(s, e-s); + if (pa_atou(e+1, &p) < 0) + return NULL; + + *ret_port = (uint16_t) p; + return pa_xstrndup(s, (size_t) (e-s)); } } diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index e6a6ae4d..00df0f79 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -255,7 +255,7 @@ finish: return ret; } -static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { +static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, const struct timeval *tv, void *userdata) { struct reply_info*r = userdata; pa_assert(r); diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c index addb17cc..bf9ba983 100644 --- a/src/pulsecore/pid.c +++ b/src/pulsecore/pid.c @@ -73,6 +73,7 @@ static pid_t read_pid(const char *fn, int fd) { if (pa_atou(t, &pid) < 0) { pa_log_warn("Failed to parse PID file '%s'", fn); + errno = EINVAL; return (pid_t) -1; } @@ -110,7 +111,7 @@ static int open_pid_file(const char *fn, int mode) { goto fail; } - /* Does the file still exist in the file system? When ye, w're done, otherwise restart */ + /* Does the file still exist in the file system? When yes, we're done, otherwise restart */ if (st.st_nlink >= 1) break; @@ -131,8 +132,10 @@ static int open_pid_file(const char *fn, int mode) { fail: if (fd >= 0) { + int saved_errno = errno; pa_lock_fd(fd, 0); pa_close(fd); + errno = saved_errno; } return -1; @@ -154,8 +157,11 @@ static int proc_name_ours(pid_t pid, const char *procname) { char stored[64]; if (!(fgets(stored, sizeof(stored), f))) { + int saved_errno = feof(f) ? EINVAL : errno; pa_log_info("Failed to read from %s: %s", bn, feof(f) ? "EOF" : pa_cstrerror(errno)); fclose(f); + + errno = saved_errno; return -1; } @@ -165,20 +171,22 @@ static int proc_name_ours(pid_t pid, const char *procname) { good = pa_startswith(stored, expected); pa_xfree(expected); -#if !defined(__OPTIMIZE__) +/*#if !defined(__OPTIMIZE__)*/ if (!good) { /* libtool likes to rename our binary names ... */ expected = pa_sprintf_malloc("%lu (lt-%s)", (unsigned long) pid, procname); good = pa_startswith(stored, expected); pa_xfree(expected); } -#endif +/*#endif*/ return !!good; } -#endif +#else return 1; +#endif + } /* Create a new PID file for the current process. */ @@ -203,6 +211,7 @@ int pa_pid_file_create(const char *procname) { if ((pid = read_pid(fn, fd)) == (pid_t) -1) pa_log_warn("Corrupt PID file, overwriting."); else if (pid > 0) { + int ours = 1; #ifdef OS_IS_WIN32 if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) { @@ -210,11 +219,13 @@ int pa_pid_file_create(const char *procname) { #else if (kill(pid, 0) >= 0 || errno != ESRCH) { #endif - int ours = 1; if (procname) - if ((ours = proc_name_ours(pid, procname)) < 0) + if ((ours = proc_name_ours(pid, procname)) < 0) { + pa_log_warn("Could not check to see if pid %lu is a pulseaudio process. " + "Asssuming it is and the daemon is already running.", (unsigned long) pid); goto fail; + } if (ours) { pa_log("Daemon already running."); @@ -227,7 +238,7 @@ int pa_pid_file_create(const char *procname) { } /* Overwrite the current PID file */ - if (lseek(fd, 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, 0) < 0) { + if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, (off_t) 0) < 0) { pa_log("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -280,7 +291,7 @@ int pa_pid_file_remove(void) { goto fail; } - if (ftruncate(fd, 0) < 0) { + if (ftruncate(fd, (off_t) 0) < 0) { pa_log_warn("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -342,8 +353,13 @@ int pa_pid_file_kill(int sig, pid_t *pid, const char *procname) { if (!(fn = pa_runtime_path("pid"))) goto fail; - if ((fd = open_pid_file(fn, O_RDONLY)) < 0) + if ((fd = open_pid_file(fn, O_RDONLY)) < 0) { + + if (errno == ENOENT) + errno = ESRCH; + goto fail; + } if ((*pid = read_pid(fn, fd)) == (pid_t) -1) goto fail; @@ -354,8 +370,10 @@ int pa_pid_file_kill(int sig, pid_t *pid, const char *procname) { if ((ours = proc_name_ours(*pid, procname)) < 0) goto fail; - if (!ours) + if (!ours) { + errno = ESRCH; goto fail; + } } ret = kill(*pid, sig); @@ -363,8 +381,10 @@ int pa_pid_file_kill(int sig, pid_t *pid, const char *procname) { fail: if (fd >= 0) { + int saved_errno = errno; pa_lock_fd(fd, 0); pa_close(fd); + errno = saved_errno; } #ifdef __linux__ diff --git a/src/pulsecore/prioq.c b/src/pulsecore/prioq.c new file mode 100644 index 00000000..693dc517 --- /dev/null +++ b/src/pulsecore/prioq.c @@ -0,0 +1,256 @@ +/*** + This file is part of PulseAudio. + + Copyright 2008 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <pulse/xmalloc.h> + +#include <pulsecore/flist.h> + +#include "prioq.h" + +struct pa_prioq_item { + void *value; + unsigned idx; +}; + +struct pa_prioq { + pa_prioq_item **items; + unsigned n_items; + unsigned n_allocated; + pa_compare_func_t compare_func; +}; + +PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree); + +pa_prioq *pa_prioq_new(pa_compare_func_t compare_func) { + + pa_prioq *q; + + q = pa_xnew(pa_prioq, 1); + q->compare_func = compare_func; + q->n_items = 0; + q->n_allocated = 64; + q->items = pa_xnew(pa_prioq_item*, q->n_allocated); + + return q; +} + +void pa_prioq_free(pa_prioq *q, pa_free2_cb_t free_cb, void *userdata) { + pa_prioq_item **i, **e; + + pa_assert(q); + + for (i = q->items, e = q->items + q->n_items; i < e; i++) { + + if (!*i) + continue; + + if (free_cb) + free_cb((*i)->value, userdata); + + pa_xfree(*i); + } + + pa_xfree(q->items); + pa_xfree(q); +} + +static void shuffle_up(pa_prioq *q, pa_prioq_item *i) { + unsigned j; + + pa_assert(q); + pa_assert(i); + + j = i->idx; + + while (j > 0) { + unsigned k; + + k = (j-1)/2; + + if (q->compare_func(q->items[k]->value, i->value) < 0) + break; + + q->items[k]->idx = j; + q->items[j] = q->items[k]; + + j = k; + } + + i->idx = j; + q->items[j] = i; + +} + +pa_prioq_item* pa_prioq_put(pa_prioq *q, void *p) { + pa_prioq_item *i; + + pa_assert(q); + + if (q->n_items >= q->n_allocated) { + q->n_allocated = PA_MAX(q->n_items+1, q->n_allocated)*2; + q->items = pa_xrealloc(q->items, sizeof(pa_prioq_item*) * q->n_allocated); + } + + if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items)))) + i = pa_xnew(pa_prioq_item, 1); + + i->value = p; + i->idx = q->n_items++; + + shuffle_up(q, i); + + return i; +} + +void* pa_prioq_peek(pa_prioq *q) { + pa_assert(q); + + if (q->n_items <= 0) + return NULL; + + return q->items[0]->value; +} + +void* pa_prioq_pop(pa_prioq *q){ + pa_assert(q); + + if (q->n_items <= 0) + return NULL; + + return pa_prioq_remove(q, q->items[0]); +} + +static void swap(pa_prioq *q, unsigned j, unsigned k) { + pa_prioq_item *t; + + pa_assert(q); + pa_assert(j < q->n_items); + pa_assert(k < q->n_items); + + pa_assert(q->items[j]->idx == j); + pa_assert(q->items[k]->idx == k); + + t = q->items[j]; + + q->items[j]->idx = k; + q->items[j] = q->items[k]; + + q->items[k]->idx = j; + q->items[k] = t; +} + +static void shuffle_down(pa_prioq *q, unsigned idx) { + + pa_assert(q); + pa_assert(idx < q->n_items); + + for (;;) { + unsigned j, k, s; + + k = (idx+1)*2; /* right child */ + j = k-1; /* left child */ + + if (j >= q->n_items) + break; + + if (q->compare_func(q->items[j]->value, q->items[idx]->value) < 0) + + /* So our left child is smaller than we are, let's + * remember this fact */ + s = j; + else + s = idx; + + if (k < q->n_items && + q->compare_func(q->items[k]->value, q->items[s]->value) < 0) + + /* So our right child is smaller than we are, let's + * remember this fact */ + s = k; + + /* s now points to the smallest of the three items */ + + if (s == idx) + /* No swap necessary, we're done */ + break; + + swap(q, idx, s); + idx = s; + } +} + +void* pa_prioq_remove(pa_prioq *q, pa_prioq_item *i) { + void *p; + + pa_assert(q); + pa_assert(i); + pa_assert(q->n_items >= 1); + + p = i->value; + + if (q->n_items-1 == i->idx) { + /* We are the last entry, so let's just remove us and good */ + q->n_items--; + + } else { + + /* We are not the last entry, we need to replace ourselves + * with the last node and reshuffle */ + + q->items[i->idx] = q->items[q->n_items-1]; + q->items[i->idx]->idx = i->idx; + q->n_items--; + + shuffle_down(q, i->idx); + } + + if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0) + pa_xfree(i); + + return p; +} + +unsigned pa_prioq_size(pa_prioq *q) { + pa_assert(q); + + return q->n_items; +} + +pa_bool_t pa_prioq_isempty(pa_prioq *q) { + pa_assert(q); + + return q->n_items == 0; +} + +void pa_prioq_reshuffle(pa_prioq *q, pa_prioq_item *i) { + pa_assert(q); + pa_assert(i); + + /* This will move the entry down as far as necessary */ + shuffle_down(q, i->idx); + + /* And this will move the entry up as far as necessary */ + shuffle_up(q, i); +} diff --git a/src/pulsecore/prioq.h b/src/pulsecore/prioq.h new file mode 100644 index 00000000..fd3550b7 --- /dev/null +++ b/src/pulsecore/prioq.h @@ -0,0 +1,64 @@ +#ifndef foopulsecoreprioqhfoo +#define foopulsecoreprioqhfoo + +/*** + This file is part of PulseAudio. + + Copyright 2008 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include <inttypes.h> + +#include <pulsecore/macro.h> +#include <pulsecore/idxset.h> + +/* A heap-based priority queue. Removal and insertion is O(log + * n). Removal can happen a the top or at any position referenced by a + * pa_prioq_item. */ + +typedef struct pa_prioq pa_prioq; +typedef struct pa_prioq_item pa_prioq_item; + +/* Instantiate a new prioq with the specified comparison functions */ +pa_prioq* pa_prioq_new(pa_compare_func_t compare_func); + +/* Free the prioq. When the prioq is not empty the specified function is called for every entry contained */ +void pa_prioq_free(pa_prioq *q, pa_free2_cb_t free_cb, void *userdata); + +/* Store a new item in the prioq. */ +pa_prioq_item* pa_prioq_put(pa_prioq *q, void* data); + +/* Get the item on the top of the queue, but don't remove it from the queue*/ +void* pa_prioq_peek(pa_prioq*q); + +/* Get the item on the top of the queue, and remove it from thq queue */ +void* pa_prioq_pop(pa_prioq*q); + +/* Remove an arbitrary from theq prioq, returning it's data */ +void* pa_prioq_remove(pa_prioq*q, pa_prioq_item *i); + +/* The priority of an item was modified. Adjustthe queue to that */ +void pa_prioq_reshuffle(pa_prioq *q, pa_prioq_item *i); + +/* Return the current number of items in the prioq */ +unsigned pa_prioq_size(pa_prioq*s); + +/* Return TRUE of the prioq is empty */ +pa_bool_t pa_prioq_isempty(pa_prioq *s); + +#endif diff --git a/src/pulsecore/proplist-util.c b/src/pulsecore/proplist-util.c index 6005775e..4d505f57 100644 --- a/src/pulsecore/proplist-util.c +++ b/src/pulsecore/proplist-util.c @@ -37,7 +37,7 @@ void pa_init_proplist(pa_proplist *p) { int a, b; -#ifndef HAVE_DECL_ENVIRON +#if !HAVE_DECL_ENVIRON extern char **environ; #endif char **e; diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 4f121a3a..460119a9 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -184,7 +184,7 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = { { sizeof(int), esd_proto_sample_free_or_play, "sample play" }, /* 8 */ { sizeof(int), NULL, "sample loop" }, { sizeof(int), NULL, "sample stop" }, - { -1, NULL, "TODO: sample kill" }, + { (size_t) -1, NULL, "TODO: sample kill" }, { ESD_KEY_LEN + sizeof(int), esd_proto_standby_or_resume, "standby" }, /* NOOP! */ { ESD_KEY_LEN + sizeof(int), esd_proto_standby_or_resume, "resume" }, /* NOOP! */ /* 13 */ @@ -194,8 +194,8 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = { { sizeof(int), esd_proto_server_info, "server info" }, { sizeof(int), esd_proto_all_info, "all info" }, - { -1, NULL, "TODO: subscribe" }, - { -1, NULL, "TODO: unsubscribe" }, + { (size_t) -1, NULL, "TODO: subscribe" }, + { (size_t) -1, NULL, "TODO: unsubscribe" }, { 3 * sizeof(int), esd_proto_stream_pan, "stream pan"}, { 3 * sizeof(int), NULL, "sample pan" }, @@ -309,7 +309,7 @@ static void connection_write(connection *c, const void *data, size_t length) { static void format_esd2native(int format, pa_bool_t swap_bytes, pa_sample_spec *ss) { pa_assert(ss); - ss->channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1; + ss->channels = (uint8_t) (((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1); if ((format & ESD_MASK_BITS) == ESD_BITS16) ss->format = swap_bytes ? PA_SAMPLE_S16RE : PA_SAMPLE_S16NE; else @@ -334,7 +334,7 @@ static int format_native2esd(pa_sample_spec *ss) { /*** esound commands ***/ -static int esd_proto_connect(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_connect(connection *c, esd_proto_t request, const void *data, size_t length) { uint32_t ekey; int ok; @@ -377,7 +377,7 @@ static int esd_proto_connect(connection *c, PA_GCC_UNUSED esd_proto_t request, c return 0; } -static int esd_proto_stream_play(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_stream_play(connection *c, esd_proto_t request, const void *data, size_t length) { char name[ESD_NAME_MAX], *utf8_name; int32_t format, rate; pa_sample_spec ss; @@ -397,7 +397,7 @@ static int esd_proto_stream_play(connection *c, PA_GCC_UNUSED esd_proto_t reques rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate); data = (const char*) data + sizeof(int32_t); - ss.rate = rate; + ss.rate = (uint32_t) rate; format_esd2native(format, c->swap_byte_order, &ss); CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification"); @@ -430,7 +430,7 @@ static int esd_proto_stream_play(connection *c, PA_GCC_UNUSED esd_proto_t reques CHECK_VALIDITY(c->sink_input, "Failed to create sink input."); - l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS); + l = (size_t) ((double) pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS); c->input_memblockq = pa_memblockq_new( 0, l, @@ -455,7 +455,7 @@ static int esd_proto_stream_play(connection *c, PA_GCC_UNUSED esd_proto_t reques c->protocol->n_player++; - pa_atomic_store(&c->playback.missing, pa_memblockq_missing(c->input_memblockq)); + pa_atomic_store(&c->playback.missing, (int) pa_memblockq_missing(c->input_memblockq)); pa_sink_input_put(c->sink_input); @@ -482,7 +482,7 @@ static int esd_proto_stream_record(connection *c, esd_proto_t request, const voi rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate); data = (const char*) data + sizeof(int32_t); - ss.rate = rate; + ss.rate = (uint32_t) rate; format_esd2native(format, c->swap_byte_order, &ss); CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification."); @@ -561,7 +561,7 @@ static int esd_proto_stream_record(connection *c, esd_proto_t request, const voi return 0; } -static int esd_proto_get_latency(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_get_latency(connection *c, esd_proto_t request, const void *data, size_t length) { pa_sink *sink; int32_t latency; @@ -572,7 +572,7 @@ static int esd_proto_get_latency(connection *c, PA_GCC_UNUSED esd_proto_t reques if (!(sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK, 1))) latency = 0; else { - double usec = pa_sink_get_latency(sink); + double usec = (double) pa_sink_get_latency(sink); latency = (int) ((usec*44100)/1000000); } @@ -581,7 +581,7 @@ static int esd_proto_get_latency(connection *c, PA_GCC_UNUSED esd_proto_t reques return 0; } -static int esd_proto_server_info(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_server_info(connection *c, esd_proto_t request, const void *data, size_t length) { int32_t rate = 44100, format = ESD_STEREO|ESD_BITS16; int32_t response; pa_sink *sink; @@ -591,7 +591,7 @@ static int esd_proto_server_info(connection *c, PA_GCC_UNUSED esd_proto_t reques pa_assert(length == sizeof(int32_t)); if ((sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK, 1))) { - rate = sink->sample_spec.rate; + rate = (int32_t) sink->sample_spec.rate; format = format_native2esd(&sink->sample_spec); } @@ -641,9 +641,9 @@ static int esd_proto_all_info(connection *c, esd_proto_t request, const void *da if (conn->sink_input) { pa_cvolume volume = *pa_sink_input_get_volume(conn->sink_input); - rate = conn->sink_input->sample_spec.rate; - lvolume = (volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM; - rvolume = (volume.values[1]*ESD_VOLUME_BASE)/PA_VOLUME_NORM; + rate = (int32_t) conn->sink_input->sample_spec.rate; + lvolume = (int32_t) ((volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); + rvolume = (int32_t) ((volume.values[1]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); format = format_native2esd(&conn->sink_input->sample_spec); } @@ -706,15 +706,15 @@ static int esd_proto_all_info(connection *c, esd_proto_t request, const void *da connection_write(c, name, ESD_NAME_MAX); /* rate */ - rate = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, ce->sample_spec.rate); + rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) ce->sample_spec.rate); connection_write(c, &rate, sizeof(int32_t)); /* left */ - lvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); + lvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) ((ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM)); connection_write(c, &lvolume, sizeof(int32_t)); /*right*/ - rvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); + rvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) ((ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM)); connection_write(c, &rvolume, sizeof(int32_t)); /*format*/ @@ -736,7 +736,7 @@ static int esd_proto_all_info(connection *c, esd_proto_t request, const void *da return 0; } -static int esd_proto_stream_pan(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_stream_pan(connection *c, esd_proto_t request, const void *data, size_t length) { int32_t ok; uint32_t idx, lvolume, rvolume; connection *conn; @@ -772,7 +772,7 @@ static int esd_proto_stream_pan(connection *c, PA_GCC_UNUSED esd_proto_t request return 0; } -static int esd_proto_sample_cache(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_sample_cache(connection *c, esd_proto_t request, const void *data, size_t length) { pa_sample_spec ss; int32_t format, rate, sc_length; uint32_t idx; @@ -790,7 +790,7 @@ static int esd_proto_sample_cache(connection *c, PA_GCC_UNUSED esd_proto_t reque rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate); data = (const char*)data + sizeof(int32_t); - ss.rate = rate; + ss.rate = (uint32_t) rate; format_esd2native(format, c->swap_byte_order, &ss); CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification."); @@ -807,9 +807,9 @@ static int esd_proto_sample_cache(connection *c, PA_GCC_UNUSED esd_proto_t reque CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name."); pa_assert(!c->scache.memchunk.memblock); - c->scache.memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, sc_length); + c->scache.memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, (size_t) sc_length); c->scache.memchunk.index = 0; - c->scache.memchunk.length = sc_length; + c->scache.memchunk.length = (size_t) sc_length; c->scache.sample_spec = ss; pa_assert(!c->scache.name); c->scache.name = pa_xstrdup(name); @@ -824,7 +824,7 @@ static int esd_proto_sample_cache(connection *c, PA_GCC_UNUSED esd_proto_t reque return 0; } -static int esd_proto_sample_get_id(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_sample_get_id(connection *c, esd_proto_t request, const void *data, size_t length) { int32_t ok; uint32_t idx; char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1]; @@ -840,7 +840,7 @@ static int esd_proto_sample_get_id(connection *c, PA_GCC_UNUSED esd_proto_t requ ok = -1; if ((idx = pa_scache_get_id_by_name(c->protocol->core, name)) != PA_IDXSET_INVALID) - ok = idx + 1; + ok = (int32_t) idx + 1; connection_write(c, &ok, sizeof(int32_t)); @@ -867,12 +867,12 @@ static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, con if ((sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK, 1))) if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM, c->client->proplist, NULL) >= 0) - ok = idx + 1; + ok = (int32_t) idx + 1; } else { pa_assert(request == ESD_PROTO_SAMPLE_FREE); if (pa_scache_remove_item(c->protocol->core, name) >= 0) - ok = idx + 1; + ok = (int32_t) idx + 1; } } @@ -881,7 +881,7 @@ static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, con return 0; } -static int esd_proto_standby_or_resume(connection *c, PA_GCC_UNUSED esd_proto_t request, PA_GCC_UNUSED const void *data, PA_GCC_UNUSED size_t length) { +static int esd_proto_standby_or_resume(connection *c, esd_proto_t request, const void *data, size_t length) { int32_t ok; connection_assert_ref(c); @@ -919,7 +919,9 @@ static int do_read(connection *c) { return -1; } - if ((c->read_data_length+= r) >= sizeof(c->request)) { + c->read_data_length += (size_t) r; + + if (c->read_data_length >= sizeof(c->request)) { struct proto_handler *handler; c->request = PA_MAYBE_INT32_SWAP(c->swap_byte_order, c->request); @@ -970,7 +972,8 @@ static int do_read(connection *c) { return -1; } - if ((c->read_data_length += r) >= handler->data_length) { + c->read_data_length += (size_t) r; + if (c->read_data_length >= handler->data_length) { size_t l = c->read_data_length; pa_assert(handler->proc); @@ -1000,7 +1003,7 @@ static int do_read(connection *c) { return -1; } - c->scache.memchunk.index += r; + c->scache.memchunk.index += (size_t) r; pa_assert(c->scache.memchunk.index <= c->scache.memchunk.length); if (c->scache.memchunk.index == c->scache.memchunk.length) { @@ -1033,7 +1036,7 @@ static int do_read(connection *c) { /* pa_log("STREAMING_DATA"); */ - if (!(l = pa_atomic_load(&c->playback.missing))) + if (!(l = (size_t) pa_atomic_load(&c->playback.missing))) return 0; if (c->playback.current_memblock) { @@ -1071,12 +1074,12 @@ static int do_read(connection *c) { chunk.memblock = c->playback.current_memblock; chunk.index = c->playback.memblock_index; - chunk.length = r; + chunk.length = (size_t) r; - c->playback.memblock_index += r; + c->playback.memblock_index += (size_t) r; pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, &chunk, NULL); - pa_atomic_sub(&c->playback.missing, r); + pa_atomic_sub(&c->playback.missing, (int) r); } return 0; @@ -1100,7 +1103,8 @@ static int do_write(connection *c) { return -1; } - if ((c->write_data_index +=r) >= c->write_data_length) + c->write_data_index += (size_t) r; + if (c->write_data_index >= c->write_data_length) c->write_data_length = c->write_data_index = 0; } else if (c->state == ESD_STREAMING_DATA && c->source_output) { @@ -1129,7 +1133,7 @@ static int do_write(connection *c) { return -1; } - pa_memblockq_drop(c->output_memblockq, r); + pa_memblockq_drop(c->output_memblockq, (size_t) r); } return 0; @@ -1288,7 +1292,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk m = pa_memblockq_pop_missing(c->input_memblockq); if (m > 0) - if (pa_atomic_add(&c->playback.missing, m) <= 0) + if (pa_atomic_add(&c->playback.missing, (int) m) <= 0) pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL); return 0; @@ -1574,7 +1578,7 @@ int pa_esound_options_parse(pa_esound_options *o, pa_core *c, pa_modargs *ma) { if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) { pa_ip_acl *ipa; - if (!(o->auth_ip_acl = pa_ip_acl_new(acl))) { + if (!(ipa = pa_ip_acl_new(acl))) { pa_log("Failed to parse IP ACL '%s'", acl); return -1; } diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index b9f6f083..56e86cb4 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -469,51 +469,102 @@ static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, i return 0; } -static void fix_record_buffer_attr_pre(record_stream *s, pa_bool_t adjust_latency, uint32_t *maxlength, uint32_t *fragsize) { +static void fix_record_buffer_attr_pre( + record_stream *s, + pa_bool_t adjust_latency, + pa_bool_t early_requests, + uint32_t *maxlength, + uint32_t *fragsize) { + + size_t frame_size; + pa_usec_t orig_fragsize_usec, fragsize_usec, source_usec; + pa_assert(s); pa_assert(maxlength); pa_assert(fragsize); + frame_size = pa_frame_size(&s->source_output->sample_spec); + if (*maxlength == (uint32_t) -1 || *maxlength > MAX_MEMBLOCKQ_LENGTH) *maxlength = MAX_MEMBLOCKQ_LENGTH; if (*maxlength <= 0) - *maxlength = pa_frame_size(&s->source_output->sample_spec); + *maxlength = (uint32_t) frame_size; if (*fragsize == (uint32_t) -1) - *fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &s->source_output->sample_spec); + *fragsize = (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &s->source_output->sample_spec); if (*fragsize <= 0) - *fragsize = pa_frame_size(&s->source_output->sample_spec); + *fragsize = (uint32_t) frame_size; + + orig_fragsize_usec = fragsize_usec = pa_bytes_to_usec(*fragsize, &s->source_output->sample_spec); - if (adjust_latency) { - pa_usec_t fragsize_usec; + if (early_requests) { + + /* In early request mode we need to emulate the classic + * fragment-based playback model. We do this setting the source + * latency to the fragment size. */ + + source_usec = fragsize_usec; + + } else if (adjust_latency) { /* So, the user asked us to adjust the latency according to * what the source can provide. Half the latency will be * spent on the hw buffer, half of it in the async buffer * queue we maintain for each client. */ - fragsize_usec = pa_bytes_to_usec(*fragsize, &s->source_output->sample_spec); + source_usec = fragsize_usec/2; + + } else { + + /* Ok, the user didn't ask us to adjust the latency, hence we + * don't */ - s->source_latency = pa_source_output_set_requested_latency(s->source_output, fragsize_usec/2); + source_usec = 0; + } + + if (source_usec > 0) + s->source_latency = pa_source_output_set_requested_latency(s->source_output, source_usec); + else + s->source_latency = 0; + + if (early_requests) { + + /* Ok, we didn't necessarily get what we were asking for, so + * let's tell the user */ + + fragsize_usec = s->source_latency; + + } else if (adjust_latency) { + + /* Now subtract what we actually got */ if (fragsize_usec >= s->source_latency*2) fragsize_usec -= s->source_latency; else fragsize_usec = s->source_latency; + } - *fragsize = pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec); - } else - s->source_latency = 0; + if (pa_usec_to_bytes(orig_fragsize_usec, &s->source_output->sample_spec) != + pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec)) + + *fragsize = (uint32_t) pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec); + + if (*fragsize <= 0) + *fragsize = (uint32_t) frame_size; } -static void fix_record_buffer_attr_post(record_stream *s, uint32_t *maxlength, uint32_t *fragsize) { +static void fix_record_buffer_attr_post( + record_stream *s, + uint32_t *maxlength, + uint32_t *fragsize) { + size_t base; pa_assert(s); pa_assert(maxlength); pa_assert(fragsize); - *maxlength = pa_memblockq_get_maxlength(s->memblockq); + *maxlength = (uint32_t) pa_memblockq_get_maxlength(s->memblockq); base = pa_frame_size(&s->source_output->sample_spec); @@ -524,7 +575,7 @@ static void fix_record_buffer_attr_post(record_stream *s, uint32_t *maxlength, u if (s->fragment_size > *maxlength) s->fragment_size = *maxlength; - *fragsize = s->fragment_size; + *fragsize = (uint32_t) s->fragment_size; } static record_stream* record_stream_new( @@ -538,7 +589,8 @@ static record_stream* record_stream_new( pa_source_output_flags_t flags, pa_proplist *p, pa_bool_t adjust_latency, - pa_sink_input *direct_on_input) { + pa_sink_input *direct_on_input, + pa_bool_t early_requests) { record_stream *s; pa_source_output *source_output; @@ -584,7 +636,7 @@ static record_stream* record_stream_new( s->source_output->suspend = source_output_suspend_cb; s->source_output->userdata = s; - fix_record_buffer_attr_pre(s, adjust_latency, maxlength, fragsize); + fix_record_buffer_attr_pre(s, adjust_latency, early_requests, maxlength, fragsize); s->memblockq = pa_memblockq_new( 0, @@ -666,10 +718,10 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, uint32_t l = 0; for (;;) { - if ((l = pa_atomic_load(&s->missing)) <= 0) + if ((l = (uint32_t) pa_atomic_load(&s->missing)) <= 0) break; - if (pa_atomic_cmpxchg(&s->missing, l, 0)) + if (pa_atomic_cmpxchg(&s->missing, (int) l, 0)) break; } @@ -690,6 +742,8 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, case PLAYBACK_STREAM_MESSAGE_UNDERFLOW: { pa_tagstruct *t; +/* pa_log("signalling underflow"); */ + /* Report that we're empty */ t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW); @@ -734,9 +788,17 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, return 0; } -static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_latency, uint32_t *maxlength, uint32_t *tlength, uint32_t* prebuf, uint32_t* minreq) { +static void fix_playback_buffer_attr_pre( + playback_stream *s, + pa_bool_t adjust_latency, + pa_bool_t early_requests, + uint32_t *maxlength, + uint32_t *tlength, + uint32_t* prebuf, + uint32_t* minreq) { + size_t frame_size; - pa_usec_t tlength_usec, minreq_usec, sink_usec; + pa_usec_t orig_tlength_usec, tlength_usec, orig_minreq_usec, minreq_usec, sink_usec; pa_assert(s); pa_assert(maxlength); @@ -749,29 +811,39 @@ static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_la if (*maxlength == (uint32_t) -1 || *maxlength > MAX_MEMBLOCKQ_LENGTH) *maxlength = MAX_MEMBLOCKQ_LENGTH; if (*maxlength <= 0) - *maxlength = frame_size; + *maxlength = (uint32_t) frame_size; if (*tlength == (uint32_t) -1) - *tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec); + *tlength = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec); if (*tlength <= 0) - *tlength = frame_size; + *tlength = (uint32_t) frame_size; if (*minreq == (uint32_t) -1) - *minreq = pa_usec_to_bytes(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec); + *minreq = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec); if (*minreq <= 0) - *minreq = frame_size; + *minreq = (uint32_t) frame_size; if (*tlength < *minreq+frame_size) - *tlength = *minreq+frame_size; + *tlength = *minreq+(uint32_t) frame_size; - tlength_usec = pa_bytes_to_usec(*tlength, &s->sink_input->sample_spec); - minreq_usec = pa_bytes_to_usec(*minreq, &s->sink_input->sample_spec); + orig_tlength_usec = tlength_usec = pa_bytes_to_usec(*tlength, &s->sink_input->sample_spec); + orig_minreq_usec = minreq_usec = pa_bytes_to_usec(*minreq, &s->sink_input->sample_spec); pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms", (double) tlength_usec / PA_USEC_PER_MSEC, (double) minreq_usec / PA_USEC_PER_MSEC); - if (adjust_latency) { + if (early_requests) { + + /* In early request mode we need to emulate the classic + * fragment-based playback model. We do this setting the sink + * latency to the fragment size. */ + + sink_usec = minreq_usec; + + pa_log_debug("Early requests mode enabled, configuring sink latency to minreq."); + + } else if (adjust_latency) { /* So, the user asked us to adjust the latency of the stream * buffer according to the what the sink can provide. The @@ -795,6 +867,8 @@ static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_la else sink_usec = 0; + pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency."); + } else { /* Ok, the user didn't ask us to adjust the latency, but we @@ -805,11 +879,21 @@ static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_la sink_usec = (tlength_usec - minreq_usec*2); else sink_usec = 0; + + pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq."); } s->sink_latency = pa_sink_input_set_requested_latency(s->sink_input, sink_usec); - if (adjust_latency) { + if (early_requests) { + + /* Ok, we didn't necessarily get what we were asking for, so + * let's tell the user */ + + minreq_usec = s->sink_latency; + + } else if (adjust_latency) { + /* Ok, we didn't necessarily get what we were asking for, so * let's subtract from what we asked for for the remaining * buffer space */ @@ -823,22 +907,33 @@ static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_la if (tlength_usec < s->sink_latency + 2*minreq_usec) tlength_usec = s->sink_latency + 2*minreq_usec; - *tlength = pa_usec_to_bytes(tlength_usec, &s->sink_input->sample_spec); - *minreq = pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec); + if (pa_usec_to_bytes_round_up(orig_tlength_usec, &s->sink_input->sample_spec) != + pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec)) + *tlength = (uint32_t) pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec); + + if (pa_usec_to_bytes(orig_minreq_usec, &s->sink_input->sample_spec) != + pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec)) + *minreq = (uint32_t) pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec); if (*minreq <= 0) { - *minreq += frame_size; - *tlength += frame_size*2; + *minreq = (uint32_t) frame_size; + *tlength += (uint32_t) frame_size*2; } if (*tlength <= *minreq) - *tlength = *minreq*2 + frame_size; + *tlength = *minreq*2 + (uint32_t) frame_size; if (*prebuf == (uint32_t) -1 || *prebuf > *tlength) *prebuf = *tlength; } -static void fix_playback_buffer_attr_post(playback_stream *s, uint32_t *maxlength, uint32_t *tlength, uint32_t* prebuf, uint32_t* minreq) { +static void fix_playback_buffer_attr_post( + playback_stream *s, + uint32_t *maxlength, + uint32_t *tlength, + uint32_t* prebuf, + uint32_t* minreq) { + pa_assert(s); pa_assert(maxlength); pa_assert(tlength); @@ -864,11 +959,13 @@ static playback_stream* playback_stream_new( uint32_t *minreq, pa_cvolume *volume, pa_bool_t muted, + pa_bool_t muted_set, uint32_t syncid, uint32_t *missing, pa_sink_input_flags_t flags, pa_proplist *p, - pa_bool_t adjust_latency) { + pa_bool_t adjust_latency, + pa_bool_t early_requests) { playback_stream *s, *ssync; pa_sink_input *sink_input; @@ -883,7 +980,6 @@ static playback_stream* playback_stream_new( pa_assert(tlength); pa_assert(prebuf); pa_assert(minreq); - pa_assert(volume); pa_assert(missing); pa_assert(p); @@ -916,8 +1012,10 @@ static playback_stream* playback_stream_new( data.sink = sink; pa_sink_input_new_data_set_sample_spec(&data, ss); pa_sink_input_new_data_set_channel_map(&data, map); - pa_sink_input_new_data_set_volume(&data, volume); - pa_sink_input_new_data_set_muted(&data, muted); + if (volume) + pa_sink_input_new_data_set_volume(&data, volume); + if (muted_set) + pa_sink_input_new_data_set_muted(&data, muted); data.sync_base = ssync ? ssync->sink_input : NULL; sink_input = pa_sink_input_new(c->protocol->core, &data, flags); @@ -949,7 +1047,7 @@ static playback_stream* playback_stream_new( start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0; - fix_playback_buffer_attr_pre(s, adjust_latency, maxlength, tlength, prebuf, minreq); + fix_playback_buffer_attr_pre(s, adjust_latency, early_requests, maxlength, tlength, prebuf, minreq); pa_sink_input_get_silence(sink_input, &silence); s->memblockq = pa_memblockq_new( @@ -982,7 +1080,6 @@ static playback_stream* playback_stream_new( return s; } - /* Called from thread context */ static void playback_stream_request_bytes(playback_stream *s) { size_t m, previous_missing; @@ -996,7 +1093,7 @@ static void playback_stream_request_bytes(playback_stream *s) { /* pa_log("request_bytes(%lu)", (unsigned long) m); */ - previous_missing = pa_atomic_add(&s->missing, m); + previous_missing = (size_t) pa_atomic_add(&s->missing, (int) m); if (pa_memblockq_prebuf_active(s->memblockq) || (previous_missing < s->minreq && previous_missing+m >= s->minreq)) @@ -1142,7 +1239,7 @@ static void handle_seek(playback_stream *s, int64_t indexw) { pa_log_debug("Requesting rewind due to end of underrun."); pa_sink_input_request_rewind(s->sink_input, - s->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : s->sink_input->thread_info.underrun_for, + (size_t) (s->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : s->sink_input->thread_info.underrun_for), FALSE, TRUE); } @@ -1156,7 +1253,7 @@ static void handle_seek(playback_stream *s, int64_t indexw) { * let's have it usk us again */ pa_log_debug("Requesting rewind due to rewrite."); - pa_sink_input_request_rewind(s->sink_input, indexr - indexw, TRUE, FALSE); + pa_sink_input_request_rewind(s->sink_input, (size_t) (indexr - indexw), TRUE, FALSE); } } @@ -1196,7 +1293,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int if (pa_memblockq_push_align(s->memblockq, chunk) < 0) { pa_log_warn("Failed to push data into queue"); pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL); - pa_memblockq_seek(s->memblockq, chunk->length, PA_SEEK_RELATIVE); + pa_memblockq_seek(s->memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE); } handle_seek(s, windex); @@ -1426,7 +1523,7 @@ static void sink_input_moved_cb(pa_sink_input *i) { prebuf = (uint32_t) pa_memblockq_get_prebuf(s->memblockq); minreq = (uint32_t) pa_memblockq_get_minreq(s->memblockq); - fix_playback_buffer_attr_pre(s, TRUE, &maxlength, &tlength, &prebuf, &minreq); + fix_playback_buffer_attr_pre(s, TRUE, FALSE, &maxlength, &tlength, &prebuf, &minreq); pa_memblockq_set_maxlength(s->memblockq, maxlength); pa_memblockq_set_tlength(s->memblockq, tlength); pa_memblockq_set_prebuf(s->memblockq, prebuf); @@ -1525,7 +1622,7 @@ static void source_output_moved_cb(pa_source_output *o) { fragsize = (uint32_t) s->fragment_size; maxlength = (uint32_t) pa_memblockq_get_length(s->memblockq); - fix_record_buffer_attr_pre(s, TRUE, &maxlength, &fragsize); + fix_record_buffer_attr_pre(s, TRUE, FALSE, &maxlength, &fragsize); pa_memblockq_set_maxlength(s->memblockq, maxlength); fix_record_buffer_attr_post(s, &maxlength, &fragsize); @@ -1572,7 +1669,7 @@ static pa_tagstruct *reply_new(uint32_t tag) { return reply; } -static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); playback_stream *s; uint32_t maxlength, tlength, prebuf, minreq, sink_index, syncid, missing; @@ -1592,10 +1689,14 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC no_move = FALSE, variable_rate = FALSE, muted = FALSE, - adjust_latency = FALSE; + adjust_latency = FALSE, + early_requests = FALSE, + dont_inhibit_auto_suspend = FALSE, + muted_set = FALSE; pa_sink_input_flags_t flags = 0; pa_proplist *p; + pa_bool_t volume_set = TRUE; pa_native_connection_assert_ref(c); pa_assert(t); @@ -1621,7 +1722,9 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(sink_name)), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name(sink_name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID); @@ -1660,6 +1763,26 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC } } + if (c->version >= 14) { + + if (pa_tagstruct_get_boolean(t, &volume_set) < 0 || + pa_tagstruct_get_boolean(t, &early_requests) < 0) { + protocol_error(c); + pa_proplist_free(p); + return; + } + } + + if (c->version >= 15) { + + if (pa_tagstruct_get_boolean(t, &muted_set) < 0 || + pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0) { + protocol_error(c); + pa_proplist_free(p); + return; + } + } + if (!pa_tagstruct_eof(t)) { protocol_error(c); pa_proplist_free(p); @@ -1691,9 +1814,14 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC (fix_rate ? PA_SINK_INPUT_FIX_RATE : 0) | (fix_channels ? PA_SINK_INPUT_FIX_CHANNELS : 0) | (no_move ? PA_SINK_INPUT_DONT_MOVE : 0) | - (variable_rate ? PA_SINK_INPUT_VARIABLE_RATE : 0); + (variable_rate ? PA_SINK_INPUT_VARIABLE_RATE : 0) | + (dont_inhibit_auto_suspend ? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND : 0); + + /* Only since protocol version 15 there's a seperate muted_set + * flag. For older versions we synthesize it here */ + muted_set = muted_set || muted; - s = playback_stream_new(c, sink, &ss, &map, &maxlength, &tlength, &prebuf, &minreq, &volume, muted, syncid, &missing, flags, p, adjust_latency); + s = playback_stream_new(c, sink, &ss, &map, &maxlength, &tlength, &prebuf, &minreq, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests); pa_proplist_free(p); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); @@ -1735,7 +1863,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); uint32_t channel; @@ -1793,7 +1921,7 @@ static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); record_stream *s; uint32_t maxlength, fragment_size; @@ -1813,7 +1941,9 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ no_move = FALSE, variable_rate = FALSE, adjust_latency = FALSE, - peak_detect = FALSE; + peak_detect = FALSE, + early_requests = FALSE, + dont_inhibit_auto_suspend = FALSE; pa_source_output_flags_t flags = 0; pa_proplist *p; uint32_t direct_on_input_idx = PA_INVALID_INDEX; @@ -1835,9 +1965,11 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, !source_name || pa_namereg_is_valid_name(source_name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, source_index == PA_INVALID_INDEX || !source_name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !source_name || source_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID); - CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || (*source_name && pa_utf8_valid(source_name)), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID); p = pa_proplist_new(); @@ -1874,6 +2006,24 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ } } + if (c->version >= 14) { + + if (pa_tagstruct_get_boolean(t, &early_requests) < 0) { + protocol_error(c); + pa_proplist_free(p); + return; + } + } + + if (c->version >= 15) { + + if (pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0) { + protocol_error(c); + pa_proplist_free(p); + return; + } + } + if (!pa_tagstruct_eof(t)) { protocol_error(c); pa_proplist_free(p); @@ -1914,9 +2064,10 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ (fix_rate ? PA_SOURCE_OUTPUT_FIX_RATE : 0) | (fix_channels ? PA_SOURCE_OUTPUT_FIX_CHANNELS : 0) | (no_move ? PA_SOURCE_OUTPUT_DONT_MOVE : 0) | - (variable_rate ? PA_SOURCE_OUTPUT_VARIABLE_RATE : 0); + (variable_rate ? PA_SOURCE_OUTPUT_VARIABLE_RATE : 0) | + (dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0); - s = record_stream_new(c, source, &ss, &map, peak_detect, &maxlength, &fragment_size, flags, p, adjust_latency, direct_on_input); + s = record_stream_new(c, source, &ss, &map, peak_detect, &maxlength, &fragment_size, flags, p, adjust_latency, direct_on_input, early_requests); pa_proplist_free(p); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); @@ -1953,7 +2104,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); int ret; @@ -1972,11 +2123,11 @@ static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */ } -static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); const void*cookie; pa_tagstruct *reply; - pa_bool_t shm_on_remote, do_shm; + pa_bool_t shm_on_remote = FALSE, do_shm; pa_native_connection_assert_ref(c); pa_assert(t); @@ -2071,6 +2222,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t if (c->version < 10 || (c->version >= 13 && !shm_on_remote)) do_shm = FALSE; +#ifdef HAVE_CREDS if (do_shm) { /* Only enable SHM if both sides are owned by the same * user. This is a security measure because otherwise data @@ -2080,6 +2232,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid) do_shm = FALSE; } +#endif pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm)); pa_pstream_enable_shm(c->pstream, do_shm); @@ -2103,7 +2256,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t #endif } -static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); const char *name = NULL; pa_proplist *p; @@ -2143,7 +2296,7 @@ static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); const char *name; uint32_t idx = PA_IDXSET_INVALID; @@ -2158,7 +2311,7 @@ static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uin } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID); if (command == PA_COMMAND_LOOKUP_SINK) { pa_sink *sink; @@ -2181,7 +2334,7 @@ static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uin } } -static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); uint32_t idx; playback_stream *s; @@ -2203,7 +2356,7 @@ static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC pa_asyncmsgq_post(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_DRAIN, PA_UINT_TO_PTR(tag), 0, NULL, NULL); } -static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); pa_tagstruct *reply; const pa_mempool_stat *stat; @@ -2225,11 +2378,11 @@ static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->allocated_size)); pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_accumulated)); pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->accumulated_size)); - pa_tagstruct_putu32(reply, pa_scache_total_size(c->protocol->core)); + pa_tagstruct_putu32(reply, (uint32_t) pa_scache_total_size(c->protocol->core)); pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); pa_tagstruct *reply; playback_stream *s; @@ -2275,7 +2428,7 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); pa_tagstruct *reply; record_stream *s; @@ -2307,7 +2460,7 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); upload_stream *s; uint32_t length; @@ -2349,7 +2502,7 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ if (!(name = pa_proplist_gets(p, PA_PROP_EVENT_ID))) name = pa_proplist_gets(p, PA_PROP_MEDIA_NAME); - CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID); s = upload_stream_new(c, &ss, &map, name, length, p); pa_proplist_free(p); @@ -2362,7 +2515,7 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); uint32_t channel; upload_stream *s; @@ -2391,7 +2544,7 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ upload_stream_unlink(s); } -static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); uint32_t sink_index; pa_volume_t volume; @@ -2414,8 +2567,10 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui return; } - CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); - CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name(sink_name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID); if (sink_index != PA_INVALID_INDEX) sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); @@ -2451,7 +2606,7 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); const char *name; @@ -2465,7 +2620,7 @@ static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID); if (pa_scache_remove_item(c->protocol->core, name) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); @@ -2509,8 +2664,8 @@ static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sin PA_TAG_SAMPLE_SPEC, &fixed_ss, PA_TAG_CHANNEL_MAP, &sink->channel_map, PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX, - PA_TAG_CVOLUME, pa_sink_get_volume(sink), - PA_TAG_BOOLEAN, pa_sink_get_mute(sink), + PA_TAG_CVOLUME, pa_sink_get_volume(sink, FALSE), + PA_TAG_BOOLEAN, pa_sink_get_mute(sink, FALSE), PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX, PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL, PA_TAG_USEC, pa_sink_get_latency(sink), @@ -2540,8 +2695,8 @@ static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_s PA_TAG_SAMPLE_SPEC, &fixed_ss, PA_TAG_CHANNEL_MAP, &source->channel_map, PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX, - PA_TAG_CVOLUME, pa_source_get_volume(source), - PA_TAG_BOOLEAN, pa_source_get_mute(source), + PA_TAG_CVOLUME, pa_source_get_volume(source, FALSE), + PA_TAG_BOOLEAN, pa_source_get_mute(source, FALSE), PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX, PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL, PA_TAG_USEC, pa_source_get_latency(source), @@ -2577,7 +2732,7 @@ static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) { pa_tagstruct_putu32(t, module->index); pa_tagstruct_puts(t, module->name); pa_tagstruct_puts(t, module->argument); - pa_tagstruct_putu32(t, module->n_used); + pa_tagstruct_putu32(t, (uint32_t) module->n_used); pa_tagstruct_put_boolean(t, module->auto_unload); } @@ -2597,7 +2752,7 @@ static void sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_tagstruct_putu32(t, s->sink->index); pa_tagstruct_put_sample_spec(t, &fixed_ss); pa_tagstruct_put_channel_map(t, &s->channel_map); - pa_tagstruct_put_cvolume(t, &s->volume); + pa_tagstruct_put_cvolume(t, pa_sink_input_get_volume(s)); pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s, &sink_latency)); pa_tagstruct_put_usec(t, sink_latency); pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s))); @@ -2650,7 +2805,7 @@ static void scache_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_s pa_tagstruct_put_usec(t, e->memchunk.memblock ? pa_bytes_to_usec(e->memchunk.length, &e->sample_spec) : 0); pa_tagstruct_put_sample_spec(t, &fixed_ss); pa_tagstruct_put_channel_map(t, &e->channel_map); - pa_tagstruct_putu32(t, e->memchunk.length); + pa_tagstruct_putu32(t, (uint32_t) e->memchunk.length); pa_tagstruct_put_boolean(t, e->lazy); pa_tagstruct_puts(t, e->filename); @@ -2658,7 +2813,7 @@ static void scache_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_s pa_tagstruct_put_proplist(t, e->proplist); } -static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); uint32_t idx; pa_sink *sink = NULL; @@ -2668,7 +2823,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u pa_sink_input *si = NULL; pa_source_output *so = NULL; pa_scache_entry *sce = NULL; - const char *name; + const char *name = NULL; pa_tagstruct *reply; pa_native_connection_assert_ref(c); @@ -2686,7 +2841,10 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID); if (command == PA_COMMAND_GET_SINK_INFO) { if (idx != PA_INVALID_INDEX) @@ -2737,7 +2895,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); pa_idxset *i; uint32_t idx; @@ -2797,7 +2955,7 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); pa_tagstruct *reply; char txt[256]; @@ -2847,7 +3005,7 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint3 pa_pstream_send_tagstruct(c->pstream, t); } -static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); pa_subscription_mask_t m; @@ -2876,7 +3034,7 @@ static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint } static void command_set_volume( - PA_GCC_UNUSED pa_pdispatch *pd, + pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, @@ -2903,7 +3061,10 @@ static void command_set_volume( } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID); switch (command) { @@ -2943,7 +3104,7 @@ static void command_set_volume( } static void command_set_mute( - PA_GCC_UNUSED pa_pdispatch *pd, + pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, @@ -2970,7 +3131,10 @@ static void command_set_mute( } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID); switch (command) { @@ -3011,7 +3175,7 @@ static void command_set_mute( pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); uint32_t idx; pa_bool_t b; @@ -3034,10 +3198,14 @@ static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY); pa_sink_input_cork(s->sink_input, b); + + if (b) + s->is_underrun = TRUE; + pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_trigger_or_flush_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); uint32_t idx; playback_stream *s; @@ -3077,7 +3245,7 @@ static void command_trigger_or_flush_or_prebuf_playback_stream(PA_GCC_UNUSED pa_ pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); uint32_t idx; record_stream *s; @@ -3102,7 +3270,7 @@ static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); uint32_t idx; record_stream *s; @@ -3142,7 +3310,7 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) { playback_stream *s; - pa_bool_t adjust_latency = FALSE; + pa_bool_t adjust_latency = FALSE, early_requests = FALSE; s = pa_idxset_get_by_index(c->output_streams, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); @@ -3156,12 +3324,13 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u PA_TAG_U32, &minreq, PA_TAG_INVALID) < 0 || (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) || + (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - fix_playback_buffer_attr_pre(s, adjust_latency, &maxlength, &tlength, &prebuf, &minreq); + fix_playback_buffer_attr_pre(s, adjust_latency, early_requests, &maxlength, &tlength, &prebuf, &minreq); pa_memblockq_set_maxlength(s->memblockq, maxlength); pa_memblockq_set_tlength(s->memblockq, tlength); pa_memblockq_set_prebuf(s->memblockq, prebuf); @@ -3179,7 +3348,7 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u } else { record_stream *s; - pa_bool_t adjust_latency = FALSE; + pa_bool_t adjust_latency = FALSE, early_requests = FALSE; pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR); s = pa_idxset_get_by_index(c->record_streams, idx); @@ -3191,12 +3360,13 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u PA_TAG_U32, &fragsize, PA_TAG_INVALID) < 0 || (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) || + (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - fix_record_buffer_attr_pre(s, adjust_latency, &maxlength, &fragsize); + fix_record_buffer_attr_pre(s, adjust_latency, early_requests, &maxlength, &fragsize); pa_memblockq_set_maxlength(s->memblockq, maxlength); fix_record_buffer_attr_post(s, &maxlength, &fragsize); @@ -3387,7 +3557,7 @@ static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t if (!z) break; - changed += pa_proplist_unset(p, z) >= 0; + changed += (unsigned) (pa_proplist_unset(p, z) >= 0); pa_xfree(z); } @@ -3413,7 +3583,7 @@ static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t } } -static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); const char *s; @@ -3427,13 +3597,13 @@ static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, u } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, !s || (*s && pa_utf8_valid(s)), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !s || pa_namereg_is_valid_name(s), tag, PA_ERR_INVALID); pa_namereg_set_default(c->protocol->core, s, command == PA_COMMAND_SET_DEFAULT_SOURCE ? PA_NAMEREG_SOURCE : PA_NAMEREG_SINK); pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); uint32_t idx; const char *name; @@ -3473,7 +3643,7 @@ static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t com pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); uint32_t idx; @@ -3521,7 +3691,7 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3 pa_native_connection_unref(c); } -static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); pa_module *m; const char *name, *argument; @@ -3551,7 +3721,7 @@ static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); uint32_t idx; pa_module *m; @@ -3573,7 +3743,7 @@ static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_add_autoload(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); const char *name, *module, *argument; uint32_t type; @@ -3608,7 +3778,7 @@ static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED u pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_remove_autoload(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); const char *name = NULL; uint32_t type, idx = PA_IDXSET_INVALID; @@ -3644,12 +3814,12 @@ static void autoload_fill_tagstruct(pa_tagstruct *t, const pa_autoload_entry *e) pa_tagstruct_putu32(t, e->index); pa_tagstruct_puts(t, e->name); - pa_tagstruct_putu32(t, e->type == PA_NAMEREG_SINK ? 0 : 1); + pa_tagstruct_putu32(t, e->type == PA_NAMEREG_SINK ? 0U : 1U); pa_tagstruct_puts(t, e->module); pa_tagstruct_puts(t, e->argument); } -static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_get_autoload_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); const pa_autoload_entry *a = NULL; uint32_t type, idx; @@ -3683,7 +3853,7 @@ static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNU pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_get_autoload_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); pa_tagstruct *reply; @@ -3713,14 +3883,14 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX; - const char *name = NULL; + const char *name_device = NULL; pa_native_connection_assert_ref(c); pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_getu32(t, &idx_device) < 0 || - pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_gets(t, &name_device) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -3728,7 +3898,11 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID); - CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); + + CHECK_VALIDITY(c->pstream, !name_device || pa_namereg_is_valid_name(name_device), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || name_device, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx_device == PA_INVALID_INDEX || !name_device, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name_device || idx_device == PA_INVALID_INDEX, tag, PA_ERR_INVALID); if (command == PA_COMMAND_MOVE_SINK_INPUT) { pa_sink_input *si = NULL; @@ -3739,7 +3913,7 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag if (idx_device != PA_INVALID_INDEX) sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device); else - sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); + sink = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SINK, 1); CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY); @@ -3758,7 +3932,7 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag if (idx_device != PA_INVALID_INDEX) source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device); else - source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1); + source = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SOURCE, 1); CHECK_VALIDITY(c->pstream, so && source, tag, PA_ERR_NOENTITY); @@ -3789,7 +3963,10 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || !*name || pa_utf8_valid(name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID); if (command == PA_COMMAND_SUSPEND_SINK) { @@ -3862,7 +4039,10 @@ static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || !*name || pa_utf8_valid(name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || pa_utf8_valid(name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID); if (idx != PA_INVALID_INDEX) m = pa_idxset_get_by_index(c->protocol->core->modules, idx); @@ -3912,6 +4092,8 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o return; } +/* pa_log("got %lu bytes", (unsigned long) chunk->length); */ + if (playback_stream_isinstance(stream)) { playback_stream *ps = PLAYBACK_STREAM(stream); @@ -4299,7 +4481,7 @@ int pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma) { if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) { pa_ip_acl *ipa; - if (!(o->auth_ip_acl = pa_ip_acl_new(acl))) { + if (!(ipa = pa_ip_acl_new(acl))) { pa_log("Failed to parse IP ACL '%s'", acl); return -1; } diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 78874bb9..743bf2ee 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -159,7 +159,7 @@ static int do_read(connection *c) { connection_assert_ref(c); - if (!c->sink_input || (l = pa_atomic_load(&c->playback.missing)) <= 0) + if (!c->sink_input || (l = (size_t) pa_atomic_load(&c->playback.missing)) <= 0) return 0; if (c->playback.current_memblock) { @@ -173,7 +173,7 @@ static int do_read(connection *c) { } if (!c->playback.current_memblock) { - pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, 0)); + pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, (size_t) -1)); c->playback.memblock_index = 0; space = pa_memblock_get_length(c->playback.current_memblock); @@ -197,12 +197,12 @@ static int do_read(connection *c) { chunk.memblock = c->playback.current_memblock; chunk.index = c->playback.memblock_index; - chunk.length = r; + chunk.length = (size_t) r; - c->playback.memblock_index += r; + c->playback.memblock_index += (size_t) r; pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, &chunk, NULL); - pa_atomic_sub(&c->playback.missing, r); + pa_atomic_sub(&c->playback.missing, (int) r); return 0; } @@ -240,7 +240,7 @@ static int do_write(connection *c) { return -1; } - pa_memblockq_drop(c->output_memblockq, r); + pa_memblockq_drop(c->output_memblockq, (size_t) r); return 0; } @@ -377,7 +377,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk m = pa_memblockq_pop_missing(c->input_memblockq); if (m > 0) - if (pa_atomic_add(&c->playback.missing, m) <= 0) + if (pa_atomic_add(&c->playback.missing, (int) m) <= 0) pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL); return 0; @@ -492,6 +492,8 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp c->parent.parent.free = connection_free; c->parent.process_msg = connection_process_msg; c->io = io; + pa_iochannel_set_callback(c->io, io_callback, c); + c->sink_input = NULL; c->source_output = NULL; c->input_memblockq = c->output_memblockq = NULL; @@ -546,7 +548,7 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp pa_sink_input_set_requested_latency(c->sink_input, DEFAULT_SINK_LATENCY); - l = (size_t) (pa_bytes_per_second(&o->sample_spec)*PLAYBACK_BUFFER_SECONDS); + l = (size_t) ((double) pa_bytes_per_second(&o->sample_spec)*PLAYBACK_BUFFER_SECONDS); c->input_memblockq = pa_memblockq_new( 0, l, @@ -558,7 +560,7 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp NULL); pa_iochannel_socket_set_rcvbuf(io, l); - pa_atomic_store(&c->playback.missing, pa_memblockq_missing(c->input_memblockq)); + pa_atomic_store(&c->playback.missing, (int) pa_memblockq_missing(c->input_memblockq)); pa_sink_input_put(c->sink_input); } @@ -610,7 +612,6 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp pa_source_output_put(c->source_output); } - pa_iochannel_set_callback(c->io, io_callback, c); pa_idxset_put(p->connections, c, NULL); return; @@ -689,6 +690,9 @@ pa_simple_options* pa_simple_options_new(void) { o = pa_xnew0(pa_simple_options, 1); PA_REFCNT_INIT(o); + o->record = FALSE; + o->playback = TRUE; + return o; } @@ -733,14 +737,14 @@ int pa_simple_options_parse(pa_simple_options *o, pa_core *c, pa_modargs *ma) { pa_xfree(o->default_sink); o->default_sink = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); - enabled = FALSE; + enabled = o->record; if (pa_modargs_get_value_boolean(ma, "record", &enabled) < 0) { pa_log("record= expects a boolean argument."); return -1; } o->record = enabled; - enabled = TRUE; + enabled = o->playback; if (pa_modargs_get_value_boolean(ma, "playback", &enabled) < 0) { pa_log("playback= expects a boolean argument."); return -1; diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 6b1af67b..7ff8edc9 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -283,7 +283,7 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo return p; } -static void item_free(void *item, PA_GCC_UNUSED void *q) { +static void item_free(void *item, void *q) { struct item_info *i = item; pa_assert(i); @@ -488,7 +488,7 @@ static void prepare_next_write_item(pa_pstream *p) { pa_assert(p->write.current->packet); p->write.data = p->write.current->packet->data; - p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->packet->length); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl((uint32_t) p->write.current->packet->length); } else if (p->write.current->type == PA_PSTREAM_ITEM_SHMRELEASE) { @@ -511,7 +511,7 @@ static void prepare_next_write_item(pa_pstream *p) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = htonl((uint32_t) (((uint64_t) p->write.current->offset) >> 32)); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = htonl((uint32_t) ((uint64_t) p->write.current->offset)); - flags = p->write.current->seek_mode & PA_FLAG_SEEKMASK; + flags = (uint32_t) (p->write.current->seek_mode & PA_FLAG_SEEKMASK); if (p->use_shm) { uint32_t block_id, shm_id; @@ -542,7 +542,7 @@ static void prepare_next_write_item(pa_pstream *p) { } if (send_payload) { - p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl((uint32_t) p->write.current->chunk.length); p->write.memchunk = p->write.current->chunk; pa_memblock_ref(p->write.memchunk.memblock); p->write.data = NULL; @@ -607,7 +607,7 @@ static int do_write(pa_pstream *p) { if (release_memblock) pa_memblock_release(release_memblock); - p->write.index += r; + p->write.index += (size_t) r; if (p->write.index >= PA_PSTREAM_DESCRIPTOR_SIZE + ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH])) { pa_assert(p->write.current); @@ -675,7 +675,7 @@ static int do_read(pa_pstream *p) { if (release_memblock) pa_memblock_release(release_memblock); - p->read.index += r; + p->read.index += (size_t) r; if (p->read.index == PA_PSTREAM_DESCRIPTOR_SIZE) { uint32_t flags, length, channel; @@ -769,7 +769,7 @@ static int do_read(pa_pstream *p) { if (p->read.memblock && p->recieve_memblock_callback) { /* Is this memblock data? Than pass it to the user */ - l = (p->read.index - r) < PA_PSTREAM_DESCRIPTOR_SIZE ? p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE : (size_t) r; + l = (p->read.index - (size_t) r) < PA_PSTREAM_DESCRIPTOR_SIZE ? (size_t) (p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE) : (size_t) r; if (l > 0) { pa_memchunk chunk; diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index c82f4c1e..b2d512c8 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -373,7 +373,7 @@ size_t pa_resampler_max_block_size(pa_resampler *r) { /* We deduce the "largest" sample spec we're using during the * conversion */ - ss.channels = PA_MAX(r->i_ss.channels, r->o_ss.channels); + ss.channels = (uint8_t) (PA_MAX(r->i_ss.channels, r->o_ss.channels)); /* We silently assume that the format enum is ordered by size */ ss.format = PA_MAX(r->i_ss.format, r->o_ss.format); @@ -642,7 +642,7 @@ static void calc_map_table(pa_resampler *r) { if (n > 0) for (ic = 0; ic < r->i_ss.channels; ic++) if (on_left(r->i_cm.map[ic])) { - r->map_table[oc][ic] = 1.0 / n; + r->map_table[oc][ic] = 1.0f / (float) n; ic_connected[ic] = TRUE; } @@ -663,7 +663,7 @@ static void calc_map_table(pa_resampler *r) { if (n > 0) for (ic = 0; ic < r->i_ss.channels; ic++) if (on_right(r->i_cm.map[ic])) { - r->map_table[oc][ic] = 1.0 / n; + r->map_table[oc][ic] = 1.0f / (float) n; ic_connected[ic] = TRUE; } @@ -684,7 +684,7 @@ static void calc_map_table(pa_resampler *r) { if (n > 0) { for (ic = 0; ic < r->i_ss.channels; ic++) if (on_center(r->i_cm.map[ic])) { - r->map_table[oc][ic] = 1.0 / n; + r->map_table[oc][ic] = 1.0f / (float) n; ic_connected[ic] = TRUE; } } else { @@ -701,7 +701,7 @@ static void calc_map_table(pa_resampler *r) { if (n > 0) for (ic = 0; ic < r->i_ss.channels; ic++) if (on_left(r->i_cm.map[ic]) || on_right(r->i_cm.map[ic])) { - r->map_table[oc][ic] = 1.0 / n; + r->map_table[oc][ic] = 1.0f / (float) n; ic_connected[ic] = TRUE; } @@ -716,7 +716,11 @@ static void calc_map_table(pa_resampler *r) { * channels for LFE. */ for (ic = 0; ic < r->i_ss.channels; ic++) { - r->map_table[oc][ic] = 1.0 / r->i_ss.channels; + + if (!(r->flags & PA_RESAMPLER_NO_LFE)) + r->map_table[oc][ic] = 1.0f / (float) r->i_ss.channels; + else + r->map_table[oc][ic] = 0; /* Please note that a channel connected to LFE * doesn't really count as connected. */ @@ -763,12 +767,12 @@ static void calc_map_table(pa_resampler *r) { for (ic = 0; ic < r->i_ss.channels; ic++) { if (ic_connected[ic]) { - r->map_table[oc][ic] *= .9; + r->map_table[oc][ic] *= .9f; continue; } if (on_left(r->i_cm.map[ic])) - r->map_table[oc][ic] = .1 / ic_unconnected_left; + r->map_table[oc][ic] = .1f / (float) ic_unconnected_left; } } } @@ -788,12 +792,12 @@ static void calc_map_table(pa_resampler *r) { for (ic = 0; ic < r->i_ss.channels; ic++) { if (ic_connected[ic]) { - r->map_table[oc][ic] *= .9; + r->map_table[oc][ic] *= .9f; continue; } if (on_right(r->i_cm.map[ic])) - r->map_table[oc][ic] = .1 / ic_unconnected_right; + r->map_table[oc][ic] = .1f / (float) ic_unconnected_right; } } } @@ -814,12 +818,12 @@ static void calc_map_table(pa_resampler *r) { for (ic = 0; ic < r->i_ss.channels; ic++) { if (ic_connected[ic]) { - r->map_table[oc][ic] *= .9; + r->map_table[oc][ic] *= .9f; continue; } if (on_center(r->i_cm.map[ic])) { - r->map_table[oc][ic] = .1 / ic_unconnected_center; + r->map_table[oc][ic] = .1f / (float) ic_unconnected_center; mixed_in = TRUE; } } @@ -840,18 +844,18 @@ static void calc_map_table(pa_resampler *r) { for (ic = 0; ic < r->i_ss.channels; ic++) { if (ic_connected[ic]) { - r->map_table[oc][ic] *= .75; + r->map_table[oc][ic] *= .75f; continue; } if (on_center(r->i_cm.map[ic])) - r->map_table[oc][ic] = .375 / ic_unconnected_center; + r->map_table[oc][ic] = .375f / (float) ic_unconnected_center; } } } } - if (ic_unconnected_lfe > 0) { + if (ic_unconnected_lfe > 0 && !(r->flags & PA_RESAMPLER_NO_LFE)) { /* OK, so there is an unconnected LFE channel. Let's mix * it into all channels, with factor 0.375 */ @@ -862,7 +866,7 @@ static void calc_map_table(pa_resampler *r) { continue; for (oc = 0; oc < r->o_ss.channels; oc++) - r->map_table[oc][ic] = 0.375 / ic_unconnected_lfe; + r->map_table[oc][ic] = 0.375f / (float) ic_unconnected_lfe; } } } @@ -905,7 +909,7 @@ static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input) if (!r->to_work_format_func || !input->length) return input; - n_samples = (input->length / r->i_fz) * r->i_ss.channels; + n_samples = (unsigned) ((input->length / r->i_fz) * r->i_ss.channels); r->buf1.index = 0; r->buf1.length = r->w_sz * n_samples; @@ -974,7 +978,7 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { if (!r->map_required || !input->length) return input; - in_n_samples = input->length / r->w_sz; + in_n_samples = (unsigned) (input->length / r->w_sz); n_frames = in_n_samples / r->i_ss.channels; out_n_samples = n_frames * r->o_ss.channels; @@ -994,8 +998,8 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { memset(dst, 0, r->buf2.length); - o_skip = r->w_sz * r->o_ss.channels; - i_skip = r->w_sz * r->i_ss.channels; + o_skip = (int) (r->w_sz * r->o_ss.channels); + i_skip = (int) (r->w_sz * r->i_ss.channels); switch (r->work_format) { case PA_SAMPLE_FLOAT32NE: @@ -1013,7 +1017,7 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { (float*) dst + oc, o_skip, (float*) dst + oc, o_skip, (float*) src + ic, i_skip, - n_frames, + (int) n_frames, &one, &r->map_table[oc][ic]); } } @@ -1037,7 +1041,7 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { (int16_t*) dst + oc, o_skip, (int16_t*) dst + oc, o_skip, (int16_t*) src + ic, i_skip, - n_frames, + (int) n_frames, &one, &one); } else @@ -1046,8 +1050,8 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { (int16_t*) dst + oc, o_skip, (int16_t*) dst + oc, o_skip, (int16_t*) src + ic, i_skip, - n_frames, - 1.0, r->map_table[oc][ic]); + (int) n_frames, + 1.0f, r->map_table[oc][ic]); } } @@ -1077,8 +1081,8 @@ static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) { if (!r->impl_resample || !input->length) return input; - in_n_samples = input->length / r->w_sz; - in_n_frames = in_n_samples / r->o_ss.channels; + in_n_samples = (unsigned) (input->length / r->w_sz); + in_n_frames = (unsigned) (in_n_samples / r->o_ss.channels); out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+EXTRA_FRAMES; out_n_samples = out_n_frames * r->o_ss.channels; @@ -1112,8 +1116,8 @@ static pa_memchunk *convert_from_work_format(pa_resampler *r, pa_memchunk *input if (!r->from_work_format_func || !input->length) return input; - n_samples = input->length / r->w_sz; - n_frames = n_samples / r->o_ss.channels; + n_samples = (unsigned) (input->length / r->w_sz); + n_frames = n_samples / r->o_ss.channels; r->buf4.index = 0; r->buf4.length = r->o_fz * n_frames; @@ -1178,10 +1182,10 @@ static void libsamplerate_resample(pa_resampler *r, const pa_memchunk *input, un memset(&data, 0, sizeof(data)); data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); - data.input_frames = in_n_frames; + data.input_frames = (long int) in_n_frames; data.data_out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index); - data.output_frames = *out_n_frames; + data.output_frames = (long int) *out_n_frames; data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate; data.end_of_input = 0; @@ -1192,7 +1196,7 @@ static void libsamplerate_resample(pa_resampler *r, const pa_memchunk *input, un pa_memblock_release(input->memblock); pa_memblock_release(output->memblock); - *out_n_frames = data.output_frames_gen; + *out_n_frames = (unsigned) data.output_frames_gen; } static void libsamplerate_update_rates(pa_resampler *r) { @@ -1354,7 +1358,7 @@ static void trivial_resample(pa_resampler *r, const pa_memchunk *input, unsigned pa_assert(o_index * fz < pa_memblock_get_length(output->memblock)); oil_memcpy((uint8_t*) dst + fz * o_index, - (uint8_t*) src + fz * j, fz); + (uint8_t*) src + fz * j, (int) fz); } pa_memblock_release(input->memblock); @@ -1414,40 +1418,46 @@ static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned i unsigned j; j = ((r->peaks.o_counter * r->i_ss.rate) / r->o_ss.rate); - j = j > r->peaks.i_counter ? j - r->peaks.i_counter : 0; - if (j >= in_n_frames) - break; + if (j > r->peaks.i_counter) + j -= r->peaks.i_counter; + else + j = 0; pa_assert(o_index * fz < pa_memblock_get_length(output->memblock)); if (r->work_format == PA_SAMPLE_S16NE) { unsigned i, c; - int16_t *s = (int16_t*) ((uint8_t*) src + fz * j); + int16_t *s = (int16_t*) ((uint8_t*) src + fz * start); int16_t *d = (int16_t*) ((uint8_t*) dst + fz * o_index); - for (i = start; i <= j; i++) + for (i = start; i <= j && i < in_n_frames; i++) + for (c = 0; c < r->o_ss.channels; c++, s++) { int16_t n; - n = *s < 0 ? -*s : *s; + n = (int16_t) (*s < 0 ? -*s : *s); - if (n > r->peaks.max_i[c]) + if (PA_UNLIKELY(n > r->peaks.max_i[c])) r->peaks.max_i[c] = n; } + if (i >= in_n_frames) + break; + for (c = 0; c < r->o_ss.channels; c++, d++) { - *d = r->peaks.max_i[c]; - r->peaks.max_i[c] = 0; + *d = r->peaks.max_i[c]; + r->peaks.max_i[c] = 0; } + } else { unsigned i, c; - float *s = (float*) ((uint8_t*) src + fz * j); + float *s = (float*) ((uint8_t*) src + fz * start); float *d = (float*) ((uint8_t*) dst + fz * o_index); pa_assert(r->work_format == PA_SAMPLE_FLOAT32NE); - for (i = start; i <= j; i++) + for (i = start; i <= j && i < in_n_frames; i++) for (c = 0; c < r->o_ss.channels; c++, s++) { float n = fabsf(*s); @@ -1455,13 +1465,16 @@ static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned i r->peaks.max_f[c] = n; } + if (i >= in_n_frames) + break; + for (c = 0; c < r->o_ss.channels; c++, d++) { *d = r->peaks.max_f[c]; r->peaks.max_f[c] = 0; } } - start = j+1; + start = j; } pa_memblock_release(input->memblock); @@ -1523,7 +1536,7 @@ static void ffmpeg_resample(pa_resampler *r, const pa_memchunk *input, unsigned p = pa_memblock_acquire(b); /* Copy the remaining data into it */ - l = r->ffmpeg.buf[c].length; + l = (unsigned) r->ffmpeg.buf[c].length; if (r->ffmpeg.buf[c].memblock) { t = (int16_t*) ((uint8_t*) pa_memblock_acquire(r->ffmpeg.buf[c].memblock) + r->ffmpeg.buf[c].index); memcpy(p, t, l); @@ -1543,18 +1556,18 @@ static void ffmpeg_resample(pa_resampler *r, const pa_memchunk *input, unsigned pa_memblock_release(input->memblock); /* Calculate the resulting number of frames */ - in = in_n_frames + l / sizeof(int16_t); + in = (unsigned) in_n_frames + l / (unsigned) sizeof(int16_t); /* Allocate buffer for the result */ w = pa_memblock_new(r->mempool, *out_n_frames * sizeof(int16_t)); q = pa_memblock_acquire(w); /* Now, resample */ - used_frames = av_resample(r->ffmpeg.state, - q, p, - &consumed_frames, - in, *out_n_frames, - c >= (unsigned) r->o_ss.channels-1); + used_frames = (unsigned) av_resample(r->ffmpeg.state, + q, p, + &consumed_frames, + (int) in, (int) *out_n_frames, + c >= (unsigned) (r->o_ss.channels-1)); pa_memblock_release(b); @@ -1562,8 +1575,8 @@ static void ffmpeg_resample(pa_resampler *r, const pa_memchunk *input, unsigned pa_assert(consumed_frames <= (int) in); if (consumed_frames < (int) in) { r->ffmpeg.buf[c].memblock = b; - r->ffmpeg.buf[c].index = consumed_frames * sizeof(int16_t); - r->ffmpeg.buf[c].length = (in - consumed_frames) * sizeof(int16_t); + r->ffmpeg.buf[c].index = (size_t) consumed_frames * sizeof(int16_t); + r->ffmpeg.buf[c].length = (size_t) (in - (unsigned) consumed_frames) * sizeof(int16_t); } else pa_memblock_unref(b); @@ -1605,7 +1618,7 @@ static int ffmpeg_init(pa_resampler *r) { * internally only uses these hardcoded values, so let's use them * here for now as well until ffmpeg makes this configurable. */ - if (!(r->ffmpeg.state = av_resample_init(r->o_ss.rate, r->i_ss.rate, 16, 10, 0, 0.8))) + if (!(r->ffmpeg.state = av_resample_init((int) r->o_ss.rate, (int) r->i_ss.rate, 16, 10, 0, 0.8))) return -1; r->impl_free = ffmpeg_free; diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h index 5e302a9b..87110cc2 100644 --- a/src/pulsecore/resampler.h +++ b/src/pulsecore/resampler.h @@ -49,9 +49,10 @@ typedef enum pa_resample_method { } pa_resample_method_t; typedef enum pa_resample_flags { - PA_RESAMPLER_VARIABLE_RATE = 1, - PA_RESAMPLER_NO_REMAP = 2, /* implies NO_REMIX */ - PA_RESAMPLER_NO_REMIX = 4 + PA_RESAMPLER_VARIABLE_RATE = 0x0001U, + PA_RESAMPLER_NO_REMAP = 0x0002U, /* implies NO_REMIX */ + PA_RESAMPLER_NO_REMIX = 0x0004U, + PA_RESAMPLER_NO_LFE = 0x0008U } pa_resample_flags_t; pa_resampler* pa_resampler_new( diff --git a/src/pulsecore/rtclock.h b/src/pulsecore/rtclock.h index 705de48f..aa2cdace 100644 --- a/src/pulsecore/rtclock.h +++ b/src/pulsecore/rtclock.h @@ -23,6 +23,7 @@ ***/ #include <pulsecore/macro.h> +#include <pulse/sample.h> struct timeval; diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c index a67a5516..543262bc 100644 --- a/src/pulsecore/rtpoll.c +++ b/src/pulsecore/rtpoll.c @@ -394,7 +394,7 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) { #endif #endif - r = poll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || p->timer_enabled) ? (timeout.tv_sec*1000) + (timeout.tv_usec / 1000) : -1); + r = poll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || p->timer_enabled) ? (int) ((timeout.tv_sec*1000) + (timeout.tv_usec / 1000)) : -1); if (r < 0) { if (errno == EAGAIN || errno == EINTR) diff --git a/src/pulsecore/rtsig.c b/src/pulsecore/rtsig.c index 4df217c3..4cd6aa8f 100644 --- a/src/pulsecore/rtsig.c +++ b/src/pulsecore/rtsig.c @@ -40,7 +40,7 @@ static void _free_rtsig(void *p) { pa_rtsig_put(PA_PTR_TO_INT(p)); } -PA_STATIC_FLIST_DECLARE(rtsig_flist, pa_make_power_of_two(SIGRTMAX-SIGRTMIN+1), NULL); +PA_STATIC_FLIST_DECLARE(rtsig_flist, pa_make_power_of_two((unsigned) (SIGRTMAX-SIGRTMIN+1)), NULL); PA_STATIC_TLS_DECLARE(rtsig_tls, _free_rtsig); static pa_atomic_t rtsig_current = PA_ATOMIC_INIT(-1); diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index b42b79d1..9f0f795c 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -31,6 +31,8 @@ #include <liboil/liboilfuncs.h> #include <liboil/liboil.h> +#include <pulse/timeval.h> + #include <pulsecore/log.h> #include <pulsecore/macro.h> #include <pulsecore/g711.h> @@ -85,7 +87,6 @@ static uint8_t silence_byte(pa_sample_format_t format) { default: pa_assert_not_reached(); } - return 0; } void* pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { @@ -97,56 +98,62 @@ void* pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { return p; } -static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_sample_spec *spec) { - unsigned k; - - pa_assert(streams); - pa_assert(spec); +static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volume) { + unsigned channel; - for (k = 0; k < nstreams; k++) { - unsigned channel; + pa_assert(linear); + pa_assert(volume); - for (channel = 0; channel < spec->channels; channel++) { - pa_mix_info *m = streams + k; - m->linear[channel].i = (int32_t) (pa_sw_volume_to_linear(m->volume.values[channel]) * 0x10000); - } - } + for (channel = 0; channel < volume->channels; channel++) + linear[channel] = (int32_t) lrint(pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); } -static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volume) { +static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) { unsigned channel; pa_assert(linear); pa_assert(volume); for (channel = 0; channel < volume->channels; channel++) - linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); + linear[channel] = (float) pa_sw_volume_to_linear(volume->values[channel]); } -static void calc_linear_float_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_sample_spec *spec) { - unsigned k; +static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) { + unsigned k, channel; + float linear[PA_CHANNELS_MAX]; pa_assert(streams); pa_assert(spec); + pa_assert(volume); + + calc_linear_float_volume(linear, volume); for (k = 0; k < nstreams; k++) { - unsigned channel; for (channel = 0; channel < spec->channels; channel++) { pa_mix_info *m = streams + k; - m->linear[channel].f = pa_sw_volume_to_linear(m->volume.values[channel]); + m->linear[channel].i = (int32_t) lrint(pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel] * 0x10000); } } } -static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) { - unsigned channel; +static void calc_linear_float_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) { + unsigned k, channel; + float linear[PA_CHANNELS_MAX]; - pa_assert(linear); + pa_assert(streams); + pa_assert(spec); pa_assert(volume); - for (channel = 0; channel < volume->channels; channel++) - linear[channel] = pa_sw_volume_to_linear(volume->values[channel]); + calc_linear_float_volume(linear, volume); + + for (k = 0; k < nstreams; k++) { + + for (channel = 0; channel < spec->channels; channel++) { + pa_mix_info *m = streams + k; + m->linear[channel].f = (float) (pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel]); + } + } } size_t pa_mix( @@ -160,7 +167,8 @@ size_t pa_mix( pa_cvolume full_volume; unsigned k; - size_t d = 0; + unsigned z; + void *end; pa_assert(streams); pa_assert(data); @@ -170,45 +178,46 @@ size_t pa_mix( if (!volume) volume = pa_cvolume_reset(&full_volume, spec->channels); + if (mute || pa_cvolume_is_muted(volume) || nstreams <= 0) { + pa_silence_memory(data, length, spec); + return length; + } + for (k = 0; k < nstreams; k++) streams[k].ptr = (uint8_t*) pa_memblock_acquire(streams[k].chunk.memblock) + streams[k].chunk.index; + for (z = 0; z < nstreams; z++) + if (length > streams[z].chunk.length) + length = streams[z].chunk.length; + + end = (uint8_t*) data + length; + switch (spec->format) { case PA_SAMPLE_S16NE:{ unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); - for (d = 0;; d += sizeof(int16_t)) { + while (data < end) { int32_t sum = 0; unsigned i; - if (PA_UNLIKELY(d >= length)) - goto finish; - for (i = 0; i < nstreams; i++) { pa_mix_info *m = streams + i; int32_t v, cv = m->linear[channel].i; - if (PA_UNLIKELY(d >= m->chunk.length)) - goto finish; - - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = *((int16_t*) m->ptr); - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = *((int16_t*) m->ptr); + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(int16_t); } sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); - sum = (sum * linear[channel]) / 0x10000; *((int16_t*) data) = (int16_t) sum; data = (uint8_t*) data + sizeof(int16_t); @@ -222,38 +231,28 @@ size_t pa_mix( case PA_SAMPLE_S16RE:{ unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); - for (d = 0;; d += sizeof(int16_t)) { + while (data < end) { int32_t sum = 0; unsigned i; - if (PA_UNLIKELY(d >= length)) - goto finish; - for (i = 0; i < nstreams; i++) { pa_mix_info *m = streams + i; int32_t v, cv = m->linear[channel].i; - if (PA_UNLIKELY(d >= m->chunk.length)) - goto finish; - - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = PA_INT16_SWAP(*((int16_t*) m->ptr)); - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = PA_INT16_SWAP(*((int16_t*) m->ptr)); + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(int16_t); } sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); - sum = (sum * linear[channel]) / 0x10000; *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum); data = (uint8_t*) data + sizeof(int16_t); @@ -267,39 +266,29 @@ size_t pa_mix( case PA_SAMPLE_S32NE:{ unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); - for (d = 0;; d += sizeof(int32_t)) { + while (data < end) { int64_t sum = 0; unsigned i; - if (PA_UNLIKELY(d >= length)) - goto finish; - for (i = 0; i < nstreams; i++) { pa_mix_info *m = streams + i; - int64_t v; int32_t cv = m->linear[channel].i; + int64_t v; - if (PA_UNLIKELY(d >= m->chunk.length)) - goto finish; - - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = *((int32_t*) m->ptr); - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = *((int32_t*) m->ptr); + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(int32_t); } sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); - sum = (sum * linear[channel]) / 0x10000; *((int32_t*) data) = (int32_t) sum; data = (uint8_t*) data + sizeof(int32_t); @@ -313,39 +302,29 @@ size_t pa_mix( case PA_SAMPLE_S32RE:{ unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); - for (d = 0;; d += sizeof(int32_t)) { + while (data < end) { int64_t sum = 0; unsigned i; - if (PA_UNLIKELY(d >= length)) - goto finish; - for (i = 0; i < nstreams; i++) { pa_mix_info *m = streams + i; - int64_t v; int32_t cv = m->linear[channel].i; + int64_t v; - if (PA_UNLIKELY(d >= m->chunk.length)) - goto finish; - - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = PA_INT32_SWAP(*((int32_t*) m->ptr)); - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = PA_INT32_SWAP(*((int32_t*) m->ptr)); + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(int32_t); } sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); - sum = (sum * linear[channel]) / 0x10000; *((int32_t*) data) = PA_INT32_SWAP((int32_t) sum); data = (uint8_t*) data + sizeof(int32_t); @@ -359,37 +338,27 @@ size_t pa_mix( case PA_SAMPLE_U8: { unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); - for (d = 0;; d ++) { + while (data < end) { int32_t sum = 0; unsigned i; - if (PA_UNLIKELY(d >= length)) - goto finish; - for (i = 0; i < nstreams; i++) { pa_mix_info *m = streams + i; int32_t v, cv = m->linear[channel].i; - if (PA_UNLIKELY(d >= m->chunk.length)) - goto finish; - - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = (int32_t) *((uint8_t*) m->ptr) - 0x80; - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = (int32_t) *((uint8_t*) m->ptr) - 0x80; + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + 1; } - sum = (sum * linear[channel]) / 0x10000; sum = PA_CLAMP_UNLIKELY(sum, -0x80, 0x7F); *((uint8_t*) data) = (uint8_t) (sum + 0x80); @@ -404,39 +373,29 @@ size_t pa_mix( case PA_SAMPLE_ULAW: { unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); - for (d = 0;; d ++) { + while (data < end) { int32_t sum = 0; unsigned i; - if (PA_UNLIKELY(d >= length)) - goto finish; - for (i = 0; i < nstreams; i++) { pa_mix_info *m = streams + i; int32_t v, cv = m->linear[channel].i; - if (PA_UNLIKELY(d >= m->chunk.length)) - goto finish; - - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = (int32_t) st_ulaw2linear16(*((uint8_t*) m->ptr)); - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = (int32_t) st_ulaw2linear16(*((uint8_t*) m->ptr)); + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + 1; } sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); - sum = (sum * linear[channel]) / 0x10000; - *((uint8_t*) data) = (uint8_t) st_14linear2ulaw(sum >> 2); + *((uint8_t*) data) = (uint8_t) st_14linear2ulaw((int16_t) sum >> 2); data = (uint8_t*) data + 1; @@ -449,39 +408,29 @@ size_t pa_mix( case PA_SAMPLE_ALAW: { unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); - for (d = 0;; d ++) { + while (data < end) { int32_t sum = 0; unsigned i; - if (PA_UNLIKELY(d >= length)) - goto finish; - for (i = 0; i < nstreams; i++) { pa_mix_info *m = streams + i; int32_t v, cv = m->linear[channel].i; - if (PA_UNLIKELY(d >= m->chunk.length)) - goto finish; - - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = (int32_t) st_alaw2linear16(*((uint8_t*) m->ptr)); - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = (int32_t) st_alaw2linear16(*((uint8_t*) m->ptr)); + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + 1; } sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); - sum = (sum * linear[channel]) / 0x10000; - *((uint8_t*) data) = (uint8_t) st_13linear2alaw(sum >> 3); + *((uint8_t*) data) = (uint8_t) st_13linear2alaw((int16_t) sum >> 3); data = (uint8_t*) data + 1; @@ -494,37 +443,27 @@ size_t pa_mix( case PA_SAMPLE_FLOAT32NE: { unsigned channel = 0; - float linear[PA_CHANNELS_MAX]; - calc_linear_float_stream_volumes(streams, nstreams, spec); - calc_linear_float_volume(linear, volume); + calc_linear_float_stream_volumes(streams, nstreams, volume, spec); - for (d = 0;; d += sizeof(float)) { + while (data < end) { float sum = 0; unsigned i; - if (PA_UNLIKELY(d >= length)) - goto finish; - for (i = 0; i < nstreams; i++) { pa_mix_info *m = streams + i; float v, cv = m->linear[channel].f; - if (PA_UNLIKELY(d >= m->chunk.length)) - goto finish; - - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = *((float*) m->ptr); - v *= cv; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = *((float*) m->ptr); + v *= cv; sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(float); } - sum *= linear[channel]; *((float*) data) = sum; data = (uint8_t*) data + sizeof(float); @@ -540,38 +479,27 @@ size_t pa_mix( unsigned channel = 0; float linear[PA_CHANNELS_MAX]; - calc_linear_float_stream_volumes(streams, nstreams, spec); - calc_linear_float_volume(linear, volume); + calc_linear_float_stream_volumes(streams, nstreams, volume, spec); - for (d = 0;; d += sizeof(float)) { + while (data < end) { float sum = 0; unsigned i; - if (PA_UNLIKELY(d >= length)) - goto finish; - for (i = 0; i < nstreams; i++) { pa_mix_info *m = streams + i; float v, cv = m->linear[channel].f; - if (PA_UNLIKELY(d >= m->chunk.length)) - goto finish; - - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - uint32_t z = *(uint32_t*) m->ptr; - z = PA_UINT32_SWAP(z); - v = *((float*) &z); - v *= cv; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = PA_FLOAT32_SWAP(*(float*) m->ptr); + v *= cv; sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(float); } - sum *= linear[channel]; - *((uint32_t*) data) = PA_UINT32_SWAP(*(uint32_t*) &sum); + *((float*) data) = PA_FLOAT32_SWAP(sum); data = (uint8_t*) data + sizeof(float); @@ -583,16 +511,14 @@ size_t pa_mix( } default: - pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format)); + pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format)); pa_assert_not_reached(); } -finish: - for (k = 0; k < nstreams; k++) pa_memblock_release(streams[k].chunk.memblock); - return d; + return length; } @@ -624,14 +550,15 @@ void pa_volume_memchunk( switch (spec->format) { case PA_SAMPLE_S16NE: { - int16_t *d; - size_t n; + int16_t *d, *e; unsigned channel; int32_t linear[PA_CHANNELS_MAX]; calc_linear_integer_volume(linear, volume); - for (channel = 0, d = ptr, n = c->length/sizeof(int16_t); n > 0; d++, n--) { + e = (int16_t*) ptr + c->length/sizeof(int16_t); + + for (channel = 0, d = ptr; d < e; d++) { int32_t t; t = (int32_t)(*d); @@ -646,17 +573,18 @@ void pa_volume_memchunk( } case PA_SAMPLE_S16RE: { - int16_t *d; - size_t n; + int16_t *d, *e; unsigned channel; int32_t linear[PA_CHANNELS_MAX]; calc_linear_integer_volume(linear, volume); - for (channel = 0, d = ptr, n = c->length/sizeof(int16_t); n > 0; d++, n--) { + e = (int16_t*) ptr + c->length/sizeof(int16_t); + + for (channel = 0, d = ptr; d < e; d++) { int32_t t; - t = (int32_t)(PA_INT16_SWAP(*d)); + t = (int32_t) PA_INT16_SWAP(*d); t = (t * linear[channel]) / 0x10000; t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF); *d = PA_INT16_SWAP((int16_t) t); @@ -669,14 +597,15 @@ void pa_volume_memchunk( } case PA_SAMPLE_S32NE: { - int32_t *d; - size_t n; + int32_t *d, *e; unsigned channel; int32_t linear[PA_CHANNELS_MAX]; calc_linear_integer_volume(linear, volume); - for (channel = 0, d = ptr, n = c->length/sizeof(int32_t); n > 0; d++, n--) { + e = (int32_t*) ptr + c->length/sizeof(int32_t); + + for (channel = 0, d = ptr; d < e; d++) { int64_t t; t = (int64_t)(*d); @@ -691,17 +620,18 @@ void pa_volume_memchunk( } case PA_SAMPLE_S32RE: { - int32_t *d; - size_t n; + int32_t *d, *e; unsigned channel; int32_t linear[PA_CHANNELS_MAX]; calc_linear_integer_volume(linear, volume); - for (channel = 0, d = ptr, n = c->length/sizeof(int32_t); n > 0; d++, n--) { + e = (int32_t*) ptr + c->length/sizeof(int32_t); + + for (channel = 0, d = ptr; d < e; d++) { int64_t t; - t = (int64_t)(PA_INT32_SWAP(*d)); + t = (int64_t) PA_INT32_SWAP(*d); t = (t * linear[channel]) / 0x10000; t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL); *d = PA_INT32_SWAP((int32_t) t); @@ -714,14 +644,15 @@ void pa_volume_memchunk( } case PA_SAMPLE_U8: { - uint8_t *d; - size_t n; + uint8_t *d, *e; unsigned channel; int32_t linear[PA_CHANNELS_MAX]; calc_linear_integer_volume(linear, volume); - for (channel = 0, d = ptr, n = c->length; n > 0; d++, n--) { + e = (uint8_t*) ptr + c->length; + + for (channel = 0, d = ptr; d < e; d++) { int32_t t; t = (int32_t) *d - 0x80; @@ -736,20 +667,21 @@ void pa_volume_memchunk( } case PA_SAMPLE_ULAW: { - uint8_t *d; - size_t n; + uint8_t *d, *e; unsigned channel; int32_t linear[PA_CHANNELS_MAX]; calc_linear_integer_volume(linear, volume); - for (channel = 0, d = ptr, n = c->length; n > 0; d++, n--) { + e = (uint8_t*) ptr + c->length; + + for (channel = 0, d = ptr; d < e; d++) { int32_t t; t = (int32_t) st_ulaw2linear16(*d); t = (t * linear[channel]) / 0x10000; t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF); - *d = (uint8_t) st_14linear2ulaw(t >> 2); + *d = (uint8_t) st_14linear2ulaw((int16_t) t >> 2); if (PA_UNLIKELY(++channel >= spec->channels)) channel = 0; @@ -758,20 +690,21 @@ void pa_volume_memchunk( } case PA_SAMPLE_ALAW: { - uint8_t *d; - size_t n; + uint8_t *d, *e; unsigned channel; int32_t linear[PA_CHANNELS_MAX]; calc_linear_integer_volume(linear, volume); - for (channel = 0, d = ptr, n = c->length; n > 0; d++, n--) { + e = (uint8_t*) ptr + c->length; + + for (channel = 0, d = ptr; d < e; d++) { int32_t t; t = (int32_t) st_alaw2linear16(*d); t = (t * linear[channel]) / 0x10000; t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF); - *d = (uint8_t) st_13linear2alaw(t >> 3); + *d = (uint8_t) st_13linear2alaw((int16_t) t >> 3); if (PA_UNLIKELY(++channel >= spec->channels)) channel = 0; @@ -786,8 +719,8 @@ void pa_volume_memchunk( unsigned channel; d = ptr; - skip = spec->channels * sizeof(float); - n = c->length/sizeof(float)/spec->channels; + skip = (int) (spec->channels * sizeof(float)); + n = (unsigned) (c->length/sizeof(float)/spec->channels); for (channel = 0; channel < spec->channels; channel ++) { float v, *t; @@ -797,28 +730,26 @@ void pa_volume_memchunk( v = (float) pa_sw_volume_to_linear(volume->values[channel]); t = d + channel; - oil_scalarmult_f32(t, skip, t, skip, &v, n); + oil_scalarmult_f32(t, skip, t, skip, &v, (int) n); } break; } case PA_SAMPLE_FLOAT32RE: { - uint32_t *d; - size_t n; + float *d, *e; unsigned channel; float linear[PA_CHANNELS_MAX]; calc_linear_float_volume(linear, volume); - for (channel = 0, d = ptr, n = c->length/sizeof(float); n > 0; d++, n--) { + e = (float*) ptr + c->length/sizeof(float); + + for (channel = 0, d = ptr; d < e; d++) { float t; - uint32_t z; - z = PA_UINT32_SWAP(*d); - t = *(float*) &z; + t = PA_FLOAT32_SWAP(*d); t *= linear[channel]; - z = *(uint32_t*) &t; - *d = PA_UINT32_SWAP(z); + *d = PA_FLOAT32_SWAP(t); if (PA_UNLIKELY(++channel >= spec->channels)) channel = 0; @@ -846,7 +777,7 @@ size_t pa_frame_align(size_t l, const pa_sample_spec *ss) { return (l/fs) * fs; } -int pa_frame_aligned(size_t l, const pa_sample_spec *ss) { +pa_bool_t pa_frame_aligned(size_t l, const pa_sample_spec *ss) { size_t fs; pa_assert(ss); @@ -877,7 +808,7 @@ void pa_interleave(const void *src[], unsigned channels, void *dst, size_t ss, u d = (uint8_t*) dst + c * ss; for (j = 0; j < n; j ++) { - oil_memcpy(d, s, ss); + oil_memcpy(d, s, (int) ss); s = (uint8_t*) s + ss; d = (uint8_t*) d + fs; } @@ -905,7 +836,7 @@ void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss, d = dst[c]; for (j = 0; j < n; j ++) { - oil_memcpy(d, s, ss); + oil_memcpy(d, s, (int) ss); s = (uint8_t*) s + fs; d = (uint8_t*) d + ss; } @@ -1008,7 +939,7 @@ void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const vo if (format == PA_SAMPLE_FLOAT32NE) { float minus_one = -1.0, plus_one = 1.0; - oil_clip_f32(d, dstr, s, sstr, n, &minus_one, &plus_one); + oil_clip_f32(d, (int) dstr, s, (int) sstr, (int) n, &minus_one, &plus_one); } else { pa_assert(format == PA_SAMPLE_FLOAT32RE); @@ -1017,7 +948,7 @@ void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const vo float f; f = PA_FLOAT32_SWAP(*s); - f = PA_CLAMP_UNLIKELY(f, -1.0, 1.0); + f = PA_CLAMP_UNLIKELY(f, -1.0f, 1.0f); *d = PA_FLOAT32_SWAP(f); s = (const float*) ((const uint8_t*) s + sstr); @@ -1025,3 +956,34 @@ void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const vo } } } + +/* Similar to pa_bytes_to_usec() but rounds up, not down */ + +pa_usec_t pa_bytes_to_usec_round_up(uint64_t length, const pa_sample_spec *spec) { + size_t fs; + pa_usec_t usec; + + pa_assert(spec); + + fs = pa_frame_size(spec); + length = (length + fs - 1) / fs; + + usec = (pa_usec_t) length * PA_USEC_PER_SEC; + + return (usec + spec->rate - 1) / spec->rate; +} + +/* Similar to pa_usec_to_bytes() but rounds up, not down */ + +size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec) { + uint64_t u; + pa_assert(spec); + + u = (uint64_t) t * (uint64_t) spec->rate; + + u = (u + PA_USEC_PER_SEC - 1) / PA_USEC_PER_SEC; + + u *= pa_frame_size(spec); + + return (size_t) u; +} diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h index cef70750..2fe2c81d 100644 --- a/src/pulsecore/sample-util.h +++ b/src/pulsecore/sample-util.h @@ -71,11 +71,14 @@ void pa_volume_memchunk( size_t pa_frame_align(size_t l, const pa_sample_spec *ss) PA_GCC_PURE; -int pa_frame_aligned(size_t l, const pa_sample_spec *ss) PA_GCC_PURE; +pa_bool_t pa_frame_aligned(size_t l, const pa_sample_spec *ss) PA_GCC_PURE; void pa_interleave(const void *src[], unsigned channels, void *dst, size_t ss, unsigned n); void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss, unsigned n); void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const void *src, size_t sstr, unsigned n); +pa_usec_t pa_bytes_to_usec_round_up(uint64_t length, const pa_sample_spec *spec); +size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec); + #endif diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c index 41670f27..159c4655 100644 --- a/src/pulsecore/sconv-s16le.c +++ b/src/pulsecore/sconv-s16le.c @@ -70,13 +70,13 @@ void pa_sconv_s16le_to_float32ne(unsigned n, const int16_t *a, float *b) { for (; n > 0; n--) { int16_t s = *(a++); - *(b++) = ((float) INT16_FROM(s))/0x7FFF; + *(b++) = ((float) INT16_FROM(s))/(float) 0x7FFF; } #else { static const double add = 0, factor = 1.0/0x7FFF; - oil_scaleconv_f32_s16(b, a, n, &add, &factor); + oil_scaleconv_f32_s16(b, a, (int) n, &add, &factor); } #endif } @@ -95,7 +95,7 @@ void pa_sconv_s32le_to_float32ne(unsigned n, const int32_t *a, float *b) { #else { static const double add = 0, factor = 1.0/0x7FFFFFFF; - oil_scaleconv_f32_s32(b, a, n, &add, &factor); + oil_scaleconv_f32_s32(b, a, (int) n, &add, &factor); } #endif } @@ -110,15 +110,15 @@ void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b) { int16_t s; float v = *(a++); - v = PA_CLAMP_UNLIKELY(v, -1, 1); - s = (int16_t) (v * 0x7FFF); + v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.f); + s = (int16_t) lrintf(v * 0x7FFF); *(b++) = INT16_TO(s); } #else { static const double add = 0, factor = 0x7FFF; - oil_scaleconv_s16_f32(b, a, n, &add, &factor); + oil_scaleconv_s16_f32(b, a, (int) n, &add, &factor); } #endif } @@ -133,15 +133,15 @@ void pa_sconv_s32le_from_float32ne(unsigned n, const float *a, int32_t *b) { int32_t s; float v = *(a++); - v = PA_CLAMP_UNLIKELY(v, -1, 1); - s = (int32_t) ((double) v * (double) 0x7FFFFFFF); + v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); + s = (int32_t) lrint((double) v * (double) 0x7FFFFFFF); *(b++) = INT32_TO(s); } #else { static const double add = 0, factor = 0x7FFFFFFF; - oil_scaleconv_s32_f32(b, a, n, &add, &factor); + oil_scaleconv_s32_f32(b, a, (int) n, &add, &factor); } #endif } @@ -153,8 +153,7 @@ void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b) { for (; n > 0; n--) { int16_t s = *(a++); float k = ((float) INT16_FROM(s))/0x7FFF; - uint32_t *j = (uint32_t*) &k; - *j = PA_UINT32_SWAP(*j); + k = PA_FLOAT32_SWAP(k); *(b++) = k; } } @@ -166,8 +165,7 @@ void pa_sconv_s32le_to_float32re(unsigned n, const int32_t *a, float *b) { for (; n > 0; n--) { int32_t s = *(a++); float k = (float) (((double) INT32_FROM(s))/0x7FFFFFFF); - uint32_t *j = (uint32_t*) &k; - *j = PA_UINT32_SWAP(*j); + k = PA_FLOAT32_SWAP(k); *(b++) = k; } } @@ -179,10 +177,9 @@ void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) { for (; n > 0; n--) { int16_t s; float v = *(a++); - uint32_t *j = (uint32_t*) &v; - *j = PA_UINT32_SWAP(*j); - v = PA_CLAMP_UNLIKELY(v, -1, 1); - s = (int16_t) (v * 0x7FFF); + v = PA_FLOAT32_SWAP(v); + v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); + s = (int16_t) lrintf(v * 0x7FFF); *(b++) = INT16_TO(s); } } @@ -194,10 +191,9 @@ void pa_sconv_s32le_from_float32re(unsigned n, const float *a, int32_t *b) { for (; n > 0; n--) { int32_t s; float v = *(a++); - uint32_t *j = (uint32_t*) &v; - *j = PA_UINT32_SWAP(*j); - v = PA_CLAMP_UNLIKELY(v, -1, 1); - s = (int32_t) ((double) v * 0x7FFFFFFF); + v = PA_FLOAT32_SWAP(v); + v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); + s = (int32_t) lrint((double) v * 0x7FFFFFFF); *(b++) = INT32_TO(s); } } @@ -219,7 +215,7 @@ void pa_sconv_s32le_to_s16re(unsigned n, const int32_t*a, int16_t *b) { for (; n > 0; n--) { int16_t s = (int16_t) (INT32_FROM(*a) >> 16); - *b = PA_UINT32_SWAP(s); + *b = PA_INT16_SWAP(s); a++; b++; } @@ -241,7 +237,7 @@ void pa_sconv_s32le_from_s16re(unsigned n, const int16_t *a, int32_t *b) { pa_assert(b); for (; n > 0; n--) { - int32_t s = ((int32_t) PA_UINT16_SWAP(*a)) << 16; + int32_t s = ((int32_t) PA_INT16_SWAP(*a)) << 16; *b = INT32_TO(s); a++; b++; diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c index 581e4681..6c4d420e 100644 --- a/src/pulsecore/sconv.c +++ b/src/pulsecore/sconv.c @@ -46,7 +46,7 @@ static void u8_to_float32ne(unsigned n, const uint8_t *a, float *b) { pa_assert(a); pa_assert(b); - oil_scaleconv_f32_u8(b, a, n, &add, &factor); + oil_scaleconv_f32_u8(b, a, (int) n, &add, &factor); } static void u8_from_float32ne(unsigned n, const float *a, uint8_t *b) { @@ -55,7 +55,7 @@ static void u8_from_float32ne(unsigned n, const float *a, uint8_t *b) { pa_assert(a); pa_assert(b); - oil_scaleconv_u8_f32(b, a, n, &add, &factor); + oil_scaleconv_u8_f32(b, a, (int) n, &add, &factor); } static void u8_to_s16ne(unsigned n, const uint8_t *a, int16_t *b) { @@ -64,9 +64,9 @@ static void u8_to_s16ne(unsigned n, const uint8_t *a, int16_t *b) { pa_assert(a); pa_assert(b); - oil_conv_s16_u8(b, 2, a, 1, n); - oil_scalaradd_s16(b, 2, b, 2, &add, n); - oil_scalarmult_s16(b, 2, b, 2, &factor, n); + oil_conv_s16_u8(b, 2, a, 1, (int) n); + oil_scalaradd_s16(b, 2, b, 2, &add, (int) n); + oil_scalarmult_s16(b, 2, b, 2, &factor, (int) n); } static void u8_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) { @@ -84,7 +84,7 @@ static void float32ne_to_float32ne(unsigned n, const float *a, float *b) { pa_assert(a); pa_assert(b); - oil_memcpy(b, a, sizeof(float) * n); + oil_memcpy(b, a, (int) (sizeof(float) * n)); } static void float32re_to_float32ne(unsigned n, const float *a, float *b) { @@ -101,7 +101,7 @@ static void s16ne_to_s16ne(unsigned n, const int16_t *a, int16_t *b) { pa_assert(a); pa_assert(b); - oil_memcpy(b, a, sizeof(int16_t) * n); + oil_memcpy(b, a, (int) (sizeof(int16_t) * n)); } static void s16re_to_s16ne(unsigned n, const int16_t *a, int16_t *b) { @@ -109,7 +109,7 @@ static void s16re_to_s16ne(unsigned n, const int16_t *a, int16_t *b) { pa_assert(b); for (; n > 0; n--, a++, b++) - *b = PA_UINT16_SWAP(*a); + *b = PA_INT16_SWAP(*a); } /* ulaw */ @@ -128,9 +128,9 @@ static void ulaw_from_float32ne(unsigned n, const float *a, uint8_t *b) { for (; n > 0; n--) { float v = *(a++); - v = PA_CLAMP_UNLIKELY(v, -1, 1); + v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); v *= 0x1FFF; - *(b++) = st_14linear2ulaw((int16_t) v); + *(b++) = st_14linear2ulaw((int16_t) lrintf(v)); } } @@ -166,9 +166,9 @@ static void alaw_from_float32ne(unsigned n, const float *a, uint8_t *b) { for (; n > 0; n--, a++, b++) { float v = *a; - v = PA_CLAMP_UNLIKELY(v, -1, 1); + v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); v *= 0xFFF; - *b = st_13linear2alaw((int16_t) v); + *b = st_13linear2alaw((int16_t) lrintf(v)); } } @@ -177,7 +177,7 @@ static void alaw_to_s16ne(unsigned n, const int8_t *a, int16_t *b) { pa_assert(b); for (; n > 0; n--, a++, b++) - *b = st_alaw2linear16(*a); + *b = st_alaw2linear16((uint8_t) *a); } static void alaw_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) { diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c index 298bf716..c59d247c 100644 --- a/src/pulsecore/shm.c +++ b/src/pulsecore/shm.c @@ -73,10 +73,10 @@ struct shm_marker PA_GCC_PACKED { pa_atomic_t marker; /* 0xbeefcafe */ pa_atomic_t pid; - uint64_t *_reserverd1; - uint64_t *_reserverd2; - uint64_t *_reserverd3; - uint64_t *_reserverd4; + uint64_t _reserved1; + uint64_t _reserved2; + uint64_t _reserved3; + uint64_t _reserved4; }; static char *segment_name(char *fn, size_t l, unsigned id) { @@ -105,7 +105,7 @@ int pa_shm_create_rw(pa_shm *m, size_t size, pa_bool_t shared, mode_t mode) { m->size = size; #ifdef MAP_ANONYMOUS - if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)) == MAP_FAILED) { + if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, (off_t) 0)) == MAP_FAILED) { pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } @@ -138,12 +138,12 @@ int pa_shm_create_rw(pa_shm *m, size_t size, pa_bool_t shared, mode_t mode) { m->size = size + PA_ALIGN(sizeof(struct shm_marker)); - if (ftruncate(fd, m->size) < 0) { + if (ftruncate(fd, (off_t) m->size) < 0) { pa_log("ftruncate() failed: %s", pa_cstrerror(errno)); goto fail; } - if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { + if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off_t) 0)) == MAP_FAILED) { pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } @@ -235,7 +235,7 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { /* Align this to multiples of the page size */ ptr = (uint8_t*) m->ptr + offset; - o = (uint8_t*) ptr - (uint8_t*) PA_PAGE_ALIGN_PTR(ptr); + o = (size_t) ((uint8_t*) ptr - (uint8_t*) PA_PAGE_ALIGN_PTR(ptr)); if (o > 0) { ps = PA_PAGE_SIZE; @@ -289,9 +289,9 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) { goto fail; } - m->size = st.st_size; + m->size = (size_t) st.st_size; - if ((m->ptr = mmap(NULL, m->size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + if ((m->ptr = mmap(NULL, m->size, PROT_READ, MAP_SHARED, fd, (off_t) 0)) == MAP_FAILED) { pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 64a6cdf9..0e1224f1 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -75,7 +75,7 @@ void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cv pa_assert(data); if ((data->volume_is_set = !!volume)) - data->volume = *volume; + data->volume = data->virtual_volume = *volume; } void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) { @@ -108,6 +108,7 @@ static void reset_callbacks(pa_sink_input *i) { i->kill = NULL; i->get_latency = NULL; i->state_change = NULL; + i->may_move_to = NULL; } /* Called from main context */ @@ -119,6 +120,7 @@ pa_sink_input* pa_sink_input_new( pa_sink_input *i; pa_resampler *resampler = NULL; char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + pa_channel_map original_cm; pa_assert(core); pa_assert(data); @@ -141,20 +143,25 @@ pa_sink_input* pa_sink_input_new( pa_return_null_if_fail(pa_sample_spec_valid(&data->sample_spec)); if (!data->channel_map_is_set) { - if (data->sink->channel_map.channels == data->sample_spec.channels) + if (pa_channel_map_compatible(&data->sink->channel_map, &data->sample_spec)) data->channel_map = data->sink->channel_map; else - pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT)); + pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); } pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map)); - pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels); + pa_return_null_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec)); - if (!data->volume_is_set) + if (!data->volume_is_set) { pa_cvolume_reset(&data->volume, data->sample_spec.channels); + pa_cvolume_reset(&data->virtual_volume, data->sample_spec.channels); + } pa_return_null_if_fail(pa_cvolume_valid(&data->volume)); - pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels); + pa_return_null_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec)); + + pa_return_null_if_fail(pa_cvolume_valid(&data->virtual_volume)); + pa_return_null_if_fail(pa_cvolume_compatible(&data->virtual_volume, &data->sample_spec)); if (!data->muted_is_set) data->muted = FALSE; @@ -165,6 +172,8 @@ pa_sink_input* pa_sink_input_new( if (flags & PA_SINK_INPUT_FIX_RATE) data->sample_spec.rate = data->sink->sample_spec.rate; + original_cm = data->channel_map; + if (flags & PA_SINK_INPUT_FIX_CHANNELS) { data->sample_spec.channels = data->sink->sample_spec.channels; data->channel_map = data->sink->channel_map; @@ -174,8 +183,7 @@ pa_sink_input* pa_sink_input_new( pa_assert(pa_channel_map_valid(&data->channel_map)); /* Due to the fixing of the sample spec the volume might not match anymore */ - if (data->volume.channels != data->sample_spec.channels) - pa_cvolume_set(&data->volume, data->sample_spec.channels, pa_cvolume_avg(&data->volume)); + pa_cvolume_remap(&data->volume, &original_cm, &data->channel_map); if (data->resample_method == PA_RESAMPLER_INVALID) data->resample_method = core->resample_method; @@ -201,7 +209,8 @@ pa_sink_input* pa_sink_input_new( data->resample_method, ((flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) | ((flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | - (core->disable_remixing || (flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) { + (core->disable_remixing || (flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) | + (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) { pa_log_warn("Unsupported resampling operation."); return NULL; } @@ -226,7 +235,9 @@ pa_sink_input* pa_sink_input_new( i->sample_spec = data->sample_spec; i->channel_map = data->channel_map; + i->virtual_volume = data->virtual_volume; i->volume = data->volume; + i->muted = data->muted; if (data->sync_base) { @@ -535,7 +546,7 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa * data, so let's just hand out silence */ pa_atomic_store(&i->thread_info.drained, 1); - pa_memblockq_seek(i->thread_info.render_memblockq, slength, PA_SEEK_RELATIVE); + pa_memblockq_seek(i->thread_info.render_memblockq, (int64_t) slength, PA_SEEK_RELATIVE); i->thread_info.playing_for = 0; if (i->thread_info.underrun_for != (uint64_t) -1) i->thread_info.underrun_for += ilength; @@ -756,14 +767,11 @@ pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) if (PA_SINK_INPUT_IS_LINKED(i->state)) pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0); - else { + else /* If this sink input is not realized yet, we have to touch * the thread info data directly */ - usec = fixup_latency(i->sink, usec); i->thread_info.requested_sink_latency = usec; - i->sink->thread_info.requested_latency_valid = FALSE; - } return usec; } @@ -786,17 +794,34 @@ pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) { /* Called from main context */ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) { + pa_sink_input_set_volume_data data; + pa_sink_input_assert_ref(i); pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); pa_assert(volume); + pa_assert(pa_cvolume_valid(volume)); + pa_assert(pa_cvolume_compatible(volume, &i->sample_spec)); + + data.sink_input = i; + data.virtual_volume = *volume; + data.volume = *volume; + + /* If you change something here, consider looking into + * module-flat-volume.c as well since it uses very similar + * code. */ - if (pa_cvolume_equal(&i->volume, volume)) + if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME], &data) < 0) return; - i->volume = *volume; + if (!pa_cvolume_equal(&i->volume, &data.volume)) { + i->volume = data.volume; + pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME, &data.volume, 0, NULL) == 0); + } - pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME, &i->volume, 0, NULL) == 0); - pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); + if (!pa_cvolume_equal(&i->virtual_volume, &data.virtual_volume)) { + i->virtual_volume = data.virtual_volume; + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); + } } /* Called from main context */ @@ -804,7 +829,7 @@ const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i) { pa_sink_input_assert_ref(i); pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); - return &i->volume; + return &i->virtual_volume; } /* Called from main context */ @@ -887,6 +912,35 @@ pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) { } /* Called from main context */ +pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) { + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); + pa_sink_assert_ref(dest); + + if (dest == i->sink) + return TRUE; + + if (i->flags & PA_SINK_INPUT_DONT_MOVE) + return FALSE; + + if (i->sync_next || i->sync_prev) { + pa_log_warn("Moving synchronised streams not supported."); + return FALSE; + } + + if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) { + pa_log_warn("Failed to move sink input: too many inputs per sink."); + return FALSE; + } + + if (i->may_move_to) + if (!i->may_move_to(i, dest)) + return FALSE; + + return TRUE; +} + +/* Called from main context */ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest) { pa_resampler *new_resampler; pa_sink *origin; @@ -902,18 +956,8 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest) { if (dest == origin) return 0; - if (i->flags & PA_SINK_INPUT_DONT_MOVE) - return -1; - - if (i->sync_next || i->sync_prev) { - pa_log_warn("Moving synchronised streams not supported."); + if (!pa_sink_input_may_move_to(i, dest)) return -1; - } - - if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) { - pa_log_warn("Failed to move sink input: too many inputs per sink."); - return -1; - } /* Kill directly connected outputs */ while ((o = pa_idxset_first(i->direct_outputs, NULL))) { @@ -1032,6 +1076,9 @@ void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state } else if (uncorking) { + i->thread_info.underrun_for = (uint64_t) -1; + i->thread_info.playing_for = 0; + pa_log_debug("Requesting rewind due to uncorking"); /* OK, we're being uncorked. Make sure we're not rewound when diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index c07a7404..27125988 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -56,7 +56,8 @@ typedef enum pa_sink_input_flags { PA_SINK_INPUT_NO_REMIX = 16, PA_SINK_INPUT_FIX_FORMAT = 32, PA_SINK_INPUT_FIX_RATE = 64, - PA_SINK_INPUT_FIX_CHANNELS = 128 + PA_SINK_INPUT_FIX_CHANNELS = 128, + PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND = 256, } pa_sink_input_flags_t; struct pa_sink_input { @@ -89,6 +90,8 @@ struct pa_sink_input { pa_sink_input *sync_prev, *sync_next; + pa_cvolume virtual_volume; + pa_cvolume volume; pa_bool_t muted; @@ -154,10 +157,15 @@ struct pa_sink_input { returns */ pa_usec_t (*get_latency) (pa_sink_input *i); /* may be NULL */ - /* If non_NULL this function is called from thread context if the + /* If non-NULL this function is called from thread context if the * state changes. The old state is found in thread_info.state. */ void (*state_change) (pa_sink_input *i, pa_sink_input_state_t state); /* may be NULL */ + /* If non-NULL this function is called before this sink input is + * move to a sink and if it returns FALSE the move will not + * be allowed */ + pa_bool_t (*may_move_to) (pa_sink_input *i, pa_sink *s); /* may be NULL */ + struct { pa_sink_input_state_t state; pa_atomic_t drained; @@ -212,19 +220,22 @@ typedef struct pa_sink_input_new_data { pa_sink *sink; + pa_resample_method_t resample_method; + + pa_sink_input *sync_base; + pa_sample_spec sample_spec; - pa_bool_t sample_spec_is_set; pa_channel_map channel_map; - pa_bool_t channel_map_is_set; - pa_cvolume volume; - pa_bool_t volume_is_set; - pa_bool_t muted; - pa_bool_t muted_is_set; + pa_cvolume virtual_volume; - pa_resample_method_t resample_method; + pa_cvolume volume; + pa_bool_t muted:1; - pa_sink_input *sync_base; + pa_bool_t sample_spec_is_set:1; + pa_bool_t channel_map_is_set:1; + pa_bool_t volume_is_set:1; + pa_bool_t muted_is_set:1; } pa_sink_input_new_data; pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data); @@ -239,6 +250,12 @@ typedef struct pa_sink_input_move_hook_data { pa_sink *destination; } pa_sink_input_move_hook_data; +typedef struct pa_sink_set_input_volume_data { + pa_sink_input *sink_input; + pa_cvolume virtual_volume; + pa_cvolume volume; +} pa_sink_input_set_volume_data; + /* To be called by the implementing module only */ pa_sink_input* pa_sink_input_new( @@ -281,6 +298,7 @@ pa_bool_t pa_sink_input_get_mute(pa_sink_input *i); pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i); int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest); +pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest); pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i); diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 4102f31d..a6027e70 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -663,7 +663,6 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume); if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) { - pa_log("adjusting volume "); pa_memchunk_make_writable(result, 0); if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) pa_silence_memchunk(result, &s->sample_spec); @@ -844,30 +843,55 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) { /* Called from main thread */ void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume) { pa_bool_t changed; + pa_sink_set_volume_data data; pa_sink_assert_ref(s); pa_assert(PA_SINK_IS_LINKED(s->state)); pa_assert(volume); + pa_assert(pa_cvolume_valid(volume)); + pa_assert(pa_cvolume_compatible(volume, &s->sample_spec)); - changed = !pa_cvolume_equal(volume, &s->volume); - s->volume = *volume; + data.sink = s; + data.volume = *volume; + + changed = !pa_cvolume_equal(&data.volume, &s->volume); + + if (changed) { + if (pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_SET_VOLUME], &data) < 0) + return; + + changed = !pa_cvolume_equal(&data.volume, &s->volume); + } + + s->volume = data.volume; if (s->set_volume && s->set_volume(s) < 0) s->set_volume = NULL; if (!s->set_volume) - pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, volume, 0, NULL); + pa_sink_set_soft_volume(s, volume); if (changed) pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } /* Called from main thread */ -const pa_cvolume *pa_sink_get_volume(pa_sink *s) { +void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) { + pa_sink_assert_ref(s); + pa_assert(volume); + + if (PA_SINK_IS_LINKED(s->state)) + pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, volume, 0, NULL); + else + s->thread_info.soft_volume = *volume; +} + +/* Called from main thread */ +const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_bool_t force_refresh) { pa_sink_assert_ref(s); pa_assert(PA_SINK_IS_LINKED(s->state)); - if (s->refresh_volume) { + if (s->refresh_volume || force_refresh) { struct pa_cvolume old_volume = s->volume; if (s->get_volume && s->get_volume(s) < 0) @@ -904,12 +928,12 @@ void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) { } /* Called from main thread */ -pa_bool_t pa_sink_get_mute(pa_sink *s) { +pa_bool_t pa_sink_get_mute(pa_sink *s, pa_bool_t force_refresh) { pa_sink_assert_ref(s); pa_assert(PA_SINK_IS_LINKED(s->state)); - if (s->refresh_muted) { + if (s->refresh_muted || force_refresh) { pa_bool_t old_muted = s->muted; if (s->get_mute && s->get_mute(s) < 0) @@ -967,7 +991,7 @@ unsigned pa_sink_linked_by(pa_sink *s) { ret = pa_idxset_size(s->inputs); /* We add in the number of streams connected to us here. Please - * not the asymmmetry to pa_sink_used_by()! */ + * note the asymmmetry to pa_sink_used_by()! */ if (s->monitor_source) ret += pa_source_linked_by(s->monitor_source); @@ -991,6 +1015,38 @@ unsigned pa_sink_used_by(pa_sink *s) { return ret - s->n_corked; } +/* Called from main thread */ +unsigned pa_sink_check_suspend(pa_sink *s) { + unsigned ret; + pa_sink_input *i; + uint32_t idx; + + pa_sink_assert_ref(s); + pa_assert(PA_SINK_IS_LINKED(s->state)); + + ret = 0; + + for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) { + pa_sink_input_state_t st; + + st = pa_sink_input_get_state(i); + pa_assert(PA_SINK_INPUT_IS_LINKED(st)); + + if (st == PA_SINK_INPUT_CORKED) + continue; + + if (i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND) + continue; + + ret ++; + } + + if (s->monitor_source) + ret += pa_source_check_suspend(s->monitor_source); + + return ret; +} + /* Called from IO thread, except when it is not */ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) { pa_sink *s = PA_SINK(o); @@ -1031,11 +1087,15 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse pa_sink_input_set_state_within_thread(i, i->state); + /* The requested latency of the sink input needs to be + * fixed up and then configured on the sink */ + + if (i->thread_info.requested_sink_latency != (pa_usec_t) -1) + pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency); + pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind); pa_sink_input_update_max_request(i, s->thread_info.max_request); - pa_sink_invalidate_requested_latency(s); - /* We don't rewind here automatically. This is left to the * sink input implementor because some sink inputs need a * slow start, i.e. need some time to buffer client @@ -1147,11 +1207,12 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse if (i->attach) i->attach(i); + if (i->thread_info.requested_sink_latency != (pa_usec_t) -1) + pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency); + pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind); pa_sink_input_update_max_request(i, s->thread_info.max_request); - pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency); - if (i->thread_info.state != PA_SINK_INPUT_CORKED) { pa_usec_t usec = 0; size_t nbytes; @@ -1413,7 +1474,6 @@ void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) { /* Called from IO thread */ void pa_sink_set_max_request(pa_sink *s, size_t max_request) { - pa_sink_input *i; void *state = NULL; pa_sink_assert_ref(s); @@ -1424,6 +1484,8 @@ void pa_sink_set_max_request(pa_sink *s, size_t max_request) { s->thread_info.max_request = max_request; if (PA_SINK_IS_LINKED(s->thread_info.state)) { + pa_sink_input *i; + while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) pa_sink_input_update_max_request(i, s->thread_info.max_request); } diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index 604be269..c5a73214 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -180,21 +180,22 @@ typedef enum pa_sink_message { typedef struct pa_sink_new_data { char *name; - pa_bool_t namereg_fail; pa_proplist *proplist; const char *driver; pa_module *module; pa_sample_spec sample_spec; - pa_bool_t sample_spec_is_set; pa_channel_map channel_map; - pa_bool_t channel_map_is_set; - pa_cvolume volume; - pa_bool_t volume_is_set; - pa_bool_t muted; - pa_bool_t muted_is_set; + pa_bool_t muted :1; + + pa_bool_t sample_spec_is_set:1; + pa_bool_t channel_map_is_set:1; + pa_bool_t volume_is_set:1; + pa_bool_t muted_is_set:1; + + pa_bool_t namereg_fail:1; } pa_sink_new_data; pa_sink_new_data* pa_sink_new_data_init(pa_sink_new_data *data); @@ -205,6 +206,11 @@ void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volum void pa_sink_new_data_set_muted(pa_sink_new_data *data, pa_bool_t mute); void pa_sink_new_data_done(pa_sink_new_data *data); +typedef struct pa_sink_set_volume_data { + pa_sink *sink; + pa_cvolume volume; +} pa_sink_set_volume_data; + /* To be called exclusively by the sink driver, from main context */ pa_sink* pa_sink_new( @@ -239,12 +245,14 @@ int pa_sink_suspend(pa_sink *s, pa_bool_t suspend); int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend); void pa_sink_set_volume(pa_sink *sink, const pa_cvolume *volume); -const pa_cvolume *pa_sink_get_volume(pa_sink *sink); +void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume); +const pa_cvolume *pa_sink_get_volume(pa_sink *sink, pa_bool_t force_refresh); void pa_sink_set_mute(pa_sink *sink, pa_bool_t mute); -pa_bool_t pa_sink_get_mute(pa_sink *sink); +pa_bool_t pa_sink_get_mute(pa_sink *sink, pa_bool_t force_refres); unsigned pa_sink_linked_by(pa_sink *s); /* Number of connected streams */ unsigned pa_sink_used_by(pa_sink *s); /* Number of connected streams which are not corked */ +unsigned pa_sink_check_suspend(pa_sink *s); /* Returns how many streams are active that don't allow suspensions */ #define pa_sink_get_state(s) ((s)->state) /* To be called exclusively by the sink driver, from IO context */ diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c index e69a63da..6739effd 100644 --- a/src/pulsecore/socket-client.c +++ b/src/pulsecore/socket-client.c @@ -187,7 +187,7 @@ static void connect_defer_cb(pa_mainloop_api *m, pa_defer_event *e, void *userda do_call(c); } -static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { +static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { pa_socket_client *c = userdata; pa_assert(m); @@ -283,7 +283,7 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size else pa_make_socket_low_delay(c->fd); - if (do_connect(c, sa, salen) < 0) + if (do_connect(c, sa, (socklen_t) salen) < 0) return -1; return 0; @@ -370,7 +370,7 @@ pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[ #ifdef HAVE_LIBASYNCNS -static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { +static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { pa_socket_client *c = userdata; struct addrinfo *res = NULL; int ret; @@ -437,7 +437,7 @@ static void start_timeout(pa_socket_client *c) { pa_assert(!c->timeout_event); pa_gettimeofday(&tv); - pa_timeval_add(&tv, CONNECT_TIMEOUT * 1000000); + pa_timeval_add(&tv, CONNECT_TIMEOUT * PA_USEC_PER_SEC); c->timeout_event = c->mainloop->time_new(c->mainloop, &tv, timeout_cb, c); } diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c index 9885a02b..a600e0a6 100644 --- a/src/pulsecore/socket-server.c +++ b/src/pulsecore/socket-server.c @@ -199,7 +199,7 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file pa_make_socket_low_delay(fd); - if (bind(fd, (struct sockaddr*) &sa, SUN_LEN(&sa)) < 0) { + if (bind(fd, (struct sockaddr*) &sa, (socklen_t) SUN_LEN(&sa)) < 0) { pa_log("bind(): %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c index 8b2a29b9..c30c16eb 100644 --- a/src/pulsecore/sound-file-stream.c +++ b/src/pulsecore/sound-file-stream.c @@ -170,10 +170,10 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk if (u->readf_function) { fs = pa_frame_size(&i->sample_spec); - n = u->readf_function(u->sndfile, p, length/fs); + n = u->readf_function(u->sndfile, p, (sf_count_t) (length/fs)); } else { fs = 1; - n = sf_read_raw(u->sndfile, p, length); + n = sf_read_raw(u->sndfile, p, (sf_count_t) length); } pa_memblock_release(tchunk.memblock); @@ -186,7 +186,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk break; } - tchunk.length = n * fs; + tchunk.length = (size_t) n * fs; pa_memblockq_push(u->memblockq, &tchunk); pa_memblock_unref(tchunk.memblock); @@ -310,8 +310,8 @@ int pa_play_file( break; } - ss.rate = sfinfo.samplerate; - ss.channels = sfinfo.channels; + ss.rate = (uint32_t) sfinfo.samplerate; + ss.channels = (uint8_t) sfinfo.channels; if (!pa_sample_spec_valid(&ss)) { pa_log("Unsupported sample format in file %s", fname); diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c index 3183ede6..380cef16 100644 --- a/src/pulsecore/sound-file.c +++ b/src/pulsecore/sound-file.c @@ -89,7 +89,7 @@ int pa_sound_file_load( case SF_FORMAT_PCM_U8: case SF_FORMAT_PCM_S8: ss->format = PA_SAMPLE_S16NE; - readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_short; + readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *_ptr, sf_count_t frames)) sf_readf_short; break; case SF_FORMAT_ULAW: @@ -104,12 +104,12 @@ int pa_sound_file_load( case SF_FORMAT_DOUBLE: default: ss->format = PA_SAMPLE_FLOAT32NE; - readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_float; + readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *_ptr, sf_count_t frames)) sf_readf_float; break; } - ss->rate = sfinfo.samplerate; - ss->channels = sfinfo.channels; + ss->rate = (uint32_t) sfinfo.samplerate; + ss->channels = (uint8_t) sfinfo.channels; if (!pa_sample_spec_valid(ss)) { pa_log("Unsupported sample format in file %s", fname); @@ -119,7 +119,7 @@ int pa_sound_file_load( if (map) pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_DEFAULT); - if ((l = pa_frame_size(ss) * sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { + if ((l = pa_frame_size(ss) * (size_t) sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { pa_log("File too large"); goto finish; } @@ -131,7 +131,7 @@ int pa_sound_file_load( ptr = pa_memblock_acquire(chunk->memblock); if ((readf_function && readf_function(sf, ptr, sfinfo.frames) != sfinfo.frames) || - (!readf_function && sf_read_raw(sf, ptr, l) != (sf_count_t) l)) { + (!readf_function && sf_read_raw(sf, ptr, (sf_count_t) l) != (sf_count_t) l)) { pa_log("Premature file end"); goto finish; } @@ -189,15 +189,15 @@ int pa_sound_file_too_big_to_cache(const char *fname) { break; } - ss.rate = sfinfo.samplerate; - ss.channels = sfinfo.channels; + ss.rate = (uint32_t) sfinfo.samplerate; + ss.channels = (uint8_t) sfinfo.channels; if (!pa_sample_spec_valid(&ss)) { pa_log("Unsupported sample format in file %s", fname); return -1; } - if ((pa_frame_size(&ss) * sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { + if ((pa_frame_size(&ss) * (size_t) sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { pa_log("File too large: %s", fname); return 1; } diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index dbf3af94..376402fa 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -90,6 +90,7 @@ static void reset_callbacks(pa_source_output *o) { o->kill = NULL; o->get_latency = NULL; o->state_change = NULL; + o->may_move_to = NULL; } /* Called from main context */ @@ -124,14 +125,14 @@ pa_source_output* pa_source_output_new( pa_return_null_if_fail(pa_sample_spec_valid(&data->sample_spec)); if (!data->channel_map_is_set) { - if (data->source->channel_map.channels == data->sample_spec.channels) + if (pa_channel_map_compatible(&data->source->channel_map, &data->sample_spec)) data->channel_map = data->source->channel_map; else - pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT)); + pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); } pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map)); - pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels); + pa_return_null_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec)); if (flags & PA_SOURCE_OUTPUT_FIX_FORMAT) data->sample_spec.format = data->source->sample_spec.format; @@ -171,7 +172,8 @@ pa_source_output* pa_source_output_new( data->resample_method, ((flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) | ((flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | - (core->disable_remixing || (flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) { + (core->disable_remixing || (flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) | + (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) { pa_log_warn("Unsupported resampling operation."); return NULL; } @@ -397,7 +399,7 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) { if (pa_memblockq_push(o->thread_info.delay_memblockq, chunk) < 0) { pa_log_debug("Delay queue overflow!"); - pa_memblockq_seek(o->thread_info.delay_memblockq, chunk->length, PA_SEEK_RELATIVE); + pa_memblockq_seek(o->thread_info.delay_memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE); } limit = o->process_rewind ? 0 : o->source->thread_info.max_rewind; @@ -511,14 +513,11 @@ pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t if (PA_SOURCE_OUTPUT_IS_LINKED(o->state)) pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0); - else { + else /* If this source output is not realized yet, we have to touch * the thread info data directly */ - usec = fixup_latency(o->source, usec); o->thread_info.requested_source_latency = usec; - o->source->thread_info.requested_latency_valid = FALSE; - } return usec; } @@ -595,6 +594,32 @@ pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) { return o->resample_method; } +pa_bool_t pa_source_output_may_move_to(pa_source_output *o, pa_source *dest) { + pa_source_output_assert_ref(o); + pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state)); + pa_source_assert_ref(dest); + + if (dest == o->source) + return TRUE; + + if (o->flags & PA_SOURCE_OUTPUT_DONT_MOVE) + return FALSE; + + if (o->direct_on_input) + return FALSE; + + if (pa_idxset_size(dest->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { + pa_log_warn("Failed to move source output: too many outputs per source."); + return FALSE; + } + + if (o->may_move_to) + if (!o->may_move_to(o, dest)) + return FALSE; + + return TRUE; +} + /* Called from main context */ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { pa_source *origin; @@ -610,17 +635,9 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { if (dest == origin) return 0; - if (o->flags & PA_SOURCE_OUTPUT_DONT_MOVE) + if (!pa_source_output_may_move_to(o, dest)) return -1; - if (o->direct_on_input) - return -1; - - if (pa_idxset_size(dest->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { - pa_log_warn("Failed to move source output: too many outputs per source."); - return -1; - } - if (o->thread_info.resampler && pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) && pa_channel_map_equal(&origin->channel_map, &dest->channel_map)) diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index 61825b22..f011f9bd 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -52,7 +52,8 @@ typedef enum pa_source_output_flags { PA_SOURCE_OUTPUT_NO_REMIX = 16, PA_SOURCE_OUTPUT_FIX_FORMAT = 32, PA_SOURCE_OUTPUT_FIX_RATE = 64, - PA_SOURCE_OUTPUT_FIX_CHANNELS = 128 + PA_SOURCE_OUTPUT_FIX_CHANNELS = 128, + PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND = 256 } pa_source_output_flags_t; struct pa_source_output { @@ -126,10 +127,15 @@ struct pa_source_output { returns */ pa_usec_t (*get_latency) (pa_source_output *o); /* may be NULL */ - /* If non_NULL this function is called from thread context if the + /* If non-NULL this function is called from thread context if the * state changes. The old state is found in thread_info.state. */ void (*state_change) (pa_source_output *o, pa_source_output_state_t state); /* may be NULL */ + /* If non-NULL this function is called before this source output + * is moved to a source and if it returns FALSE the move + * will not be allowed */ + pa_bool_t (*may_move_to) (pa_source_output *o, pa_source *s); /* may be NULL */ + struct { pa_source_output_state_t state; @@ -174,12 +180,13 @@ typedef struct pa_source_output_new_data { pa_source *source; + pa_resample_method_t resample_method; + pa_sample_spec sample_spec; - pa_bool_t sample_spec_is_set; pa_channel_map channel_map; - pa_bool_t channel_map_is_set; - pa_resample_method_t resample_method; + pa_bool_t sample_spec_is_set:1; + pa_bool_t channel_map_is_set:1; } pa_source_output_new_data; pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data); @@ -219,6 +226,7 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *i, pa_usec_t *source_la pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o); +pa_bool_t pa_source_output_may_move_to(pa_source_output *o, pa_source *dest); int pa_source_output_move_to(pa_source_output *o, pa_source *dest); #define pa_source_output_get_state(o) ((o)->state) diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 31620690..7d927faa 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -520,18 +520,29 @@ void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) { s->set_volume = NULL; if (!s->set_volume) - pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, volume, 0, NULL); + pa_source_set_soft_volume(s, volume); if (changed) pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } /* Called from main thread */ -const pa_cvolume *pa_source_get_volume(pa_source *s) { +void pa_source_set_soft_volume(pa_source *s, const pa_cvolume *volume) { + pa_source_assert_ref(s); + pa_assert(volume); + + if (PA_SOURCE_IS_LINKED(s->state)) + pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, volume, 0, NULL); + else + s->thread_info.soft_volume = *volume; +} + +/* Called from main thread */ +const pa_cvolume *pa_source_get_volume(pa_source *s, pa_bool_t force_refresh) { pa_source_assert_ref(s); pa_assert(PA_SOURCE_IS_LINKED(s->state)); - if (s->refresh_volume) { + if (s->refresh_volume || force_refresh) { pa_cvolume old_volume = s->volume; if (s->get_volume && s->get_volume(s) < 0) @@ -568,12 +579,12 @@ void pa_source_set_mute(pa_source *s, pa_bool_t mute) { } /* Called from main thread */ -pa_bool_t pa_source_get_mute(pa_source *s) { +pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) { pa_source_assert_ref(s); pa_assert(PA_SOURCE_IS_LINKED(s->state)); - if (s->refresh_muted) { + if (s->refresh_muted || force_refresh) { pa_bool_t old_muted = s->muted; if (s->get_mute && s->get_mute(s) < 0) @@ -634,6 +645,35 @@ unsigned pa_source_used_by(pa_source *s) { return ret - s->n_corked; } +/* Called from main thread */ +unsigned pa_source_check_suspend(pa_source *s) { + unsigned ret; + pa_source_output *o; + uint32_t idx; + + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_IS_LINKED(s->state)); + + ret = 0; + + for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx))) { + pa_source_output_state_t st; + + st = pa_source_output_get_state(o); + pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(st)); + + if (st == PA_SOURCE_OUTPUT_CORKED) + continue; + + if (o->flags & PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND) + continue; + + ret ++; + } + + return ret; +} + /* Called from IO thread, except when it is not */ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *chunk) { pa_source *s = PA_SOURCE(object); @@ -659,6 +699,9 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_ pa_source_output_set_state_within_thread(o, o->state); + if (o->thread_info.requested_source_latency != (pa_usec_t) -1) + pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency); + pa_source_output_update_max_rewind(o, s->thread_info.max_rewind); /* We don't just invalidate the requested latency here, diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index f4a17e8d..aaf904b4 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -168,21 +168,22 @@ typedef enum pa_source_message { typedef struct pa_source_new_data { char *name; - pa_bool_t namereg_fail; pa_proplist *proplist; const char *driver; pa_module *module; pa_sample_spec sample_spec; - pa_bool_t sample_spec_is_set; pa_channel_map channel_map; - pa_bool_t channel_map_is_set; - pa_cvolume volume; - pa_bool_t volume_is_set; - pa_bool_t muted; - pa_bool_t muted_is_set; + pa_bool_t muted:1; + + pa_bool_t volume_is_set:1; + pa_bool_t muted_is_set:1; + pa_bool_t sample_spec_is_set:1; + pa_bool_t channel_map_is_set:1; + + pa_bool_t namereg_fail:1; } pa_source_new_data; pa_source_new_data* pa_source_new_data_init(pa_source_new_data *data); @@ -226,12 +227,14 @@ int pa_source_suspend(pa_source *s, pa_bool_t suspend); int pa_source_suspend_all(pa_core *c, pa_bool_t suspend); void pa_source_set_volume(pa_source *source, const pa_cvolume *volume); -const pa_cvolume *pa_source_get_volume(pa_source *source); +void pa_source_set_soft_volume(pa_source *s, const pa_cvolume *volume); +const pa_cvolume *pa_source_get_volume(pa_source *source, pa_bool_t force_refresh); void pa_source_set_mute(pa_source *source, pa_bool_t mute); -pa_bool_t pa_source_get_mute(pa_source *source); +pa_bool_t pa_source_get_mute(pa_source *source, pa_bool_t force_refresh); unsigned pa_source_linked_by(pa_source *s); /* Number of connected streams */ unsigned pa_source_used_by(pa_source *s); /* Number of connected streams that are not corked */ +unsigned pa_source_check_suspend(pa_source *s); /* Returns how many streams are active that don't allow suspensions */ #define pa_source_get_state(s) ((pa_source_state_t) (s)->state) /* To be called exclusively by the source driver, from IO context */ diff --git a/src/pulsecore/start-child.c b/src/pulsecore/start-child.c index 1661383d..7774bde6 100644 --- a/src/pulsecore/start-child.c +++ b/src/pulsecore/start-child.c @@ -66,11 +66,6 @@ int pa_start_child_for_read(const char *name, const char *argv1, pid_t *pid) { return pipe_fds[0]; } else { -#ifdef __linux__ - DIR* d; -#endif - int max_fd, i; - /* child */ pa_reset_priority(); @@ -87,48 +82,9 @@ int pa_start_child_for_read(const char *name, const char *argv1, pid_t *pid) { pa_close(2); pa_assert_se(open("/dev/null", O_WRONLY) == 2); -#ifdef __linux__ - - if ((d = opendir("/proc/self/fd/"))) { - - struct dirent *de; - - while ((de = readdir(d))) { - char *e = NULL; - int fd; - - if (de->d_name[0] == '.') - continue; - - errno = 0; - fd = strtol(de->d_name, &e, 10); - pa_assert(errno == 0 && e && *e == 0); - - if (fd >= 3 && dirfd(d) != fd) - pa_close(fd); - } - - closedir(d); - } else { - -#endif - - max_fd = 1024; - -#ifdef HAVE_SYS_RESOURCE_H - { - struct rlimit r; - if (getrlimit(RLIMIT_NOFILE, &r) == 0) - max_fd = r.rlim_max; - } -#endif - - for (i = 3; i < max_fd; i++) - pa_close(i); - -#ifdef __linux__ - } -#endif + pa_close_all(-1); + pa_reset_sigs(-1); + pa_unblock_sigs(-1); #ifdef PR_SET_PDEATHSIG /* On Linux we can use PR_SET_PDEATHSIG to have the helper @@ -139,16 +95,6 @@ int pa_start_child_for_read(const char *name, const char *argv1, pid_t *pid) { prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); #endif -#ifdef SIGPIPE - /* Make sure that SIGPIPE kills the child process */ - signal(SIGPIPE, SIG_DFL); -#endif - -#ifdef SIGTERM - /* Make sure that SIGTERM kills the child process */ - signal(SIGTERM, SIG_DFL); -#endif - execl(name, name, argv1, NULL); _exit(1); } diff --git a/src/pulsecore/strbuf.c b/src/pulsecore/strbuf.c index b59b6f49..540faef9 100644 --- a/src/pulsecore/strbuf.c +++ b/src/pulsecore/strbuf.c @@ -77,7 +77,7 @@ char *pa_strbuf_tostring(pa_strbuf *sb) { pa_assert(sb); - e = t = pa_xnew(char, sb->length+1); + e = t = pa_xmalloc(sb->length+1); for (c = sb->head; c; c = c->next) { pa_assert((size_t) (e-t) <= sb->length); @@ -150,8 +150,8 @@ void pa_strbuf_putsn(pa_strbuf *sb, const char *t, size_t l) { /* Append a printf() style formatted string to the string buffer. */ /* The following is based on an example from the GNU libc documentation */ -int pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) { - int size = 100; +size_t pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) { + size_t size = 100; struct chunk *c = NULL; pa_assert(sb); @@ -168,14 +168,14 @@ int pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) { CHUNK_TO_TEXT(c)[size-1] = 0; va_end(ap); - if (r > -1 && r < size) { - c->length = r; + if (r > -1 && (size_t) r < size) { + c->length = (size_t) r; append(sb, c); - return r; + return (size_t) r; } if (r > -1) /* glibc 2.1 */ - size = r+1; + size = (size_t) r+1; else /* glibc 2.0 */ size *= 2; } diff --git a/src/pulsecore/strbuf.h b/src/pulsecore/strbuf.h index 24c876d5..ac68d7be 100644 --- a/src/pulsecore/strbuf.h +++ b/src/pulsecore/strbuf.h @@ -31,7 +31,7 @@ void pa_strbuf_free(pa_strbuf *sb); char *pa_strbuf_tostring(pa_strbuf *sb); char *pa_strbuf_tostring_free(pa_strbuf *sb); -int pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); +size_t pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); void pa_strbuf_puts(pa_strbuf *sb, const char *t); void pa_strbuf_putsn(pa_strbuf *sb, const char *t, size_t m); diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c index b0ed59ef..62a30144 100644 --- a/src/pulsecore/tagstruct.c +++ b/src/pulsecore/tagstruct.c @@ -154,7 +154,7 @@ void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) { extend(t, 5+length); t->data[t->length] = PA_TAG_ARBITRARY; - tmp = htonl(length); + tmp = htonl((uint32_t) length); memcpy(t->data+t->length+1, &tmp, 4); if (length) memcpy(t->data+t->length+5, p, length); @@ -165,7 +165,7 @@ void pa_tagstruct_put_boolean(pa_tagstruct*t, pa_bool_t b) { pa_assert(t); extend(t, 1); - t->data[t->length] = b ? PA_TAG_BOOLEAN_TRUE : PA_TAG_BOOLEAN_FALSE; + t->data[t->length] = (uint8_t) (b ? PA_TAG_BOOLEAN_TRUE : PA_TAG_BOOLEAN_FALSE); t->length += 1; } @@ -175,9 +175,9 @@ void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv) { extend(t, 9); t->data[t->length] = PA_TAG_TIMEVAL; - tmp = htonl(tv->tv_sec); + tmp = htonl((uint32_t) tv->tv_sec); memcpy(t->data+t->length+1, &tmp, 4); - tmp = htonl(tv->tv_usec); + tmp = htonl((uint32_t) tv->tv_usec); memcpy(t->data+t->length+5, &tmp, 4); t->length += 9; } @@ -228,7 +228,7 @@ void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) { unsigned i; pa_assert(t); - extend(t, 2 + map->channels); + extend(t, 2 + (size_t) map->channels); t->data[t->length++] = PA_TAG_CHANNEL_MAP; t->data[t->length++] = map->channels; @@ -435,9 +435,9 @@ int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv) { return -1; memcpy(&tv->tv_sec, t->data+t->rindex+1, 4); - tv->tv_sec = ntohl(tv->tv_sec); + tv->tv_sec = (time_t) ntohl((uint32_t) tv->tv_sec); memcpy(&tv->tv_usec, t->data+t->rindex+5, 4); - tv->tv_usec = ntohl(tv->tv_usec); + tv->tv_usec = (suseconds_t) ntohl((uint32_t) tv->tv_usec); t->rindex += 9; return 0; } @@ -523,7 +523,7 @@ int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) { for (i = 0; i < map->channels; i ++) map->map[i] = (int8_t) t->data[t->rindex + 2 + i]; - t->rindex += 2 + map->channels; + t->rindex += 2 + (size_t) map->channels; return 0; } diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index 20ed16d9..ade398f9 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -41,6 +41,7 @@ struct pa_thread { pa_thread_func_t thread_func; void *userdata; pa_atomic_t running; + pa_bool_t joined; }; struct pa_tls { @@ -82,6 +83,7 @@ pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) { t = pa_xnew(pa_thread, 1); t->thread_func = thread_func; t->userdata = userdata; + t->joined = FALSE; pa_atomic_store(&t->running, 0); if (pthread_create(&t->id, NULL, internal_thread_func, t) < 0) { @@ -115,7 +117,12 @@ void pa_thread_free(pa_thread *t) { int pa_thread_join(pa_thread *t) { pa_assert(t); + pa_assert(t->thread_func); + + if (t->joined) + return -1; + t->joined = TRUE; return pthread_join(t->id, NULL); } @@ -132,6 +139,7 @@ pa_thread* pa_thread_self(void) { t->id = pthread_self(); t->thread_func = NULL; t->userdata = NULL; + t->joined = TRUE; pa_atomic_store(&t->running, 2); PA_STATIC_TLS_SET(current_thread, t); @@ -192,4 +200,3 @@ void *pa_tls_set(pa_tls *t, void *userdata) { pa_assert_se(pthread_setspecific(t->key, userdata) == 0); return r; } - diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h index f3aca13e..eabe9ba4 100644 --- a/src/pulsecore/thread.h +++ b/src/pulsecore/thread.h @@ -25,6 +25,7 @@ #include <pulse/def.h> #include <pulsecore/once.h> +#include <pulsecore/core-util.h> #ifndef PACKAGE #error "Please include config.h before including this file!" @@ -69,6 +70,8 @@ void *pa_tls_set(pa_tls *t, void *userdata); static void name##_tls_destructor(void) PA_GCC_DESTRUCTOR; \ static void name##_tls_destructor(void) { \ static void (*_free_cb)(void*) = free_cb; \ + if (!pa_in_valgrind()) \ + return; \ if (!name##_tls.tls) \ return; \ if (_free_cb) { \ @@ -86,7 +89,7 @@ void *pa_tls_set(pa_tls *t, void *userdata); } \ struct __stupid_useless_struct_to_allow_trailing_semicolon -#ifdef HAVE_TLS_BUILTIN +#ifdef SUPPORT_TLS___THREAD /* An optimized version of the above that requires no dynamic * allocation if the compiler supports __thread */ #define PA_STATIC_TLS_DECLARE_NO_FREE(name) \ diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c index d0231486..65621948 100644 --- a/src/pulsecore/time-smoother.c +++ b/src/pulsecore/time-smoother.c @@ -209,8 +209,8 @@ static double avg_gradient(pa_smoother *s, pa_usec_t x) { i = s->history_idx; for (j = s->n_history; j > 0; j--) { - ax += s->history_x[i]; - ay += s->history_y[i]; + ax += (int64_t) s->history_x[i]; + ay += (int64_t) s->history_y[i]; c++; REDUCE_INC(i); @@ -236,7 +236,7 @@ static double avg_gradient(pa_smoother *s, pa_usec_t x) { REDUCE_INC(i); } - r = (double) k / t; + r = (double) k / (double) t; return (s->monotonic && r < 0) ? 0 : r; } @@ -268,8 +268,8 @@ static void calc_abc(pa_smoother *s) { /* Calculate a, b, c for y=ax^3+bx^2+cx */ s->c = de; - s->b = (((double) (3*ky)/kx - dp - 2*de)) / kx; - s->a = (dp/kx - 2*s->b - de/kx) / (3*kx); + s->b = (((double) (3*ky)/ (double) kx - dp - (double) (2*de))) / (double) kx; + s->a = (dp/(double) kx - 2*s->b - de/(double) kx) / (double) (3*kx); s->abc_valid = TRUE; } @@ -284,7 +284,7 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) { /* The requested point is right of the point where we wanted * to be on track again, thus just linearly estimate */ - t = (int64_t) s->py + (int64_t) (s->dp * (x - s->px)); + t = (int64_t) s->py + (int64_t) llrint(s->dp * (double) (x - s->px)); if (t < 0) t = 0; @@ -313,7 +313,7 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) { /* Move back from origin */ ty += (double) s->ey; - *y = ty >= 0 ? (pa_usec_t) ty : 0; + *y = ty >= 0 ? (pa_usec_t) llrint(ty) : 0; /* Horner scheme */ if (deriv) @@ -360,7 +360,7 @@ void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) { /* And calculate when we want to be on track again */ s->px = s->ex + s->adjust_time; - s->py = s->ry + s->dp *s->adjust_time; + s->py = s->ry + (pa_usec_t) llrint(s->dp * (double) s->adjust_time); s->abc_valid = FALSE; @@ -456,7 +456,7 @@ pa_usec_t pa_smoother_translate(pa_smoother *s, pa_usec_t x, pa_usec_t y_delay) /* pa_log_debug("translate(%llu) = %llu (%0.2f)", (unsigned long long) y_delay, (unsigned long long) ((double) y_delay / nde), nde); */ - return (pa_usec_t) ((double) y_delay / nde); + return (pa_usec_t) llrint((double) y_delay / nde); } void pa_smoother_reset(pa_smoother *s) { diff --git a/src/pulsecore/tokenizer.c b/src/pulsecore/tokenizer.c index d1e0836b..07a9f3ac 100644 --- a/src/pulsecore/tokenizer.c +++ b/src/pulsecore/tokenizer.c @@ -34,7 +34,7 @@ #include "tokenizer.h" -static void token_free(void *p, PA_GCC_UNUSED void *userdata) { +static void token_free(void *p, void *userdata) { pa_xfree(p); } diff --git a/src/pulsecore/x11prop.c b/src/pulsecore/x11prop.c index 9e75f63a..7f91ba3c 100644 --- a/src/pulsecore/x11prop.c +++ b/src/pulsecore/x11prop.c @@ -32,7 +32,7 @@ void pa_x11_set_prop(Display *d, const char *name, const char *data) { Atom a = XInternAtom(d, name, False); - XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (const unsigned char*) data, strlen(data)+1); + XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (const unsigned char*) data, (int) (strlen(data)+1)); } void pa_x11_del_prop(Display *d, const char *name) { @@ -49,7 +49,7 @@ char* pa_x11_get_prop(Display *d, const char *name, char *p, size_t l) { char *ret = NULL; Atom a = XInternAtom(d, name, False); - if (XGetWindowProperty(d, RootWindow(d, 0), a, 0, (l+2)/4, False, XA_STRING, &actual_type, &actual_format, &nitems, &nbytes_after, &prop) != Success) + if (XGetWindowProperty(d, RootWindow(d, 0), a, 0, (long) ((l+2)/4), False, XA_STRING, &actual_type, &actual_format, &nitems, &nbytes_after, &prop) != Success) goto finish; if (actual_type != XA_STRING) diff --git a/src/pulsecore/x11wrap.c b/src/pulsecore/x11wrap.c index 17f8e6a4..332ebb2e 100644 --- a/src/pulsecore/x11wrap.c +++ b/src/pulsecore/x11wrap.c @@ -91,7 +91,7 @@ static void work(pa_x11_wrapper *w) { } /* IO notification event for the X11 display connection */ -static void display_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { +static void display_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { pa_x11_wrapper *w = userdata; pa_assert(m); @@ -118,7 +118,7 @@ static void defer_event(pa_mainloop_api *m, pa_defer_event *e, void *userdata) { } /* IO notification event for X11 internal connections */ -static void internal_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { +static void internal_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { pa_x11_wrapper *w = userdata; pa_assert(m); diff --git a/src/tests/channelmap-test.c b/src/tests/channelmap-test.c index 9c234602..6cf58fb0 100644 --- a/src/tests/channelmap-test.c +++ b/src/tests/channelmap-test.c @@ -1,10 +1,14 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + #include <stdio.h> #include <assert.h> #include <pulse/channelmap.h> #include <pulse/gccmacro.h> -int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { +int main(int argc, char *argv[]) { char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; pa_channel_map map, map2; diff --git a/src/tests/cpulimit-test.c b/src/tests/cpulimit-test.c index b7145e8a..fdc0162e 100644 --- a/src/tests/cpulimit-test.c +++ b/src/tests/cpulimit-test.c @@ -42,7 +42,7 @@ static time_t start; #ifdef TEST2 -static void func(pa_mainloop_api *m, PA_GCC_UNUSED pa_signal_event *e, PA_GCC_UNUSED int sig, PA_GCC_UNUSED void *userdata) { +static void func(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) { time_t now; time(&now); @@ -55,7 +55,7 @@ static void func(pa_mainloop_api *m, PA_GCC_UNUSED pa_signal_event *e, PA_GCC_UN #endif -int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { +int main(int argc, char *argv[]) { pa_mainloop *m; m = pa_mainloop_new(); diff --git a/src/tests/envelope-test.c b/src/tests/envelope-test.c index 9f914553..4a72f5a3 100644 --- a/src/tests/envelope-test.c +++ b/src/tests/envelope-test.c @@ -40,7 +40,7 @@ const pa_envelope_def ramp_down = { .n_points = 2, .points_x = { 100*PA_USEC_PER_MSEC, 300*PA_USEC_PER_MSEC }, .points_y = { - .f = { 1.0, 0.2 }, + .f = { 1.0f, 0.2f }, .i = { 0x10000, 0x10000/5 } } }; @@ -49,7 +49,7 @@ const pa_envelope_def ramp_up = { .n_points = 2, .points_x = { 100*PA_USEC_PER_MSEC, 300*PA_USEC_PER_MSEC }, .points_y = { - .f = { 0.2, 1.0 }, + .f = { 0.2f, 1.0f }, .i = { 0x10000/5, 0x10000 } } }; @@ -58,7 +58,7 @@ const pa_envelope_def ramp_down2 = { .n_points = 2, .points_x = { 50*PA_USEC_PER_MSEC, 900*PA_USEC_PER_MSEC }, .points_y = { - .f = { 0.8, 0.7 }, + .f = { 0.8f, 0.7f }, .i = { 0x10000*4/5, 0x10000*7/10 } } }; @@ -67,7 +67,7 @@ const pa_envelope_def ramp_up2 = { .n_points = 2, .points_x = { 50*PA_USEC_PER_MSEC, 900*PA_USEC_PER_MSEC }, .points_y = { - .f = { 0.7, 0.9 }, + .f = { 0.7f, 0.9f }, .i = { 0x10000*7/10, 0x10000*9/10 } } }; @@ -140,7 +140,7 @@ static pa_memblock * generate_block(pa_mempool *pool, const pa_sample_spec *ss) unsigned n_samples; block = pa_memblock_new(pool, pa_bytes_per_second(ss)); - n_samples = pa_memblock_get_length(block) / pa_sample_size(ss); + n_samples = (unsigned) (pa_memblock_get_length(block) / pa_sample_size(ss)); d = pa_memblock_acquire(block); @@ -171,7 +171,7 @@ static pa_memblock * generate_block(pa_mempool *pool, const pa_sample_spec *ss) float *f; for (f = d; n_samples > 0; n_samples--, f++) - *f = PA_MAYBE_FLOAT32_SWAP(ss->format == PA_SAMPLE_FLOAT32RE, 1.0); + *f = PA_MAYBE_FLOAT32_SWAP(ss->format == PA_SAMPLE_FLOAT32RE, 1.0f); break; } @@ -205,7 +205,7 @@ int main(int argc, char *argv[]) { oil_init(); pa_log_set_maximal_level(PA_LOG_DEBUG); - pa_assert_se(pool = pa_mempool_new(FALSE)); + pa_assert_se(pool = pa_mempool_new(FALSE, 0)); pa_assert_se(envelope = pa_envelope_new(&ss)); block = generate_block(pool, &ss); diff --git a/src/tests/lock-autospawn-test.c b/src/tests/lock-autospawn-test.c new file mode 100644 index 00000000..80cfda6a --- /dev/null +++ b/src/tests/lock-autospawn-test.c @@ -0,0 +1,109 @@ +/*** + This file is part of PulseAudio. + + Copyright 2008 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <sys/poll.h> +#include <string.h> + +#include <pulsecore/macro.h> +#include <pulsecore/thread.h> +#include <pulsecore/lock-autospawn.h> +#include <pulse/util.h> + +static void thread_func(void*k) { + pa_assert_se(pa_autospawn_lock_init() >= 0); + + pa_log("%i, Trying to acquire lock.", PA_PTR_TO_INT(k)); + + pa_assert_se(pa_autospawn_lock_acquire(TRUE) > 0); + + pa_log("%i, Got the lock!, Sleeping for 5s", PA_PTR_TO_INT(k)); + + pa_msleep(5000); + + pa_log("%i, Releasing", PA_PTR_TO_INT(k)); + + pa_autospawn_lock_release(); + + pa_autospawn_lock_done(FALSE); +} + +static void thread_func2(void *k) { + int fd; + + pa_assert_se((fd = pa_autospawn_lock_init()) >= 0); + + pa_log("%i, Trying to acquire lock.", PA_PTR_TO_INT(k)); + + for (;;) { + struct pollfd pollfd; + int j; + + if ((j = pa_autospawn_lock_acquire(FALSE)) > 0) + break; + + pa_assert(j == 0); + + memset(&pollfd, 0, sizeof(pollfd)); + pollfd.fd = fd; + pollfd.events = POLLIN; + + pa_assert_se(poll(&pollfd, 1, -1) == 1); + + pa_log("%i, woke up", PA_PTR_TO_INT(k)); + } + + pa_log("%i, Got the lock!, Sleeping for 5s", PA_PTR_TO_INT(k)); + + pa_msleep(5000); + + pa_log("%i, Releasing", PA_PTR_TO_INT(k)); + + pa_autospawn_lock_release(); + + pa_autospawn_lock_done(FALSE); +} + +int main(int argc, char**argv) { + pa_thread *a, *b, *c, *d; + + pa_assert_se((a = pa_thread_new(thread_func, PA_INT_TO_PTR(1)))); + pa_assert_se((b = pa_thread_new(thread_func2, PA_INT_TO_PTR(2)))); + pa_assert_se((c = pa_thread_new(thread_func2, PA_INT_TO_PTR(3)))); + pa_assert_se((d = pa_thread_new(thread_func, PA_INT_TO_PTR(4)))); + + pa_thread_join(a); + pa_thread_join(b); + pa_thread_join(c); + pa_thread_join(d); + + pa_thread_free(a); + pa_thread_free(b); + pa_thread_free(c); + pa_thread_free(d); + + pa_log("End"); + + return 0; +} diff --git a/src/tests/mainloop-test.c b/src/tests/mainloop-test.c index 9fa2e466..2580fa72 100644 --- a/src/tests/mainloop-test.c +++ b/src/tests/mainloop-test.c @@ -66,7 +66,7 @@ static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, v #endif } -int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { +int main(int argc, char *argv[]) { pa_mainloop_api *a; pa_io_event *ioe; pa_time_event *te; diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c index 9e358359..92e3e14e 100644 --- a/src/tests/mcalign-test.c +++ b/src/tests/mcalign-test.c @@ -36,18 +36,18 @@ /* A simple program for testing pa_mcalign */ -int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { +int main(int argc, char *argv[]) { pa_mempool *p; pa_mcalign *a; pa_memchunk c; - p = pa_mempool_new(0); + p = pa_mempool_new(FALSE, 0); a = pa_mcalign_new(11); pa_memchunk_reset(&c); - srand(time(NULL)); + srand((unsigned) time(NULL)); for (;;) { ssize_t r; @@ -62,7 +62,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { l = pa_memblock_get_length(c.memblock) - c.index; - l = l <= 1 ? l : rand() % (l-1) +1 ; + l = l <= 1 ? l : (size_t) rand() % (l-1) +1; p = pa_memblock_acquire(c.memblock); @@ -74,11 +74,11 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { pa_memblock_release(c.memblock); - c.length = r; + c.length = (size_t) r; pa_mcalign_push(a, &c); fprintf(stderr, "Read %ld bytes\n", (long)r); - c.index += r; + c.index += (size_t) r; if (c.index >= pa_memblock_get_length(c.memblock)) { pa_memblock_unref(c.memblock); diff --git a/src/tests/memblock-test.c b/src/tests/memblock-test.c index 6da1b1e9..37b5b403 100644 --- a/src/tests/memblock-test.c +++ b/src/tests/memblock-test.c @@ -78,9 +78,9 @@ int main(int argc, char *argv[]) { const char txt[] = "This is a test!"; - pool_a = pa_mempool_new(1); - pool_b = pa_mempool_new(1); - pool_c = pa_mempool_new(1); + pool_a = pa_mempool_new(TRUE, 0); + pool_b = pa_mempool_new(TRUE, 0); + pool_c = pa_mempool_new(TRUE, 0); pa_mempool_get_shm_id(pool_a, &id_a); pa_mempool_get_shm_id(pool_b, &id_b); diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c index 7bf992a1..c53945b4 100644 --- a/src/tests/memblockq-test.c +++ b/src/tests/memblockq-test.c @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) { pa_log_set_maximal_level(PA_LOG_DEBUG); - p = pa_mempool_new(0); + p = pa_mempool_new(FALSE, 0); silence.memblock = pa_memblock_new_fixed(p, (char*) "__", 2, 1); assert(silence.memblock); diff --git a/src/tests/mix-test.c b/src/tests/mix-test.c index f3f6f829..cc21ab03 100644 --- a/src/tests/mix-test.c +++ b/src/tests/mix-test.c @@ -166,16 +166,16 @@ static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) { case PA_SAMPLE_FLOAT32RE: { float *u = d; - u[0] = 0.0; - u[1] = -1.0; - u[2] = 1.0; - u[3] = 4711; - u[4] = 0.222; - u[5] = 0.33; - u[6] = -.3; - u[7] = 99; - u[8] = -0.555; - u[9] = -.123; + u[0] = 0.0f; + u[1] = -1.0f; + u[2] = 1.0f; + u[3] = 4711.0f; + u[4] = 0.222f; + u[5] = 0.33f; + u[6] = -.3f; + u[7] = 99.0f; + u[8] = -0.555f; + u[9] = -.123f; if (ss->format == PA_SAMPLE_FLOAT32RE) for (i = 0; i < 10; i++) @@ -201,7 +201,7 @@ int main(int argc, char *argv[]) { oil_init(); pa_log_set_maximal_level(PA_LOG_DEBUG); - pa_assert_se(pool = pa_mempool_new(FALSE)); + pa_assert_se(pool = pa_mempool_new(FALSE, 0)); a.channels = 1; a.rate = 44100; @@ -221,6 +221,8 @@ int main(int argc, char *argv[]) { i.length = pa_memblock_get_length(i.memblock); i.index = 0; + dump_block(&a, &i); + /* Make a copy */ j = i; pa_memblock_ref(j.memblock); @@ -229,6 +231,8 @@ int main(int argc, char *argv[]) { /* Adjust volume of the copy */ pa_volume_memchunk(&j, &a, &v); + dump_block(&a, &j); + m[0].chunk = i; m[0].volume.values[0] = PA_VOLUME_NORM; m[0].volume.channels = a.channels; @@ -244,8 +248,6 @@ int main(int argc, char *argv[]) { pa_mix(m, 2, ptr, k.length, &a, NULL, FALSE); pa_memblock_release(k.memblock); - dump_block(&a, &i); - dump_block(&a, &j); dump_block(&a, &k); pa_memblock_unref(i.memblock); diff --git a/src/tests/pacat-simple.c b/src/tests/pacat-simple.c index b26e4b68..ffe3176a 100644 --- a/src/tests/pacat-simple.c +++ b/src/tests/pacat-simple.c @@ -33,7 +33,7 @@ #define BUFSIZE 1024 -int main(PA_GCC_UNUSED int argc, char*argv[]) { +int main(int argc, char*argv[]) { /* The Sample format to use */ static const pa_sample_spec ss = { @@ -94,7 +94,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) { } /* ... and play it */ - if (pa_simple_write(s, buf, r, &error) < 0) { + if (pa_simple_write(s, buf, (size_t) r, &error) < 0) { fprintf(stderr, __FILE__": pa_simple_write() failed: %s\n", pa_strerror(error)); goto finish; } diff --git a/src/tests/parec-simple.c b/src/tests/parec-simple.c index 6c0d529b..c9d3bef5 100644 --- a/src/tests/parec-simple.c +++ b/src/tests/parec-simple.c @@ -47,13 +47,13 @@ static ssize_t loop_write(int fd, const void*data, size_t size) { ret += r; data = (const uint8_t*) data + r; - size -= r; + size -= (size_t) r; } return ret; } -int main(PA_GCC_UNUSED int argc, char*argv[]) { +int main(int argc, char*argv[]) { /* The sample type to use */ static const pa_sample_spec ss = { .format = PA_SAMPLE_S16LE, @@ -72,7 +72,6 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) { for (;;) { uint8_t buf[BUFSIZE]; - ssize_t r; /* Record some data ... */ if (pa_simple_read(s, buf, sizeof(buf), &error) < 0) { @@ -81,7 +80,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) { } /* And write it to STDOUT */ - if ((r = loop_write(STDOUT_FILENO, buf, sizeof(buf))) <= 0) { + if (loop_write(STDOUT_FILENO, buf, sizeof(buf)) != sizeof(buf)) { fprintf(stderr, __FILE__": write() failed: %s\n", strerror(errno)); goto finish; } diff --git a/src/tests/prioq-test.c b/src/tests/prioq-test.c new file mode 100644 index 00000000..120b512b --- /dev/null +++ b/src/tests/prioq-test.c @@ -0,0 +1,44 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <pulsecore/prioq.h> +#include <pulsecore/macro.h> + +#define N 1024 + +int main(int argc, char *argv[]) { + pa_prioq *q; + unsigned i; + + srand(0); + + q = pa_prioq_new(pa_idxset_trivial_compare_func); + + /* Fill in 1024 */ + for (i = 0; i < N; i++) + pa_prioq_put(q, PA_UINT_TO_PTR((unsigned) rand())); + + /* Remove half of it again */ + for (i = 0; i < N/2; i++){ + unsigned u = PA_PTR_TO_UINT(pa_prioq_pop(q)); + pa_log("%16u", u); + } + + pa_log("Refilling"); + + /* Fill in another 1024 */ + for (i = 0; i < N; i++) + pa_prioq_put(q, PA_UINT_TO_PTR((unsigned) rand())); + + + /* Remove everything */ + while (!pa_prioq_isempty(q)) { + unsigned u = PA_PTR_TO_UINT(pa_prioq_pop(q)); + pa_log("%16u", u); + } + + pa_prioq_free(q, NULL, NULL); + + return 0; +} diff --git a/src/tests/remix-test.c b/src/tests/remix-test.c index 4777c150..3538d7d4 100644 --- a/src/tests/remix-test.c +++ b/src/tests/remix-test.c @@ -58,7 +58,7 @@ int main(int argc, char *argv[]) { oil_init(); pa_log_set_maximal_level(PA_LOG_DEBUG); - pa_assert_se(pool = pa_mempool_new(FALSE)); + pa_assert_se(pool = pa_mempool_new(FALSE, 0)); for (i = 0; maps[i].channels > 0; i++) for (j = 0; maps[j].channels > 0; j++) { diff --git a/src/tests/resampler-test.c b/src/tests/resampler-test.c index 1a20be2c..2d591867 100644 --- a/src/tests/resampler-test.c +++ b/src/tests/resampler-test.c @@ -166,16 +166,16 @@ static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) { case PA_SAMPLE_FLOAT32RE: { float *u = d; - u[0] = 0.0; - u[1] = -1.0; - u[2] = 1.0; - u[3] = 4711; - u[4] = 0.222; - u[5] = 0.33; - u[6] = -.3; - u[7] = 99; - u[8] = -0.555; - u[9] = -.123; + u[0] = 0.0f; + u[1] = -1.0f; + u[2] = 1.0f; + u[3] = 4711.0f; + u[4] = 0.222f; + u[5] = 0.33f; + u[6] = -.3f; + u[7] = 99.0f; + u[8] = -0.555f; + u[9] = -.123f; if (ss->format == PA_SAMPLE_FLOAT32RE) for (i = 0; i < 10; i++) @@ -201,7 +201,7 @@ int main(int argc, char *argv[]) { oil_init(); pa_log_set_maximal_level(PA_LOG_DEBUG); - pa_assert_se(pool = pa_mempool_new(FALSE)); + pa_assert_se(pool = pa_mempool_new(FALSE, 0)); a.channels = b.channels = 1; a.rate = b.rate = 44100; diff --git a/src/tests/rtstutter.c b/src/tests/rtstutter.c index 91e85c36..6b0cb8f7 100644 --- a/src/tests/rtstutter.c +++ b/src/tests/rtstutter.c @@ -52,7 +52,7 @@ static void* work(void *p) { pa_assert_se(pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m) == 0); CPU_ZERO(&mask); - CPU_SET(PA_PTR_TO_INT(p), &mask); + CPU_SET((size_t) PA_PTR_TO_INT(p), &mask); pa_assert_se(pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) == 0); for (;;) { @@ -65,17 +65,17 @@ static void* work(void *p) { pa_assert_se(clock_gettime(CLOCK_REALTIME, &end) == 0); nsec = - (uint64_t) ((((double) rand())*(msec_upper-msec_lower)*PA_NSEC_PER_MSEC)/RAND_MAX) + - (uint64_t) (msec_lower*PA_NSEC_PER_MSEC); + (uint64_t) ((((double) rand())*(double)(msec_upper-msec_lower)*PA_NSEC_PER_MSEC)/RAND_MAX) + + (uint64_t) ((uint64_t) msec_lower*PA_NSEC_PER_MSEC); pa_log_notice("CPU%i: Freezing for %ims", PA_PTR_TO_INT(p), (int) (nsec/PA_NSEC_PER_MSEC)); - end.tv_sec += nsec / PA_NSEC_PER_SEC; - end.tv_nsec += nsec % PA_NSEC_PER_SEC; + end.tv_sec += (time_t) (nsec / PA_NSEC_PER_SEC); + end.tv_nsec += (long int) (nsec % PA_NSEC_PER_SEC); while ((pa_usec_t) end.tv_nsec > PA_NSEC_PER_SEC) { end.tv_sec++; - end.tv_nsec -= PA_NSEC_PER_SEC; + end.tv_nsec -= (long int) PA_NSEC_PER_SEC; } do { @@ -88,7 +88,7 @@ static void* work(void *p) { int main(int argc, char*argv[]) { int n; - srand(time(NULL)); + srand((unsigned) time(NULL)); if (argc >= 3) { msec_lower = atoi(argv[1]); diff --git a/src/tests/smoother-test.c b/src/tests/smoother-test.c index b78f3c91..15700ec2 100644 --- a/src/tests/smoother-test.c +++ b/src/tests/smoother-test.c @@ -64,7 +64,7 @@ int main(int argc, char*argv[]) { for (x = 0, u = 0; x < PA_USEC_PER_SEC * 10; x += PA_USEC_PER_MSEC) { while (u < PA_ELEMENTSOF(msec) && (pa_usec_t) msec[u]*PA_USEC_PER_MSEC < x) { - pa_smoother_put(s, msec[u]*PA_USEC_PER_MSEC, msec[u+1]*PA_USEC_PER_MSEC); + pa_smoother_put(s, (pa_usec_t) msec[u] * PA_USEC_PER_MSEC, (pa_usec_t) msec[u+1] * PA_USEC_PER_MSEC); printf("%i\t\t%i\n", msec[u], msec[u+1]); u += 2; } diff --git a/src/tests/stripnul.c b/src/tests/stripnul.c index 0ab06776..2b8aa083 100644 --- a/src/tests/stripnul.c +++ b/src/tests/stripnul.c @@ -35,7 +35,7 @@ int main(int argc, char *argv[]) { uint8_t *zero; pa_assert_se(argc >= 2); - pa_assert_se((granularity = atoi(argv[1])) >= 1); + pa_assert_se((granularity = (size_t) atoi(argv[1])) >= 1); pa_assert_se((i = (argc >= 3) ? fopen(argv[2], "r") : stdin)); pa_assert_se((o = (argc >= 4) ? fopen(argv[3], "w") : stdout)); @@ -53,11 +53,11 @@ int main(int argc, char *argv[]) { if (found) pa_assert_se(fwrite(buffer, granularity, k, o) == k); else { - for (p = buffer; (p-buffer)/granularity < k; p += granularity) + for (p = buffer; ((size_t) (p-buffer)/granularity) < k; p += granularity) if (memcmp(p, zero, granularity)) { size_t left; found = TRUE; - left = k - (p-buffer)/granularity; + left = (size_t) (k - (size_t) (p-buffer)/granularity); pa_assert_se(fwrite(p, granularity, left, o) == left); break; } diff --git a/src/tests/strlist-test.c b/src/tests/strlist-test.c index 2bd1645c..10f370c2 100644 --- a/src/tests/strlist-test.c +++ b/src/tests/strlist-test.c @@ -5,7 +5,7 @@ #include <pulsecore/strlist.h> -int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char* argv[]) { +int main(int argc, char* argv[]) { char *t, *u; pa_strlist *l = NULL; diff --git a/src/tests/sync-playback.c b/src/tests/sync-playback.c index 7e364685..42c479a1 100644 --- a/src/tests/sync-playback.c +++ b/src/tests/sync-playback.c @@ -89,7 +89,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) { fprintf(stderr, "Writing data to stream %i.\n", i); - r = pa_stream_write(s, data, sizeof(data), nop_free_cb, sizeof(data) * i, PA_SEEK_ABSOLUTE); + r = pa_stream_write(s, data, sizeof(data), nop_free_cb, (int64_t) sizeof(data) * (int64_t) i, PA_SEEK_ABSOLUTE); assert(r == 0); /* Be notified when this stream is drained */ diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c index 7a62f85a..263cd57d 100644 --- a/src/tests/thread-mainloop-test.c +++ b/src/tests/thread-mainloop-test.c @@ -39,7 +39,7 @@ static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, v fprintf(stderr, "TIME EVENT END\n"); } -int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { +int main(int argc, char *argv[]) { pa_mainloop_api *a; pa_threaded_mainloop *m; struct timeval tv; diff --git a/src/tests/voltest.c b/src/tests/voltest.c index d2c0ff69..5bfc97e0 100644 --- a/src/tests/voltest.c +++ b/src/tests/voltest.c @@ -3,8 +3,9 @@ #include <pulse/volume.h> #include <pulse/gccmacro.h> -int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { +int main(int argc, char *argv[]) { pa_volume_t v; + pa_cvolume cv; for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) { @@ -13,6 +14,17 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { printf("Volume: %3i; percent: %i%%; decibel %0.2f; linear = %0.2f; volume(decibel): %3i; volume(linear): %3i\n", v, (v*100)/PA_VOLUME_NORM, dB, f, pa_sw_volume_from_dB(dB), pa_sw_volume_from_linear(f)); + } + + for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) { + char s[PA_CVOLUME_SNPRINT_MAX], t[PA_SW_CVOLUME_SNPRINT_DB_MAX]; + + pa_cvolume_set(&cv, 2, v); + + printf("Volume: %3i [%s] [%s]\n", + v, + pa_cvolume_snprint(s, sizeof(s), &cv), + pa_sw_cvolume_snprint_dB(t, sizeof(t), &cv)); } diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 32fa6bcf..ea736e23 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -57,6 +57,7 @@ static char *stream_name = NULL, *client_name = NULL, *device = NULL; static int verbose = 0; static pa_volume_t volume = PA_VOLUME_NORM; +static int volume_is_set = 0; static pa_sample_spec sample_spec = { .format = PA_SAMPLE_S16LE, @@ -274,8 +275,8 @@ static void context_state_callback(pa_context *c, void *userdata) { if (latency > 0) { memset(&buffer_attr, 0, sizeof(buffer_attr)); - buffer_attr.tlength = latency; - buffer_attr.minreq = process_time; + buffer_attr.tlength = (uint32_t) latency; + buffer_attr.minreq = (uint32_t) process_time; buffer_attr.maxlength = (uint32_t) -1; buffer_attr.prebuf = (uint32_t) -1; flags |= PA_STREAM_ADJUST_LATENCY; @@ -283,7 +284,7 @@ static void context_state_callback(pa_context *c, void *userdata) { if (mode == PLAYBACK) { pa_cvolume cv; - if ((r = pa_stream_connect_playback(stream, device, latency > 0 ? &buffer_attr : NULL, flags, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL)) < 0) { + if ((r = pa_stream_connect_playback(stream, device, latency > 0 ? &buffer_attr : NULL, flags, volume_is_set ? pa_cvolume_set(&cv, sample_spec.channels, volume) : NULL, NULL)) < 0) { fprintf(stderr, _("pa_stream_connect_playback() failed: %s\n"), pa_strerror(pa_context_errno(c))); goto fail; } @@ -391,7 +392,7 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even return; } - buffer_length = r; + buffer_length = (uint32_t) r; buffer_index = 0; if (w) @@ -422,8 +423,8 @@ static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_eve return; } - buffer_length -= r; - buffer_index += r; + buffer_length -= (uint32_t) r; + buffer_index += (uint32_t) r; if (!buffer_length) { pa_xfree(buffer); @@ -456,7 +457,7 @@ static void stream_update_timing_callback(pa_stream *s, int success, void *userd fprintf(stderr, _("Time: %0.3f sec; Latency: %0.0f usec. \r"), (float) usec / 1000000, - (float) l * (negative?-1:1)); + (float) l * (negative?-1.0f:1.0f)); } /* Someone requested that the latency is shown */ @@ -500,7 +501,7 @@ static void help(const char *argv0) { " --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n" " --rate=SAMPLERATE The sample rate in Hz (defaults to 44100)\n" " --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n" - " float32be, ulaw, alaw (defaults to s16ne)\n" + " float32be, ulaw, alaw, s32le, s32be (defaults to s16ne)\n" " --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n" " (defaults to 2)\n" " --channel-map=CHANNELMAP Channel map to use instead of the default\n" @@ -626,12 +627,13 @@ int main(int argc, char *argv[]) { case ARG_VOLUME: { int v = atoi(optarg); - volume = v < 0 ? 0 : v; + volume = v < 0 ? 0U : (pa_volume_t) v; + volume_is_set = 1; break; } case ARG_CHANNELS: - sample_spec.channels = atoi(optarg); + sample_spec.channels = (uint8_t) atoi(optarg); break; case ARG_SAMPLEFORMAT: @@ -639,7 +641,7 @@ int main(int argc, char *argv[]) { break; case ARG_SAMPLERATE: - sample_spec.rate = atoi(optarg); + sample_spec.rate = (uint32_t) atoi(optarg); break; case ARG_CHANNELMAP: @@ -672,14 +674,14 @@ int main(int argc, char *argv[]) { break; case ARG_LATENCY: - if (((latency = atoi(optarg))) <= 0) { + if (((latency = (size_t) atoi(optarg))) <= 0) { fprintf(stderr, _("Invalid latency specification '%s'\n"), optarg); goto quit; } break; case ARG_PROCESS_TIME: - if (((process_time = atoi(optarg))) <= 0) { + if (((process_time = (size_t) atoi(optarg))) <= 0) { fprintf(stderr, _("Invalid process time specification '%s'\n"), optarg); goto quit; } @@ -695,7 +697,7 @@ int main(int argc, char *argv[]) { goto quit; } - if (channel_map_set && channel_map.channels != sample_spec.channels) { + if (channel_map_set && pa_channel_map_compatible(&channel_map, &sample_spec)) { fprintf(stderr, _("Channel map doesn't match sample specification\n")); goto quit; } @@ -773,7 +775,10 @@ int main(int argc, char *argv[]) { pa_context_set_state_callback(context, context_state_callback, NULL); /* Connect the context */ - pa_context_connect(context, server, 0, NULL); + if (pa_context_connect(context, server, 0, NULL) < 0) { + fprintf(stderr, _("pa_context_connect() failed: %s"), pa_strerror(pa_context_errno(context))); + goto quit; + } if (verbose) { struct timeval tv; diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index 24cddaa3..2c89c8d9 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -42,7 +42,7 @@ #include <pulsecore/log.h> #include <pulsecore/pid.h> -int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { +int main(int argc, char*argv[]) { pid_t pid ; int fd = -1; int ret = 1, i; diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 3f00df1b..2f430ca7 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -555,7 +555,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { d = pa_xmalloc(length); assert(sample_length >= length); - l = length/pa_frame_size(&sample_spec); + l = (sf_count_t) (length/pa_frame_size(&sample_spec)); if ((sf_readf_float(sndfile, d, l)) != l) { pa_xfree(d); @@ -791,11 +791,11 @@ int main(int argc, char *argv[]) { goto quit; } - sample_spec.format = PA_SAMPLE_FLOAT32; - sample_spec.rate = sfinfo.samplerate; - sample_spec.channels = sfinfo.channels; + sample_spec.format = PA_SAMPLE_FLOAT32; + sample_spec.rate = (uint32_t) sfinfo.samplerate; + sample_spec.channels = (uint8_t) sfinfo.channels; - sample_length = sfinfo.frames*pa_frame_size(&sample_spec); + sample_length = (size_t)sfinfo.frames*pa_frame_size(&sample_spec); } else if (!strcmp(argv[optind], "play-sample")) { action = PLAY_SAMPLE; if (argc != optind+2 && argc != optind+3) { @@ -823,7 +823,7 @@ int main(int argc, char *argv[]) { goto quit; } - sink_input_idx = atoi(argv[optind+1]); + sink_input_idx = (uint32_t) atoi(argv[optind+1]); sink_name = pa_xstrdup(argv[optind+2]); } else if (!strcmp(argv[optind], "move-source-output")) { action = MOVE_SOURCE_OUTPUT; @@ -832,7 +832,7 @@ int main(int argc, char *argv[]) { goto quit; } - source_output_idx = atoi(argv[optind+1]); + source_output_idx = (uint32_t) atoi(argv[optind+1]); source_name = pa_xstrdup(argv[optind+2]); } else if (!strcmp(argv[optind], "load-module")) { int i; @@ -852,7 +852,7 @@ int main(int argc, char *argv[]) { n += strlen(argv[i])+1; if (n > 0) { - p = module_args = pa_xnew0(char, n); + p = module_args = pa_xmalloc(n); for (i = optind+2; i < argc; i++) p += sprintf(p, "%s%s", p == module_args ? "" : " ", argv[i]); @@ -866,7 +866,7 @@ int main(int argc, char *argv[]) { goto quit; } - module_index = atoi(argv[optind+1]); + module_index = (uint32_t) atoi(argv[optind+1]); } else if (!strcmp(argv[optind], "suspend-sink")) { action = SUSPEND_SINK; diff --git a/src/utils/padsp.c b/src/utils/padsp.c index c82fde64..2e6e5575 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -422,7 +422,7 @@ static void fd_info_unref(fd_info *i) { pthread_mutex_lock(&i->mutex); assert(i->ref >= 1); r = --i->ref; - debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref); pthread_mutex_unlock(&i->mutex); if (r <= 0) @@ -498,7 +498,6 @@ static void atfork_prepare(void) { pthread_mutex_lock(&func_mutex); - debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() exit\n"); } @@ -550,12 +549,14 @@ static void atfork_child(void) { } if (i->app_fd >= 0) { - close(i->app_fd); + LOAD_CLOSE_FUNC(); + _close(i->app_fd); i->app_fd = -1; } if (i->thread_fd >= 0) { - close(i->thread_fd); + LOAD_CLOSE_FUNC(); + _close(i->thread_fd); i->thread_fd = -1; } @@ -748,7 +749,7 @@ static void fix_metrics(fd_info *i) { /* Number of fragments set? */ if (i->n_fragments < 2) { if (i->fragment_size > 0) { - i->n_fragments = pa_bytes_per_second(&i->sample_spec) / 2 / i->fragment_size; + i->n_fragments = (unsigned) (pa_bytes_per_second(&i->sample_spec) / 2 / i->fragment_size); if (i->n_fragments < 2) i->n_fragments = 2; } else @@ -864,7 +865,7 @@ static int fd_info_copy_data(fd_info *i, int force) { return -1; } - if (pa_stream_write(i->play_stream, i->buf, r, free, 0, PA_SEEK_RELATIVE) < 0) { + if (pa_stream_write(i->play_stream, i->buf, (size_t) r, free, 0LL, PA_SEEK_RELATIVE) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context))); return -1; } @@ -872,7 +873,7 @@ static int fd_info_copy_data(fd_info *i, int force) { i->buf = NULL; assert(n >= (size_t) r); - n -= r; + n -= (size_t) r; } if (n >= i->fragment_size) @@ -916,7 +917,7 @@ static int fd_info_copy_data(fd_info *i, int force) { } assert((size_t)r <= len - i->rec_offset); - i->rec_offset += r; + i->rec_offset += (size_t) r; if (i->rec_offset == len) { if (pa_stream_drop(i->rec_stream) < 0) { @@ -927,7 +928,7 @@ static int fd_info_copy_data(fd_info *i, int force) { } assert(n >= (size_t) r); - n -= r; + n -= (size_t) r; } if (n >= i->fragment_size) @@ -943,6 +944,10 @@ static int fd_info_copy_data(fd_info *i, int force) { api->io_enable(i->io_event, i->io_flags); } + /* So, we emptied the socket now, let's tell dsp_empty_socket() + * about this */ + pa_threaded_mainloop_signal(i->mainloop, 0); + return 0; } @@ -998,12 +1003,12 @@ static int create_playback_stream(fd_info *i) { pa_stream_set_latency_update_callback(i->play_stream, stream_latency_update_cb, i); memset(&attr, 0, sizeof(attr)); - attr.maxlength = i->fragment_size * (i->n_fragments+1); - attr.tlength = i->fragment_size * i->n_fragments; - attr.prebuf = i->fragment_size; - attr.minreq = i->fragment_size; + attr.maxlength = (uint32_t) (i->fragment_size * (i->n_fragments+1)); + attr.tlength = (uint32_t) (i->fragment_size * i->n_fragments); + attr.prebuf = (uint32_t) i->fragment_size; + attr.minreq = (uint32_t) i->fragment_size; - flags = PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE; + flags = PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_EARLY_REQUESTS; if (i->play_precork) { flags |= PA_STREAM_START_CORKED; debug(DEBUG_LEVEL_NORMAL, __FILE__": creating stream corked\n"); @@ -1013,9 +1018,9 @@ static int create_playback_stream(fd_info *i) { goto fail; } - n = i->fragment_size; + n = (int) i->fragment_size; setsockopt(i->app_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)); - n = i->fragment_size; + n = (int) i->fragment_size; setsockopt(i->thread_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); return 0; @@ -1042,8 +1047,8 @@ static int create_record_stream(fd_info *i) { pa_stream_set_latency_update_callback(i->rec_stream, stream_latency_update_cb, i); memset(&attr, 0, sizeof(attr)); - attr.maxlength = i->fragment_size * (i->n_fragments+1); - attr.fragsize = i->fragment_size; + attr.maxlength = (uint32_t) (i->fragment_size * (i->n_fragments+1)); + attr.fragsize = (uint32_t) i->fragment_size; flags = PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE; if (i->rec_precork) { @@ -1055,9 +1060,9 @@ static int create_record_stream(fd_info *i) { goto fail; } - n = i->fragment_size; + n = (int) i->fragment_size; setsockopt(i->app_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); - n = i->fragment_size; + n = (int) i->fragment_size; setsockopt(i->thread_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)); return 0; @@ -1474,7 +1479,7 @@ int open(const char *filename, int flags, ...) { if (flags & O_CREAT) { va_start(args, flags); if (sizeof(mode_t) < sizeof(int)) - mode = va_arg(args, int); + mode = (mode_t) va_arg(args, int); else mode = va_arg(args, mode_t); va_end(args); diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 9264a940..df2edf62 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -107,14 +107,14 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { if (readf_function) { size_t k = pa_frame_size(&sample_spec); - if ((bytes = readf_function(sndfile, data, length/k)) > 0) - bytes *= k; + if ((bytes = readf_function(sndfile, data, (sf_count_t) (length/k))) > 0) + bytes *= (sf_count_t) k; } else - bytes = sf_read_raw(sndfile, data, length); + bytes = sf_read_raw(sndfile, data, (sf_count_t) length); if (bytes > 0) - pa_stream_write(s, data, bytes, pa_xfree, 0, PA_SEEK_RELATIVE); + pa_stream_write(s, data, (size_t) bytes, pa_xfree, 0, PA_SEEK_RELATIVE); else pa_xfree(data); @@ -283,7 +283,7 @@ int main(int argc, char *argv[]) { case ARG_VOLUME: { int v = atoi(optarg); - volume = v < 0 ? 0 : v; + volume = v < 0 ? 0U : (pa_volume_t) v; break; } @@ -315,8 +315,8 @@ int main(int argc, char *argv[]) { goto quit; } - sample_spec.rate = sfinfo.samplerate; - sample_spec.channels = sfinfo.channels; + sample_spec.rate = (uint32_t) sfinfo.samplerate; + sample_spec.channels = (uint8_t) sfinfo.channels; readf_function = NULL; |