diff options
author | Sebastien Bacher <seb128@ubuntu.com> | 2020-02-19 18:32:27 +0100 |
---|---|---|
committer | Sebastien Bacher <seb128@ubuntu.com> | 2020-02-20 15:24:34 +0100 |
commit | b95cf1075e28f266a3af795f8ecbd74e606e9ebd (patch) | |
tree | b6380320d5f75a9cc2cea707f95785a08ff051db | |
parent | a003359ee4da70b85db93f50ab3f013a08bbd63f (diff) | |
parent | bb5f82cb41d3d34eb11e13cb19bec99ab276d142 (diff) |
Update upstream source from tag 'upstream/13.99.1'
Update to upstream version '13.99.1'
with Debian dir 0836e984298802a1852083259fe694e7f27afe82
188 files changed, 6737 insertions, 4782 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0c00925..dcb4a98 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,91 @@ -image: registry.freedesktop.org/pulseaudio/pulseaudio/ubuntu:18.04 +# The build has two stages. The 'container' stage is used to build a Docker +# container and push it to the project's container registry on fd.o GitLab. +# This step is only run when the tag for the container changes, else it is +# effectively a no-op. All of this infrastructure is inherited from the +# wayland/ci-templates repository which is the recommended way to set up CI +# infrastructure on fd.o GitLab. +# +# Once the container stage is done, we move on to the 'build' stage where we +# run an autotools and meson build in parallel. Currently, tests are also run +# as part of the build stage as there doesn't seem to be significant value to +# splitting the stages at the moment. + +stages: + - container + - build + +variables: + # Update this tag when you want to trigger a rebuild the container in which + # CI runs, for example when adding new packages to UBUNTU_DEBS. The tag is + # an arbitrary string that identifies the exact container contents. + UBUNTU_TAG: '2019-11-21-01' + UBUNTU_VERSION: '18.04' + UBUNTU_IMAGE: "$CI_REGISTRY_IMAGE/ubuntu/$UBUNTU_VERSION:$UBUNTU_TAG" + +include: + - project: 'wayland/ci-templates' + ref: master + file: '/templates/ubuntu.yml' + +build-container: + extends: .ubuntu@container-ifnot-exists + stage: container + variables: + GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image + + # Remember to update UBUNTU_TAG when modifying this package list! Otherwise + # the changes won't have effect since an old container image will be used. + UBUNTU_DEBS: >- + autoconf + automake + autopoint + bash-completion + check + curl + dbus-x11 + g++ + gcc + gettext + git-core + libasound2-dev + libasyncns-dev + libavahi-client-dev + libbluetooth-dev + libcap-dev + libfftw3-dev + libglib2.0-dev + libgtk-3-dev + libice-dev + libjack-dev + liblircclient-dev + libltdl-dev + liborc-0.4-dev + libsbc-dev + libsndfile1-dev + libsoxr-dev + libspeexdsp-dev + libssl-dev + libsystemd-dev + libtdb-dev + libtool + libudev-dev + libwebrtc-audio-processing-dev + libwrap0-dev + libx11-xcb-dev + libxcb1-dev + libxml-parser-perl + libxml2-utils + libxtst-dev + make + ninja-build + pkg-config + python3-setuptools + systemd + wget build-autotools: stage: build + image: $UBUNTU_IMAGE script: - export MAKEFLAGS="-j$(nproc)" - NOCONFIGURE=1 ./bootstrap.sh @@ -19,7 +103,15 @@ build-autotools: build-meson: stage: build + image: $UBUNTU_IMAGE script: + # Install meson + - wget -q https://github.com/mesonbuild/meson/releases/download/0.50.0/meson-0.50.0.tar.gz + - tar -xf meson-0.50.0.tar.gz + - cd meson-0.50.0 + - python3 setup.py install + - cd .. + # Do the actual build - meson build - cd build - ninja diff --git a/.tarball-version b/.tarball-version index f075061..99bc3d6 100644 --- a/.tarball-version +++ b/.tarball-version @@ -1 +1 @@ -13.0 +13.99.1 @@ -1 +1 @@ -13.0 +13.99.1 diff --git a/Makefile.am b/Makefile.am index 7784135..1cca140 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,7 +32,6 @@ EXTRA_DIST = \ README \ CODE_OF_CONDUCT.md \ scripts/benchmark_memory_usage.sh \ - scripts/Dockerfile \ scripts/plot_memory_usage.gp \ scripts/benchmarks/README \ todo \ @@ -58,7 +57,7 @@ EXTRA_DIST = \ src/modules/bluetooth/meson.build \ src/modules/echo-cancel/meson.build \ src/modules/gsettings/meson.build \ - src/modules/gsettings/post-install.sh \ + src/modules/gsettings/meson_post_install.py \ src/modules/meson.build \ src/modules/oss/meson.build \ src/modules/raop/meson.build \ diff --git a/Makefile.in b/Makefile.in index 3e18b95..6e9da6c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -240,7 +240,7 @@ am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/missing \ $(top_srcdir)/src/pulse/version.h.in ABOUT-NLS NEWS README \ build-aux/compile build-aux/config.guess \ - build-aux/config.rpath build-aux/config.sub \ + build-aux/config.rpath build-aux/config.sub build-aux/depcomp \ build-aux/install-sh build-aux/ltmain.sh build-aux/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) @@ -342,6 +342,8 @@ GREP = @GREP@ GSETTINGS_CFLAGS = @GSETTINGS_CFLAGS@ GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ GSETTINGS_LIBS = @GSETTINGS_LIBS@ +GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@ +GSTREAMER_LIBS = @GSTREAMER_LIBS@ GTK30_CFLAGS = @GTK30_CFLAGS@ GTK30_LIBS = @GTK30_LIBS@ HAVE_AF_UNIX = @HAVE_AF_UNIX@ @@ -552,7 +554,6 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pulseconfdir = @pulseconfdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -582,7 +583,6 @@ EXTRA_DIST = \ README \ CODE_OF_CONDUCT.md \ scripts/benchmark_memory_usage.sh \ - scripts/Dockerfile \ scripts/plot_memory_usage.gp \ scripts/benchmarks/README \ todo \ @@ -608,7 +608,7 @@ EXTRA_DIST = \ src/modules/bluetooth/meson.build \ src/modules/echo-cancel/meson.build \ src/modules/gsettings/meson.build \ - src/modules/gsettings/post-install.sh \ + src/modules/gsettings/meson_post_install.py \ src/modules/meson.build \ src/modules/oss/meson.build \ src/modules/raop/meson.build \ @@ -3,20 +3,32 @@ PulseAudio 13.0 Changes at a glance: * Added support for Dolby TrueHD and DTS-HD Master Audio + * Improved 5.1 surround channel routing * Improved initial card profile selection for ALSA cards + * Automatically switch away from unavailable card profiles * Bluetooth card profile choices aren't persistent any more by default - * Added support for SteelSeries Arctis 5 USB headset + * Added support for some SteelSeries Arctis 5 USB headsets + * Removed KDE specific routing configuration + * New information collection script for bug reports: pa-info * New "max_latency_msec" module argument for module-loopback + * New "fast_adjust_threshold_msec" module argument for module-loopback * New "stream_name" module argument for module-rtp-send * Fixed S/PDIF for CMEDIA USB2.0 High-Speed True HD Audio * Use source sample spec and channel map by default in module-loopback + * module-role-cork and module-role-ducking can now use recording streams as triggers * New "avoid_resampling" module argument for module-udev-detect and module-alsa-card * "avoid_resampling" also tries to avoid format conversion if the ALSA device supports it + * Added support for non-PCM formats in module-null-sink + * More efficient channel remapping in some cases for 32-bit streams + * Removed the "latency_time" option from module-null-source * New function to enable realtime scheduling for client threads + * New convenience functions for getting parameters from pa_format_info + * New function for pa_threaded_mainloop to run a callback in the mainloop thread without the mainloop lock being held + * Const-ification of parameters across headers * Removed BlueZ 4 support * Dropped intltool * Introduction of the Meson build system - * Const-ification of parameters across headers + * New build option for improving build reproducibility * Minor bug-fixes, bindings updates and several translation updates Detailed change log: diff --git a/build-aux/config.guess b/build-aux/config.guess index f50dcdb..b33c9e8 100755 --- a/build-aux/config.guess +++ b/build-aux/config.guess @@ -2,7 +2,7 @@ # Attempt to guess a canonical system name. # Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2018-02-24' +timestamp='2018-08-29' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -84,8 +84,6 @@ if test $# != 0; then exit 1 fi -trap 'exit 1' 1 2 15 - # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a @@ -96,34 +94,39 @@ trap 'exit 1' 1 2 15 # Portable tmp directory creation inspired by the Autoconf team. -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > "$dummy.c" ; - for c in cc gcc c89 c99 ; do - if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 1 2 13 15 +trap 'exitcode=$?; test -z "$tmp" || rm -fr "$tmp"; exit $exitcode' 0 + +set_cc_for_build() { + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$driver" + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then +if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi @@ -138,7 +141,7 @@ Linux|GNU|GNU/*) # We could probably try harder. LIBC=gnu - eval "$set_cc_for_build" + set_cc_for_build cat <<-EOF > "$dummy.c" #include <features.h> #if defined(__UCLIBC__) @@ -199,7 +202,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval "$set_cc_for_build" + set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -237,7 +240,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "$machine-${os}${release}${abi}" + echo "$machine-${os}${release}${abi-}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` @@ -389,20 +392,15 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval "$set_cc_for_build" - SUN_ARCH=i386 - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH=x86_64 - fi - fi - echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + UNAME_REL="`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + case `isainfo -b` in + 32) + echo i386-pc-solaris2"$UNAME_REL" + ;; + 64) + echo x86_64-pc-solaris2"$UNAME_REL" + ;; + esac exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize @@ -482,7 +480,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include <stdio.h> /* for printf() prototype */ @@ -579,7 +577,7 @@ EOF exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include <sys/systemcfg.h> @@ -660,7 +658,7 @@ EOF esac fi if [ "$HP_ARCH" = "" ]; then - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE @@ -700,7 +698,7 @@ EOF esac if [ "$HP_ARCH" = hppa2.0w ] then - eval "$set_cc_for_build" + set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -726,7 +724,7 @@ EOF echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include <unistd.h> int @@ -840,6 +838,17 @@ EOF *:BSD/OS:*:*) echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi + else + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf + fi + exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case "$UNAME_PROCESSOR" in @@ -894,8 +903,8 @@ EOF # other systems with GNU libc and userland echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; - i*86:Minix:*:*) - echo "$UNAME_MACHINE"-pc-minix + *:Minix:*:*) + echo "$UNAME_MACHINE"-unknown-minix exit ;; aarch64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" @@ -922,7 +931,7 @@ EOF echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) - eval "$set_cc_for_build" + set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then @@ -971,7 +980,7 @@ EOF echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef ${UNAME_MACHINE} @@ -1046,11 +1055,7 @@ EOF echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) - if objdump -f /bin/sh | grep -q elf32-x86-64; then - echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 - else - echo "$UNAME_MACHINE"-pc-linux-"$LIBC" - fi + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; xtensa*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" @@ -1289,7 +1294,7 @@ EOF exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval "$set_cc_for_build" + set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi @@ -1362,6 +1367,7 @@ EOF # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. + # shellcheck disable=SC2154 if test "$cputype" = 386; then UNAME_MACHINE=i386 else @@ -1473,7 +1479,7 @@ EOF exit 1 # Local variables: -# eval: (add-hook 'write-file-functions 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/build-aux/config.sub b/build-aux/config.sub index 1d8e98b..b51fb8c 100755 --- a/build-aux/config.sub +++ b/build-aux/config.sub @@ -2,7 +2,7 @@ # Configuration validation subroutine script. # Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2018-02-22' +timestamp='2018-08-29' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -110,1223 +110,1159 @@ case $# in exit 1;; esac -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ - kopensolaris*-gnu* | cloudabi*-eabi* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo "$1" | sed 's/-[^-]*$//'` - if [ "$basic_machine" != "$1" ] - then os=`echo "$1" | sed 's/.*-/-/'` - else os=; fi - ;; -esac +# Split fields of configuration type +IFS="-" read -r field1 field2 field3 field4 <<EOF +$1 +EOF -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 +# Separate into logical components for further validation +case $1 in + *-*-*-*-*) + echo Invalid configuration \`"$1"\': more than four components >&2 + exit 1 ;; - -lynx*) - os=-lynxos + *-*-*-*) + basic_machine=$field1-$field2 + os=$field3-$field4 ;; - -ptx*) - basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \ + | linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova*) + basic_machine=$field1 + os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + os=linux-android + ;; + *) + basic_machine=$field1-$field2 + os=$field3 + ;; + esac ;; - -psos*) - os=-psos + *-*) + # A lone config we happen to match not fitting any patern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec + os= + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + os= + ;; + *) + basic_machine=$field1 + os=$field2 + ;; + esac + ;; + esac ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + os=bsd + ;; + a29khif) + basic_machine=a29k-amd + os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=scout + ;; + alliant) + basic_machine=fx80-alliant + os= + ;; + altos | altos3068) + basic_machine=m68k-altos + os= + ;; + am29k) + basic_machine=a29k-none + os=bsd + ;; + amdahl) + basic_machine=580-amdahl + os=sysv + ;; + amiga) + basic_machine=m68k-unknown + os= + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=bsd + ;; + aros) + basic_machine=i386-pc + os=aros + ;; + aux) + basic_machine=m68k-apple + os=aux + ;; + balance) + basic_machine=ns32k-sequent + os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=linux + ;; + cegcc) + basic_machine=arm-unknown + os=cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=bsd + ;; + convex-c2) + basic_machine=c2-convex + os=bsd + ;; + convex-c32) + basic_machine=c32-convex + os=bsd + ;; + convex-c34) + basic_machine=c34-convex + os=bsd + ;; + convex-c38) + basic_machine=c38-convex + os=bsd + ;; + cray) + basic_machine=j90-cray + os=unicos + ;; + crds | unos) + basic_machine=m68k-crds + os= + ;; + da30) + basic_machine=m68k-da30 + os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + os= + ;; + delta88) + basic_machine=m88k-motorola + os=sysv3 + ;; + dicos) + basic_machine=i686-pc + os=dicos + ;; + djgpp) + basic_machine=i586-pc + os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=ose + ;; + gmicro) + basic_machine=tron-gmicro + os=sysv + ;; + go32) + basic_machine=i386-pc + os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=hms + ;; + harris) + basic_machine=m88k-harris + os=sysv3 + ;; + hp300) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=hpux + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=proelf + ;; + i386mach) + basic_machine=i386-mach + os=mach + ;; + vsta) + basic_machine=i386-pc + os=vsta + ;; + isi68 | isi) + basic_machine=m68k-isi + os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + os=sysv + ;; + merlin) + basic_machine=ns32k-utek + os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + os=coff + ;; + morphos) + basic_machine=powerpc-unknown + os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=moxiebox + ;; + msdos) + basic_machine=i386-pc + os=msdos + ;; + msys) + basic_machine=i686-pc + os=msys + ;; + mvs) + basic_machine=i370-ibm + os=mvs + ;; + nacl) + basic_machine=le32-unknown + os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=sysv4 + ;; + netbsd386) + basic_machine=i386-pc + os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=newsos + ;; + news1000) + basic_machine=m68030-sony + os=newsos + ;; + necv70) + basic_machine=v70-nec + os=sysv + ;; + nh3000) + basic_machine=m68k-harris + os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=cxux + ;; + nindy960) + basic_machine=i960-intel + os=nindy + ;; + mon960) + basic_machine=i960-intel + os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=ose + ;; + os68k) + basic_machine=m68k-none + os=os68k + ;; + paragon) + basic_machine=i860-intel + os=osf + ;; + parisc) + basic_machine=hppa-unknown + os=linux + ;; + pw32) + basic_machine=i586-unknown + os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=rdos + ;; + rdos32) + basic_machine=i386-pc + os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=coff + ;; + sa29200) + basic_machine=a29k-amd + os=udi + ;; + sei) + basic_machine=mips-sei + os=seiux + ;; + sequent) + basic_machine=i386-sequent + os= + ;; + sps7) + basic_machine=m68k-bull + os=sysv2 + ;; + st2000) + basic_machine=m68k-tandem + os= + ;; + stratus) + basic_machine=i860-stratus + os=sysv4 + ;; + sun2) + basic_machine=m68000-sun + os= + ;; + sun2os3) + basic_machine=m68000-sun + os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=sunos4 + ;; + sun3) + basic_machine=m68k-sun + os= + ;; + sun3os3) + basic_machine=m68k-sun + os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=sunos4 + ;; + sun4) + basic_machine=sparc-sun + os= + ;; + sun4os3) + basic_machine=sparc-sun + os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=solaris2 + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + os= + ;; + sv1) + basic_machine=sv1-cray + os=unicos + ;; + symmetry) + basic_machine=i386-sequent + os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=unicos + ;; + t90) + basic_machine=t90-cray + os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + os=tpf + ;; + udi29k) + basic_machine=a29k-amd + os=udi + ;; + ultra3) + basic_machine=a29k-nyu + os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=none + ;; + vaxv) + basic_machine=vax-dec + os=sysv + ;; + vms) + basic_machine=vax-dec + os=vms + ;; + vxworks960) + basic_machine=i960-wrs + os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=vxworks + ;; + xbox) + basic_machine=i686-pc + os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + os=unicos + ;; + *) + basic_machine=$1 + os= + ;; + esac ;; esac -# Decode aliases for certain CPU-COMPANY combinations. +# Decode 1-component or ad-hoc basic machines case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ - | avr | avr32 \ - | ba \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | e2k | epiphany \ - | fido | fr30 | frv | ft32 \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia16 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 | or1k | or1knd | or32 \ - | pdp10 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pru \ - | pyramid \ - | riscv32 | riscv64 \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | visium \ - | wasm32 \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - leon|leon[3-9]) - basic_machine=sparc-$basic_machine - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=-none + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + op50n) + cpu=hppa1.1 + vendor=oki ;; - ms1) - basic_machine=mt-unknown + op60c) + cpu=hppa1.1 + vendor=oki ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown + ibm*) + cpu=i370 + vendor=ibm ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none + orion105) + cpu=clipper + vendor=highlevel ;; - xscaleeb) - basic_machine=armeb-unknown + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple ;; - - xscaleel) - basic_machine=armel-unknown + pmac | pmac-mpw) + cpu=powerpc + vendor=apple ;; - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | ba-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | e2k-* | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa32r6-* | mipsisa32r6el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64r6-* | mipsisa64r6el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | or1k*-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pru-* \ - | pyramid-* \ - | riscv32-* | riscv64-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | visium-* \ - | wasm32-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-pc - os=-bsd - ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att + cpu=m68000 + vendor=att ;; 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - asmjs) - basic_machine=asmjs-unknown - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=-linux + cpu=we32k + vendor=att ;; bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec + cpu=powerpc + vendor=ibm + os=cnk ;; decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 + cpu=pdp10 + vendor=dec + os=tops10 ;; decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 + cpu=pdp10 + vendor=dec + os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx + cpu=m68k + vendor=motorola ;; dpx2*) - basic_machine=m68k-bull - os=-sysv3 - ;; - e500v[12]) - basic_machine=powerpc-unknown - os=$os"spe" - ;; - e500v[12]-*) - basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=$os"spe" - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd + cpu=m68k + vendor=bull + os=sysv3 ;; encore | umax | mmax) - basic_machine=ns32k-encore + cpu=ns32k + vendor=encore ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose + elxsi) + cpu=elxsi + vendor=elxsi + os=${os:-bsd} ;; fx2800) - basic_machine=i860-alliant + cpu=i860 + vendor=alliant ;; genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 + cpu=ns32k + vendor=ns ;; h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux + cpu=hppa1.1 + vendor=hitachi + os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp + cpu=m68000 + vendor=hp ;; hp9k3[2-9][0-9]) - basic_machine=m68k-hp + cpu=m68k + vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm + cpu=hppa1.0 + vendor=hp ;; i*86v32) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-sysv32 + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=sysv32 ;; i*86v4*) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-sysv4 + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=sysv4 ;; i*86v) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-sysv + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=sysv ;; i*86sol2) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-solaris2 + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=solaris2 ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - vsta) - basic_machine=i386-unknown - os=-vsta + j90 | j90-cray) + cpu=j90 + vendor=cray + os=${os:-unicos} ;; iris | iris4d) - basic_machine=mips-sgi + cpu=mips + vendor=sgi case $os in - -irix*) + irix*) ;; *) - os=-irix4 + os=irix4 ;; esac ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - leon-*|leon[3-9]-*) - basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=-linux - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i686-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - moxiebox) - basic_machine=moxie-unknown - os=-moxiebox - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i686-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl + cpu=m68000 + vendor=convergent ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + cpu=m68k + vendor=atari + os=mint ;; news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv + cpu=mips + vendor=sony + os=newsos ;; next | m*-next) - basic_machine=m68k-next + cpu=m68k + vendor=next case $os in - -nextstep* ) + nextstep* ) ;; - -ns2*) - os=-nextstep2 + ns2*) + os=nextstep2 ;; *) - os=-nextstep3 + os=nextstep3 ;; esac ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - nsv-tandem) - basic_machine=nsv-tandem - ;; - nsx-tandem) - basic_machine=nsx-tandem + cpu=np1 + vendor=gould ;; op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k + cpu=hppa1.1 + vendor=oki + os=proelf ;; pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=-linux + cpu=hppa1.1 + vendor=hitachi + os=hiuxwe2 ;; pbd) - basic_machine=sparc-tti + cpu=sparc + vendor=tti ;; pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + cpu=m68k + vendor=tti ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` + pc532) + cpu=ns32k + vendor=pc532 ;; pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + cpu=pn + vendor=gould ;; - ppcle | powerpclittle) - basic_machine=powerpcle-unknown + power) + cpu=power + vendor=ibm ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown + ps2) + cpu=i386 + vendor=ibm ;; - ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + rm[46]00) + cpu=mips + vendor=siemens ;; - ppc64le | powerpc64little) - basic_machine=powerpc64le-unknown + rtpc | rtpc-*) + cpu=romp + vendor=ibm ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` + sde) + cpu=mipsisa32 + vendor=sde + os=${os:-elf} ;; - ps2) - basic_machine=i386-ibm + simso-wrs) + cpu=sparclite + vendor=wrs + os=vxworks ;; - pw32) - basic_machine=i586-unknown - os=-pw32 + tower | tower-32) + cpu=m68k + vendor=ncr ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu ;; - rdos32) - basic_machine=i386-pc - os=-rdos + w65) + cpu=w65 + vendor=wdc ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff + w89k-*) + cpu=hppa1.1 + vendor=winbond + os=proelf ;; - rm[46]00) - basic_machine=mips-siemens + none) + cpu=none + vendor=none ;; - rtpc | rtpc-*) - basic_machine=romp-ibm + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine ;; - s390 | s390-*) - basic_machine=s390-ibm + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; - s390x | s390x-*) - basic_machine=s390x-ibm + + *-*) + IFS="-" read -r cpu vendor <<EOF +$basic_machine +EOF ;; - sa29200) - basic_machine=a29k-amd - os=-udi + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + cpu=$basic_machine + vendor=pc ;; - sb1) - basic_machine=mipsisa64sb1-unknown + # These rules are duplicated from below for sake of the special case above; + # i.e. things that normalized to x86 arches should also default to "pc" + pc98) + cpu=i386 + vendor=pc ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown + x64 | amd64) + cpu=x86_64 + vendor=pc ;; - sde) - basic_machine=mipsisa32-sde - os=-elf + # Recognize the basic CPU types without company name. + *) + cpu=$basic_machine + vendor=unknown ;; - sei) - basic_machine=mips-sei - os=-seiux +esac + +unset -v basic_machine + +# Decode basic machines in the full and proper CPU-Company form. +case $cpu-$vendor in + # Here we handle the default manufacturer of certain CPU types in cannonical form. It is in + # some cases the only manufacturer, in others, it is the most popular. + craynv-unknown) + vendor=cray + os=${os:-unicosmp} ;; - sequent) - basic_machine=i386-sequent + c90-unknown | c90-cray) + vendor=cray + os=${os:-unicos} ;; - sh5el) - basic_machine=sh5le-unknown + fx80-unknown) + vendor=alliant ;; - simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks + romp-unknown) + vendor=ibm ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 + mmix-unknown) + vendor=knuth ;; - spur) - basic_machine=spur-unknown + microblaze-unknown | microblazeel-unknown) + vendor=xilinx ;; - st2000) - basic_machine=m68k-tandem + rs6000-unknown) + vendor=ibm ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 + vax-unknown) + vendor=dec ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` + pdp11-unknown) + vendor=dec ;; - sun2) - basic_machine=m68000-sun + we32k-unknown) + vendor=att ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 + cydra-unknown) + vendor=cydrome ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 + i370-ibm*) + vendor=ibm ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 + orion-unknown) + vendor=highlevel ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 + xps-unknown | xps100-unknown) + cpu=xps100 + vendor=honeywell ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 + + # Here we normalize CPU types with a missing or matching vendor + dpx20-unknown | dpx20-bull) + cpu=rs6000 + vendor=bull + os=${os:-bosx} ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 + + # Here we normalize CPU types irrespective of the vendor + amd64-*) + cpu=x86_64 ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 + blackfin-*) + cpu=bfin + os=linux ;; - sun3 | sun3-*) - basic_machine=m68k-sun + c54x-*) + cpu=tic54x ;; - sun4) - basic_machine=sparc-sun + c55x-*) + cpu=tic55x ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun + c6x-*) + cpu=tic6x ;; - sv1) - basic_machine=sv1-cray - os=-unicos + e500v[12]-*) + cpu=powerpc + os=$os"spe" ;; - symmetry) - basic_machine=i386-sequent - os=-dynix + mips3*-*) + cpu=mips64 ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos + ms1-*) + cpu=mt ;; - t90) - basic_machine=t90-cray - os=-unicos + m68knommu-*) + cpu=m68k + os=linux ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu + m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*) + cpu=s12z ;; - tx39) - basic_machine=mipstx39-unknown + openrisc-*) + cpu=or32 ;; - tx39el) - basic_machine=mipstx39el-unknown + parisc-*) + cpu=hppa + os=linux ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + cpu=i586 ;; - tower | tower-32) - basic_machine=m68k-ncr + pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) + cpu=i686 ;; - tpf) - basic_machine=s390x-ibm - os=-tpf + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + cpu=i686 ;; - udi29k) - basic_machine=a29k-amd - os=-udi + pentium4-*) + cpu=i786 ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 + pc98-*) + cpu=i386 ;; - v810 | necv810) - basic_machine=v810-nec - os=-none + ppc-* | ppcbe-*) + cpu=powerpc ;; - vaxv) - basic_machine=vax-dec - os=-sysv + ppcle-* | powerpclittle-*) + cpu=powerpcle ;; - vms) - basic_machine=vax-dec - os=-vms + ppc64-*) + cpu=powerpc64 ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu + ppc64le-* | powerpc64little-*) + cpu=powerpc64le ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks + sb1-*) + cpu=mipsisa64sb1 ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks + sb1el-*) + cpu=mipsisa64sb1el ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks + sh5e[lb]-*) + cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'` ;; - w65*) - basic_machine=w65-wdc - os=-none + spur-*) + cpu=spur ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf + strongarm-* | thumb-*) + cpu=arm ;; - x64) - basic_machine=x86_64-pc + tx39-*) + cpu=mipstx39 ;; - xbox) - basic_machine=i686-pc - os=-mingw32 + tx39el-*) + cpu=mipstx39el ;; - xps | xps100) - basic_machine=xps100-honeywell + x64-*) + cpu=x86_64 ;; xscale-* | xscalee[bl]-*) - basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - none) - basic_machine=none-none - os=-none + cpu=`echo "$cpu" | sed 's/^xscale/arm/'` ;; -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond + # Recognize the cannonical CPU Types that limit and/or modify the + # company names they are paired with. + cr16-*) + os=${os:-elf} ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm + crisv32-* | etraxfs*-*) + cpu=crisv32 + vendor=axis ;; - mmix) - basic_machine=mmix-knuth + cris-* | etrax*-*) + cpu=cris + vendor=axis ;; - rs6000) - basic_machine=rs6000-ibm + crx-*) + os=${os:-elf} ;; - vax) - basic_machine=vax-dec - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att + neo-tandem) + cpu=neo + vendor=tandem ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown + nse-tandem) + cpu=nse + vendor=tandem ;; - cydra) - basic_machine=cydra-cydrome + nsr-tandem) + cpu=nsr + vendor=tandem ;; - orion) - basic_machine=orion-highlevel + nsv-tandem) + cpu=nsv + vendor=tandem ;; - orion105) - basic_machine=clipper-highlevel + nsx-tandem) + cpu=nsx + vendor=tandem ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple + s390-*) + cpu=s390 + vendor=ibm ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple + s390x-*) + cpu=s390x + vendor=ibm ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. + tile*-*) + os=${os:-linux-gnu} ;; + *) - echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 - exit 1 + # Recognize the cannonical CPU types that are allowed with any + # company name. + case $cpu in + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ + | alphapca5[67] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[lb]e | arme[lb] | armv* \ + | avr | avr32 \ + | asmjs \ + | ba \ + | be32 | be64 \ + | bfin | bs2000 \ + | c[123]* | c30 | [cjt]90 | c4x \ + | c8051 | clipper | craynv | csky | cydra \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | elxsi | epiphany \ + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | h8300 | h8500 \ + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k | v70 | w65 \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip \ + | m88110 | m88k | maxq | mb | mcore | mep | metag \ + | microblaze | microblazeel \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mmix \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ + | none | np1 | ns16k | ns32k \ + | open8 \ + | or1k* \ + | or32 \ + | orion \ + | pdp10 | pdp11 | pj | pjl | pn | power \ + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ + | pru \ + | pyramid \ + | riscv | riscv32 | riscv64 \ + | rl78 | romp | rs6000 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \ + | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ + | spu \ + | tahoe \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ + | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ + | vax \ + | visium \ + | wasm32 \ + | we32k \ + | x86 | x86_64 | xc16x | xgate | xps100 \ + | xstormy16 | xtensa* \ + | ymp \ + | z8k | z80) + ;; + + *) + echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + exit 1 + ;; + esac ;; esac # Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` +case $vendor in + digital*) + vendor=dec ;; - *-commodore*) - basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` + commodore*) + vendor=cbm ;; *) ;; @@ -1334,199 +1270,245 @@ esac # Decode manufacturer-specific aliases for certain operating systems. -if [ x"$os" != x"" ] +if [ x$os != x ] then case $os in # First match some system type aliases that might get confused # with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux + # solaris* is a basic system type, with this one exception. + auroraux) + os=auroraux ;; - -solaris1 | -solaris1.*) + bluegene*) + os=cnk + ;; + solaris1 | solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; - -solaris) - os=-solaris2 + solaris) + os=solaris2 ;; - -unixware*) - os=-sysv4.2uw + unixware*) + os=sysv4.2uw ;; - -gnu/linux*) + gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # es1800 is here to avoid being matched by es* (a different OS) - -es1800*) - os=-ose + es1800*) + os=ose + ;; + # Some version numbers need modification + chorusos*) + os=chorusos + ;; + isc) + os=isc2.2 + ;; + sco6) + os=sco5v6 + ;; + sco5) + os=sco3.2v5 + ;; + sco4) + os=sco3.2v4 + ;; + sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + ;; + sco3.2v[4-9]* | sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + ;; + scout) + # Don't match below + ;; + sco*) + os=sco3.2v2 + ;; + psos*) + os=psos ;; # Now accept the basic system types. # The portable systems comes first. # Each alternative MUST end in a * to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* | -plan9* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* | -cloudabi* | -sortix* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ - | -midnightbsd*) + # sysv* is not here because it comes later, after sysvr4. + gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ + | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\ + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ + | sym* | kopensolaris* | plan9* \ + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ + | aos* | aros* | cloudabi* | sortix* \ + | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ + | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ + | knetbsd* | mirbsd* | netbsd* \ + | bitrig* | openbsd* | solidbsd* | libertybsd* \ + | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \ + | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ + | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ + | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \ + | chorusrdb* | cegcc* | glidix* \ + | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ + | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \ + | linux-newlib* | linux-musl* | linux-uclibc* \ + | uxpv* | beos* | mpeix* | udk* | moxiebox* \ + | interix* | uwin* | mks* | rhapsody* | darwin* \ + | openstep* | oskit* | conix* | pw32* | nonstopux* \ + | storm-chaos* | tops10* | tenex* | tops20* | its* \ + | os2* | vos* | palmos* | uclinux* | nucleus* \ + | morphos* | superux* | rtmk* | windiss* \ + | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ + | skyos* | haiku* | rdos* | toppers* | drops* | es* \ + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ + | midnightbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) + qnx*) + case $cpu in + x86 | i*86) ;; *) - os=-nto$os + os=nto-$os ;; esac ;; - -nto-qnx*) + hiux*) + os=hiuxwe2 + ;; + nto-qnx*) ;; - -nto*) + nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; - -sim | -xray | -os68k* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + sim | xray | os68k* | v88r* \ + | windows* | osx | abug | netware* | os9* \ + | macos* | mpw* | magic* | mmixware* | mon960* | lnews*) + ;; + linux-dietlibc) + os=linux-dietlibc + ;; + linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + lynx*178) + os=lynxos178 ;; - -mac*) + lynx*5) + os=lynxos5 + ;; + lynx*) + os=lynxos + ;; + mac*) os=`echo "$os" | sed -e 's|mac|macos|'` ;; - -linux-dietlibc) - os=-linux-dietlibc + opened*) + os=openedition ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` + os400*) + os=os400 ;; - -sunos5*) + sunos5*) os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; - -sunos6*) + sunos6*) os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 + wince*) + os=wince ;; - -wince*) - os=-wince + utek*) + os=bsd ;; - -utek*) - os=-bsd + dynix*) + os=bsd ;; - -dynix*) - os=-bsd + acis*) + os=aos ;; - -acis*) - os=-aos + atheos*) + os=atheos ;; - -atheos*) - os=-atheos + syllable*) + os=syllable ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd + 386bsd) + os=bsd ;; - -ctix* | -uts*) - os=-sysv + ctix* | uts*) + os=sysv ;; - -nova*) - os=-rtmk-nova + nova*) + os=rtmk-nova ;; - -ns2) - os=-nextstep2 + ns2) + os=nextstep2 ;; - -nsk*) - os=-nsk + nsk*) + os=nsk ;; # Preserve the version number of sinix5. - -sinix5.*) + sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; - -sinix*) - os=-sysv4 + sinix*) + os=sysv4 ;; - -tpf*) - os=-tpf + tpf*) + os=tpf ;; - -triton*) - os=-sysv3 + triton*) + os=sysv3 ;; - -oss*) - os=-sysv3 + oss*) + os=sysv3 ;; - -svr4*) - os=-sysv4 + svr4*) + os=sysv4 ;; - -svr3) - os=-sysv3 + svr3) + os=sysv3 ;; - -sysvr4) - os=-sysv4 + sysvr4) + os=sysv4 ;; - # This must come after -sysvr4. - -sysv*) + # This must come after sysvr4. + sysv*) ;; - -ose*) - os=-ose + ose*) + os=ose ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint + *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) + os=mint ;; - -zvmoe) - os=-zvmoe + zvmoe) + os=zvmoe ;; - -dicos*) - os=-dicos + dicos*) + os=dicos ;; - -pikeos*) + pikeos*) # Until real need of OS specific support for # particular features comes up, bare metal # configurations are quite functional. - case $basic_machine in + case $cpu in arm*) - os=-eabi + os=eabi ;; *) - os=-elf + os=elf ;; esac ;; - -nacl*) + nacl*) ;; - -ios) + ios) ;; - -none) + none) + ;; + *-eabi) ;; *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; @@ -1543,258 +1525,265 @@ else # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. -case $basic_machine in +case $cpu-$vendor in score-*) - os=-elf + os=elf ;; spu-*) - os=-elf + os=elf ;; *-acorn) - os=-riscix1.2 + os=riscix1.2 ;; arm*-rebel) - os=-linux + os=linux ;; arm*-semi) - os=-aout + os=aout ;; c4x-* | tic4x-*) - os=-coff + os=coff ;; c8051-*) - os=-elf + os=elf + ;; + clipper-intergraph) + os=clix ;; hexagon-*) - os=-elf + os=elf ;; tic54x-*) - os=-coff + os=coff ;; tic55x-*) - os=-coff + os=coff ;; tic6x-*) - os=-coff + os=coff ;; # This must come before the *-dec entry. pdp10-*) - os=-tops20 + os=tops20 ;; pdp11-*) - os=-none + os=none ;; *-dec | vax-*) - os=-ultrix4.2 + os=ultrix4.2 ;; m68*-apollo) - os=-domain + os=domain ;; i386-sun) - os=-sunos4.0.2 + os=sunos4.0.2 ;; m68000-sun) - os=-sunos3 + os=sunos3 ;; m68*-cisco) - os=-aout + os=aout ;; mep-*) - os=-elf + os=elf ;; mips*-cisco) - os=-elf + os=elf ;; mips*-*) - os=-elf + os=elf ;; or32-*) - os=-coff + os=coff ;; *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 + os=sysv3 ;; sparc-* | *-sun) - os=-sunos4.1.1 + os=sunos4.1.1 ;; pru-*) - os=-elf + os=elf ;; *-be) - os=-beos + os=beos ;; *-ibm) - os=-aix + os=aix ;; *-knuth) - os=-mmixware + os=mmixware ;; *-wec) - os=-proelf + os=proelf ;; *-winbond) - os=-proelf + os=proelf ;; *-oki) - os=-proelf + os=proelf ;; *-hp) - os=-hpux + os=hpux ;; *-hitachi) - os=-hiux + os=hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv + os=sysv ;; *-cbm) - os=-amigaos + os=amigaos ;; *-dg) - os=-dgux + os=dgux ;; *-dolphin) - os=-sysv3 + os=sysv3 ;; m68k-ccur) - os=-rtu + os=rtu ;; m88k-omron*) - os=-luna + os=luna ;; *-next) - os=-nextstep + os=nextstep ;; *-sequent) - os=-ptx + os=ptx ;; *-crds) - os=-unos + os=unos ;; *-ns) - os=-genix + os=genix ;; i370-*) - os=-mvs + os=mvs ;; *-gould) - os=-sysv + os=sysv ;; *-highlevel) - os=-bsd + os=bsd ;; *-encore) - os=-bsd + os=bsd ;; *-sgi) - os=-irix + os=irix ;; *-siemens) - os=-sysv4 + os=sysv4 ;; *-masscomp) - os=-rtu + os=rtu ;; f30[01]-fujitsu | f700-fujitsu) - os=-uxpv + os=uxpv ;; *-rom68k) - os=-coff + os=coff ;; *-*bug) - os=-coff + os=coff ;; *-apple) - os=-macos + os=macos ;; *-atari*) - os=-mint + os=mint + ;; + *-wrs) + os=vxworks ;; *) - os=-none + os=none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) +case $vendor in + unknown) case $os in - -riscix*) + riscix*) vendor=acorn ;; - -sunos*) + sunos*) vendor=sun ;; - -cnk*|-aix*) + cnk*|-aix*) vendor=ibm ;; - -beos*) + beos*) vendor=be ;; - -hpux*) + hpux*) vendor=hp ;; - -mpeix*) + mpeix*) vendor=hp ;; - -hiux*) + hiux*) vendor=hitachi ;; - -unos*) + unos*) vendor=crds ;; - -dgux*) + dgux*) vendor=dg ;; - -luna*) + luna*) vendor=omron ;; - -genix*) + genix*) vendor=ns ;; - -mvs* | -opened*) + clix*) + vendor=intergraph + ;; + mvs* | opened*) vendor=ibm ;; - -os400*) + os400*) vendor=ibm ;; - -ptx*) + ptx*) vendor=sequent ;; - -tpf*) + tpf*) vendor=ibm ;; - -vxsim* | -vxworks* | -windiss*) + vxsim* | vxworks* | windiss*) vendor=wrs ;; - -aux*) + aux*) vendor=apple ;; - -hms*) + hms*) vendor=hitachi ;; - -mpw* | -macos*) + mpw* | macos*) vendor=apple ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) vendor=atari ;; - -vos*) + vos*) vendor=stratus ;; esac - basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo "$basic_machine$os" +echo "$cpu-$vendor-$os" exit # Local variables: -# eval: (add-hook 'write-file-functions 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh index c12c197..7f3523d 100644 --- a/build-aux/ltmain.sh +++ b/build-aux/ltmain.sh @@ -31,7 +31,7 @@ PROGRAM=libtool PACKAGE=libtool -VERSION="2.4.6 Debian-2.4.6-9" +VERSION=2.4.6 package_revision=2.4.6 @@ -1370,7 +1370,7 @@ func_lt_ver () #! /bin/sh # Set a version string for this script. -scriptversion=2015-10-07.11; # UTC +scriptversion=2014-01-07.03; # UTC # A portable, pluggable option parser for Bourne shell. # Written by Gary V. Vaughan, 2010 @@ -1530,8 +1530,6 @@ func_run_hooks () { $debug_cmd - _G_rc_run_hooks=false - case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not support hook funcions.n" ;; @@ -1540,16 +1538,16 @@ func_run_hooks () eval _G_hook_fns=\$$1_hooks; shift for _G_hook in $_G_hook_fns; do - if eval $_G_hook '"$@"'; then - # store returned options list back into positional - # parameters for next 'cmd' execution. - eval _G_hook_result=\$${_G_hook}_result - eval set dummy "$_G_hook_result"; shift - _G_rc_run_hooks=: - fi + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift done - $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result } @@ -1559,16 +1557,10 @@ func_run_hooks () ## --------------- ## # In order to add your own option parsing hooks, you must accept the -# full positional parameter list in your hook function, you may remove/edit -# any options that you action, and then pass back the remaining unprocessed +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed # options in '<hooked_function_name>_result', escaped suitably for -# 'eval'. In this case you also must return $EXIT_SUCCESS to let the -# hook's caller know that it should pay attention to -# '<hooked_function_name>_result'. Returning $EXIT_FAILURE signalizes that -# arguments are left untouched by the hook and therefore caller will ignore the -# result variable. -# -# Like this: +# 'eval'. Like this: # # my_options_prep () # { @@ -1578,11 +1570,9 @@ func_run_hooks () # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' -# # No change in '$@' (ignored completely by this hook). There is -# # no need to do the equivalent (but slower) action: -# # func_quote_for_eval ${1+"$@"} -# # my_options_prep_result=$func_quote_for_eval_result -# false +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result # } # func_add_hook func_options_prep my_options_prep # @@ -1591,37 +1581,25 @@ func_run_hooks () # { # $debug_cmd # -# args_changed=false -# # # Note that for efficiency, we parse as many options as we can # # recognise in a loop before passing the remainder back to the # # caller on the first unrecognised argument we encounter. # while test $# -gt 0; do # opt=$1; shift # case $opt in -# --silent|-s) opt_silent=: -# args_changed=: -# ;; +# --silent|-s) opt_silent=: ;; # # Separate non-argument short options: # -s*) func_split_short_opt "$_G_opt" # set dummy "$func_split_short_opt_name" \ # "-$func_split_short_opt_arg" ${1+"$@"} # shift -# args_changed=: # ;; -# *) # Make sure the first unrecognised option "$_G_opt" -# # is added back to "$@", we could need that later -# # if $args_changed is true. -# set dummy "$_G_opt" ${1+"$@"}; shift; break ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; # esac # done # -# if $args_changed; then -# func_quote_for_eval ${1+"$@"} -# my_silent_option_result=$func_quote_for_eval_result -# fi -# -# $args_changed +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result # } # func_add_hook func_parse_options my_silent_option # @@ -1633,32 +1611,16 @@ func_run_hooks () # $opt_silent && $opt_verbose && func_fatal_help "\ # '--silent' and '--verbose' options are mutually exclusive." # -# false +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result # } # func_add_hook func_validate_options my_option_validation # -# You'll also need to manually amend $usage_message to reflect the extra +# You'll alse need to manually amend $usage_message to reflect the extra # options you parse. It's preferable to append if you can, so that # multiple option parsing hooks can be added safely. -# func_options_finish [ARG]... -# ---------------------------- -# Finishing the option parse loop (call 'func_options' hooks ATM). -func_options_finish () -{ - $debug_cmd - - _G_func_options_finish_exit=false - if func_run_hooks func_options ${1+"$@"}; then - func_options_finish_result=$func_run_hooks_result - _G_func_options_finish_exit=: - fi - - $_G_func_options_finish_exit -} - - # func_options [ARG]... # --------------------- # All the functions called inside func_options are hookable. See the @@ -1668,28 +1630,17 @@ func_options () { $debug_cmd - _G_rc_options=false - - for my_func in options_prep parse_options validate_options options_finish - do - if eval func_$my_func '${1+"$@"}'; then - eval _G_res_var='$'"func_${my_func}_result" - eval set dummy "$_G_res_var" ; shift - _G_rc_options=: - fi - done + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} - # Save modified positional parameters for caller. As a top-level - # options-parser function we always need to set the 'func_options_result' - # variable (regardless the $_G_rc_options value). - if $_G_rc_options; then - func_options_result=$_G_res_var - else - func_quote_for_eval ${1+"$@"} - func_options_result=$func_quote_for_eval_result - fi + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} - $_G_rc_options + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result } @@ -1698,9 +1649,9 @@ func_options () # All initialisations required before starting the option parse loop. # Note that when calling hook functions, we pass through the list of # positional parameters. If a hook function modifies that list, and -# needs to propagate that back to rest of this script, then the complete +# needs to propogate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before -# returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned). +# returning. func_hookable func_options_prep func_options_prep () { @@ -1710,14 +1661,10 @@ func_options_prep () opt_verbose=false opt_warning_types= - _G_rc_options_prep=false - if func_run_hooks func_options_prep ${1+"$@"}; then - _G_rc_options_prep=: - # save modified positional parameters for caller - func_options_prep_result=$func_run_hooks_result - fi + func_run_hooks func_options_prep ${1+"$@"} - $_G_rc_options_prep + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result } @@ -1731,20 +1678,18 @@ func_parse_options () func_parse_options_result= - _G_rc_parse_options=false # this just eases exit handling while test $# -gt 0; do # Defer to hook functions for initial option parsing, so they # get priority in the event of reusing an option name. - if func_run_hooks func_parse_options ${1+"$@"}; then - eval set dummy "$func_run_hooks_result"; shift - _G_rc_parse_options=: - fi + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift # Break out of the loop if we already parsed every option. test $# -gt 0 || break - _G_match_parse_options=: _G_opt=$1 shift case $_G_opt in @@ -1759,10 +1704,7 @@ func_parse_options () ;; --warnings|--warning|-W) - if test $# = 0 && func_missing_arg $_G_opt; then - _G_rc_parse_options=: - break - fi + test $# = 0 && func_missing_arg $_G_opt && break case " $warning_categories $1" in *" $1 "*) # trailing space prevents matching last $1 above @@ -1815,25 +1757,15 @@ func_parse_options () shift ;; - --) _G_rc_parse_options=: ; break ;; + --) break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; - *) set dummy "$_G_opt" ${1+"$@"}; shift - _G_match_parse_options=false - break - ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac - - $_G_match_parse_options && _G_rc_parse_options=: done - - if $_G_rc_parse_options; then - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - func_parse_options_result=$func_quote_for_eval_result - fi - - $_G_rc_parse_options + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result } @@ -1846,21 +1778,16 @@ func_validate_options () { $debug_cmd - _G_rc_validate_options=false - # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" - if func_run_hooks func_validate_options ${1+"$@"}; then - # save modified positional parameters for caller - func_validate_options_result=$func_run_hooks_result - _G_rc_validate_options=: - fi + func_run_hooks func_validate_options ${1+"$@"} # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE - $_G_rc_validate_options + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result } @@ -2141,12 +2068,12 @@ include the following information: compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) - version: $progname $scriptversion Debian-2.4.6-9 + version: $progname (GNU libtool) 2.4.6 automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` Report bugs to <bug-libtool@gnu.org>. -GNU libtool home page: <http://www.gnu.org/s/libtool/>. +GNU libtool home page: <http://www.gnu.org/software/libtool/>. General help using GNU software: <http://www.gnu.org/gethelp/>." exit 0 } @@ -2197,7 +2124,7 @@ fi # a configuration failure hint, and exit. func_fatal_configuration () { - func__fatal_error ${1+"$@"} \ + func_fatal_error ${1+"$@"} \ "See the $PACKAGE documentation for more information." \ "Fatal configuration error." } @@ -2343,8 +2270,6 @@ libtool_options_prep () nonopt= preserve_args= - _G_rc_lt_options_prep=: - # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) @@ -2368,18 +2293,11 @@ libtool_options_prep () uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; - *) - _G_rc_lt_options_prep=false - ;; esac - if $_G_rc_lt_options_prep; then - # Pass back the list of options. - func_quote_for_eval ${1+"$@"} - libtool_options_prep_result=$func_quote_for_eval_result - fi - - $_G_rc_lt_options_prep + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result } func_add_hook func_options_prep libtool_options_prep @@ -2391,12 +2309,9 @@ libtool_parse_options () { $debug_cmd - _G_rc_lt_parse_options=false - # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do - _G_match_lt_parse_options=: _G_opt=$1 shift case $_G_opt in @@ -2471,22 +2386,15 @@ libtool_parse_options () func_append preserve_args " $_G_opt" ;; - # An option not handled by this hook function: - *) set dummy "$_G_opt" ${1+"$@"} ; shift - _G_match_lt_parse_options=false - break - ;; + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac - $_G_match_lt_parse_options && _G_rc_lt_parse_options=: done - if $_G_rc_lt_parse_options; then - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - libtool_parse_options_result=$func_quote_for_eval_result - fi - $_G_rc_lt_parse_options + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result } func_add_hook func_parse_options libtool_parse_options @@ -7366,12 +7274,10 @@ func_mode_link () # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -specs=* GCC specs files # -stdlib=* select c++ std lib with clang - # -fsanitize=* Clang/GCC memory and address sanitizer - # -fuse-ld=* Linker select flags for GCC -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ - -specs=*|-fsanitize=*|-fuse-ld=*) + -specs=*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result func_append compile_command " $arg" @@ -7664,10 +7570,7 @@ func_mode_link () case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; - link) - libs="$deplibs %DEPLIBS%" - test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" - ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then @@ -7986,19 +7889,19 @@ func_mode_link () # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" - tmp_libs= - for deplib in $dependency_libs; do - deplibs="$deplib $deplibs" - if $opt_preserve_dup_deps; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done continue fi # $pass = conv @@ -8922,9 +8825,6 @@ func_mode_link () revision=$number_minor lt_irix_increment=no ;; - *) - func_fatal_configuration "$modename: unknown library version type '$version_type'" - ;; esac ;; no) diff --git a/config.h.in b/config.h.in index 7c73c67..87c4007 100644 --- a/config.h.in +++ b/config.h.in @@ -210,6 +210,9 @@ /* Define to 1 if you have the <grp.h> header file. */ #undef HAVE_GRP_H +/* Have GStreamer? */ +#undef HAVE_GSTREAMER + /* Have GTK? */ #undef HAVE_GTK @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for pulseaudio 13.0. +# Generated by GNU Autoconf 2.69 for pulseaudio 13.99.1. # # Report bugs to <pulseaudio-discuss (at) lists (dot) freedesktop (dot) org>. # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='pulseaudio' PACKAGE_TARNAME='pulseaudio' -PACKAGE_VERSION='13.0' -PACKAGE_STRING='pulseaudio 13.0' +PACKAGE_VERSION='13.99.1' +PACKAGE_STRING='pulseaudio 13.99.1' PACKAGE_BUGREPORT='pulseaudio-discuss (at) lists (dot) freedesktop (dot) org' PACKAGE_URL='http://pulseaudio.org/' @@ -678,6 +678,10 @@ PA_SYSTEM_GROUP PA_SYSTEM_USER BUILD_MANPAGES_FALSE BUILD_MANPAGES_TRUE +HAVE_GSTREAMER_FALSE +HAVE_GSTREAMER_TRUE +GSTREAMER_LIBS +GSTREAMER_CFLAGS HAVE_SYSTEMD_JOURNAL_FALSE HAVE_SYSTEMD_JOURNAL_TRUE HAVE_SYSTEMD_JOURNAL @@ -1013,7 +1017,6 @@ infodir docdir oldincludedir includedir -runstatedir localstatedir sharedstatedir sysconfdir @@ -1098,6 +1101,7 @@ enable_systemd_daemon enable_systemd_login enable_systemd_journal with_systemduserunitdir +enable_gstreamer enable_manpages with_system_user with_system_group @@ -1188,6 +1192,8 @@ SYSTEMDLOGIN_CFLAGS SYSTEMDLOGIN_LIBS SYSTEMDJOURNAL_CFLAGS SYSTEMDJOURNAL_LIBS +GSTREAMER_CFLAGS +GSTREAMER_LIBS WEBRTC_CFLAGS WEBRTC_LIBS' @@ -1228,7 +1234,6 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1481,15 +1486,6 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1627,7 +1623,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir + libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1740,7 +1736,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures pulseaudio 13.0 to adapt to many kinds of systems. +\`configure' configures pulseaudio 13.99.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1780,7 +1776,6 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1811,7 +1806,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pulseaudio 13.0:";; + short | recursive ) echo "Configuration of pulseaudio 13.99.1:";; esac cat <<\_ACEOF @@ -1888,6 +1883,7 @@ Optional Features: --disable-systemd-login Disable optional systemd login support --disable-systemd-journal Disable optional systemd journal support + --disable-gstreamer Disable optional GStreamer-based RTP support --disable-manpages Disable building and installation of man pages --disable-per-user-esound-socket Use global esound socket directory /tmp/.esd/socket. @@ -2058,6 +2054,10 @@ Some influential environment variables: C compiler flags for SYSTEMDJOURNAL, overriding pkg-config SYSTEMDJOURNAL_LIBS linker flags for SYSTEMDJOURNAL, overriding pkg-config + GSTREAMER_CFLAGS + C compiler flags for GSTREAMER, overriding pkg-config + GSTREAMER_LIBS + linker flags for GSTREAMER, overriding pkg-config WEBRTC_CFLAGS C compiler flags for WEBRTC, overriding pkg-config WEBRTC_LIBS linker flags for WEBRTC, overriding pkg-config @@ -2129,7 +2129,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pulseaudio configure 13.0 +pulseaudio configure 13.99.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2902,7 +2902,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pulseaudio $as_me 13.0, which was +It was created by pulseaudio $as_me 13.99.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3859,7 +3859,7 @@ fi # Define the identity of the package. PACKAGE='pulseaudio' - VERSION='13.0' + VERSION='13.99.1' cat >>confdefs.h <<_ACEOF @@ -4116,7 +4116,7 @@ PA_PROTOCOL_VERSION=33 # The stable ABI for client applications, for the version info x:y:z # always will hold x=z -LIBPULSE_VERSION_INFO=21:1:21 +LIBPULSE_VERSION_INFO=21:2:21 # A simplified, synchronous, ABI-stable interface for client @@ -8286,16 +8286,21 @@ else /* end confdefs.h. */ #include <libintl.h> -$gt_revision_test_code +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION extern int _nl_msg_cat_cntr; extern int *_nl_domain_bindings; +#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_domain_bindings) +#else +#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 +#endif +$gt_revision_test_code int main () { bindtextdomain ("", ""); -return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings +return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION ; return 0; @@ -8415,36 +8420,42 @@ else if test $am_cv_lib_iconv = yes; then LIBS="$LIBS $LIBICONV" fi - if test "$cross_compiling" = yes; then : - - case "$host_os" in - aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; - *) am_cv_func_iconv_works="guessing yes" ;; - esac - + am_cv_func_iconv_works=no + for ac_iconv_const in '' 'const'; do + if test "$cross_compiling" = yes; then : + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <iconv.h> #include <string.h> -int main () + +#ifndef ICONV_CONST +# define ICONV_CONST $ac_iconv_const +#endif + +int +main () { - int result = 0; +int result = 0; /* Test against AIX 5.1 bug: Failures are not distinguishable from successful returns. */ { iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); if (cd_utf8_to_88591 != (iconv_t)(-1)) { - static const char input[] = "\342\202\254"; /* EURO SIGN */ + static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */ char buf[10]; - const char *inptr = input; + ICONV_CONST char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_utf8_to_88591, - (char **) &inptr, &inbytesleft, + &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) result |= 1; @@ -8457,14 +8468,14 @@ int main () iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); if (cd_ascii_to_88591 != (iconv_t)(-1)) { - static const char input[] = "\263"; + static ICONV_CONST char input[] = "\263"; char buf[10]; - const char *inptr = input; + ICONV_CONST char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_ascii_to_88591, - (char **) &inptr, &inbytesleft, + &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) result |= 2; @@ -8476,14 +8487,14 @@ int main () iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); if (cd_88591_to_utf8 != (iconv_t)(-1)) { - static const char input[] = "\304"; + static ICONV_CONST char input[] = "\304"; static char buf[2] = { (char)0xDE, (char)0xAD }; - const char *inptr = input; + ICONV_CONST char *inptr = input; size_t inbytesleft = 1; char *outptr = buf; size_t outbytesleft = 1; size_t res = iconv (cd_88591_to_utf8, - (char **) &inptr, &inbytesleft, + &inptr, &inbytesleft, &outptr, &outbytesleft); if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) result |= 4; @@ -8496,14 +8507,14 @@ int main () iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); if (cd_88591_to_utf8 != (iconv_t)(-1)) { - static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; char buf[50]; - const char *inptr = input; + ICONV_CONST char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_88591_to_utf8, - (char **) &inptr, &inbytesleft, + &inptr, &inbytesleft, &outptr, &outbytesleft); if ((int)res > 0) result |= 8; @@ -8523,17 +8534,20 @@ int main () && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) result |= 16; return result; + + ; + return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : am_cv_func_iconv_works=yes -else - am_cv_func_iconv_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi + test "$am_cv_func_iconv_works" = no || break + done LIBS="$am_save_LIBS" fi @@ -9039,20 +9053,25 @@ else /* end confdefs.h. */ #include <libintl.h> -$gt_revision_test_code +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); +#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_expand_alias ("")) +#else +#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 +#endif +$gt_revision_test_code int main () { bindtextdomain ("", ""); -return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") +return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION ; return 0; @@ -9071,20 +9090,25 @@ rm -f core conftest.err conftest.$ac_objext \ /* end confdefs.h. */ #include <libintl.h> -$gt_revision_test_code +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); +#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_expand_alias ("")) +#else +#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 +#endif +$gt_revision_test_code int main () { bindtextdomain ("", ""); -return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") +return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION ; return 0; @@ -11076,7 +11100,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; -netbsd* | netbsdelf*-gnu) +netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else @@ -11936,8 +11960,11 @@ _LT_EOF test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm - $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5 - if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" @@ -14801,9 +14828,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie openbsd* | bitrig*) with_gnu_ld=no ;; - linux* | k*bsd*-gnu | gnu*) - link_all_deplibs=no - ;; esac ld_shlibs=yes @@ -15058,7 +15082,7 @@ _LT_EOF fi ;; - netbsd* | netbsdelf*-gnu) + netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= @@ -15728,7 +15752,6 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi - link_all_deplibs=no else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' @@ -15750,7 +15773,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } esac ;; - netbsd* | netbsdelf*-gnu) + netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else @@ -16845,6 +16868,9 @@ fi # before this can be enabled. hardcode_into_libs=yes + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command @@ -16853,7 +16879,7 @@ fi # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -16865,18 +16891,6 @@ fi dynamic_linker='GNU/Linux ld.so' ;; -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - netbsd*) version_type=sunos need_lib_prefix=no @@ -18267,7 +18281,7 @@ with_gnu_ld=$lt_cv_prog_gnu_ld # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no @@ -18759,7 +18773,7 @@ fi # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then @@ -18824,7 +18838,7 @@ fi # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then @@ -19163,7 +19177,7 @@ fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support @@ -19247,7 +19261,7 @@ fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. @@ -19258,7 +19272,7 @@ fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' @@ -19771,7 +19785,7 @@ lt_prog_compiler_static_CXX= ;; esac ;; - netbsd* | netbsdelf*-gnu) + netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise @@ -20146,9 +20160,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie ;; esac ;; - linux* | k*bsd*-gnu | gnu*) - link_all_deplibs_CXX=no - ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; @@ -20822,6 +20833,9 @@ fi # before this can be enabled. hardcode_into_libs=yes + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command @@ -20830,7 +20844,7 @@ fi # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -20842,18 +20856,6 @@ fi dynamic_linker='GNU/Linux ld.so' ;; -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - netbsd*) version_type=sunos need_lib_prefix=no @@ -23747,7 +23749,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -23793,7 +23795,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -23817,7 +23819,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -23862,7 +23864,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -23886,7 +23888,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -24096,36 +24098,42 @@ else if test $am_cv_lib_iconv = yes; then LIBS="$LIBS $LIBICONV" fi - if test "$cross_compiling" = yes; then : - - case "$host_os" in - aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; - *) am_cv_func_iconv_works="guessing yes" ;; - esac - + am_cv_func_iconv_works=no + for ac_iconv_const in '' 'const'; do + if test "$cross_compiling" = yes; then : + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <iconv.h> #include <string.h> -int main () + +#ifndef ICONV_CONST +# define ICONV_CONST $ac_iconv_const +#endif + +int +main () { - int result = 0; +int result = 0; /* Test against AIX 5.1 bug: Failures are not distinguishable from successful returns. */ { iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); if (cd_utf8_to_88591 != (iconv_t)(-1)) { - static const char input[] = "\342\202\254"; /* EURO SIGN */ + static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */ char buf[10]; - const char *inptr = input; + ICONV_CONST char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_utf8_to_88591, - (char **) &inptr, &inbytesleft, + &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) result |= 1; @@ -24138,14 +24146,14 @@ int main () iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); if (cd_ascii_to_88591 != (iconv_t)(-1)) { - static const char input[] = "\263"; + static ICONV_CONST char input[] = "\263"; char buf[10]; - const char *inptr = input; + ICONV_CONST char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_ascii_to_88591, - (char **) &inptr, &inbytesleft, + &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) result |= 2; @@ -24157,14 +24165,14 @@ int main () iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); if (cd_88591_to_utf8 != (iconv_t)(-1)) { - static const char input[] = "\304"; + static ICONV_CONST char input[] = "\304"; static char buf[2] = { (char)0xDE, (char)0xAD }; - const char *inptr = input; + ICONV_CONST char *inptr = input; size_t inbytesleft = 1; char *outptr = buf; size_t outbytesleft = 1; size_t res = iconv (cd_88591_to_utf8, - (char **) &inptr, &inbytesleft, + &inptr, &inbytesleft, &outptr, &outbytesleft); if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) result |= 4; @@ -24177,14 +24185,14 @@ int main () iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); if (cd_88591_to_utf8 != (iconv_t)(-1)) { - static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; char buf[50]; - const char *inptr = input; + ICONV_CONST char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_88591_to_utf8, - (char **) &inptr, &inbytesleft, + &inptr, &inbytesleft, &outptr, &outbytesleft); if ((int)res > 0) result |= 8; @@ -24204,17 +24212,20 @@ int main () && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) result |= 16; return result; + + ; + return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : am_cv_func_iconv_works=yes -else - am_cv_func_iconv_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi + test "$am_cv_func_iconv_works" = no || break + done LIBS="$am_save_LIBS" fi @@ -28226,6 +28237,108 @@ $as_echo "#define HAVE_SYSTEMD_JOURNAL 1" >>confdefs.h fi +#### GStreamer-based RTP support (optional) #### + +# Check whether --enable-gstreamer was given. +if test "${enable_gstreamer+set}" = set; then : + enableval=$enable_gstreamer; +fi + + +if test "x$enable_gstreamer" != "xno"; then : + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GSTREAMER" >&5 +$as_echo_n "checking for GSTREAMER... " >&6; } + +if test -n "$GSTREAMER_CFLAGS"; then + pkg_cv_GSTREAMER_CFLAGS="$GSTREAMER_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \" gstreamer-1.0 gstreamer-app-1.0 gstreamer-rtp-1.0 gio-2.0 \""; } >&5 + ($PKG_CONFIG --exists --print-errors " gstreamer-1.0 gstreamer-app-1.0 gstreamer-rtp-1.0 gio-2.0 ") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GSTREAMER_CFLAGS=`$PKG_CONFIG --cflags " gstreamer-1.0 gstreamer-app-1.0 gstreamer-rtp-1.0 gio-2.0 " 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GSTREAMER_LIBS"; then + pkg_cv_GSTREAMER_LIBS="$GSTREAMER_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \" gstreamer-1.0 gstreamer-app-1.0 gstreamer-rtp-1.0 gio-2.0 \""; } >&5 + ($PKG_CONFIG --exists --print-errors " gstreamer-1.0 gstreamer-app-1.0 gstreamer-rtp-1.0 gio-2.0 ") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GSTREAMER_LIBS=`$PKG_CONFIG --libs " gstreamer-1.0 gstreamer-app-1.0 gstreamer-rtp-1.0 gio-2.0 " 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GSTREAMER_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs " gstreamer-1.0 gstreamer-app-1.0 gstreamer-rtp-1.0 gio-2.0 " 2>&1` + else + GSTREAMER_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs " gstreamer-1.0 gstreamer-app-1.0 gstreamer-rtp-1.0 gio-2.0 " 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GSTREAMER_PKG_ERRORS" >&5 + + HAVE_GSTREAMER=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + HAVE_GSTREAMER=no +else + GSTREAMER_CFLAGS=$pkg_cv_GSTREAMER_CFLAGS + GSTREAMER_LIBS=$pkg_cv_GSTREAMER_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + HAVE_GSTREAMER=yes +fi +else + HAVE_GSTREAMER=no +fi + +if test "x$enable_gstreamer" = "xyes" && test "x$HAVE_GSTREAMER" = "xno"; then : + as_fn_error $? "*** GStreamer 1.0 support not found" "$LINENO" 5 +fi + + if test "x$HAVE_GSTREAMER" = xyes; then + HAVE_GSTREAMER_TRUE= + HAVE_GSTREAMER_FALSE='#' +else + HAVE_GSTREAMER_TRUE='#' + HAVE_GSTREAMER_FALSE= +fi + +if test "x$HAVE_GSTREAMER" = "xyes"; then : + +$as_echo "#define HAVE_GSTREAMER 1" >>confdefs.h + +fi + #### Build and Install man pages #### # Check whether --enable-manpages was given. @@ -29648,6 +29761,10 @@ if test -z "${HAVE_SYSTEMD_JOURNAL_TRUE}" && test -z "${HAVE_SYSTEMD_JOURNAL_FAL as_fn_error $? "conditional \"HAVE_SYSTEMD_JOURNAL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${HAVE_GSTREAMER_TRUE}" && test -z "${HAVE_GSTREAMER_FALSE}"; then + as_fn_error $? "conditional \"HAVE_GSTREAMER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${BUILD_MANPAGES_TRUE}" && test -z "${BUILD_MANPAGES_FALSE}"; then as_fn_error $? "conditional \"BUILD_MANPAGES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -30073,7 +30190,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pulseaudio $as_me 13.0, which was +This file was extended by pulseaudio $as_me 13.99.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -30140,7 +30257,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -pulseaudio config.status 13.0 +pulseaudio config.status 13.99.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -31513,6 +31630,7 @@ See \`config.log' for more details" "$LINENO" 5; } cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. @@ -32432,6 +32550,11 @@ if test "x$HAVE_WEBRTC" = "x1"; then : else ENABLE_WEBRTC=no fi +if test "x$HAVE_GSTREAMER" = "x1"; then : + ENABLE_GSTREAMER=yes +else + ENABLE_GSTREAMER=no +fi if test "x$HAVE_TDB" = "x1"; then : ENABLE_TDB=yes else @@ -32527,6 +32650,7 @@ echo " Enable speex (resampler, AEC): ${ENABLE_SPEEX} Enable soxr (resampler): ${ENABLE_SOXR} Enable WebRTC echo canceller: ${ENABLE_WEBRTC} + Enable GStreamer-based RTP: ${ENABLE_GSTREAMER} Enable gcov coverage: ${ENABLE_GCOV} Enable unit tests: ${ENABLE_TESTS} Database diff --git a/configure.ac b/configure.ac index 8278353..0ac5651 100644 --- a/configure.ac +++ b/configure.ac @@ -46,7 +46,7 @@ AC_SUBST(PA_PROTOCOL_VERSION, 33) # The stable ABI for client applications, for the version info x:y:z # always will hold x=z -AC_SUBST(LIBPULSE_VERSION_INFO, [21:1:21]) +AC_SUBST(LIBPULSE_VERSION_INFO, [21:2:21]) # A simplified, synchronous, ABI-stable interface for client # applications, for the version info x:y:z always will hold x=z @@ -1310,6 +1310,22 @@ AC_SUBST(HAVE_SYSTEMD_JOURNAL) AM_CONDITIONAL([HAVE_SYSTEMD_JOURNAL], [test "x$HAVE_SYSTEMD_JOURNAL" = x1]) AS_IF([test "x$HAVE_SYSTEMD_JOURNAL" = "x1"], AC_DEFINE([HAVE_SYSTEMD_JOURNAL], 1, [Have SYSTEMDJOURNAL?])) +#### GStreamer-based RTP support (optional) #### + +AC_ARG_ENABLE([gstreamer], + AS_HELP_STRING([--disable-gstreamer],[Disable optional GStreamer-based RTP support])) + +AS_IF([test "x$enable_gstreamer" != "xno"], + [PKG_CHECK_MODULES(GSTREAMER, [ gstreamer-1.0 gstreamer-app-1.0 gstreamer-rtp-1.0 gio-2.0 ], + HAVE_GSTREAMER=yes, HAVE_GSTREAMER=no)], + HAVE_GSTREAMER=no) + +AS_IF([test "x$enable_gstreamer" = "xyes" && test "x$HAVE_GSTREAMER" = "xno"], + [AC_MSG_ERROR([*** GStreamer 1.0 support not found])]) + +AM_CONDITIONAL([HAVE_GSTREAMER], [test "x$HAVE_GSTREAMER" = xyes]) +AS_IF([test "x$HAVE_GSTREAMER" = "xyes"], AC_DEFINE([HAVE_GSTREAMER], 1, [Have GStreamer?])) + #### Build and Install man pages #### AC_ARG_ENABLE([manpages], @@ -1614,6 +1630,7 @@ AS_IF([test "x$HAVE_ADRIAN_EC" = "x1"], ENABLE_ADRIAN_EC=yes, ENABLE_ADRIAN_EC=n AS_IF([test "x$HAVE_SPEEX" = "x1"], ENABLE_SPEEX=yes, ENABLE_SPEEX=no) AS_IF([test "x$HAVE_SOXR" = "x1"], ENABLE_SOXR=yes, ENABLE_SOXR=no) AS_IF([test "x$HAVE_WEBRTC" = "x1"], ENABLE_WEBRTC=yes, ENABLE_WEBRTC=no) +AS_IF([test "x$HAVE_GSTREAMER" = "x1"], ENABLE_GSTREAMER=yes, ENABLE_GSTREAMER=no) AS_IF([test "x$HAVE_TDB" = "x1"], ENABLE_TDB=yes, ENABLE_TDB=no) AS_IF([test "x$HAVE_GDBM" = "x1"], ENABLE_GDBM=yes, ENABLE_GDBM=no) AS_IF([test "x$HAVE_SIMPLEDB" = "x1"], ENABLE_SIMPLEDB=yes, ENABLE_SIMPLEDB=no) @@ -1677,6 +1694,7 @@ echo " Enable speex (resampler, AEC): ${ENABLE_SPEEX} Enable soxr (resampler): ${ENABLE_SOXR} Enable WebRTC echo canceller: ${ENABLE_WEBRTC} + Enable GStreamer-based RTP: ${ENABLE_GSTREAMER} Enable gcov coverage: ${ENABLE_GCOV} Enable unit tests: ${ENABLE_TESTS} Database diff --git a/debian/changelog b/debian/changelog index d532f22..69f8ccd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,19 @@ +pulseaudio (13.99.1-1) UNRELEASED; urgency=medium + + * New upstream rc version, including those changes: + - default sink selection for a better user experience, ALSA UCM support, + disabling flat volumes by default, stream rescue moving to core, + GStreamer-based RTP support, and qpaeq moving to Python 3. + * debian/control: + - B-D on libgstreamer1.0-dev and libgstreamer-plugins-base1.0-dev, + needed to enable the gstreamer based RTP support + * debian/patches/qpaeq-Drop-unused-imports.patch, + debian/patches/qpaeq-use-python3-instead-of-python-2.patch, + debian/patches/daemon-conf-disable-flat-volumes-by-default.patch: + - dropped the changes included in the new version + + -- Sebastien Bacher <seb128@ubuntu.com> Wed, 19 Feb 2020 18:34:48 +0100 + pulseaudio (13.0-5) unstable; urgency=medium * Fix removal of 00-disable-autospawn.conf. diff --git a/debian/control b/debian/control index 15011f9..9c25891 100644 --- a/debian/control +++ b/debian/control @@ -17,6 +17,8 @@ Build-Depends: debhelper-compat (= 12), libcap-dev [linux-any], libfftw3-dev, libglib2.0-dev, + libgstreamer1.0-dev, + libgstreamer-plugins-base1.0-dev, libgtk-3-dev, libice-dev, libjack-dev, diff --git a/debian/patches/daemon-conf-disable-flat-volumes-by-default.patch b/debian/patches/daemon-conf-disable-flat-volumes-by-default.patch deleted file mode 100644 index 680a818..0000000 --- a/debian/patches/daemon-conf-disable-flat-volumes-by-default.patch +++ /dev/null @@ -1,57 +0,0 @@ -From: Tanu Kaskinen <tanuk@iki.fi> -Date: Mon, 23 Sep 2019 07:48:48 +0300 -Subject: daemon-conf: disable flat-volumes by default - -Almost all distributions patch the configuration to disable -flat-volumes, because users tend to find the concept confusing (and it -also causes nasty surprises when some application pushes the volume to -100%). Let's remove the need for patching and disable the feature by -default. - -Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/691 -(cherry picked from commit ba73faa4c05717d74fbfd17e8175731e60d8841d) ---- - man/pulse-daemon.conf.5.xml.in | 2 +- - src/daemon/daemon-conf.c | 2 +- - src/daemon/daemon.conf.in | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in -index f49fa9b..1436126 100644 ---- a/man/pulse-daemon.conf.5.xml.in -+++ b/man/pulse-daemon.conf.5.xml.in -@@ -237,7 +237,7 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. - <p><opt>flat-volumes=</opt> Enable 'flat' volumes, i.e. where - possible let the sink volume equal the maximum of the volumes of - the inputs connected to it. Takes a boolean argument, defaults -- to <opt>yes</opt>.</p> -+ to <opt>no</opt>.</p> - </option> - - </section> -diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c -index 33cf7a7..e74b4ba 100644 ---- a/src/daemon/daemon-conf.c -+++ b/src/daemon/daemon-conf.c -@@ -68,7 +68,7 @@ static const pa_daemon_conf default_conf = { - .realtime_priority = 5, /* Half of JACK's default rtprio */ - .disallow_module_loading = false, - .disallow_exit = false, -- .flat_volumes = true, -+ .flat_volumes = false, - .exit_idle_time = 20, - .scache_idle_time = 20, - .script_commands = NULL, -diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in -index a955523..480608e 100644 ---- a/src/daemon/daemon.conf.in -+++ b/src/daemon/daemon.conf.in -@@ -60,7 +60,7 @@ ifelse(@HAVE_DBUS@, 1, [dnl - ; enable-lfe-remixing = no - ; lfe-crossover-freq = 0 - --; flat-volumes = yes -+; flat-volumes = no - - ifelse(@HAVE_SYS_RESOURCE_H@, 1, [dnl - ; rlimit-fsize = -1 diff --git a/debian/patches/qpaeq-Drop-unused-imports.patch b/debian/patches/qpaeq-Drop-unused-imports.patch deleted file mode 100644 index 823ba81..0000000 --- a/debian/patches/qpaeq-Drop-unused-imports.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Felipe Sateler <fsateler@debian.org> -Date: Fri, 25 Oct 2019 08:34:59 -0300 -Subject: qpaeq: Drop unused imports - -Neither sip nor PyQt5 are used. From PyQt5 we only use the named imports just below -Forwarded: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/merge_requests/197 ---- - src/utils/qpaeq | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/utils/qpaeq b/src/utils/qpaeq -index ac0daec..914aedf 100755 ---- a/src/utils/qpaeq -+++ b/src/utils/qpaeq -@@ -18,7 +18,6 @@ - - import os,math,sys - try: -- import PyQt5,sip - from PyQt5 import QtWidgets,QtCore - import dbus.mainloop.pyqt5 - import dbus diff --git a/debian/patches/qpaeq-use-python3-instead-of-python-2.patch b/debian/patches/qpaeq-use-python3-instead-of-python-2.patch deleted file mode 100644 index 9abe160..0000000 --- a/debian/patches/qpaeq-use-python3-instead-of-python-2.patch +++ /dev/null @@ -1,20 +0,0 @@ -From: Felipe Sateler <fsateler@debian.org> -Date: Fri, 25 Oct 2019 08:39:03 -0300 -Subject: qpaeq: use python3 instead of python 2 - -The script was already compatible, so lets just switch interpreter -Forwarded: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/merge_requests/197 ---- - src/utils/qpaeq | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/utils/qpaeq b/src/utils/qpaeq -index 914aedf..7e01d87 100755 ---- a/src/utils/qpaeq -+++ b/src/utils/qpaeq -@@ -1,4 +1,4 @@ --#!/usr/bin/env python -+#!/usr/bin/env python3 - # qpaeq is a equalizer interface for pulseaudio's equalizer sinks - # Copyright (C) 2009 Jason Newton <nevion@gmail.com - # diff --git a/debian/patches/series b/debian/patches/series index 80a5590..e62843a 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,4 +1 @@ -qpaeq-Drop-unused-imports.patch -qpaeq-use-python3-instead-of-python-2.patch -daemon-conf-disable-flat-volumes-by-default.patch disable-autospawn.patch diff --git a/doxygen/Makefile.in b/doxygen/Makefile.in index c7c0b85..3ea5da4 100644 --- a/doxygen/Makefile.in +++ b/doxygen/Makefile.in @@ -206,6 +206,8 @@ GREP = @GREP@ GSETTINGS_CFLAGS = @GSETTINGS_CFLAGS@ GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ GSETTINGS_LIBS = @GSETTINGS_LIBS@ +GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@ +GSTREAMER_LIBS = @GSTREAMER_LIBS@ GTK30_CFLAGS = @GTK30_CFLAGS@ GTK30_LIBS = @GTK30_LIBS@ HAVE_AF_UNIX = @HAVE_AF_UNIX@ @@ -416,7 +418,6 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pulseconfdir = @pulseconfdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/m4/gettext.m4 b/m4/gettext.m4 index be247bf..eef5073 100644 --- a/m4/gettext.m4 +++ b/m4/gettext.m4 @@ -1,16 +1,16 @@ -# gettext.m4 serial 66 (gettext-0.18.2) -dnl Copyright (C) 1995-2014 Free Software Foundation, Inc. +# gettext.m4 serial 68 (gettext-0.19.8) +dnl Copyright (C) 1995-2014, 2016 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl -dnl This file can can be used in projects which are not available under +dnl This file can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU -dnl gettext package package is covered by the GNU General Public License. +dnl gettext package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: @@ -161,13 +161,18 @@ changequote([,])dnl [AC_LANG_PROGRAM( [[ #include <libintl.h> -$gt_revision_test_code +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION extern int _nl_msg_cat_cntr; extern int *_nl_domain_bindings; +#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_domain_bindings) +#else +#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 +#endif +$gt_revision_test_code ]], [[ bindtextdomain ("", ""); -return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings +return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION ]])], [eval "$gt_func_gnugettext_libc=yes"], [eval "$gt_func_gnugettext_libc=no"])]) @@ -193,17 +198,22 @@ return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_b [AC_LANG_PROGRAM( [[ #include <libintl.h> -$gt_revision_test_code +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); +#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_expand_alias ("")) +#else +#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 +#endif +$gt_revision_test_code ]], [[ bindtextdomain ("", ""); -return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") +return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION ]])], [eval "$gt_func_gnugettext_libintl=yes"], [eval "$gt_func_gnugettext_libintl=no"]) @@ -214,17 +224,22 @@ return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_a [AC_LANG_PROGRAM( [[ #include <libintl.h> -$gt_revision_test_code +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); +#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_expand_alias ("")) +#else +#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 +#endif +$gt_revision_test_code ]], [[ bindtextdomain ("", ""); -return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") +return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION ]])], [LIBINTL="$LIBINTL $LIBICONV" LTLIBINTL="$LTLIBINTL $LTLIBICONV" @@ -399,3 +414,7 @@ AC_DEFUN([AM_GNU_GETTEXT_NEED], dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) + + +dnl Usage: AM_GNU_GETTEXT_REQUIRE_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_REQUIRE_VERSION], []) diff --git a/m4/iconv.m4 b/m4/iconv.m4 index 4b29c5f..aa159c5 100644 --- a/m4/iconv.m4 +++ b/m4/iconv.m4 @@ -1,5 +1,5 @@ -# iconv.m4 serial 18 (gettext-0.18.2) -dnl Copyright (C) 2000-2002, 2007-2014 Free Software Foundation, Inc. +# iconv.m4 serial 19 (gettext-0.18.2) +dnl Copyright (C) 2000-2002, 2007-2014, 2016 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -72,27 +72,33 @@ AC_DEFUN([AM_ICONV_LINK], if test $am_cv_lib_iconv = yes; then LIBS="$LIBS $LIBICONV" fi - AC_RUN_IFELSE( - [AC_LANG_SOURCE([[ + am_cv_func_iconv_works=no + for ac_iconv_const in '' 'const'; do + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[ #include <iconv.h> #include <string.h> -int main () -{ - int result = 0; + +#ifndef ICONV_CONST +# define ICONV_CONST $ac_iconv_const +#endif + ]], + [[int result = 0; /* Test against AIX 5.1 bug: Failures are not distinguishable from successful returns. */ { iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); if (cd_utf8_to_88591 != (iconv_t)(-1)) { - static const char input[] = "\342\202\254"; /* EURO SIGN */ + static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */ char buf[10]; - const char *inptr = input; + ICONV_CONST char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_utf8_to_88591, - (char **) &inptr, &inbytesleft, + &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) result |= 1; @@ -105,14 +111,14 @@ int main () iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); if (cd_ascii_to_88591 != (iconv_t)(-1)) { - static const char input[] = "\263"; + static ICONV_CONST char input[] = "\263"; char buf[10]; - const char *inptr = input; + ICONV_CONST char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_ascii_to_88591, - (char **) &inptr, &inbytesleft, + &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) result |= 2; @@ -124,14 +130,14 @@ int main () iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); if (cd_88591_to_utf8 != (iconv_t)(-1)) { - static const char input[] = "\304"; + static ICONV_CONST char input[] = "\304"; static char buf[2] = { (char)0xDE, (char)0xAD }; - const char *inptr = input; + ICONV_CONST char *inptr = input; size_t inbytesleft = 1; char *outptr = buf; size_t outbytesleft = 1; size_t res = iconv (cd_88591_to_utf8, - (char **) &inptr, &inbytesleft, + &inptr, &inbytesleft, &outptr, &outbytesleft); if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) result |= 4; @@ -144,14 +150,14 @@ int main () iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); if (cd_88591_to_utf8 != (iconv_t)(-1)) { - static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; char buf[50]; - const char *inptr = input; + ICONV_CONST char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_88591_to_utf8, - (char **) &inptr, &inbytesleft, + &inptr, &inbytesleft, &outptr, &outbytesleft); if ((int)res > 0) result |= 8; @@ -171,17 +177,14 @@ int main () && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) result |= 16; return result; -}]])], - [am_cv_func_iconv_works=yes], - [am_cv_func_iconv_works=no], - [ -changequote(,)dnl - case "$host_os" in - aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; - *) am_cv_func_iconv_works="guessing yes" ;; - esac -changequote([,])dnl - ]) +]])], + [am_cv_func_iconv_works=yes], , + [case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac]) + test "$am_cv_func_iconv_works" = no || break + done LIBS="$am_save_LIBS" ]) case "$am_cv_func_iconv_works" in diff --git a/m4/intlmacosx.m4 b/m4/intlmacosx.m4 index 8a045f6..aca924c 100644 --- a/m4/intlmacosx.m4 +++ b/m4/intlmacosx.m4 @@ -1,16 +1,16 @@ # intlmacosx.m4 serial 5 (gettext-0.18.2) -dnl Copyright (C) 2004-2014 Free Software Foundation, Inc. +dnl Copyright (C) 2004-2014, 2016 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl -dnl This file can can be used in projects which are not available under +dnl This file can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU -dnl gettext package package is covered by the GNU General Public License. +dnl gettext package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Checks for special options needed on Mac OS X. diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4 index ddc569f..6209de6 100644 --- a/m4/lib-ld.m4 +++ b/m4/lib-ld.m4 @@ -1,5 +1,5 @@ # lib-ld.m4 serial 6 -dnl Copyright (C) 1996-2003, 2009-2014 Free Software Foundation, Inc. +dnl Copyright (C) 1996-2003, 2009-2016 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. diff --git a/m4/lib-link.m4 b/m4/lib-link.m4 index 3522d99..2f51855 100644 --- a/m4/lib-link.m4 +++ b/m4/lib-link.m4 @@ -1,5 +1,5 @@ # lib-link.m4 serial 26 (gettext-0.18.2) -dnl Copyright (C) 2001-2014 Free Software Foundation, Inc. +dnl Copyright (C) 2001-2016 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4 index 31f49e4..1601cea 100644 --- a/m4/lib-prefix.m4 +++ b/m4/lib-prefix.m4 @@ -1,5 +1,5 @@ # lib-prefix.m4 serial 7 (gettext-0.18) -dnl Copyright (C) 2001-2005, 2008-2014 Free Software Foundation, Inc. +dnl Copyright (C) 2001-2005, 2008-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. diff --git a/m4/libtool.m4 b/m4/libtool.m4 index c81e669..a644432 100644 --- a/m4/libtool.m4 +++ b/m4/libtool.m4 @@ -728,6 +728,7 @@ _LT_CONFIG_SAVE_COMMANDS([ cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. @@ -2866,6 +2867,9 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) # before this can be enabled. hardcode_into_libs=yes + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command @@ -2874,7 +2878,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -2886,18 +2890,6 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) dynamic_linker='GNU/Linux ld.so' ;; -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - netbsd*) version_type=sunos need_lib_prefix=no @@ -3557,7 +3549,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; -netbsd* | netbsdelf*-gnu) +netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else @@ -4063,8 +4055,7 @@ _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm - $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD - if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" @@ -4436,7 +4427,7 @@ m4_if([$1], [CXX], [ ;; esac ;; - netbsd* | netbsdelf*-gnu) + netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise @@ -4948,9 +4939,6 @@ m4_if([$1], [CXX], [ ;; esac ;; - linux* | k*bsd*-gnu | gnu*) - _LT_TAGVAR(link_all_deplibs, $1)=no - ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; @@ -5013,9 +5001,6 @@ dnl Note also adjust exclude_expsyms for C++ above. openbsd* | bitrig*) with_gnu_ld=no ;; - linux* | k*bsd*-gnu | gnu*) - _LT_TAGVAR(link_all_deplibs, $1)=no - ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes @@ -5270,7 +5255,7 @@ _LT_EOF fi ;; - netbsd* | netbsdelf*-gnu) + netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= @@ -5791,7 +5776,6 @@ _LT_EOF if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi - _LT_TAGVAR(link_all_deplibs, $1)=no else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' @@ -5813,7 +5797,7 @@ _LT_EOF esac ;; - netbsd* | netbsdelf*-gnu) + netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else @@ -6439,7 +6423,7 @@ if test yes != "$_lt_caught_CXX_error"; then # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no @@ -6814,7 +6798,7 @@ if test yes != "$_lt_caught_CXX_error"; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then @@ -6879,7 +6863,7 @@ if test yes != "$_lt_caught_CXX_error"; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then @@ -7218,7 +7202,7 @@ if test yes != "$_lt_caught_CXX_error"; then # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support @@ -7302,7 +7286,7 @@ if test yes != "$_lt_caught_CXX_error"; then # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. @@ -7313,7 +7297,7 @@ if test yes != "$_lt_caught_CXX_error"; then # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' @@ -1,5 +1,5 @@ # nls.m4 serial 5 (gettext-0.18) -dnl Copyright (C) 1995-2003, 2005-2006, 2008-2014 Free Software Foundation, +dnl Copyright (C) 1995-2003, 2005-2006, 2008-2010 Free Software Foundation, dnl Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -1,16 +1,16 @@ -# po.m4 serial 22 (gettext-0.19) -dnl Copyright (C) 1995-2014 Free Software Foundation, Inc. +# po.m4 serial 24 (gettext-0.19) +dnl Copyright (C) 1995-2014, 2016 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl -dnl This file can can be used in projects which are not available under +dnl This file can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU -dnl gettext package package is covered by the GNU General Public License. +dnl gettext package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: diff --git a/m4/progtest.m4 b/m4/progtest.m4 index b499f79..9ace7c3 100644 --- a/m4/progtest.m4 +++ b/m4/progtest.m4 @@ -1,16 +1,16 @@ # progtest.m4 serial 7 (gettext-0.18.2) -dnl Copyright (C) 1996-2003, 2005, 2008-2014 Free Software Foundation, Inc. +dnl Copyright (C) 1996-2003, 2005, 2008-2016 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl -dnl This file can can be used in projects which are not available under +dnl This file can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU -dnl gettext package package is covered by the GNU General Public License. +dnl gettext package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: diff --git a/man/Makefile.in b/man/Makefile.in index 0e4cc9d..0026d18 100644 --- a/man/Makefile.in +++ b/man/Makefile.in @@ -255,6 +255,8 @@ GREP = @GREP@ GSETTINGS_CFLAGS = @GSETTINGS_CFLAGS@ GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ GSETTINGS_LIBS = @GSETTINGS_LIBS@ +GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@ +GSTREAMER_LIBS = @GSTREAMER_LIBS@ GTK30_CFLAGS = @GTK30_CFLAGS@ GTK30_LIBS = @GTK30_LIBS@ HAVE_AF_UNIX = @HAVE_AF_UNIX@ @@ -465,7 +467,6 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pulseconfdir = @pulseconfdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/man/default.pa.5 b/man/default.pa.5 index 11438a5..08885a0 100644 --- a/man/default.pa.5 +++ b/man/default.pa.5 @@ -4,12 +4,12 @@ default.pa \- PulseAudio Sound Server Startup Script .SH SYNOPSIS \fB\fI~/.config/pulse/default.pa\fB -\fI/usr/local/etc/pulse/default.pa\fB +\fI/home/arun/local/pulseaudio/etc/pulse/default.pa\fB -\fI/usr/local/etc/pulse/system.pa\fB +\fI/home/arun/local/pulseaudio/etc/pulse/system.pa\fB \f1 .SH DESCRIPTION -The PulseAudio sound server interprets a configuration script on startup, which is mainly used to define the set of modules to load. When PulseAudio runs in the per-user mode and \fI~/.config/pulse/default.pa\f1 exists, that file is used. When PulseAudio runs in the per-user mode and that file doesn't exist, \fI/usr/local/etc/pulse/default.pa\f1 is used. When PulseAudio runs as a system service, \fI/usr/local/etc/pulse/system.pa\f1 is used. +The PulseAudio sound server interprets a configuration script on startup, which is mainly used to define the set of modules to load. When PulseAudio runs in the per-user mode and \fI~/.config/pulse/default.pa\f1 exists, that file is used. When PulseAudio runs in the per-user mode and that file doesn't exist, \fI/home/arun/local/pulseaudio/etc/pulse/default.pa\f1 is used. When PulseAudio runs as a system service, \fI/home/arun/local/pulseaudio/etc/pulse/system.pa\f1 is used. The script should contain directives in the PulseAudio CLI language, as documented in \fBpulse-cli-syntax(5)\f1. .SH AUTHORS diff --git a/man/pax11publish.1 b/man/pax11publish.1 index ec241b9..740841a 100644 --- a/man/pax11publish.1 +++ b/man/pax11publish.1 @@ -32,7 +32,7 @@ Read the PulseAudio server credentials currently set on the X11 root window and Similar to \fB-d\f1, however dumps them in a Bourne shell compatible format so they may be used together with the \fIeval\f1 shell command to set the $PULSE_SERVER, $PULSE_SINK, $PULSE_SOURCE environment variables. Also reads the authentication cookie from the root window and stores it in \fI~/.config/pulse/cookie\f1. .TP \fB-e\f1 -Export the currently locally used sound server, sink, source configuration to the X11 root window. This takes the data from the $PULSE_SERVER, $PULSE_SINK, $PULSE_SOURCE environment variables and combines them with the data from \fI~/.config/pulse/client.conf\f1 (or \fI/usr/local/etc/pulse/client.conf\f1 if that file does not exist). If specific options are passed on the command line (\fB-S\f1, \fB-O\f1, \fB-I\f1, \fB-c\f1, see below), they take precedence. Also uploads the local authentication cookie \fI~/.config/pulse/cookie\f1 to the X11 server. +Export the currently locally used sound server, sink, source configuration to the X11 root window. This takes the data from the $PULSE_SERVER, $PULSE_SINK, $PULSE_SOURCE environment variables and combines them with the data from \fI~/.config/pulse/client.conf\f1 (or \fI/home/arun/local/pulseaudio/etc/pulse/client.conf\f1 if that file does not exist). If specific options are passed on the command line (\fB-S\f1, \fB-O\f1, \fB-I\f1, \fB-c\f1, see below), they take precedence. Also uploads the local authentication cookie \fI~/.config/pulse/cookie\f1 to the X11 server. .TP \fB-r\f1 Removes the configured PulseAudio configuration from the X11 root window. diff --git a/man/pulse-cli-syntax.5 b/man/pulse-cli-syntax.5 index 879ce2c..acaec39 100644 --- a/man/pulse-cli-syntax.5 +++ b/man/pulse-cli-syntax.5 @@ -4,9 +4,9 @@ pulse-cli-syntax \- PulseAudio Command Line Interface Syntax .SH SYNOPSIS \fB\fI~/.config/pulse/default.pa\fB -\fI/usr/local/etc/pulse/default.pa\fB +\fI/home/arun/local/pulseaudio/etc/pulse/default.pa\fB -\fI/usr/local/etc/pulse/system.pa\fB +\fI/home/arun/local/pulseaudio/etc/pulse/system.pa\fB \f1 .SH DESCRIPTION PulseAudio provides a simple command line language used by configuration scripts, the pacmd interactive shell, and the modules module-cli and module-cli-protocol-{unix,tcp}. Empty lines and lines beginning with a hashmark (#) are silently ignored. Several commands are supported. diff --git a/man/pulse-client.conf.5 b/man/pulse-client.conf.5 index 7bddd74..fdf3888 100644 --- a/man/pulse-client.conf.5 +++ b/man/pulse-client.conf.5 @@ -6,12 +6,12 @@ pulse-client.conf \- PulseAudio client configuration file \fI~/.config/pulse/client.conf.d/*.conf\fB -\fI/usr/local/etc/pulse/client.conf\fB +\fI/home/arun/local/pulseaudio/etc/pulse/client.conf\fB -\fI/usr/local/etc/pulse/client.conf.d/*.conf\fB +\fI/home/arun/local/pulseaudio/etc/pulse/client.conf.d/*.conf\fB \f1 .SH DESCRIPTION -The PulseAudio client library reads configuration directives from a configuration file on startup. If the per-user file \fI~/.config/pulse/client.conf\f1 exists, it is used, otherwise the system configuration file \fI/usr/local/etc/pulse/client.conf\f1 is used. In addition to those main files, configuration directives can also be put in files under directories \fI~/.config/pulse/client.conf.d/\f1 and \fI/usr/local/etc/pulse/client.conf.d/\f1. Those files have to have the .conf file name extension, but otherwise the file names can be chosen freely. The files under client.conf.d are processed in alphabetical order. In case the same option is set in multiple files, the last file to set an option overrides earlier files. The main client.conf file is processed first, so options set in files under client.conf.d override the main file. +The PulseAudio client library reads configuration directives from a configuration file on startup. If the per-user file \fI~/.config/pulse/client.conf\f1 exists, it is used, otherwise the system configuration file \fI/home/arun/local/pulseaudio/etc/pulse/client.conf\f1 is used. In addition to those main files, configuration directives can also be put in files under directories \fI~/.config/pulse/client.conf.d/\f1 and \fI/home/arun/local/pulseaudio/etc/pulse/client.conf.d/\f1. Those files have to have the .conf file name extension, but otherwise the file names can be chosen freely. The files under client.conf.d are processed in alphabetical order. In case the same option is set in multiple files, the last file to set an option overrides earlier files. The main client.conf file is processed first, so options set in files under client.conf.d override the main file. The configuration file is a simple collection of variable declarations. If the configuration file parser encounters either ; or # it ignores the rest of the line until its end. diff --git a/man/pulse-daemon.conf.5 b/man/pulse-daemon.conf.5 index ae99147..b2f34ac 100644 --- a/man/pulse-daemon.conf.5 +++ b/man/pulse-daemon.conf.5 @@ -6,12 +6,12 @@ pulse-daemon.conf \- PulseAudio daemon configuration file \fI~/.config/pulse/daemon.conf.d/*.conf\fB -\fI/usr/local/etc/pulse/daemon.conf\fB +\fI/home/arun/local/pulseaudio/etc/pulse/daemon.conf\fB -\fI/usr/local/etc/pulse/daemon.conf.d/*.conf\fB +\fI/home/arun/local/pulseaudio/etc/pulse/daemon.conf.d/*.conf\fB \f1 .SH DESCRIPTION -The PulseAudio sound server reads configuration directives from a configuration file on startup. If the per-user file \fI~/.config/pulse/daemon.conf\f1 exists, it is used, otherwise the system configuration file \fI/usr/local/etc/pulse/daemon.conf\f1 is used. In addition to those main files, configuration directives can also be put in files under directories \fI~/.config/pulse/daemon.conf.d/\f1 and \fI/usr/local/etc/pulse/daemon.conf.d/\f1. Those files have to have the .conf file name extension, but otherwise the file names can be chosen freely. The files under daemon.conf.d are processed in alphabetical order. In case the same option is set in multiple files, the last file to set an option overrides earlier files. The main daemon.conf file is processed first, so options set in files under daemon.conf.d override the main file. +The PulseAudio sound server reads configuration directives from a configuration file on startup. If the per-user file \fI~/.config/pulse/daemon.conf\f1 exists, it is used, otherwise the system configuration file \fI/home/arun/local/pulseaudio/etc/pulse/daemon.conf\f1 is used. In addition to those main files, configuration directives can also be put in files under directories \fI~/.config/pulse/daemon.conf.d/\f1 and \fI/home/arun/local/pulseaudio/etc/pulse/daemon.conf.d/\f1. Those files have to have the .conf file name extension, but otherwise the file names can be chosen freely. The files under daemon.conf.d are processed in alphabetical order. In case the same option is set in multiple files, the last file to set an option overrides earlier files. The main daemon.conf file is processed first, so options set in files under daemon.conf.d override the main file. Please note that the server also reads a configuration script on startup. See \fBdefault.pa(5)\f1. @@ -36,7 +36,11 @@ For the settings that take a boolean argument the values \fBtrue\f1, \fByes\f1, .TP \fBremixing-use-all-sink-channels=\f1 If enabled, use all sink channels when remixing. Otherwise, remix to the minimal set of sink channels needed to reproduce all of the source channels. (This has no effect on LFE remixing.) Defaults to \fByes\f1. .TP -\fBenable-lfe-remixing=\f1 If disabled when upmixing or downmixing ignore LFE channels. When this option is disabled 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 \fBno\f1. +\fBenable-lfe-remixing=\f1 This is a way to set \fBremixing-produce-lfe\f1 and \fBremixing-consume-lfe\f1 to the same value at once. This option only exists for backward compatibility and may be removed in a future version of PulseAudio. +.TP +\fBremixing-produce-lfe=\f1 If enabled, and the sink input does not have the LFE channel, synthesize the output LFE channel as a (lowpass-filtered, if \fBlfe-crossover-freq\f1 is not 0) average of all input channels. Also, when \fBlfe-crossover-freq\f1 is not 0, filter out low frequencies from other channels while producing a synthetic LFE output. If disabled, the output LFE channel will only get a signal when an input LFE channel is available as well. Defaults to \fBno\f1. +.TP +\fBremixing-consume-lfe=\f1 If enabled, and the sink does not have an LFE channel, redirect the input LFE channel (if any) to other channels. If disabled, the input LFE channel will remain unused unless the sink has the LFE channel as well. Defaults to \fBno\f1. .TP \fBlfe-crossover-freq=\f1 The crossover frequency (in Hz) for the LFE filter. Set it to 0 to disable the LFE filter. Defaults to 0. .TP @@ -56,7 +60,9 @@ For the settings that take a boolean argument the values \fBtrue\f1, \fByes\f1, .TP \fBlock-memory=\f1 Locks the entire PulseAudio process into memory. While this might increase drop-out safety when used in conjunction with real-time scheduling this takes away a lot of memory from other processes and might hence considerably slow down your system. Defaults to \fBno\f1. .TP -\fBflat-volumes=\f1 Enable 'flat' volumes, i.e. where possible let the sink volume equal the maximum of the volumes of the inputs connected to it. Takes a boolean argument, defaults to \fByes\f1. +\fBflat-volumes=\f1 Enable 'flat' volumes, i.e. where possible let the sink volume equal the maximum of the volumes of the inputs connected to it. Takes a boolean argument, defaults to \fBno\f1. +.TP +\fBrescue-streams=\f1 Enable rescuing of streams if the used sink or source becomes unavailable. Takes a boolean argument. If set to \fByes\f1, pulseaudio will try to move the streams from a sink or source that becomes unavailable to the default sink or source. If set to \fBno\f1, streams will be killed if the corresponding sink or source disappears. Defaults to \fByes\f1. .SH SCHEDULING .TP \fBhigh-priority=\f1 Renice the daemon after startup to become a high-priority process. This a good idea if you experience drop-outs during playback. However, this is a certain security issue, since it works when called SUID root only, or RLIMIT_NICE is used. root is dropped immediately after gaining the nice level on startup, thus it is presumably safe. See \fBpulseaudio(1)\f1 for more information. Takes a boolean argument, defaults to \fByes\f1. The \fB--high-priority\f1 command line option takes precedence. @@ -79,7 +85,7 @@ When PulseAudio runs in the system mode, automatic exit is always disabled, so t .TP \fBdl-search-path=\f1 The path where to look for dynamic shared objects (DSOs/plugins). You may specify more than one path separated by colons. The default path depends on compile time settings. The \fB--dl-search-path\f1 command line option takes precedence. .TP -\fBdefault-script-file=\f1 The default configuration script file to load. Specify an empty string for not loading a default script file. The default behaviour is to load \fI~/.config/pulse/default.pa\f1, and if that file does not exist fall back to the system wide installed version \fI/usr/local/etc/pulse/default.pa\f1. If run in system-wide mode the file \fI/usr/local/etc/pulse/system.pa\f1 is used instead. If \fB-n\f1 is passed on the command line or \fBdefault-script-file=\f1 is disabled the default configuration script is ignored. +\fBdefault-script-file=\f1 The default configuration script file to load. Specify an empty string for not loading a default script file. The default behaviour is to load \fI~/.config/pulse/default.pa\f1, and if that file does not exist fall back to the system wide installed version \fI/home/arun/local/pulseaudio/etc/pulse/default.pa\f1. If run in system-wide mode the file \fI/home/arun/local/pulseaudio/etc/pulse/system.pa\f1 is used instead. If \fB-n\f1 is passed on the command line or \fBdefault-script-file=\f1 is disabled the default configuration script is ignored. .TP \fBload-default-script-file=\f1 Load the default configuration script file as specified in \fBdefault-script-file=\f1. Defaults to \fByes\f1. .SH LOGGING diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in index f49fa9b..e64b20f 100644 --- a/man/pulse-daemon.conf.5.xml.in +++ b/man/pulse-daemon.conf.5.xml.in @@ -147,13 +147,28 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. </option> <option> - <p><opt>enable-lfe-remixing=</opt> If disabled when upmixing or - downmixing ignore LFE channels. When this option is disabled 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 <opt>no</opt>.</p> + <p><opt>enable-lfe-remixing=</opt> This is a way to set + <opt>remixing-produce-lfe</opt> and <opt>remixing-consume-lfe</opt> + to the same value at once. This option only exists for backward + compatibility and may be removed in a future version of PulseAudio.</p> + </option> + + <option> + <p><opt>remixing-produce-lfe=</opt> If enabled, and the sink input + does not have the LFE channel, synthesize the output LFE channel + as a (lowpass-filtered, if <opt>lfe-crossover-freq</opt> is not 0) + average of all input channels. Also, when <opt>lfe-crossover-freq</opt> + is not 0, filter out low frequencies from other channels while + producing a synthetic LFE output. If disabled, the output LFE channel + will only get a signal when an input LFE channel is available as well. + Defaults to <opt>no</opt>.</p> + </option> + + <option> + <p><opt>remixing-consume-lfe=</opt> If enabled, and the sink does not + have an LFE channel, redirect the input LFE channel (if any) to other + channels. If disabled, the input LFE channel will remain unused unless + the sink has the LFE channel as well. Defaults to <opt>no</opt>.</p> </option> <option> @@ -237,7 +252,16 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. <p><opt>flat-volumes=</opt> Enable 'flat' volumes, i.e. where possible let the sink volume equal the maximum of the volumes of the inputs connected to it. Takes a boolean argument, defaults - to <opt>yes</opt>.</p> + to <opt>no</opt>.</p> + </option> + + <option> + <p><opt>rescue-streams=</opt> Enable rescuing of streams if the + used sink or source becomes unavailable. Takes a boolean argument. + If set to <opt>yes</opt>, pulseaudio will try to move the streams + from a sink or source that becomes unavailable to the default sink + or source. If set to <opt>no</opt>, streams will be killed if the + corresponding sink or source disappears. Defaults to <opt>yes</opt>.</p> </option> </section> diff --git a/man/pulseaudio.1 b/man/pulseaudio.1 index 9537ab3..27aa054 100644 --- a/man/pulseaudio.1 +++ b/man/pulseaudio.1 @@ -63,10 +63,10 @@ Daemonize after startup, i.e. detach from the terminal. Note that when running a Fail startup when any of the commands specified in the startup script \fIdefault.pa\f1 (see below) fails. .TP \fB--high-priority\f1\fI[=BOOL]\f1 -Try to acquire a high Unix nice level. This will only succeed if the calling user has a non-zero RLIMIT_NICE resource limit set (on systems that support this), or we're called SUID root (see below), or we are configure to be run as system daemon (see \fI--system\f1 above). It is recommended to enable this, since it is only a negligible security risk (see below). +Try to acquire a high Unix nice level. This will only succeed if the calling user has a non-zero RLIMIT_NICE resource limit set (on systems that support this), or we're configured to be run as system daemon (see \fI--system\f1 above). It is recommended to enable this, since it is only a negligible security risk (see below). .TP \fB--realtime\f1\fI[=BOOL]\f1 -Try to acquire a real-time scheduling for PulseAudio's I/O threads. This will only succeed if the calling user has a non-zero RLIMIT_RTPRIO resource limit set (on systems that support this), or we're called SUID root (see below), or we are configure to be run as system daemon (see \fI--system\f1 above). It is recommended to enable this only for trusted users, since it is a major security risk (see below). +Try to acquire a real-time scheduling for PulseAudio's I/O threads. This will only succeed if the calling user has a non-zero RLIMIT_RTPRIO resource limit set (on systems that support this), or rtkit is available and allows PulseAudio to enable real-time scheduling, or we are configured to be run as system daemon (see \fI--system\f1 above). .TP \fB--disallow-module-loading\f1\fI[=BOOL]\f1 Disallow module loading after startup. This is a security feature since it disallows additional module loading during runtime and on user request. It is highly recommended when \fI--system\f1 is used (see above). Note however, that this breaks certain features like automatic module loading on hot plug. @@ -132,11 +132,11 @@ Open a command interpreter on STDIN/STDOUT after startup. This may be used to co \fB-n\f1 Don't load default script file \fIdefault.pa\f1 (see below) on startup. Useful in conjunction with \fB-C\f1 or \fB--file\f1. .SH FILES -\fI~/.config/pulse/daemon.conf\f1, \fI/usr/local/etc/pulse/daemon.conf\f1: configuration settings for the PulseAudio daemon. If the version in the user's home directory does not exist the global configuration file is loaded. See \fBpulse-daemon.conf(5)\f1 for more information. +\fI~/.config/pulse/daemon.conf\f1, \fI/home/arun/local/pulseaudio/etc/pulse/daemon.conf\f1: configuration settings for the PulseAudio daemon. If the version in the user's home directory does not exist the global configuration file is loaded. See \fBpulse-daemon.conf(5)\f1 for more information. -\fI~/.config/pulse/default.pa\f1, \fI/usr/local/etc/pulse/default.pa\f1: the default configuration script to execute when the PulseAudio daemon is started. If the version in the user's home directory does not exist the global configuration script is loaded. See \fBdefault.pa(5)\f1 for more information. +\fI~/.config/pulse/default.pa\f1, \fI/home/arun/local/pulseaudio/etc/pulse/default.pa\f1: the default configuration script to execute when the PulseAudio daemon is started. If the version in the user's home directory does not exist the global configuration script is loaded. See \fBdefault.pa(5)\f1 for more information. -\fI~/.config/pulse/client.conf\f1, \fI/usr/local/etc/pulse/client.conf\f1: configuration settings for PulseAudio client applications. If the version in the user's home directory does not exist the global configuration file is loaded. See \fBpulse-client.conf(5)\f1 for more information. +\fI~/.config/pulse/client.conf\f1, \fI/home/arun/local/pulseaudio/etc/pulse/client.conf\f1: configuration settings for PulseAudio client applications. If the version in the user's home directory does not exist the global configuration file is loaded. See \fBpulse-client.conf(5)\f1 for more information. .SH SIGNALS \fISIGINT, SIGTERM\f1: the PulseAudio daemon will shut down (Same as \fB--kill\f1). @@ -146,21 +146,13 @@ Don't load default script file \fIdefault.pa\f1 (see below) on startup. Useful i \fISIGUSR2\f1: load module-cli-protocol-unix, allowing runtime reconfiguration via a AF_UNIX socket. See \fBpacmd(1)\f1 for more information. .SH UNIX GROUPS AND USERS -Group \fIpulse-rt\f1: if the PulseAudio binary is marked SUID root, then membership of the calling user in this group decides whether real-time and/or high-priority scheduling is enabled. Please note that enabling real-time scheduling is a security risk (see below). - Group \fIpulse-access\f1: if PulseAudio is running as a system daemon (see \fB--system\f1 above) access is granted to members of this group when they connect via AF_UNIX sockets. If PulseAudio is running as a user daemon this group has no meaning. User \fIpulse\f1, group \fIpulse\f1: if PulseAudio is running as a system daemon (see \fB--system\f1 above) and is started as root the daemon will drop privileges and become a normal user process using this user and group. If PulseAudio is running as a user daemon this user and group has no meaning. .SH REAL-TIME AND HIGH-PRIORITY SCHEDULING -To minimize the risk of drop-outs during playback it is recommended to run PulseAudio with real-time scheduling if the underlying platform supports it. This decouples the scheduling latency of the PulseAudio daemon from the system load and is thus the best way to make sure that PulseAudio always gets CPU time when it needs it to refill the hardware playback buffers. Unfortunately this is a security risk on most systems, since PulseAudio runs as user process, and giving realtime scheduling privileges to a user process always comes with the risk that the user misuses it to lock up the system -- which is possible since making a process real-time effectively disables preemption. - -To minimize the risk PulseAudio by default does not enable real-time scheduling. It is however recommended to enable it on trusted systems. To do that start PulseAudio with \fB--realtime\f1 (see above) or enabled the appropriate option in \fIdaemon.conf\f1. Since acquiring realtime scheduling is a privileged operation on most systems, some special changes to the system configuration need to be made to allow them to the calling user. Two options are available: - -On newer Linux systems the system resource limit RLIMIT_RTPRIO (see \fBsetrlimit(2)\f1 for more information) can be used to allow specific users to acquire real-time scheduling. This can be configured in \fI/etc/security/limits.conf\f1, a resource limit of 9 is recommended. - -Alternatively, the SUID root bit can be set for the PulseAudio binary. Then, the daemon will drop root privileges immediately on startup, however retain the CAP_NICE capability (on systems that support it), but only if the calling user is a member of the \fIpulse-rt\f1 group (see above). For all other users all capabilities are dropped immediately. The advantage of this solution is that the real-time privileges are only granted to the PulseAudio daemon -- not to all the user's processes. +To minimize the risk of drop-outs during playback it is recommended to run PulseAudio with real-time scheduling if the underlying platform supports it. This decouples the scheduling latency of the PulseAudio daemon from the system load and is thus the best way to make sure that PulseAudio always gets CPU time when it needs it to refill the hardware playback buffers. Unfortunately this can be a security risk on some systems, since PulseAudio runs as user process, and giving realtime scheduling privileges to a user always comes with the risk that the user misuses it to lock up the system -- which is possible since making a process real-time effectively disables preemption. To solve this problem, PulseAudio uses rtkit to safely acquire real-time scheduling when available. -Alternatively, if the risk of locking up the machine is considered too big to enable real-time scheduling, high-priority scheduling can be enabled instead (i.e. negative nice level). This can be enabled by passing \fB--high-priority\f1 (see above) when starting PulseAudio and may also be enabled with the appropriate option in \fIdaemon.conf\f1. Negative nice levels can only be enabled when the appropriate resource limit RLIMIT_NICE is set (see \fBsetrlimit(2)\f1 for more information), possibly configured in \fI/etc/security/limits.conf\f1. A resource limit of 31 (corresponding with nice level -11) is recommended. +If the risk of locking up the machine is considered too big to enable real-time scheduling, high-priority scheduling can be enabled instead (i.e. negative nice level). This can be enabled by passing \fB--high-priority\f1 (see above) when starting PulseAudio and may also be enabled with the appropriate option in \fIdaemon.conf\f1. Negative nice levels can only be enabled when the appropriate resource limit RLIMIT_NICE is set (see \fBsetrlimit(2)\f1 for more information), possibly configured in \fI/etc/security/limits.conf\f1. A resource limit of 31 (corresponding with nice level -11) is recommended. .SH ENVIRONMENT VARIABLES The PulseAudio client libraries check for the existence of the following environment variables and change their local configuration accordingly: diff --git a/man/pulseaudio.1.xml.in b/man/pulseaudio.1.xml.in index 824eddb..fdfb6e7 100644 --- a/man/pulseaudio.1.xml.in +++ b/man/pulseaudio.1.xml.in @@ -149,7 +149,7 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. <optdesc><p>Try to acquire a high Unix nice level. This will only succeed if the calling user has a non-zero RLIMIT_NICE resource limit set (on systems that support this), or we're - called SUID root (see below), or we are configure to be run as + configured to be run as system daemon (see <arg>--system</arg> above). It is recommended to enable this, since it is only a negligible security risk (see below).</p></optdesc> @@ -161,11 +161,9 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. <optdesc><p>Try to acquire a real-time scheduling for PulseAudio's I/O threads. This will only succeed if the calling user has a non-zero RLIMIT_RTPRIO resource limit set (on systems - that support this), or we're called SUID root (see below), or we - are configure to be run as system daemon (see - <arg>--system</arg> above). It is recommended to enable this - only for trusted users, since it is a major security risk (see - below).</p></optdesc> + that support this), or rtkit is available and allows PulseAudio + to enable real-time scheduling, or we are configured to be run as + system daemon (see <arg>--system</arg> above).</p></optdesc> </option> <option> @@ -400,12 +398,6 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. <section name="UNIX Groups and users"> - <p>Group <arg>pulse-rt</arg>: if the PulseAudio binary is marked - SUID root, then membership of the calling user in this group - decides whether real-time and/or high-priority scheduling is - enabled. Please note that enabling real-time scheduling is a - security risk (see below).</p> - <p>Group <arg>pulse-access</arg>: if PulseAudio is running as a system daemon (see <opt>--system</opt> above) access is granted to members of this group when they connect via AF_UNIX sockets. If @@ -426,38 +418,15 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. latency of the PulseAudio daemon from the system load and is thus the best way to make sure that PulseAudio always gets CPU time when it needs it to refill the hardware playback - buffers. Unfortunately this is a security risk on most systems, + buffers. Unfortunately this can be a security risk on some systems, since PulseAudio runs as user process, and giving realtime - scheduling privileges to a user process always comes with the risk + scheduling privileges to a user always comes with the risk that the user misuses it to lock up the system -- which is possible since making a process real-time effectively disables - preemption.</p> - - <p>To minimize the risk PulseAudio by default does not enable - real-time scheduling. It is however recommended to enable it - on trusted systems. To do that start PulseAudio with - <opt>--realtime</opt> (see above) or enabled the appropriate option in - <file>daemon.conf</file>. Since acquiring realtime scheduling is a - privileged operation on most systems, some special changes to the - system configuration need to be made to allow them to the calling - user. Two options are available:</p> - - <p>On newer Linux systems the system resource limit RLIMIT_RTPRIO - (see <manref name="setrlimit" section="2"/> for more information) - can be used to allow specific users to acquire real-time - scheduling. This can be configured in - <file>/etc/security/limits.conf</file>, a resource limit of 9 is recommended.</p> - - <p>Alternatively, the SUID root bit can be set for the PulseAudio - binary. Then, the daemon will drop root privileges immediately on - startup, however retain the CAP_NICE capability (on systems that - support it), but only if the calling user is a member of the - <arg>pulse-rt</arg> group (see above). For all other users all - capabilities are dropped immediately. The advantage of this - solution is that the real-time privileges are only granted to the - PulseAudio daemon -- not to all the user's processes.</p> - - <p>Alternatively, if the risk of locking up the machine is + preemption. To solve this problem, PulseAudio uses rtkit to safely + acquire real-time scheduling when available.</p> + + <p>If the risk of locking up the machine is considered too big to enable real-time scheduling, high-priority scheduling can be enabled instead (i.e. negative nice level). This can be enabled by passing <opt>--high-priority</opt> (see above) diff --git a/meson.build b/meson.build index a10a1b3..88394e4 100644 --- a/meson.build +++ b/meson.build @@ -23,7 +23,7 @@ pa_protocol_version = 33 # The stable ABI for client applications, for the version info x:y:z # always will hold x=z -libpulse_version_info = [21, 1, 21] +libpulse_version_info = [21, 2, 21] # A simplified, synchronous, ABI-stable interface for client # applications, for the version info x:y:z always will hold x=z @@ -296,6 +296,12 @@ if cc.has_function('SYS_memfd_create', prefix : '#include <sys/syscall.h>') cdata.set('HAVE_MEMFD', 1) endif +if cc.has_function('dgettext') + libintl_dep = [] +else + libintl_dep = cc.find_library('intl') +endif + # Symbols if cc.has_header_symbol('signal.h', 'SIGXCPU') @@ -663,6 +669,15 @@ if webrtc_dep.found() cdata.set('HAVE_WEBRTC', 1) endif +gst_dep = dependency('gstreamer-1.0', required : get_option('gstreamer')) +gstapp_dep = dependency('gstreamer-app-1.0', required : get_option('gstreamer')) +gstrtp_dep = dependency('gstreamer-rtp-1.0', required : get_option('gstreamer')) + +have_gstreamer = false +if gst_dep.found() and gstapp_dep.found() and gstrtp_dep.found() + have_gstreamer = true +endif + # These are required for the CMake file generation cdata.set('PA_LIBDIR', libdir) cdata.set('PA_INCDIR', includedir) @@ -809,6 +824,7 @@ summary = [ 'Enable OpenSSL (for Airtunes): @0@'.format(openssl_dep.found()), 'Enable FFTW: @0@'.format(fftw_dep.found()), 'Enable ORC: @0@'.format(have_orcc), + 'Enable GStreamer: @0@'.format(have_gstreamer), 'Enable Adrian echo canceller: @0@'.format(get_option('adrian-aec')), 'Enable Speex (resampler, AEC): @0@'.format(speex_dep.found()), 'Enable SoXR (resampler): @0@'.format(soxr_dep.found()), diff --git a/meson_options.txt b/meson_options.txt index 7668773..8178892 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -56,10 +56,10 @@ option('udevrulesdir', description : 'Directory for udev rules (defaults to /lib/udev/rules.d)') option('bashcompletiondir', type : 'string', - description : 'Directory for bash completion files') + description : 'Directory for bash completion scripts ["no" disables]') option('zshcompletiondir', type : 'string', - description : 'Zsh completions directory') + description : 'Directory for zsh completion scripts ["no" disables]') # Optional features @@ -93,6 +93,9 @@ option('glib', option('gsettings', type : 'feature', value : 'auto', description : 'Optional GSettings support') +option('gstreamer', + type : 'feature', value : 'auto', + description : 'Optional GStreamer dependency for media-related functionality') option('gtk', type : 'feature', value : 'auto', description : 'Optional Gtk+ 3 support') diff --git a/po/POTFILES.in b/po/POTFILES.in index 0b51946..33f7ae3 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -66,7 +66,9 @@ src/modules/raop/raop-sink.c src/modules/reserve-wrap.c src/modules/rtp/module-rtp-recv.c src/modules/rtp/module-rtp-send.c -src/modules/rtp/rtp.c +src/modules/rtp/rtp-common.c +src/modules/rtp/rtp-native.c +src/modules/rtp/rtp-gstreamer.c src/modules/rtp/sap.c src/modules/rtp/sdp.c src/modules/x11/module-x11-bell.c Binary files differBinary files differdiff --git a/po/bn_IN.gmo b/po/bn_IN.gmo Binary files differBinary files differBinary files differindex 6237262..342f119 100644 --- a/po/bn_IN.gmo +++ b/po/bn_IN.gmo diff --git a/po/de_CH.gmo b/po/de_CH.gmo Binary files differBinary files differBinary files differBinary files differBinary files differBinary files differBinary files differBinary files differindex 808b012..75b3395 100644 --- a/po/de_CH.gmo +++ b/po/de_CH.gmo @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-23 13:50+0200\n" -"PO-Revision-Date: 2019-06-23 14:20+0200\n" +"POT-Creation-Date: 2019-11-10 14:12+0100\n" +"PO-Revision-Date: 2019-11-10 14:21+0100\n" "Last-Translator: gogo <trebelnik2@gmail.com>\n" "Language-Team: Croatian <hr@li.org>\n" "Language: hr\n" @@ -578,165 +578,165 @@ msgid "Daemon startup without any loaded modules, refusing to work." msgstr "" "Pozadinski program je pokrenut bez ijednog učitanog modula, odbija raditi." -#: ../src/modules/alsa/alsa-mixer.c:2443 +#: ../src/modules/alsa/alsa-mixer.c:2442 msgid "Input" msgstr "Ulaz" -#: ../src/modules/alsa/alsa-mixer.c:2444 +#: ../src/modules/alsa/alsa-mixer.c:2443 msgid "Docking Station Input" msgstr "Ulaz priključne stanice" -#: ../src/modules/alsa/alsa-mixer.c:2445 +#: ../src/modules/alsa/alsa-mixer.c:2444 msgid "Docking Station Microphone" msgstr "Mikrofon priključne stanice" -#: ../src/modules/alsa/alsa-mixer.c:2446 +#: ../src/modules/alsa/alsa-mixer.c:2445 msgid "Docking Station Line In" msgstr "Ulaz priključne stanice" -#: ../src/modules/alsa/alsa-mixer.c:2447 ../src/modules/alsa/alsa-mixer.c:2532 +#: ../src/modules/alsa/alsa-mixer.c:2446 ../src/modules/alsa/alsa-mixer.c:2531 msgid "Line In" msgstr "Ulaz" -#: ../src/modules/alsa/alsa-mixer.c:2448 ../src/modules/alsa/alsa-mixer.c:2526 -#: ../src/modules/bluetooth/module-bluez5-device.c:1709 +#: ../src/modules/alsa/alsa-mixer.c:2447 ../src/modules/alsa/alsa-mixer.c:2525 +#: ../src/modules/bluetooth/module-bluez5-device.c:1757 msgid "Microphone" msgstr "Mikrofon" -#: ../src/modules/alsa/alsa-mixer.c:2449 ../src/modules/alsa/alsa-mixer.c:2527 +#: ../src/modules/alsa/alsa-mixer.c:2448 ../src/modules/alsa/alsa-mixer.c:2526 msgid "Front Microphone" msgstr "Prednji mikrofon" -#: ../src/modules/alsa/alsa-mixer.c:2450 ../src/modules/alsa/alsa-mixer.c:2528 +#: ../src/modules/alsa/alsa-mixer.c:2449 ../src/modules/alsa/alsa-mixer.c:2527 msgid "Rear Microphone" msgstr "Stražnji mikrofon" -#: ../src/modules/alsa/alsa-mixer.c:2451 +#: ../src/modules/alsa/alsa-mixer.c:2450 msgid "External Microphone" msgstr "Vanjski mikrofon" -#: ../src/modules/alsa/alsa-mixer.c:2452 ../src/modules/alsa/alsa-mixer.c:2530 +#: ../src/modules/alsa/alsa-mixer.c:2451 ../src/modules/alsa/alsa-mixer.c:2529 msgid "Internal Microphone" msgstr "Unutarnji mikrofon" -#: ../src/modules/alsa/alsa-mixer.c:2453 ../src/modules/alsa/alsa-mixer.c:2533 +#: ../src/modules/alsa/alsa-mixer.c:2452 ../src/modules/alsa/alsa-mixer.c:2532 msgid "Radio" msgstr "Radio" -#: ../src/modules/alsa/alsa-mixer.c:2454 ../src/modules/alsa/alsa-mixer.c:2534 +#: ../src/modules/alsa/alsa-mixer.c:2453 ../src/modules/alsa/alsa-mixer.c:2533 msgid "Video" msgstr "Video" -#: ../src/modules/alsa/alsa-mixer.c:2455 +#: ../src/modules/alsa/alsa-mixer.c:2454 msgid "Automatic Gain Control" msgstr "Automatska kontrola pojačanja" -#: ../src/modules/alsa/alsa-mixer.c:2456 +#: ../src/modules/alsa/alsa-mixer.c:2455 msgid "No Automatic Gain Control" msgstr "Bez automatske kontrole pojačanja" -#: ../src/modules/alsa/alsa-mixer.c:2457 +#: ../src/modules/alsa/alsa-mixer.c:2456 msgid "Boost" msgstr "Pojačanje" -#: ../src/modules/alsa/alsa-mixer.c:2458 +#: ../src/modules/alsa/alsa-mixer.c:2457 msgid "No Boost" msgstr "Bez pojačanja" -#: ../src/modules/alsa/alsa-mixer.c:2459 +#: ../src/modules/alsa/alsa-mixer.c:2458 msgid "Amplifier" msgstr "Pojačalo" -#: ../src/modules/alsa/alsa-mixer.c:2460 +#: ../src/modules/alsa/alsa-mixer.c:2459 msgid "No Amplifier" msgstr "Bez pojačala" -#: ../src/modules/alsa/alsa-mixer.c:2461 +#: ../src/modules/alsa/alsa-mixer.c:2460 msgid "Bass Boost" msgstr "Pojačanje basa" -#: ../src/modules/alsa/alsa-mixer.c:2462 +#: ../src/modules/alsa/alsa-mixer.c:2461 msgid "No Bass Boost" msgstr "Bez pojačanja basa" -#: ../src/modules/alsa/alsa-mixer.c:2463 -#: ../src/modules/bluetooth/module-bluez5-device.c:1716 +#: ../src/modules/alsa/alsa-mixer.c:2462 +#: ../src/modules/bluetooth/module-bluez5-device.c:1764 msgid "Speaker" msgstr "Zvučnik" -#: ../src/modules/alsa/alsa-mixer.c:2464 ../src/modules/alsa/alsa-mixer.c:2536 +#: ../src/modules/alsa/alsa-mixer.c:2463 ../src/modules/alsa/alsa-mixer.c:2535 msgid "Headphones" msgstr "Slušalice" -#: ../src/modules/alsa/alsa-mixer.c:2525 +#: ../src/modules/alsa/alsa-mixer.c:2524 msgid "Analog Input" msgstr "Analogni ulaz" -#: ../src/modules/alsa/alsa-mixer.c:2529 +#: ../src/modules/alsa/alsa-mixer.c:2528 msgid "Dock Microphone" msgstr "Ugrađeni mikrofon" -#: ../src/modules/alsa/alsa-mixer.c:2531 +#: ../src/modules/alsa/alsa-mixer.c:2530 msgid "Headset Microphone" msgstr "Mikrofon sa slušalicama" -#: ../src/modules/alsa/alsa-mixer.c:2535 +#: ../src/modules/alsa/alsa-mixer.c:2534 msgid "Analog Output" msgstr "Analogni izlaz" -#: ../src/modules/alsa/alsa-mixer.c:2537 +#: ../src/modules/alsa/alsa-mixer.c:2536 msgid "Headphones Mono Output" msgstr "Mono izlaz za slušalice" -#: ../src/modules/alsa/alsa-mixer.c:2538 +#: ../src/modules/alsa/alsa-mixer.c:2537 msgid "LFE on Separate Mono Output" msgstr "(LFE) Efekti niske frekvencije na odvojenom mono izlazu" -#: ../src/modules/alsa/alsa-mixer.c:2539 +#: ../src/modules/alsa/alsa-mixer.c:2538 msgid "Line Out" msgstr "Izlaz" -#: ../src/modules/alsa/alsa-mixer.c:2540 +#: ../src/modules/alsa/alsa-mixer.c:2539 msgid "Analog Mono Output" msgstr "Analogni mono izlaz" -#: ../src/modules/alsa/alsa-mixer.c:2541 +#: ../src/modules/alsa/alsa-mixer.c:2540 msgid "Speakers" msgstr "Zvučnici" -#: ../src/modules/alsa/alsa-mixer.c:2542 +#: ../src/modules/alsa/alsa-mixer.c:2541 msgid "HDMI / DisplayPort" msgstr "HDMI / DisplayPort" -#: ../src/modules/alsa/alsa-mixer.c:2543 +#: ../src/modules/alsa/alsa-mixer.c:2542 msgid "Digital Output (S/PDIF)" msgstr "Digitalni izlaz (S/PDIF)" -#: ../src/modules/alsa/alsa-mixer.c:2544 +#: ../src/modules/alsa/alsa-mixer.c:2543 msgid "Digital Input (S/PDIF)" msgstr "Digitalni ulaz (S/PDIF)" -#: ../src/modules/alsa/alsa-mixer.c:2545 +#: ../src/modules/alsa/alsa-mixer.c:2544 msgid "Digital Passthrough (S/PDIF)" msgstr "Digitalni prolaz (S/PDIF)" -#: ../src/modules/alsa/alsa-mixer.c:2546 +#: ../src/modules/alsa/alsa-mixer.c:2545 msgid "Multichannel Input" msgstr "Višekanalni ulaz" -#: ../src/modules/alsa/alsa-mixer.c:2547 +#: ../src/modules/alsa/alsa-mixer.c:2546 msgid "Multichannel Output" msgstr "Višekanalni izlaz" -#: ../src/modules/alsa/alsa-mixer.c:2548 +#: ../src/modules/alsa/alsa-mixer.c:2547 msgid "Game Output" msgstr "Izlaz za igre" -#: ../src/modules/alsa/alsa-mixer.c:2549 +#: ../src/modules/alsa/alsa-mixer.c:2548 msgid "Chat Output" msgstr "Izlaz razgovora" -#: ../src/modules/alsa/alsa-mixer.c:4063 +#: ../src/modules/alsa/alsa-mixer.c:4062 msgid "Analog Mono" msgstr "Analogni mono" @@ -745,128 +745,128 @@ msgstr "Analogni mono" #. * here would lead to the source name to become "Analog Stereo Input #. * Input". The same logic applies to analog-stereo-output, #. * multichannel-input and multichannel-output. -#: ../src/modules/alsa/alsa-mixer.c:4064 ../src/modules/alsa/alsa-mixer.c:4072 -#: ../src/modules/alsa/alsa-mixer.c:4073 +#: ../src/modules/alsa/alsa-mixer.c:4063 ../src/modules/alsa/alsa-mixer.c:4071 +#: ../src/modules/alsa/alsa-mixer.c:4072 msgid "Analog Stereo" msgstr "Analogni stereo" -#: ../src/modules/alsa/alsa-mixer.c:4065 ../src/pulse/channelmap.c:103 +#: ../src/modules/alsa/alsa-mixer.c:4064 ../src/pulse/channelmap.c:103 #: ../src/pulse/channelmap.c:771 msgid "Mono" msgstr "Mono" -#: ../src/modules/alsa/alsa-mixer.c:4066 ../src/pulse/channelmap.c:775 +#: ../src/modules/alsa/alsa-mixer.c:4065 ../src/pulse/channelmap.c:775 msgid "Stereo" msgstr "Stereo" -#: ../src/modules/alsa/alsa-mixer.c:4074 ../src/modules/alsa/alsa-mixer.c:4075 +#: ../src/modules/alsa/alsa-mixer.c:4073 ../src/modules/alsa/alsa-mixer.c:4074 msgid "Multichannel" msgstr "Višekanalni" -#: ../src/modules/alsa/alsa-mixer.c:4076 +#: ../src/modules/alsa/alsa-mixer.c:4075 msgid "Analog Surround 2.1" msgstr "Analogni surround 2.1" -#: ../src/modules/alsa/alsa-mixer.c:4077 +#: ../src/modules/alsa/alsa-mixer.c:4076 msgid "Analog Surround 3.0" msgstr "Analogni surround 3.0" -#: ../src/modules/alsa/alsa-mixer.c:4078 +#: ../src/modules/alsa/alsa-mixer.c:4077 msgid "Analog Surround 3.1" msgstr "Analogni surround 3.1" -#: ../src/modules/alsa/alsa-mixer.c:4079 +#: ../src/modules/alsa/alsa-mixer.c:4078 msgid "Analog Surround 4.0" msgstr "Analogni surround 4.0" -#: ../src/modules/alsa/alsa-mixer.c:4080 +#: ../src/modules/alsa/alsa-mixer.c:4079 msgid "Analog Surround 4.1" msgstr "Analogni surround 4.1" -#: ../src/modules/alsa/alsa-mixer.c:4081 +#: ../src/modules/alsa/alsa-mixer.c:4080 msgid "Analog Surround 5.0" msgstr "Analogni surround 5.0" -#: ../src/modules/alsa/alsa-mixer.c:4082 +#: ../src/modules/alsa/alsa-mixer.c:4081 msgid "Analog Surround 5.1" msgstr "Analogni surround 5.1" -#: ../src/modules/alsa/alsa-mixer.c:4083 +#: ../src/modules/alsa/alsa-mixer.c:4082 msgid "Analog Surround 6.0" msgstr "Analogni surround 6.0" -#: ../src/modules/alsa/alsa-mixer.c:4084 +#: ../src/modules/alsa/alsa-mixer.c:4083 msgid "Analog Surround 6.1" msgstr "Analogni surround 6.1" -#: ../src/modules/alsa/alsa-mixer.c:4085 +#: ../src/modules/alsa/alsa-mixer.c:4084 msgid "Analog Surround 7.0" msgstr "Analogni surround 7.0" -#: ../src/modules/alsa/alsa-mixer.c:4086 +#: ../src/modules/alsa/alsa-mixer.c:4085 msgid "Analog Surround 7.1" msgstr "Analogni surround 7.1" -#: ../src/modules/alsa/alsa-mixer.c:4087 +#: ../src/modules/alsa/alsa-mixer.c:4086 msgid "Digital Stereo (IEC958)" msgstr "Digitalni stereo (IEC958)" -#: ../src/modules/alsa/alsa-mixer.c:4088 +#: ../src/modules/alsa/alsa-mixer.c:4087 msgid "Digital Passthrough (IEC958)" msgstr "Digitalni prolaz (IEC958)" -#: ../src/modules/alsa/alsa-mixer.c:4089 +#: ../src/modules/alsa/alsa-mixer.c:4088 msgid "Digital Surround 4.0 (IEC958/AC3)" msgstr "Digitalni surround 4.0 (IEC958/AC3)" -#: ../src/modules/alsa/alsa-mixer.c:4090 +#: ../src/modules/alsa/alsa-mixer.c:4089 msgid "Digital Surround 5.1 (IEC958/AC3)" msgstr "Digitalni surround 5.1 (IEC958/AC3)" -#: ../src/modules/alsa/alsa-mixer.c:4091 +#: ../src/modules/alsa/alsa-mixer.c:4090 msgid "Digital Surround 5.1 (IEC958/DTS)" msgstr "Digitalni surround 5.1 (IEC958/DTS)" -#: ../src/modules/alsa/alsa-mixer.c:4092 +#: ../src/modules/alsa/alsa-mixer.c:4091 msgid "Digital Stereo (HDMI)" msgstr "Digitalni stereo (HDMI)" -#: ../src/modules/alsa/alsa-mixer.c:4093 +#: ../src/modules/alsa/alsa-mixer.c:4092 msgid "Digital Surround 5.1 (HDMI)" msgstr "Digitalni surround 5.1 (HDMI)" -#: ../src/modules/alsa/alsa-mixer.c:4226 +#: ../src/modules/alsa/alsa-mixer.c:4225 msgid "Analog Mono Duplex" msgstr "Analogni mono obostrani" -#: ../src/modules/alsa/alsa-mixer.c:4227 +#: ../src/modules/alsa/alsa-mixer.c:4226 msgid "Analog Stereo Duplex" msgstr "Analogni stereo obostrani" -#: ../src/modules/alsa/alsa-mixer.c:4228 +#: ../src/modules/alsa/alsa-mixer.c:4227 msgid "Digital Stereo Duplex (IEC958)" msgstr "Digitalni stereo obostrani (IEC958)" -#: ../src/modules/alsa/alsa-mixer.c:4229 +#: ../src/modules/alsa/alsa-mixer.c:4228 msgid "Multichannel Duplex" msgstr "Višekanalni obostrani" -#: ../src/modules/alsa/alsa-mixer.c:4230 +#: ../src/modules/alsa/alsa-mixer.c:4229 msgid "Stereo Duplex" msgstr "Stereo obostrani" -#: ../src/modules/alsa/alsa-mixer.c:4231 +#: ../src/modules/alsa/alsa-mixer.c:4230 #: ../src/modules/alsa/module-alsa-card.c:189 -#: ../src/modules/bluetooth/module-bluez5-device.c:1964 +#: ../src/modules/bluetooth/module-bluez5-device.c:2012 msgid "Off" msgstr "Isključeno" -#: ../src/modules/alsa/alsa-mixer.c:4330 +#: ../src/modules/alsa/alsa-mixer.c:4329 #, c-format msgid "%s Output" msgstr "%s izlaz" -#: ../src/modules/alsa/alsa-mixer.c:4338 +#: ../src/modules/alsa/alsa-mixer.c:4337 #, c-format msgid "%s Input" msgstr "%s ulaz" @@ -1002,60 +1002,60 @@ msgstr[2] "" "Najvjerojatnije je ovo greška ALSA upravljačkog programa '%s'. Prijavite " "problem ALSA razvijateljima." -#: ../src/modules/bluetooth/module-bluez5-device.c:1693 -#: ../src/modules/bluetooth/module-bluez5-device.c:1715 -#: ../src/modules/bluetooth/module-bluez5-device.c:1721 -#: ../src/modules/bluetooth/module-bluez5-device.c:1747 +#: ../src/modules/bluetooth/module-bluez5-device.c:1741 +#: ../src/modules/bluetooth/module-bluez5-device.c:1763 +#: ../src/modules/bluetooth/module-bluez5-device.c:1769 +#: ../src/modules/bluetooth/module-bluez5-device.c:1795 msgid "Bluetooth Input" msgstr "Bluetooth ulaz" -#: ../src/modules/bluetooth/module-bluez5-device.c:1694 -#: ../src/modules/bluetooth/module-bluez5-device.c:1710 -#: ../src/modules/bluetooth/module-bluez5-device.c:1748 +#: ../src/modules/bluetooth/module-bluez5-device.c:1742 +#: ../src/modules/bluetooth/module-bluez5-device.c:1758 +#: ../src/modules/bluetooth/module-bluez5-device.c:1796 msgid "Bluetooth Output" msgstr "Bluetooth izlaz" -#: ../src/modules/bluetooth/module-bluez5-device.c:1699 +#: ../src/modules/bluetooth/module-bluez5-device.c:1747 msgid "Headset" msgstr "Slušalice s mikrofonom" -#: ../src/modules/bluetooth/module-bluez5-device.c:1704 +#: ../src/modules/bluetooth/module-bluez5-device.c:1752 msgid "Handsfree" msgstr "Bez-ruku" -#: ../src/modules/bluetooth/module-bluez5-device.c:1722 +#: ../src/modules/bluetooth/module-bluez5-device.c:1770 msgid "Headphone" msgstr "Slušalice" -#: ../src/modules/bluetooth/module-bluez5-device.c:1727 +#: ../src/modules/bluetooth/module-bluez5-device.c:1775 msgid "Portable" msgstr "Prijenosnik" -#: ../src/modules/bluetooth/module-bluez5-device.c:1732 +#: ../src/modules/bluetooth/module-bluez5-device.c:1780 msgid "Car" msgstr "Automobil" -#: ../src/modules/bluetooth/module-bluez5-device.c:1737 +#: ../src/modules/bluetooth/module-bluez5-device.c:1785 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez5-device.c:1742 +#: ../src/modules/bluetooth/module-bluez5-device.c:1790 msgid "Phone" msgstr "Telefon" -#: ../src/modules/bluetooth/module-bluez5-device.c:1789 +#: ../src/modules/bluetooth/module-bluez5-device.c:1837 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Reprodukcija visoke autentičnosti (A2DP slivnik)" -#: ../src/modules/bluetooth/module-bluez5-device.c:1801 +#: ../src/modules/bluetooth/module-bluez5-device.c:1849 msgid "High Fidelity Capture (A2DP Source)" msgstr "Snimanje visoke autentičnosti (A2DP izvor)" -#: ../src/modules/bluetooth/module-bluez5-device.c:1813 +#: ../src/modules/bluetooth/module-bluez5-device.c:1861 msgid "Headset Head Unit (HSP/HFP)" msgstr "Jedinica slušalice s mikrofonom (HSP/HFP)" -#: ../src/modules/bluetooth/module-bluez5-device.c:1826 +#: ../src/modules/bluetooth/module-bluez5-device.c:1874 msgid "Headset Audio Gateway (HSP/HFP)" msgstr "Zvučni pristupnik slušalice s mikrofonom (HSP/HFP)" @@ -1221,7 +1221,7 @@ msgstr "" msgid "Unknown device model" msgstr "Nepoznat model uređaja" -#: ../src/modules/raop/raop-sink.c:507 +#: ../src/modules/raop/raop-sink.c:511 msgid "RAOP standard profile" msgstr "RAOP standardan profil" @@ -1457,29 +1457,29 @@ msgstr "Surround 5.1" msgid "Surround 7.1" msgstr "Surround 7.1" -#: ../src/pulse/client-conf-x11.c:53 ../src/utils/pax11publish.c:97 +#: ../src/pulse/client-conf-x11.c:61 ../src/utils/pax11publish.c:97 msgid "xcb_connect() failed" msgstr "xcb_connect() neuspjelo" -#: ../src/pulse/client-conf-x11.c:58 ../src/utils/pax11publish.c:102 +#: ../src/pulse/client-conf-x11.c:66 ../src/utils/pax11publish.c:102 msgid "xcb_connection_has_error() returned true" msgstr "xcb_connection_has_error() vratilo je 'true'" -#: ../src/pulse/client-conf-x11.c:94 +#: ../src/pulse/client-conf-x11.c:102 msgid "Failed to parse cookie data" msgstr "Neuspjela obrada podataka kolačića" -#: ../src/pulse/context.c:705 +#: ../src/pulse/context.c:706 #, c-format msgid "fork(): %s" msgstr "fork(): %s" -#: ../src/pulse/context.c:760 +#: ../src/pulse/context.c:761 #, c-format msgid "waitpid(): %s" msgstr "waitpid(): %s" -#: ../src/pulse/context.c:1466 +#: ../src/pulse/context.c:1467 #, c-format msgid "Received message for unknown extension '%s'" msgstr "Primljena poruka za nepoznato proširenje '%s'" @@ -3125,7 +3125,9 @@ msgstr "WARNING: podređeni proces je završen sa signalom %u\n" #: ../src/utils/pasuspender.c:228 #, c-format msgid "" -"%s [options] ... \n" +"%s [options] -- PROGRAM [ARGUMENTS ...]\n" +"\n" +"Temporarily suspend PulseAudio while PROGRAM runs.\n" "\n" " -h, --help Show this help\n" " --version Show version\n" @@ -3133,14 +3135,16 @@ msgid "" "to\n" "\n" msgstr "" -"%s [mogućnosti] ... \n" +"%s [mogućnosti] -- PROGRAM [ARGUMENTI ...]\n" +"\n" +"Privremeno suspendira PulseAudio dok je PROGRAM pokrenut.\n" "\n" " -h, --help Prikazuje ovu pomoć\n" " --version Prikazuje inačicu\n" " -s, --server=SERVER Naziv poslužitelja za povezivanje\n" "\n" -#: ../src/utils/pasuspender.c:266 +#: ../src/utils/pasuspender.c:267 #, c-format msgid "" "pasuspender %s\n" @@ -3151,17 +3155,17 @@ msgstr "" "Kompilirano s libpulse %s\n" "Povezano s libpulse %s\n" -#: ../src/utils/pasuspender.c:295 +#: ../src/utils/pasuspender.c:296 #, c-format msgid "pa_mainloop_new() failed.\n" msgstr "pa_mainloop_new() neuspjelo.\n" -#: ../src/utils/pasuspender.c:308 +#: ../src/utils/pasuspender.c:309 #, c-format msgid "pa_context_new() failed.\n" msgstr "pa_context_new() neuspjelo.\n" -#: ../src/utils/pasuspender.c:320 +#: ../src/utils/pasuspender.c:321 #, c-format msgid "pa_mainloop_run() failed.\n" msgstr "pa_mainloop_run() neuspjelo.\n" Binary files differBinary files differBinary files differ@@ -11,8 +11,8 @@ msgstr "" "Project-Id-Version: pulseaudio\n" "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/" "issues\n" -"POT-Creation-Date: 2019-02-16 11:57+0000\n" -"PO-Revision-Date: 2019-08-07 09:53+0200\n" +"POT-Creation-Date: 2019-09-17 03:33+0000\n" +"PO-Revision-Date: 2019-09-19 09:56+0200\n" "Last-Translator: Milo Casagrande <milo@milo.name>\n" "Language-Team: Italian <tp@lists.linux.it>\n" "Language: it\n" @@ -582,11 +582,20 @@ msgstr "pa_pid_file_create() non riuscita." msgid "pa_core_new() failed." msgstr "pa_core_new() non riuscita." -#: src/daemon/main.c:1109 -msgid "Failed to initialize daemon." -msgstr "Inizializzazione del demone non riuscita." +#: src/daemon/main.c:1108 +msgid "command line arguments" +msgstr "argomenti della riga di comando" -#: src/daemon/main.c:1114 +#: src/daemon/main.c:1115 +#, c-format +msgid "" +"Failed to initialize daemon due to errors while executing startup commands. " +"Source of commands: %s" +msgstr "" +"Inizializzazione del demone non riuscita a causa di errori nell'eseguire i " +"comandi di avvio. Origine dei comandi: %s" + +#: src/daemon/main.c:1120 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "Avvio del demone senza alcun modulo caricato, rifiuta di lavorare." @@ -619,7 +628,7 @@ msgid "Line In" msgstr "Line-In" #: src/modules/alsa/alsa-mixer.c:2448 src/modules/alsa/alsa-mixer.c:2526 -#: src/modules/bluetooth/module-bluez5-device.c:1909 +#: src/modules/bluetooth/module-bluez5-device.c:1757 msgid "Microphone" msgstr "Microfono" @@ -680,7 +689,7 @@ msgid "No Bass Boost" msgstr "Nessun incremento bassi" #: src/modules/alsa/alsa-mixer.c:2463 -#: src/modules/bluetooth/module-bluez5-device.c:1916 +#: src/modules/bluetooth/module-bluez5-device.c:1764 msgid "Speaker" msgstr "Altoparlante" @@ -875,8 +884,8 @@ msgstr "Duplex multi canale" msgid "Stereo Duplex" msgstr "Duplex stereo" -#: src/modules/alsa/alsa-mixer.c:4231 src/modules/alsa/module-alsa-card.c:187 -#: src/modules/bluetooth/module-bluez5-device.c:2164 +#: src/modules/alsa/alsa-mixer.c:4231 src/modules/alsa/module-alsa-card.c:189 +#: src/modules/bluetooth/module-bluez5-device.c:2012 msgid "Off" msgstr "Spento" @@ -890,7 +899,7 @@ msgstr "Uscita «%s»" msgid "%s Input" msgstr "Ingresso «%s»" -#: src/modules/alsa/alsa-sink.c:587 src/modules/alsa/alsa-sink.c:771 +#: src/modules/alsa/alsa-sink.c:651 src/modules/alsa/alsa-sink.c:841 #, c-format msgid "" "ALSA woke us up to write new data to the device, but there was actually " @@ -907,7 +916,7 @@ msgstr "" "Attivazione avvenuta con POLLOUT impostato; tuttavia, una successiva " "snd_pcm_avail() ha ritornato 0 o un altro valore < min_avail." -#: src/modules/alsa/alsa-source.c:543 src/modules/alsa/alsa-source.c:694 +#: src/modules/alsa/alsa-source.c:610 src/modules/alsa/alsa-source.c:776 #, c-format msgid "" "ALSA woke us up to read new data from the device, but there was actually " @@ -924,7 +933,7 @@ msgstr "" "Attivazione avvenuta con POLLIN impostato; tuttavia, una successiva " "snd_pcm_avail() ha ritornato 0 o un altro valore < min_avail." -#: src/modules/alsa/alsa-util.c:1168 src/modules/alsa/alsa-util.c:1262 +#: src/modules/alsa/alsa-util.c:1173 src/modules/alsa/alsa-util.c:1267 #, c-format msgid "" "snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu " @@ -945,7 +954,7 @@ msgstr[1] "" "Molto probabilmente si tratta di un bug nel driver ALSA «%s». Segnalare " "questo problema agli sviluppatori ALSA." -#: src/modules/alsa/alsa-util.c:1234 +#: src/modules/alsa/alsa-util.c:1239 #, c-format msgid "" "snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s" @@ -966,7 +975,7 @@ msgstr[1] "" "Molto probabilmente si tratta di un bug nel driver ALSA «%s». Segnalare " "questo problema agli sviluppatori ALSA." -#: src/modules/alsa/alsa-util.c:1281 +#: src/modules/alsa/alsa-util.c:1286 #, c-format msgid "" "snd_pcm_avail_delay() returned strange values: delay %lu is less than avail " @@ -979,7 +988,7 @@ msgstr "" "Molto probabilmente si tratta di un bug nel driver ALSA «%s». Segnalare " "questo problema agli sviluppatori ALSA." -#: src/modules/alsa/alsa-util.c:1324 +#: src/modules/alsa/alsa-util.c:1329 #, c-format msgid "" "snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte " @@ -1002,60 +1011,60 @@ msgstr[1] "" "Molto probabilmente si tratta di un bug nel driver ALSA «%s». Segnalare " "questo problema agli sviluppatori ALSA." -#: src/modules/bluetooth/module-bluez5-device.c:1893 -#: src/modules/bluetooth/module-bluez5-device.c:1915 -#: src/modules/bluetooth/module-bluez5-device.c:1921 -#: src/modules/bluetooth/module-bluez5-device.c:1947 +#: src/modules/bluetooth/module-bluez5-device.c:1741 +#: src/modules/bluetooth/module-bluez5-device.c:1763 +#: src/modules/bluetooth/module-bluez5-device.c:1769 +#: src/modules/bluetooth/module-bluez5-device.c:1795 msgid "Bluetooth Input" msgstr "Ingresso Bluetooth" -#: src/modules/bluetooth/module-bluez5-device.c:1894 -#: src/modules/bluetooth/module-bluez5-device.c:1910 -#: src/modules/bluetooth/module-bluez5-device.c:1948 +#: src/modules/bluetooth/module-bluez5-device.c:1742 +#: src/modules/bluetooth/module-bluez5-device.c:1758 +#: src/modules/bluetooth/module-bluez5-device.c:1796 msgid "Bluetooth Output" msgstr "Uscita Bluetooth" -#: src/modules/bluetooth/module-bluez5-device.c:1899 +#: src/modules/bluetooth/module-bluez5-device.c:1747 msgid "Headset" msgstr "Cuffie con microfono" -#: src/modules/bluetooth/module-bluez5-device.c:1904 +#: src/modules/bluetooth/module-bluez5-device.c:1752 msgid "Handsfree" msgstr "Sistema mani-libere" -#: src/modules/bluetooth/module-bluez5-device.c:1922 +#: src/modules/bluetooth/module-bluez5-device.c:1770 msgid "Headphone" msgstr "Cuffie" -#: src/modules/bluetooth/module-bluez5-device.c:1927 +#: src/modules/bluetooth/module-bluez5-device.c:1775 msgid "Portable" msgstr "Portabile" -#: src/modules/bluetooth/module-bluez5-device.c:1932 +#: src/modules/bluetooth/module-bluez5-device.c:1780 msgid "Car" msgstr "Automobile" -#: src/modules/bluetooth/module-bluez5-device.c:1937 +#: src/modules/bluetooth/module-bluez5-device.c:1785 msgid "HiFi" msgstr "HiFi" -#: src/modules/bluetooth/module-bluez5-device.c:1942 +#: src/modules/bluetooth/module-bluez5-device.c:1790 msgid "Phone" msgstr "Telefono" -#: src/modules/bluetooth/module-bluez5-device.c:1989 +#: src/modules/bluetooth/module-bluez5-device.c:1837 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Riproduzione ad alta fedeltà (sink A2DP)" -#: src/modules/bluetooth/module-bluez5-device.c:2001 +#: src/modules/bluetooth/module-bluez5-device.c:1849 msgid "High Fidelity Capture (A2DP Source)" msgstr "Registrazione ad alta fedeltà (sorgente A2DP)" -#: src/modules/bluetooth/module-bluez5-device.c:2013 +#: src/modules/bluetooth/module-bluez5-device.c:1861 msgid "Headset Head Unit (HSP/HFP)" msgstr "Unità headset head (HSP/HFP)" -#: src/modules/bluetooth/module-bluez5-device.c:2026 +#: src/modules/bluetooth/module-bluez5-device.c:1874 msgid "Headset Audio Gateway (HSP/HFP)" msgstr "Gateway headset audio (HSP/HFP)" @@ -1158,11 +1167,11 @@ msgstr "" msgid "Clocked NULL sink" msgstr "Sink NULL temporizzato" -#: src/modules/module-null-sink.c:322 +#: src/modules/module-null-sink.c:333 msgid "Null Output" msgstr "Uscita nulla" -#: src/modules/module-null-sink.c:334 src/utils/pactl.c:1058 +#: src/modules/module-null-sink.c:345 src/utils/pactl.c:1058 #, c-format msgid "Failed to set format: invalid format string %s" msgstr "Impostazione del formato non riuscita: stringa %s non valida" @@ -1222,7 +1231,7 @@ msgstr "" msgid "Unknown device model" msgstr "Modello dispositivo sconosciuto" -#: src/modules/raop/raop-sink.c:507 +#: src/modules/raop/raop-sink.c:511 msgid "RAOP standard profile" msgstr "Profilo standard RAOP" @@ -1458,15 +1467,15 @@ msgstr "Surround 5.1" msgid "Surround 7.1" msgstr "Surround 7.1" -#: src/pulse/client-conf-x11.c:53 src/utils/pax11publish.c:97 +#: src/pulse/client-conf-x11.c:61 src/utils/pax11publish.c:97 msgid "xcb_connect() failed" msgstr "xcb_connect() non riuscita" -#: src/pulse/client-conf-x11.c:58 src/utils/pax11publish.c:102 +#: src/pulse/client-conf-x11.c:66 src/utils/pax11publish.c:102 msgid "xcb_connection_has_error() returned true" msgstr "xcb_connection_has_error() ha restituito VERO" -#: src/pulse/client-conf-x11.c:94 +#: src/pulse/client-conf-x11.c:102 msgid "Failed to parse cookie data" msgstr "Analisi dei dati cookie non riuscita" @@ -1542,11 +1551,11 @@ msgstr "" msgid "Invalid log target." msgstr "Destinazione di registrazione non valida." -#: src/pulsecore/sink.c:3507 +#: src/pulsecore/sink.c:3516 msgid "Built-in Audio" msgstr "Audio interno" -#: src/pulsecore/sink.c:3512 +#: src/pulsecore/sink.c:3521 msgid "Modem" msgstr "Modem" @@ -3155,7 +3164,9 @@ msgstr "ATTENZIONE: processo figlio terminato dal segnale %u\n" #: src/utils/pasuspender.c:228 #, c-format msgid "" -"%s [options] ... \n" +"%s [options] -- PROGRAM [ARGUMENTS ...]\n" +"\n" +"Temporarily suspend PulseAudio while PROGRAM runs.\n" "\n" " -h, --help Show this help\n" " --version Show version\n" @@ -3163,7 +3174,9 @@ msgid "" "to\n" "\n" msgstr "" -"%s [OPZIONI] ... \n" +"%s [OPZIONI] -- PROGRAMMA [ARGOMENTI ...] \n" +"\n" +"Sospende temporaneamente PulseAudio mentre PROGRAMMA è in esecuzione.\n" "\n" " -h, --help Mostra questo aiuto\n" " --version Mostra la versione\n" @@ -3171,7 +3184,7 @@ msgstr "" "connettersi\n" "\n" -#: src/utils/pasuspender.c:266 +#: src/utils/pasuspender.c:267 #, c-format msgid "" "pasuspender %s\n" @@ -3182,17 +3195,17 @@ msgstr "" "Compilato con libpulse %s\n" "Link eseguito con libpulse %s\n" -#: src/utils/pasuspender.c:295 +#: src/utils/pasuspender.c:296 #, c-format msgid "pa_mainloop_new() failed.\n" msgstr "pa_mainloop_new() non riuscita.\n" -#: src/utils/pasuspender.c:308 +#: src/utils/pasuspender.c:309 #, c-format msgid "pa_context_new() failed.\n" msgstr "pa_context_new() non riuscita.\n" -#: src/utils/pasuspender.c:320 +#: src/utils/pasuspender.c:321 #, c-format msgid "pa_mainloop_run() failed.\n" msgstr "pa_mainloop_run() non riuscita.\n" Binary files differBinary files differBinary files differBinary files differBinary files differBinary files differBinary files differBinary files differBinary files differBinary files differdiff --git a/po/pulseaudio.pot b/po/pulseaudio.pot index 94633a8..a9f83a2 100644 --- a/po/pulseaudio.pot +++ b/po/pulseaudio.pot @@ -6,10 +6,10 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: pulseaudio 13.0\n" +"Project-Id-Version: pulseaudio 12.0-107-g8fdd8\n" "Report-Msgid-Bugs-To: pulseaudio-discuss (at) lists (dot) freedesktop (dot) " "org\n" -"POT-Creation-Date: 2019-09-13 16:22+0300\n" +"POT-Creation-Date: 2018-08-23 07:45+0530\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,7 +17,6 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #: src/daemon/cmdline.c:113 #, c-format @@ -50,7 +49,8 @@ msgid "" " (only available as root, when SUID " "or\n" " with elevated RLIMIT_RTPRIO)\n" -" --disallow-module-loading[=BOOL] Disallow 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 " @@ -127,7 +127,7 @@ msgstr "" #: src/daemon/cmdline.c:328 msgid "" -"Invalid log target: use either 'syslog', 'journal', 'stderr' or 'auto' or a " +"Invalid log target: use either 'syslog', 'journal','stderr' or 'auto' or a " "valid file name 'file:<path>', 'newfile:<path>'." msgstr "" @@ -166,78 +166,78 @@ msgstr "" msgid "--enable-memfd expects boolean argument" msgstr "" -#: src/daemon/daemon-conf.c:268 +#: src/daemon/daemon-conf.c:266 #, c-format msgid "[%s:%u] Invalid log target '%s'." msgstr "" -#: src/daemon/daemon-conf.c:283 +#: src/daemon/daemon-conf.c:281 #, c-format msgid "[%s:%u] Invalid log level '%s'." msgstr "" -#: src/daemon/daemon-conf.c:298 +#: src/daemon/daemon-conf.c:296 #, c-format msgid "[%s:%u] Invalid resample method '%s'." msgstr "" -#: src/daemon/daemon-conf.c:320 +#: src/daemon/daemon-conf.c:318 #, c-format msgid "[%s:%u] Invalid rlimit '%s'." msgstr "" -#: src/daemon/daemon-conf.c:340 +#: src/daemon/daemon-conf.c:338 #, c-format msgid "[%s:%u] Invalid sample format '%s'." msgstr "" -#: src/daemon/daemon-conf.c:357 src/daemon/daemon-conf.c:374 +#: src/daemon/daemon-conf.c:355 src/daemon/daemon-conf.c:372 #, c-format msgid "[%s:%u] Invalid sample rate '%s'." msgstr "" -#: src/daemon/daemon-conf.c:397 +#: src/daemon/daemon-conf.c:395 #, c-format msgid "[%s:%u] Invalid sample channels '%s'." msgstr "" -#: src/daemon/daemon-conf.c:414 +#: src/daemon/daemon-conf.c:412 #, c-format msgid "[%s:%u] Invalid channel map '%s'." msgstr "" -#: src/daemon/daemon-conf.c:431 +#: src/daemon/daemon-conf.c:429 #, c-format msgid "[%s:%u] Invalid number of fragments '%s'." msgstr "" -#: src/daemon/daemon-conf.c:448 +#: src/daemon/daemon-conf.c:446 #, c-format msgid "[%s:%u] Invalid fragment size '%s'." msgstr "" -#: src/daemon/daemon-conf.c:465 +#: src/daemon/daemon-conf.c:463 #, c-format msgid "[%s:%u] Invalid nice level '%s'." msgstr "" -#: src/daemon/daemon-conf.c:508 +#: src/daemon/daemon-conf.c:506 #, c-format msgid "[%s:%u] Invalid server type '%s'." msgstr "" -#: src/daemon/daemon-conf.c:626 +#: src/daemon/daemon-conf.c:624 #, c-format msgid "Failed to open configuration file: %s" msgstr "" -#: src/daemon/daemon-conf.c:642 +#: src/daemon/daemon-conf.c:640 msgid "" "The specified default channel map has a different number of channels than " "the specified default number of channels." msgstr "" -#: src/daemon/daemon-conf.c:729 +#: src/daemon/daemon-conf.c:727 #, c-format msgid "### Read from configuration file: %s ###\n" msgstr "" @@ -432,11 +432,11 @@ msgstr "" msgid "setsid() failed: %s" msgstr "" -#: src/daemon/main.c:965 +#: src/daemon/main.c:959 msgid "Failed to get machine ID" msgstr "" -#: src/daemon/main.c:991 +#: src/daemon/main.c:985 msgid "" "OK, so you are running PA in system mode. Please make sure that you actually " "do want to do that.\n" @@ -445,26 +445,19 @@ msgid "" "mode is usually a bad idea." msgstr "" -#: src/daemon/main.c:1007 +#: src/daemon/main.c:1001 msgid "pa_pid_file_create() failed." msgstr "" -#: src/daemon/main.c:1039 +#: src/daemon/main.c:1033 msgid "pa_core_new() failed." msgstr "" -#: src/daemon/main.c:1108 -msgid "command line arguments" -msgstr "" - -#: src/daemon/main.c:1115 -#, c-format -msgid "" -"Failed to initialize daemon due to errors while executing startup commands. " -"Source of commands: %s" +#: src/daemon/main.c:1103 +msgid "Failed to initialize daemon." msgstr "" -#: src/daemon/main.c:1120 +#: src/daemon/main.c:1108 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "" @@ -497,7 +490,7 @@ msgid "Line In" msgstr "" #: src/modules/alsa/alsa-mixer.c:2448 src/modules/alsa/alsa-mixer.c:2526 -#: src/modules/bluetooth/module-bluez5-device.c:1757 +#: src/modules/bluetooth/module-bluez5-device.c:1904 msgid "Microphone" msgstr "" @@ -558,7 +551,7 @@ msgid "No Bass Boost" msgstr "" #: src/modules/alsa/alsa-mixer.c:2463 -#: src/modules/bluetooth/module-bluez5-device.c:1764 +#: src/modules/bluetooth/module-bluez5-device.c:1911 msgid "Speaker" msgstr "" @@ -634,136 +627,136 @@ msgstr "" msgid "Chat Output" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4063 +#: src/modules/alsa/alsa-mixer.c:4061 msgid "Analog Mono" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4064 src/modules/alsa/alsa-mixer.c:4072 -#: src/modules/alsa/alsa-mixer.c:4073 +#: src/modules/alsa/alsa-mixer.c:4062 src/modules/alsa/alsa-mixer.c:4070 +#: src/modules/alsa/alsa-mixer.c:4071 msgid "Analog Stereo" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4065 src/pulse/channelmap.c:103 +#: src/modules/alsa/alsa-mixer.c:4063 src/pulse/channelmap.c:103 #: src/pulse/channelmap.c:771 msgid "Mono" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4066 src/pulse/channelmap.c:775 +#: src/modules/alsa/alsa-mixer.c:4064 src/pulse/channelmap.c:775 msgid "Stereo" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4074 src/modules/alsa/alsa-mixer.c:4075 +#: src/modules/alsa/alsa-mixer.c:4072 src/modules/alsa/alsa-mixer.c:4073 msgid "Multichannel" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4076 +#: src/modules/alsa/alsa-mixer.c:4074 msgid "Analog Surround 2.1" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4077 +#: src/modules/alsa/alsa-mixer.c:4075 msgid "Analog Surround 3.0" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4078 +#: src/modules/alsa/alsa-mixer.c:4076 msgid "Analog Surround 3.1" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4079 +#: src/modules/alsa/alsa-mixer.c:4077 msgid "Analog Surround 4.0" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4080 +#: src/modules/alsa/alsa-mixer.c:4078 msgid "Analog Surround 4.1" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4081 +#: src/modules/alsa/alsa-mixer.c:4079 msgid "Analog Surround 5.0" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4082 +#: src/modules/alsa/alsa-mixer.c:4080 msgid "Analog Surround 5.1" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4083 +#: src/modules/alsa/alsa-mixer.c:4081 msgid "Analog Surround 6.0" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4084 +#: src/modules/alsa/alsa-mixer.c:4082 msgid "Analog Surround 6.1" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4085 +#: src/modules/alsa/alsa-mixer.c:4083 msgid "Analog Surround 7.0" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4086 +#: src/modules/alsa/alsa-mixer.c:4084 msgid "Analog Surround 7.1" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4087 +#: src/modules/alsa/alsa-mixer.c:4085 msgid "Digital Stereo (IEC958)" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4088 -msgid "Digital Passthrough (IEC958)" +#: src/modules/alsa/alsa-mixer.c:4086 +msgid "Digital Passthrough (IEC958)" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4089 +#: src/modules/alsa/alsa-mixer.c:4087 msgid "Digital Surround 4.0 (IEC958/AC3)" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4090 +#: src/modules/alsa/alsa-mixer.c:4088 msgid "Digital Surround 5.1 (IEC958/AC3)" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4091 +#: src/modules/alsa/alsa-mixer.c:4089 msgid "Digital Surround 5.1 (IEC958/DTS)" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4092 +#: src/modules/alsa/alsa-mixer.c:4090 msgid "Digital Stereo (HDMI)" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4093 +#: src/modules/alsa/alsa-mixer.c:4091 msgid "Digital Surround 5.1 (HDMI)" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4226 +#: src/modules/alsa/alsa-mixer.c:4224 msgid "Analog Mono Duplex" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4227 +#: src/modules/alsa/alsa-mixer.c:4225 msgid "Analog Stereo Duplex" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4228 +#: src/modules/alsa/alsa-mixer.c:4226 msgid "Digital Stereo Duplex (IEC958)" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4229 +#: src/modules/alsa/alsa-mixer.c:4227 msgid "Multichannel Duplex" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4230 +#: src/modules/alsa/alsa-mixer.c:4228 msgid "Stereo Duplex" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4231 src/modules/alsa/module-alsa-card.c:189 -#: src/modules/bluetooth/module-bluez5-device.c:2012 +#: src/modules/alsa/alsa-mixer.c:4229 src/modules/alsa/module-alsa-card.c:187 +#: src/modules/bluetooth/module-bluez5-device.c:2159 msgid "Off" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4330 +#: src/modules/alsa/alsa-mixer.c:4328 #, c-format msgid "%s Output" msgstr "" -#: src/modules/alsa/alsa-mixer.c:4338 +#: src/modules/alsa/alsa-mixer.c:4336 #, c-format msgid "%s Input" msgstr "" -#: src/modules/alsa/alsa-sink.c:651 src/modules/alsa/alsa-sink.c:841 +#: src/modules/alsa/alsa-sink.c:578 #, c-format msgid "" "ALSA woke us up to write new data to the device, but there was actually " @@ -774,7 +767,18 @@ msgid "" "returned 0 or another value < min_avail." msgstr "" -#: src/modules/alsa/alsa-source.c:610 src/modules/alsa/alsa-source.c:776 +#: src/modules/alsa/alsa-sink.c:762 +#, c-format +msgid "" +"ALSA woke us up to write new data to the device, but there was actually " +"nothing to write!\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers.\n" +"We were woken up with POLLOUT set -- however a subsequent snd_pcm_avail() " +"returned 0 or another value < min_avail." +msgstr "" + +#: src/modules/alsa/alsa-source.c:535 #, c-format msgid "" "ALSA woke us up to read new data from the device, but there was actually " @@ -785,37 +789,36 @@ msgid "" "returned 0 or another value < min_avail." msgstr "" -#: src/modules/alsa/alsa-util.c:1173 src/modules/alsa/alsa-util.c:1267 +#: src/modules/alsa/alsa-source.c:686 #, c-format msgid "" -"snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu " -"ms).\n" +"ALSA woke us up to read new data from the device, but there was actually " +"nothing to read!\n" "Most likely this is a bug in the ALSA driver '%s'. Please report this issue " -"to the ALSA developers." -msgid_plural "" +"to the ALSA developers.\n" +"We were woken up with POLLIN set -- however a subsequent snd_pcm_avail() " +"returned 0 or another value < min_avail." +msgstr "" + +#: src/modules/alsa/alsa-util.c:1168 src/modules/alsa/alsa-util.c:1256 +#, c-format +msgid "" "snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu " "ms).\n" "Most likely this is a bug in the ALSA driver '%s'. Please report this issue " "to the ALSA developers." -msgstr[0] "" -msgstr[1] "" +msgstr "" -#: src/modules/alsa/alsa-util.c:1239 +#: src/modules/alsa/alsa-util.c:1231 #, c-format msgid "" -"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s" -"%lu ms).\n" -"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " -"to the ALSA developers." -msgid_plural "" "snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s" "%lu ms).\n" "Most likely this is a bug in the ALSA driver '%s'. Please report this issue " "to the ALSA developers." -msgstr[0] "" -msgstr[1] "" +msgstr "" -#: src/modules/alsa/alsa-util.c:1286 +#: src/modules/alsa/alsa-util.c:1272 #, c-format msgid "" "snd_pcm_avail_delay() returned strange values: delay %lu is less than avail " @@ -824,75 +827,69 @@ msgid "" "to the ALSA developers." msgstr "" -#: src/modules/alsa/alsa-util.c:1329 +#: src/modules/alsa/alsa-util.c:1315 #, c-format msgid "" -"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte " -"(%lu ms).\n" -"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " -"to the ALSA developers." -msgid_plural "" "snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes " "(%lu ms).\n" "Most likely this is a bug in the ALSA driver '%s'. Please report this issue " "to the ALSA developers." -msgstr[0] "" -msgstr[1] "" +msgstr "" -#: src/modules/bluetooth/module-bluez5-device.c:1741 -#: src/modules/bluetooth/module-bluez5-device.c:1763 -#: src/modules/bluetooth/module-bluez5-device.c:1769 -#: src/modules/bluetooth/module-bluez5-device.c:1795 +#: src/modules/bluetooth/module-bluez5-device.c:1888 +#: src/modules/bluetooth/module-bluez5-device.c:1910 +#: src/modules/bluetooth/module-bluez5-device.c:1916 +#: src/modules/bluetooth/module-bluez5-device.c:1942 msgid "Bluetooth Input" msgstr "" -#: src/modules/bluetooth/module-bluez5-device.c:1742 -#: src/modules/bluetooth/module-bluez5-device.c:1758 -#: src/modules/bluetooth/module-bluez5-device.c:1796 +#: src/modules/bluetooth/module-bluez5-device.c:1889 +#: src/modules/bluetooth/module-bluez5-device.c:1905 +#: src/modules/bluetooth/module-bluez5-device.c:1943 msgid "Bluetooth Output" msgstr "" -#: src/modules/bluetooth/module-bluez5-device.c:1747 +#: src/modules/bluetooth/module-bluez5-device.c:1894 msgid "Headset" msgstr "" -#: src/modules/bluetooth/module-bluez5-device.c:1752 +#: src/modules/bluetooth/module-bluez5-device.c:1899 msgid "Handsfree" msgstr "" -#: src/modules/bluetooth/module-bluez5-device.c:1770 +#: src/modules/bluetooth/module-bluez5-device.c:1917 msgid "Headphone" msgstr "" -#: src/modules/bluetooth/module-bluez5-device.c:1775 +#: src/modules/bluetooth/module-bluez5-device.c:1922 msgid "Portable" msgstr "" -#: src/modules/bluetooth/module-bluez5-device.c:1780 +#: src/modules/bluetooth/module-bluez5-device.c:1927 msgid "Car" msgstr "" -#: src/modules/bluetooth/module-bluez5-device.c:1785 +#: src/modules/bluetooth/module-bluez5-device.c:1932 msgid "HiFi" msgstr "" -#: src/modules/bluetooth/module-bluez5-device.c:1790 +#: src/modules/bluetooth/module-bluez5-device.c:1937 msgid "Phone" msgstr "" -#: src/modules/bluetooth/module-bluez5-device.c:1837 +#: src/modules/bluetooth/module-bluez5-device.c:1984 msgid "High Fidelity Playback (A2DP Sink)" msgstr "" -#: src/modules/bluetooth/module-bluez5-device.c:1849 +#: src/modules/bluetooth/module-bluez5-device.c:1996 msgid "High Fidelity Capture (A2DP Source)" msgstr "" -#: src/modules/bluetooth/module-bluez5-device.c:1861 +#: src/modules/bluetooth/module-bluez5-device.c:2008 msgid "Headset Head Unit (HSP/HFP)" msgstr "" -#: src/modules/bluetooth/module-bluez5-device.c:1874 +#: src/modules/bluetooth/module-bluez5-device.c:2021 msgid "Headset Audio Gateway (HSP/HFP)" msgstr "" @@ -970,15 +967,10 @@ msgstr "" msgid "Clocked NULL sink" msgstr "" -#: src/modules/module-null-sink.c:333 +#: src/modules/module-null-sink.c:292 msgid "Null Output" msgstr "" -#: src/modules/module-null-sink.c:345 src/utils/pactl.c:1058 -#, c-format -msgid "Failed to set format: invalid format string %s" -msgstr "" - #: src/modules/module-rygel-media-server.c:506 #: src/modules/module-rygel-media-server.c:544 #: src/modules/module-rygel-media-server.c:903 @@ -1025,7 +1017,7 @@ msgstr "" msgid "Unknown device model" msgstr "" -#: src/modules/raop/raop-sink.c:511 +#: src/modules/raop/raop-sink.c:507 msgid "RAOP standard profile" msgstr "" @@ -1259,15 +1251,15 @@ msgstr "" msgid "Surround 7.1" msgstr "" -#: src/pulse/client-conf-x11.c:61 src/utils/pax11publish.c:97 +#: src/pulse/client-conf-x11.c:53 src/utils/pax11publish.c:97 msgid "xcb_connect() failed" msgstr "" -#: src/pulse/client-conf-x11.c:66 src/utils/pax11publish.c:102 +#: src/pulse/client-conf-x11.c:58 src/utils/pax11publish.c:102 msgid "xcb_connection_has_error() returned true" msgstr "" -#: src/pulse/client-conf-x11.c:102 +#: src/pulse/client-conf-x11.c:94 msgid "Failed to parse cookie data" msgstr "" @@ -1306,7 +1298,7 @@ msgstr "" #, c-format msgid "" "XDG_RUNTIME_DIR (%s) is not owned by us (uid %d), but by uid %d! (This could " -"e.g. happen if you try to connect to a non-root PulseAudio as a root user, " +"e g happen if you try to connect to a non-root PulseAudio as a root user, " "over the native protocol. Don't do that.)" msgstr "" @@ -1337,11 +1329,11 @@ msgstr "" msgid "Invalid log target." msgstr "" -#: src/pulsecore/sink.c:3516 +#: src/pulsecore/sink.c:3508 msgid "Built-in Audio" msgstr "" -#: src/pulsecore/sink.c:3521 +#: src/pulsecore/sink.c:3513 msgid "Modem" msgstr "" @@ -1616,7 +1608,7 @@ msgstr "" msgid "pa_stream_connect_record() failed: %s" msgstr "" -#: src/utils/pacat.c:514 src/utils/pactl.c:1454 +#: src/utils/pacat.c:514 src/utils/pactl.c:1446 #, c-format msgid "Connection failure: %s" msgstr "" @@ -1751,7 +1743,7 @@ msgid "" "Linked with libpulse %s\n" msgstr "" -#: src/utils/pacat.c:852 src/utils/pactl.c:1656 +#: src/utils/pacat.c:852 src/utils/pactl.c:1648 #, c-format msgid "Invalid client name '%s'" msgstr "" @@ -1822,7 +1814,7 @@ msgid "" "specification from file." msgstr "" -#: src/utils/pacat.c:1079 src/utils/pactl.c:1720 +#: src/utils/pacat.c:1079 src/utils/pactl.c:1712 msgid "Failed to determine sample specification from file." msgstr "" @@ -1856,7 +1848,7 @@ msgstr "" msgid "Failed to set media name." msgstr "" -#: src/utils/pacat.c:1160 src/utils/pactl.c:2070 +#: src/utils/pacat.c:1160 src/utils/pactl.c:2062 msgid "pa_mainloop_new() failed." msgstr "" @@ -1864,11 +1856,11 @@ msgstr "" msgid "io_new() failed." msgstr "" -#: src/utils/pacat.c:1190 src/utils/pactl.c:2082 +#: src/utils/pacat.c:1190 src/utils/pactl.c:2074 msgid "pa_context_new() failed." msgstr "" -#: src/utils/pacat.c:1198 src/utils/pactl.c:2088 +#: src/utils/pacat.c:1198 src/utils/pactl.c:2080 #, c-format msgid "pa_context_connect() failed: %s" msgstr "" @@ -1877,20 +1869,20 @@ msgstr "" msgid "pa_context_rttime_new() failed." msgstr "" -#: src/utils/pacat.c:1211 src/utils/pactl.c:2093 +#: src/utils/pacat.c:1211 src/utils/pactl.c:2085 msgid "pa_mainloop_run() failed." msgstr "" -#: src/utils/pacmd.c:51 src/utils/pactl.c:1578 +#: src/utils/pacmd.c:51 src/utils/pactl.c:1570 msgid "NAME [ARGS ...]" msgstr "" -#: src/utils/pacmd.c:52 src/utils/pacmd.c:60 src/utils/pactl.c:1579 +#: src/utils/pacmd.c:52 src/utils/pacmd.c:60 src/utils/pactl.c:1571 msgid "NAME|#N" msgstr "" -#: src/utils/pacmd.c:53 src/utils/pacmd.c:63 src/utils/pactl.c:1577 -#: src/utils/pactl.c:1583 +#: src/utils/pacmd.c:53 src/utils/pacmd.c:63 src/utils/pactl.c:1569 +#: src/utils/pactl.c:1575 msgid "NAME" msgstr "" @@ -1902,7 +1894,7 @@ msgstr "" msgid "#N VOLUME" msgstr "" -#: src/utils/pacmd.c:56 src/utils/pacmd.c:70 src/utils/pactl.c:1581 +#: src/utils/pacmd.c:56 src/utils/pacmd.c:70 src/utils/pactl.c:1573 msgid "NAME|#N 1|0" msgstr "" @@ -1938,7 +1930,7 @@ msgstr "" msgid "FILENAME SINK|#N" msgstr "" -#: src/utils/pacmd.c:69 src/utils/pactl.c:1580 +#: src/utils/pacmd.c:69 src/utils/pactl.c:1572 msgid "#N SINK|SOURCE" msgstr "" @@ -1946,15 +1938,15 @@ msgstr "" msgid "1|0" msgstr "" -#: src/utils/pacmd.c:72 src/utils/pactl.c:1582 +#: src/utils/pacmd.c:72 src/utils/pactl.c:1574 msgid "CARD PROFILE" msgstr "" -#: src/utils/pacmd.c:73 src/utils/pactl.c:1584 +#: src/utils/pacmd.c:73 src/utils/pactl.c:1576 msgid "NAME|#N PORT" msgstr "" -#: src/utils/pacmd.c:74 src/utils/pactl.c:1590 +#: src/utils/pacmd.c:74 src/utils/pactl.c:1582 msgid "CARD-NAME|CARD-#N PORT OFFSET" msgstr "" @@ -2031,30 +2023,25 @@ msgstr "" #: src/utils/pactl.c:170 #, c-format -msgid "Currently in use: %u block containing %s bytes total.\n" -msgid_plural "Currently in use: %u blocks containing %s bytes total.\n" -msgstr[0] "" -msgstr[1] "" +msgid "Currently in use: %u blocks containing %s bytes total.\n" +msgstr "" -#: src/utils/pactl.c:176 +#: src/utils/pactl.c:173 #, c-format -msgid "Allocated during whole lifetime: %u block containing %s bytes total.\n" -msgid_plural "" -"Allocated during whole lifetime: %u blocks containing %s bytes total.\n" -msgstr[0] "" -msgstr[1] "" +msgid "Allocated during whole lifetime: %u blocks containing %s bytes total.\n" +msgstr "" -#: src/utils/pactl.c:182 +#: src/utils/pactl.c:176 #, c-format msgid "Sample cache size: %s\n" msgstr "" -#: src/utils/pactl.c:191 +#: src/utils/pactl.c:185 #, c-format msgid "Failed to get server information: %s" msgstr "" -#: src/utils/pactl.c:196 +#: src/utils/pactl.c:190 #, c-format msgid "" "Server String: %s\n" @@ -2065,7 +2052,7 @@ msgid "" "Tile Size: %zu\n" msgstr "" -#: src/utils/pactl.c:212 +#: src/utils/pactl.c:206 #, c-format msgid "" "User Name: %s\n" @@ -2079,12 +2066,12 @@ msgid "" "Cookie: %04x:%04x\n" msgstr "" -#: src/utils/pactl.c:261 src/utils/pactl.c:908 src/utils/pactl.c:986 +#: src/utils/pactl.c:255 src/utils/pactl.c:900 src/utils/pactl.c:978 #, c-format msgid "Failed to get sink information: %s" msgstr "" -#: src/utils/pactl.c:287 +#: src/utils/pactl.c:281 #, c-format msgid "" "Sink #%u\n" @@ -2106,27 +2093,27 @@ msgid "" "\t\t%s\n" msgstr "" -#: src/utils/pactl.c:331 src/utils/pactl.c:437 src/utils/pactl.c:598 +#: src/utils/pactl.c:325 src/utils/pactl.c:431 src/utils/pactl.c:592 #, c-format msgid "\tPorts:\n" msgstr "" -#: src/utils/pactl.c:338 src/utils/pactl.c:444 +#: src/utils/pactl.c:332 src/utils/pactl.c:438 #, c-format msgid "\tActive Port: %s\n" msgstr "" -#: src/utils/pactl.c:344 src/utils/pactl.c:450 +#: src/utils/pactl.c:338 src/utils/pactl.c:444 #, c-format msgid "\tFormats:\n" msgstr "" -#: src/utils/pactl.c:368 src/utils/pactl.c:928 src/utils/pactl.c:1001 +#: src/utils/pactl.c:362 src/utils/pactl.c:920 src/utils/pactl.c:993 #, c-format msgid "Failed to get source information: %s" msgstr "" -#: src/utils/pactl.c:394 +#: src/utils/pactl.c:388 #, c-format msgid "" "Source #%u\n" @@ -2148,20 +2135,20 @@ msgid "" "\t\t%s\n" msgstr "" -#: src/utils/pactl.c:422 src/utils/pactl.c:492 src/utils/pactl.c:535 -#: src/utils/pactl.c:577 src/utils/pactl.c:675 src/utils/pactl.c:676 -#: src/utils/pactl.c:687 src/utils/pactl.c:745 src/utils/pactl.c:746 -#: src/utils/pactl.c:757 src/utils/pactl.c:808 src/utils/pactl.c:809 -#: src/utils/pactl.c:815 +#: src/utils/pactl.c:416 src/utils/pactl.c:486 src/utils/pactl.c:529 +#: src/utils/pactl.c:571 src/utils/pactl.c:669 src/utils/pactl.c:670 +#: src/utils/pactl.c:681 src/utils/pactl.c:739 src/utils/pactl.c:740 +#: src/utils/pactl.c:751 src/utils/pactl.c:802 src/utils/pactl.c:803 +#: src/utils/pactl.c:809 msgid "n/a" msgstr "" -#: src/utils/pactl.c:461 src/utils/pactl.c:865 +#: src/utils/pactl.c:455 src/utils/pactl.c:859 #, c-format msgid "Failed to get module information: %s" msgstr "" -#: src/utils/pactl.c:484 +#: src/utils/pactl.c:478 #, c-format msgid "" "Module #%u\n" @@ -2172,12 +2159,12 @@ msgid "" "\t\t%s\n" msgstr "" -#: src/utils/pactl.c:503 +#: src/utils/pactl.c:497 #, c-format msgid "Failed to get client information: %s" msgstr "" -#: src/utils/pactl.c:529 +#: src/utils/pactl.c:523 #, c-format msgid "" "Client #%u\n" @@ -2187,12 +2174,12 @@ msgid "" "\t\t%s\n" msgstr "" -#: src/utils/pactl.c:546 +#: src/utils/pactl.c:540 #, c-format msgid "Failed to get card information: %s" msgstr "" -#: src/utils/pactl.c:569 +#: src/utils/pactl.c:563 #, c-format msgid "" "Card #%u\n" @@ -2203,39 +2190,39 @@ msgid "" "\t\t%s\n" msgstr "" -#: src/utils/pactl.c:585 +#: src/utils/pactl.c:579 #, c-format msgid "\tProfiles:\n" msgstr "" -#: src/utils/pactl.c:587 +#: src/utils/pactl.c:581 #, c-format msgid "\t\t%s: %s (sinks: %u, sources: %u, priority: %u, available: %s)\n" msgstr "" -#: src/utils/pactl.c:592 +#: src/utils/pactl.c:586 #, c-format msgid "\tActive Profile: %s\n" msgstr "" -#: src/utils/pactl.c:606 +#: src/utils/pactl.c:600 #, c-format msgid "" "\t\t\tProperties:\n" "\t\t\t\t%s\n" msgstr "" -#: src/utils/pactl.c:611 +#: src/utils/pactl.c:605 #, c-format msgid "\t\t\tPart of profile(s): %s" msgstr "" -#: src/utils/pactl.c:628 src/utils/pactl.c:948 src/utils/pactl.c:1016 +#: src/utils/pactl.c:622 src/utils/pactl.c:940 src/utils/pactl.c:1008 #, c-format msgid "Failed to get sink input information: %s" msgstr "" -#: src/utils/pactl.c:657 +#: src/utils/pactl.c:651 #, c-format msgid "" "Sink Input #%u\n" @@ -2257,12 +2244,12 @@ msgid "" "\t\t%s\n" msgstr "" -#: src/utils/pactl.c:698 src/utils/pactl.c:968 src/utils/pactl.c:1031 +#: src/utils/pactl.c:692 src/utils/pactl.c:960 src/utils/pactl.c:1023 #, c-format msgid "Failed to get source output information: %s" msgstr "" -#: src/utils/pactl.c:727 +#: src/utils/pactl.c:721 #, c-format msgid "" "Source Output #%u\n" @@ -2284,12 +2271,12 @@ msgid "" "\t\t%s\n" msgstr "" -#: src/utils/pactl.c:768 +#: src/utils/pactl.c:762 #, c-format msgid "Failed to get sample information: %s" msgstr "" -#: src/utils/pactl.c:795 +#: src/utils/pactl.c:789 #, c-format msgid "" "Sample #%u\n" @@ -2306,156 +2293,157 @@ msgid "" "\t\t%s\n" msgstr "" -#: src/utils/pactl.c:823 src/utils/pactl.c:833 +#: src/utils/pactl.c:817 src/utils/pactl.c:827 #, c-format msgid "Failure: %s" msgstr "" -#: src/utils/pactl.c:872 +#: src/utils/pactl.c:866 #, c-format msgid "Failed to unload module: Module %s not loaded" msgstr "" -#: src/utils/pactl.c:890 +#: src/utils/pactl.c:884 #, c-format msgid "" -"Failed to set volume: You tried to set volumes for %d channel, whereas " -"channel(s) supported = %d\n" -msgid_plural "" "Failed to set volume: You tried to set volumes for %d channels, whereas " -"channel(s) supported = %d\n" -msgstr[0] "" -msgstr[1] "" +"channel/s supported = %d\n" +msgstr "" -#: src/utils/pactl.c:1101 +#: src/utils/pactl.c:1050 +#, c-format +msgid "Failed to set format: invalid format string %s" +msgstr "" + +#: src/utils/pactl.c:1093 #, c-format msgid "Failed to upload sample: %s" msgstr "" -#: src/utils/pactl.c:1118 +#: src/utils/pactl.c:1110 msgid "Premature end of file" msgstr "" -#: src/utils/pactl.c:1138 +#: src/utils/pactl.c:1130 msgid "new" msgstr "" -#: src/utils/pactl.c:1141 +#: src/utils/pactl.c:1133 msgid "change" msgstr "" -#: src/utils/pactl.c:1144 +#: src/utils/pactl.c:1136 msgid "remove" msgstr "" -#: src/utils/pactl.c:1147 src/utils/pactl.c:1182 +#: src/utils/pactl.c:1139 src/utils/pactl.c:1174 msgid "unknown" msgstr "" -#: src/utils/pactl.c:1155 +#: src/utils/pactl.c:1147 msgid "sink" msgstr "" -#: src/utils/pactl.c:1158 +#: src/utils/pactl.c:1150 msgid "source" msgstr "" -#: src/utils/pactl.c:1161 +#: src/utils/pactl.c:1153 msgid "sink-input" msgstr "" -#: src/utils/pactl.c:1164 +#: src/utils/pactl.c:1156 msgid "source-output" msgstr "" -#: src/utils/pactl.c:1167 +#: src/utils/pactl.c:1159 msgid "module" msgstr "" -#: src/utils/pactl.c:1170 +#: src/utils/pactl.c:1162 msgid "client" msgstr "" -#: src/utils/pactl.c:1173 +#: src/utils/pactl.c:1165 msgid "sample-cache" msgstr "" -#: src/utils/pactl.c:1176 +#: src/utils/pactl.c:1168 msgid "server" msgstr "" -#: src/utils/pactl.c:1179 +#: src/utils/pactl.c:1171 msgid "card" msgstr "" -#: src/utils/pactl.c:1188 +#: src/utils/pactl.c:1180 #, c-format msgid "Event '%s' on %s #%u\n" msgstr "" -#: src/utils/pactl.c:1460 +#: src/utils/pactl.c:1452 msgid "Got SIGINT, exiting." msgstr "" -#: src/utils/pactl.c:1493 +#: src/utils/pactl.c:1485 msgid "Invalid volume specification" msgstr "" -#: src/utils/pactl.c:1516 +#: src/utils/pactl.c:1508 msgid "Volume outside permissible range.\n" msgstr "" -#: src/utils/pactl.c:1529 +#: src/utils/pactl.c:1521 msgid "Invalid number of volume specifications.\n" msgstr "" -#: src/utils/pactl.c:1541 +#: src/utils/pactl.c:1533 msgid "Inconsistent volume specification.\n" msgstr "" -#: src/utils/pactl.c:1571 src/utils/pactl.c:1572 src/utils/pactl.c:1573 -#: src/utils/pactl.c:1574 src/utils/pactl.c:1575 src/utils/pactl.c:1576 -#: src/utils/pactl.c:1577 src/utils/pactl.c:1578 src/utils/pactl.c:1579 -#: src/utils/pactl.c:1580 src/utils/pactl.c:1581 src/utils/pactl.c:1582 -#: src/utils/pactl.c:1583 src/utils/pactl.c:1584 src/utils/pactl.c:1585 -#: src/utils/pactl.c:1586 src/utils/pactl.c:1587 src/utils/pactl.c:1588 -#: src/utils/pactl.c:1589 src/utils/pactl.c:1590 src/utils/pactl.c:1591 +#: src/utils/pactl.c:1563 src/utils/pactl.c:1564 src/utils/pactl.c:1565 +#: src/utils/pactl.c:1566 src/utils/pactl.c:1567 src/utils/pactl.c:1568 +#: src/utils/pactl.c:1569 src/utils/pactl.c:1570 src/utils/pactl.c:1571 +#: src/utils/pactl.c:1572 src/utils/pactl.c:1573 src/utils/pactl.c:1574 +#: src/utils/pactl.c:1575 src/utils/pactl.c:1576 src/utils/pactl.c:1577 +#: src/utils/pactl.c:1578 src/utils/pactl.c:1579 src/utils/pactl.c:1580 +#: src/utils/pactl.c:1581 src/utils/pactl.c:1582 src/utils/pactl.c:1583 msgid "[options]" msgstr "" -#: src/utils/pactl.c:1573 +#: src/utils/pactl.c:1565 msgid "[TYPE]" msgstr "" -#: src/utils/pactl.c:1575 +#: src/utils/pactl.c:1567 msgid "FILENAME [NAME]" msgstr "" -#: src/utils/pactl.c:1576 +#: src/utils/pactl.c:1568 msgid "NAME [SINK]" msgstr "" -#: src/utils/pactl.c:1585 +#: src/utils/pactl.c:1577 msgid "NAME|#N VOLUME [VOLUME ...]" msgstr "" -#: src/utils/pactl.c:1586 +#: src/utils/pactl.c:1578 msgid "#N VOLUME [VOLUME ...]" msgstr "" -#: src/utils/pactl.c:1587 +#: src/utils/pactl.c:1579 msgid "NAME|#N 1|0|toggle" msgstr "" -#: src/utils/pactl.c:1588 +#: src/utils/pactl.c:1580 msgid "#N 1|0|toggle" msgstr "" -#: src/utils/pactl.c:1589 +#: src/utils/pactl.c:1581 msgid "#N FORMATS" msgstr "" -#: src/utils/pactl.c:1592 +#: src/utils/pactl.c:1584 #, c-format msgid "" "\n" @@ -2463,7 +2451,7 @@ msgid "" "can be used to specify the default sink, source and monitor.\n" msgstr "" -#: src/utils/pactl.c:1595 +#: src/utils/pactl.c:1587 #, c-format msgid "" "\n" @@ -2476,7 +2464,7 @@ msgid "" "server\n" msgstr "" -#: src/utils/pactl.c:1636 +#: src/utils/pactl.c:1628 #, c-format msgid "" "pactl %s\n" @@ -2484,155 +2472,155 @@ msgid "" "Linked with libpulse %s\n" msgstr "" -#: src/utils/pactl.c:1692 +#: src/utils/pactl.c:1684 #, c-format msgid "Specify nothing, or one of: %s" msgstr "" -#: src/utils/pactl.c:1702 +#: src/utils/pactl.c:1694 msgid "Please specify a sample file to load" msgstr "" -#: src/utils/pactl.c:1715 +#: src/utils/pactl.c:1707 msgid "Failed to open sound file." msgstr "" -#: src/utils/pactl.c:1727 +#: src/utils/pactl.c:1719 msgid "Warning: Failed to determine sample specification from file." msgstr "" -#: src/utils/pactl.c:1737 +#: src/utils/pactl.c:1729 msgid "You have to specify a sample name to play" msgstr "" -#: src/utils/pactl.c:1749 +#: src/utils/pactl.c:1741 msgid "You have to specify a sample name to remove" msgstr "" -#: src/utils/pactl.c:1758 +#: src/utils/pactl.c:1750 msgid "You have to specify a sink input index and a sink" msgstr "" -#: src/utils/pactl.c:1768 +#: src/utils/pactl.c:1760 msgid "You have to specify a source output index and a source" msgstr "" -#: src/utils/pactl.c:1783 +#: src/utils/pactl.c:1775 msgid "You have to specify a module name and arguments." msgstr "" -#: src/utils/pactl.c:1803 +#: src/utils/pactl.c:1795 msgid "You have to specify a module index or name" msgstr "" -#: src/utils/pactl.c:1816 +#: src/utils/pactl.c:1808 msgid "" "You may not specify more than one sink. You have to specify a boolean value." msgstr "" -#: src/utils/pactl.c:1821 src/utils/pactl.c:1841 +#: src/utils/pactl.c:1813 src/utils/pactl.c:1833 msgid "Invalid suspend specification." msgstr "" -#: src/utils/pactl.c:1836 +#: src/utils/pactl.c:1828 msgid "" "You may not specify more than one source. You have to specify a boolean " "value." msgstr "" -#: src/utils/pactl.c:1853 +#: src/utils/pactl.c:1845 msgid "You have to specify a card name/index and a profile name" msgstr "" -#: src/utils/pactl.c:1864 +#: src/utils/pactl.c:1856 msgid "You have to specify a sink name/index and a port name" msgstr "" -#: src/utils/pactl.c:1875 +#: src/utils/pactl.c:1867 msgid "You have to specify a sink name" msgstr "" -#: src/utils/pactl.c:1885 +#: src/utils/pactl.c:1877 msgid "You have to specify a source name/index and a port name" msgstr "" -#: src/utils/pactl.c:1896 +#: src/utils/pactl.c:1888 msgid "You have to specify a source name" msgstr "" -#: src/utils/pactl.c:1906 +#: src/utils/pactl.c:1898 msgid "You have to specify a sink name/index and a volume" msgstr "" -#: src/utils/pactl.c:1919 +#: src/utils/pactl.c:1911 msgid "You have to specify a source name/index and a volume" msgstr "" -#: src/utils/pactl.c:1932 +#: src/utils/pactl.c:1924 msgid "You have to specify a sink input index and a volume" msgstr "" -#: src/utils/pactl.c:1937 +#: src/utils/pactl.c:1929 msgid "Invalid sink input index" msgstr "" -#: src/utils/pactl.c:1948 +#: src/utils/pactl.c:1940 msgid "You have to specify a source output index and a volume" msgstr "" -#: src/utils/pactl.c:1953 +#: src/utils/pactl.c:1945 msgid "Invalid source output index" msgstr "" -#: src/utils/pactl.c:1964 +#: src/utils/pactl.c:1956 msgid "" "You have to specify a sink name/index and a mute action (0, 1, or 'toggle')" msgstr "" -#: src/utils/pactl.c:1969 src/utils/pactl.c:1984 src/utils/pactl.c:2004 -#: src/utils/pactl.c:2022 +#: src/utils/pactl.c:1961 src/utils/pactl.c:1976 src/utils/pactl.c:1996 +#: src/utils/pactl.c:2014 msgid "Invalid mute specification" msgstr "" -#: src/utils/pactl.c:1979 +#: src/utils/pactl.c:1971 msgid "" "You have to specify a source name/index and a mute action (0, 1, or 'toggle')" msgstr "" -#: src/utils/pactl.c:1994 +#: src/utils/pactl.c:1986 msgid "" "You have to specify a sink input index and a mute action (0, 1, or 'toggle')" msgstr "" -#: src/utils/pactl.c:1999 +#: src/utils/pactl.c:1991 msgid "Invalid sink input index specification" msgstr "" -#: src/utils/pactl.c:2012 +#: src/utils/pactl.c:2004 msgid "" "You have to specify a source output index and a mute action (0, 1, or " "'toggle')" msgstr "" -#: src/utils/pactl.c:2017 +#: src/utils/pactl.c:2009 msgid "Invalid source output index specification" msgstr "" -#: src/utils/pactl.c:2034 +#: src/utils/pactl.c:2026 msgid "" "You have to specify a sink index and a semicolon-separated list of supported " "formats" msgstr "" -#: src/utils/pactl.c:2046 +#: src/utils/pactl.c:2038 msgid "You have to specify a card name/index, a port name and a latency offset" msgstr "" -#: src/utils/pactl.c:2053 +#: src/utils/pactl.c:2045 msgid "Could not parse latency offset" msgstr "" -#: src/utils/pactl.c:2065 +#: src/utils/pactl.c:2057 msgid "No valid command specified." msgstr "" @@ -2679,9 +2667,7 @@ msgstr "" #: src/utils/pasuspender.c:228 #, c-format msgid "" -"%s [options] -- PROGRAM [ARGUMENTS ...]\n" -"\n" -"Temporarily suspend PulseAudio while PROGRAM runs.\n" +"%s [options] ... \n" "\n" " -h, --help Show this help\n" " --version Show version\n" @@ -2690,7 +2676,7 @@ msgid "" "\n" msgstr "" -#: src/utils/pasuspender.c:267 +#: src/utils/pasuspender.c:266 #, c-format msgid "" "pasuspender %s\n" @@ -2698,17 +2684,17 @@ msgid "" "Linked with libpulse %s\n" msgstr "" -#: src/utils/pasuspender.c:296 +#: src/utils/pasuspender.c:295 #, c-format msgid "pa_mainloop_new() failed.\n" msgstr "" -#: src/utils/pasuspender.c:309 +#: src/utils/pasuspender.c:308 #, c-format msgid "pa_context_new() failed.\n" msgstr "" -#: src/utils/pasuspender.c:321 +#: src/utils/pasuspender.c:320 #, c-format msgid "pa_mainloop_run() failed.\n" msgstr "" Binary files differBinary files differdiff --git a/po/sr@latin.gmo b/po/sr@latin.gmo Binary files differBinary files differBinary files differBinary files differindex 3e9c82c..a14e48a 100644 --- a/po/sr@latin.gmo +++ b/po/sr@latin.gmo diff --git a/po/zh_CN.gmo b/po/zh_CN.gmo Binary files differindex 3fca8fe..f807631 100644 --- a/po/zh_CN.gmo +++ b/po/zh_CN.gmo diff --git a/po/zh_TW.gmo b/po/zh_TW.gmo Binary files differindex ab5e14a..73136cf 100644 --- a/po/zh_TW.gmo +++ b/po/zh_TW.gmo diff --git a/po/zh_TW.po b/po/zh_TW.po index 5bbf0ed..475938e 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -1,24 +1,102 @@ # Chinese (Taiwan) translation for pulseaudio. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# Cheng-Chia Tseng <pswo10680@gmail.com>, 2010, 2012. # +# Cheng-Chia Tseng <pswo10680@gmail.com>, 2010, 2012. +# pan93412 <pan93412@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: PulseAudio Volume Control\n" -"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/new\n" -"POT-Creation-Date: 2017-09-14 03:26+0000\n" -"PO-Revision-Date: 2017-09-14 16:30+0800\n" -"Last-Translator: Cheng-Chia Tseng <pswo10680@gmail.com>\n" -"Language-Team: zh_TW\n" +"Report-Msgid-Bugs-To: pulseaudio-discuss (at) lists (dot) freedesktop (dot)" +" org\n" +"POT-Creation-Date: 2020-01-11 13:44+0800\n" +"PO-Revision-Date: 2020-01-11 13:49+0800\n" +"Last-Translator: pan93412 <pan93412@gmail.com>\n" +"Language-Team: Chinese <zh-l10n@lists.linux.org.tw>\n" "Language: zh_TW\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.0.3\n" - -#: ../src/daemon/cmdline.c:113 -#, c-format +"X-Generator: Lokalize 19.12.0\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: src/daemon/cmdline.c:113 +#, 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 (only " +#| "returns exit code)\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" +#| " --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 --verbose Increase the verbosity level\n" +#| " --log-target={auto,syslog,stderr,file:PATH,newfile:PATH}\n" +#| " 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" +#| " (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" +#| " --enable-memfd[=BOOL] Enable memfd 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" msgid "" "%s [options]\n" "\n" @@ -48,8 +126,7 @@ msgid "" " (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 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 " @@ -92,7 +169,7 @@ msgstr "" "%s [選項]\n" "\n" "指令:\n" -" -h, --help 顯示此幫助\n" +" -h, --help 顯示此說明\n" " --version 顯示版本\n" " --dump-conf 傾印預設組態\n" " --dump-modules 傾印可用模組清單\n" @@ -115,7 +192,7 @@ msgstr "" " (僅 root 身份可用,當有 SUID 或有 " "RLIMIT_RTPRIO \n" " 提升之時)\n" -" --disallow-module-loading[=BOOL] 不允許模組使用者請求的模組\n" +" --disallow-module-loading[=BOOL] 不允許使用者請求的模組\n" " 在初始啟動後載入/卸載\n" " --disallow-exit[=BOOL] 不允許使用者請求離開\n" " --exit-idle-time=SECS 在幕後程式閒置並經過這段時間後\n" @@ -149,15 +226,15 @@ msgstr "" "\n" " -n 不要載入預設指令稿檔案\n" -#: ../src/daemon/cmdline.c:246 +#: src/daemon/cmdline.c:246 msgid "--daemonize expects boolean argument" msgstr "--daemonize 預期布林引數" -#: ../src/daemon/cmdline.c:254 +#: src/daemon/cmdline.c:254 msgid "--fail expects boolean argument" msgstr "--fail 預期布林引數" -#: ../src/daemon/cmdline.c:265 +#: src/daemon/cmdline.c:265 msgid "" "--log-level expects log level argument (either numeric in range 0..4 or one " "of debug, info, notice, warn, error)." @@ -165,35 +242,38 @@ msgstr "" "--log-level 預期記錄層級引數 (範圍 0..4 間的數字,或是後列之一: debug、" "info、notice、warn、error)。" -#: ../src/daemon/cmdline.c:277 +#: src/daemon/cmdline.c:277 msgid "--high-priority expects boolean argument" msgstr "--high-priority 預期布林引數" -#: ../src/daemon/cmdline.c:285 +#: src/daemon/cmdline.c:285 msgid "--realtime expects boolean argument" msgstr "--realtime 預期布林引數" -#: ../src/daemon/cmdline.c:293 +#: src/daemon/cmdline.c:293 msgid "--disallow-module-loading expects boolean argument" msgstr "--disallow-module-loading 預期布林引數" -#: ../src/daemon/cmdline.c:301 +#: src/daemon/cmdline.c:301 msgid "--disallow-exit expects boolean argument" msgstr "--disallow-exit 預期布林引數" -#: ../src/daemon/cmdline.c:309 +#: src/daemon/cmdline.c:309 msgid "--use-pid-file expects boolean argument" msgstr "--use-pid-file 預期布林引數" -#: ../src/daemon/cmdline.c:328 +#: src/daemon/cmdline.c:328 +#| msgid "" +#| "Invalid log target: use either 'syslog', 'journal','stderr' or 'auto' or " +#| "a valid file name 'file:<path>', 'newfile:<path>'." msgid "" -"Invalid log target: use either 'syslog', 'journal','stderr' or 'auto' or a " +"Invalid log target: use either 'syslog', 'journal', 'stderr' or 'auto' or a " "valid file name 'file:<path>', 'newfile:<path>'." msgstr "" "無效的紀錄目標:請使用「syslog」、「journal」、「stderr」或「auto」或有效的檔" "名「file:<path>」、「newfile:<path>」。" -#: ../src/daemon/cmdline.c:330 +#: src/daemon/cmdline.c:330 msgid "" "Invalid log target: use either 'syslog', 'stderr' or 'auto' or a valid file " "name 'file:<path>', 'newfile:<path>'." @@ -201,306 +281,306 @@ msgstr "" "無效的紀錄目標:請使用「syslog」、「stderr」或「auto」或有效的檔名「file:" "<path>」、「newfile:<path>」。" -#: ../src/daemon/cmdline.c:338 +#: src/daemon/cmdline.c:338 msgid "--log-time expects boolean argument" msgstr "--log-time 預期布林引數" -#: ../src/daemon/cmdline.c:346 +#: src/daemon/cmdline.c:346 msgid "--log-meta expects boolean argument" msgstr "--log-meta 預期布林引數" -#: ../src/daemon/cmdline.c:366 +#: src/daemon/cmdline.c:366 #, c-format msgid "Invalid resample method '%s'." msgstr "無效的重新取樣方法「%s」" -#: ../src/daemon/cmdline.c:373 +#: src/daemon/cmdline.c:373 msgid "--system expects boolean argument" msgstr "--system 預期布林引數" -#: ../src/daemon/cmdline.c:381 +#: src/daemon/cmdline.c:381 msgid "--no-cpu-limit expects boolean argument" msgstr "--no-cpu-limit 預期布林引數" -#: ../src/daemon/cmdline.c:389 +#: src/daemon/cmdline.c:389 msgid "--disable-shm expects boolean argument" msgstr "--disable-shm 預期布林引數" -#: ../src/daemon/cmdline.c:397 +#: src/daemon/cmdline.c:397 msgid "--enable-memfd expects boolean argument" msgstr "--enable-memfd 預期布林引數" -#: ../src/daemon/daemon-conf.c:262 +#: src/daemon/daemon-conf.c:269 #, c-format msgid "[%s:%u] Invalid log target '%s'." msgstr "[%s:%u] 無效的記錄目標「%s」。" -#: ../src/daemon/daemon-conf.c:277 +#: src/daemon/daemon-conf.c:284 #, c-format msgid "[%s:%u] Invalid log level '%s'." msgstr "[%s:%u] 無效的紀錄層級「%s」。" -#: ../src/daemon/daemon-conf.c:292 +#: src/daemon/daemon-conf.c:299 #, c-format msgid "[%s:%u] Invalid resample method '%s'." msgstr "[%s:%u] 無效的重新取樣方法「%s」。" -#: ../src/daemon/daemon-conf.c:314 +#: src/daemon/daemon-conf.c:321 #, c-format msgid "[%s:%u] Invalid rlimit '%s'." msgstr "[%s:%u] 無效的 rlimit「%s」。" -#: ../src/daemon/daemon-conf.c:334 +#: src/daemon/daemon-conf.c:341 #, c-format msgid "[%s:%u] Invalid sample format '%s'." msgstr "[%s:%u] 無效的樣本格式「%s」。" -#: ../src/daemon/daemon-conf.c:351 ../src/daemon/daemon-conf.c:368 +#: src/daemon/daemon-conf.c:358 src/daemon/daemon-conf.c:375 #, c-format msgid "[%s:%u] Invalid sample rate '%s'." msgstr "[%s:%u] 無的取樣率「%s」。" -#: ../src/daemon/daemon-conf.c:391 +#: src/daemon/daemon-conf.c:398 #, c-format msgid "[%s:%u] Invalid sample channels '%s'." msgstr "[%s:%u] 無效的取樣聲道「%s」。" -#: ../src/daemon/daemon-conf.c:408 +#: src/daemon/daemon-conf.c:415 #, c-format msgid "[%s:%u] Invalid channel map '%s'." msgstr "[%s:%u] 無效的聲道對應表「%s」。" -#: ../src/daemon/daemon-conf.c:425 +#: src/daemon/daemon-conf.c:432 #, c-format msgid "[%s:%u] Invalid number of fragments '%s'." msgstr "[%s:%u] 無效的片段數量「%s」。" -#: ../src/daemon/daemon-conf.c:442 +#: src/daemon/daemon-conf.c:449 #, c-format msgid "[%s:%u] Invalid fragment size '%s'." msgstr "[%s:%u] 無效的片段大小「%s」。" -#: ../src/daemon/daemon-conf.c:459 +#: src/daemon/daemon-conf.c:466 #, c-format msgid "[%s:%u] Invalid nice level '%s'." msgstr "[%s:%u] 無效的良好層級「%s」。" -#: ../src/daemon/daemon-conf.c:502 +#: src/daemon/daemon-conf.c:551 #, c-format msgid "[%s:%u] Invalid server type '%s'." msgstr "[%s:%u] 無效的伺服器類型「%s」。" -#: ../src/daemon/daemon-conf.c:620 +#: src/daemon/daemon-conf.c:671 #, c-format msgid "Failed to open configuration file: %s" msgstr "未能開啟組態檔:%s" -#: ../src/daemon/daemon-conf.c:636 +#: src/daemon/daemon-conf.c:687 msgid "" "The specified default channel map has a different number of channels than " "the specified default number of channels." msgstr "指定的預設聲道對應表的聲道數與指定的預設聲道數不同。" -#: ../src/daemon/daemon-conf.c:723 +#: src/daemon/daemon-conf.c:774 #, c-format msgid "### Read from configuration file: %s ###\n" msgstr "### 從此組態檔讀取:%s ###\n" -#: ../src/daemon/dumpmodules.c:57 +#: src/daemon/dumpmodules.c:57 #, c-format msgid "Name: %s\n" msgstr "名稱:%s\n" -#: ../src/daemon/dumpmodules.c:60 +#: src/daemon/dumpmodules.c:60 #, c-format msgid "No module information available\n" msgstr "沒有可用的模組資訊\n" -#: ../src/daemon/dumpmodules.c:63 +#: src/daemon/dumpmodules.c:63 #, c-format msgid "Version: %s\n" msgstr "版本:%s\n" -#: ../src/daemon/dumpmodules.c:65 +#: src/daemon/dumpmodules.c:65 #, c-format msgid "Description: %s\n" msgstr "描述:%s\n" -#: ../src/daemon/dumpmodules.c:67 +#: src/daemon/dumpmodules.c:67 #, c-format msgid "Author: %s\n" msgstr "作者:%s\n" -#: ../src/daemon/dumpmodules.c:69 +#: src/daemon/dumpmodules.c:69 #, c-format msgid "Usage: %s\n" msgstr "用法:%s\n" -#: ../src/daemon/dumpmodules.c:70 +#: src/daemon/dumpmodules.c:70 #, c-format msgid "Load Once: %s\n" msgstr "載入一次:%s\n" -#: ../src/daemon/dumpmodules.c:72 +#: src/daemon/dumpmodules.c:72 #, c-format msgid "DEPRECATION WARNING: %s\n" msgstr "反對警告:%s\n" -#: ../src/daemon/dumpmodules.c:76 +#: src/daemon/dumpmodules.c:76 #, c-format msgid "Path: %s\n" msgstr "路徑:%s\n" -#: ../src/daemon/ltdl-bind-now.c:75 +#: src/daemon/ltdl-bind-now.c:75 #, c-format msgid "Failed to open module %s: %s" msgstr "無法開啟模組 %s:%s" -#: ../src/daemon/ltdl-bind-now.c:126 +#: src/daemon/ltdl-bind-now.c:126 msgid "Failed to find original lt_dlopen loader." msgstr "找不到 original lt_dlopen loader。" -#: ../src/daemon/ltdl-bind-now.c:131 +#: src/daemon/ltdl-bind-now.c:131 msgid "Failed to allocate new dl loader." msgstr "未能分配新的 dl loader。" -#: ../src/daemon/ltdl-bind-now.c:144 +#: src/daemon/ltdl-bind-now.c:144 msgid "Failed to add bind-now-loader." msgstr "未能加入 bind-now-loader。" -#: ../src/daemon/main.c:162 +#: src/daemon/main.c:171 #, c-format msgid "Failed to find user '%s'." msgstr "找不到使用者「%s」。" -#: ../src/daemon/main.c:167 +#: src/daemon/main.c:176 #, c-format msgid "Failed to find group '%s'." msgstr "找不到群組「%s」。" -#: ../src/daemon/main.c:176 +#: src/daemon/main.c:185 #, c-format msgid "GID of user '%s' and of group '%s' don't match." msgstr "使用者「%s」的 GID 與群組「%s」的 GID 不相符。" -#: ../src/daemon/main.c:181 +#: src/daemon/main.c:190 #, c-format msgid "Home directory of user '%s' is not '%s', ignoring." msgstr "使用者「%s」的家目錄不是「%s」,忽略中。" -#: ../src/daemon/main.c:184 ../src/daemon/main.c:189 +#: src/daemon/main.c:193 src/daemon/main.c:198 #, c-format msgid "Failed to create '%s': %s" msgstr "未能建立「%s」:%s" -#: ../src/daemon/main.c:196 +#: src/daemon/main.c:205 #, c-format msgid "Failed to change group list: %s" msgstr "未能變更群組清單:%s" -#: ../src/daemon/main.c:212 +#: src/daemon/main.c:221 #, c-format msgid "Failed to change GID: %s" msgstr "未能變更 GIC:%s" -#: ../src/daemon/main.c:228 +#: src/daemon/main.c:237 #, c-format msgid "Failed to change UID: %s" msgstr "未能變更 UID:%s" -#: ../src/daemon/main.c:257 +#: src/daemon/main.c:266 msgid "System wide mode unsupported on this platform." msgstr "本平台未支援系統域模式。" -#: ../src/daemon/main.c:486 +#: src/daemon/main.c:495 msgid "Failed to parse command line." msgstr "未能解析命令列。" -#: ../src/daemon/main.c:525 +#: src/daemon/main.c:534 msgid "" "System mode refused for non-root user. Only starting the D-Bus server lookup " "service." msgstr "系統模式拒絕非 root 使用者。僅啟動 D-Bus 伺服器查看服務。" -#: ../src/daemon/main.c:624 +#: src/daemon/main.c:633 #, c-format msgid "Failed to kill daemon: %s" msgstr "未能結束幕後程式:%s" -#: ../src/daemon/main.c:653 +#: src/daemon/main.c:662 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." msgstr "本程式不預期以 root 身份執行(除非有指定 --system)。" -#: ../src/daemon/main.c:656 +#: src/daemon/main.c:665 msgid "Root privileges required." msgstr "需要 root 特權。" -#: ../src/daemon/main.c:663 +#: src/daemon/main.c:672 msgid "--start not supported for system instances." msgstr "--start 不支援系統實體。" -#: ../src/daemon/main.c:703 +#: src/daemon/main.c:712 #, c-format msgid "User-configured server at %s, refusing to start/autospawn." msgstr "使用者於 %s 設定的伺服器,拒絕啟動/autospawn。" -#: ../src/daemon/main.c:709 +#: src/daemon/main.c:718 #, c-format msgid "" "User-configured server at %s, which appears to be local. Probing deeper." msgstr "使用者設定的伺服器位於 %s,它似乎是本機。正在深入探測。" -#: ../src/daemon/main.c:714 +#: src/daemon/main.c:723 msgid "Running in system mode, but --disallow-exit not set." msgstr "以系統模式執行中,但 --disallow-exit 未設定。" -#: ../src/daemon/main.c:717 +#: src/daemon/main.c:726 msgid "Running in system mode, but --disallow-module-loading not set." msgstr "以系統模式執行中,但 --disallow-module-loading 未設定。" -#: ../src/daemon/main.c:720 +#: src/daemon/main.c:729 msgid "Running in system mode, forcibly disabling SHM mode." msgstr "以系統模式執行中,強制停用 SHM 模式。" -#: ../src/daemon/main.c:725 +#: src/daemon/main.c:734 msgid "Running in system mode, forcibly disabling exit idle time." msgstr "以系統模式執行中,強制停用離開閒置時間。" -#: ../src/daemon/main.c:758 +#: src/daemon/main.c:767 msgid "Failed to acquire stdio." msgstr "未能獲取 stdio。" -#: ../src/daemon/main.c:764 ../src/daemon/main.c:835 +#: src/daemon/main.c:773 src/daemon/main.c:844 #, c-format msgid "pipe() failed: %s" msgstr "pipe() 失敗:%s" -#: ../src/daemon/main.c:769 ../src/daemon/main.c:840 +#: src/daemon/main.c:778 src/daemon/main.c:849 #, c-format msgid "fork() failed: %s" msgstr "fork() 失敗:%s" -#: ../src/daemon/main.c:784 ../src/daemon/main.c:855 ../src/utils/pacat.c:562 +#: src/daemon/main.c:793 src/daemon/main.c:864 src/utils/pacat.c:562 #, c-format msgid "read() failed: %s" msgstr "read() 失敗:%s" -#: ../src/daemon/main.c:790 +#: src/daemon/main.c:799 msgid "Daemon startup failed." msgstr "幕後程式啟動失敗。" -#: ../src/daemon/main.c:823 +#: src/daemon/main.c:832 #, c-format msgid "setsid() failed: %s" msgstr "setsid() 失敗:%s" -#: ../src/daemon/main.c:950 +#: src/daemon/main.c:965 msgid "Failed to get machine ID" msgstr "未能取得機器 ID" -#: ../src/daemon/main.c:976 +#: src/daemon/main.c:991 msgid "" "OK, so you are running PA in system mode. Please make sure that you actually " "do want to do that.\n" @@ -512,311 +592,331 @@ msgstr "" "請閱讀 http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/" "User/WhatIsWrongWithSystemWide/ 瞭解為何採用系統模式一般是不理想的點子。" -#: ../src/daemon/main.c:992 +#: src/daemon/main.c:1007 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() 失敗。" -#: ../src/daemon/main.c:1024 +#: src/daemon/main.c:1039 msgid "pa_core_new() failed." msgstr "pa_core_new() 失敗。" -#: ../src/daemon/main.c:1094 -msgid "Failed to initialize daemon." -msgstr "未能初始化幕後程式。" +#: src/daemon/main.c:1109 +#| msgid "Too many arguments." +msgid "command line arguments" +msgstr "指令列參數" + +#: src/daemon/main.c:1116 +#, c-format +msgid "" +"Failed to initialize daemon due to errors while executing startup commands. " +"Source of commands: %s" +msgstr "" +"因執行啟動指令時發生錯誤,而無法初始化幕後程式。" +"指令來源:%s" -#: ../src/daemon/main.c:1099 +#: src/daemon/main.c:1121 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "幕後程式啟動而沒有任何載入的模組,拒絕運作。" -#: ../src/daemon/pulseaudio.desktop.in.h:1 +#: src/daemon/pulseaudio.desktop.in:4 msgid "PulseAudio Sound System" msgstr "PulseAudio 音效系統" -#: ../src/daemon/pulseaudio.desktop.in.h:2 +#: src/daemon/pulseaudio.desktop.in:5 msgid "Start the PulseAudio Sound System" msgstr "啟動 PulseAudio 音效系統" -#: ../src/modules/alsa/alsa-mixer.c:2378 +#: src/modules/alsa/alsa-mixer.c:2544 msgid "Input" msgstr "輸入" -#: ../src/modules/alsa/alsa-mixer.c:2379 +#: src/modules/alsa/alsa-mixer.c:2545 msgid "Docking Station Input" msgstr "Docking Station 輸入" -#: ../src/modules/alsa/alsa-mixer.c:2380 +#: src/modules/alsa/alsa-mixer.c:2546 msgid "Docking Station Microphone" msgstr "Docking Station 麥克風" -#: ../src/modules/alsa/alsa-mixer.c:2381 +#: src/modules/alsa/alsa-mixer.c:2547 msgid "Docking Station Line In" msgstr "Docking Station 線路輸入" -#: ../src/modules/alsa/alsa-mixer.c:2382 ../src/modules/alsa/alsa-mixer.c:2467 +#: src/modules/alsa/alsa-mixer.c:2548 src/modules/alsa/alsa-mixer.c:2639 msgid "Line In" msgstr "線路輸入" -#: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez5-device.c:1773 +#: src/modules/alsa/alsa-mixer.c:2549 src/modules/alsa/alsa-mixer.c:2633 +#: src/modules/bluetooth/module-bluez5-device.c:1788 msgid "Microphone" msgstr "麥克風" -#: ../src/modules/alsa/alsa-mixer.c:2384 ../src/modules/alsa/alsa-mixer.c:2462 +#: src/modules/alsa/alsa-mixer.c:2550 src/modules/alsa/alsa-mixer.c:2634 msgid "Front Microphone" msgstr "前方麥克風" -#: ../src/modules/alsa/alsa-mixer.c:2385 ../src/modules/alsa/alsa-mixer.c:2463 +#: src/modules/alsa/alsa-mixer.c:2551 src/modules/alsa/alsa-mixer.c:2635 msgid "Rear Microphone" msgstr "後方麥克風" -#: ../src/modules/alsa/alsa-mixer.c:2386 +#: src/modules/alsa/alsa-mixer.c:2552 msgid "External Microphone" msgstr "外接麥克風" -#: ../src/modules/alsa/alsa-mixer.c:2387 ../src/modules/alsa/alsa-mixer.c:2465 +#: src/modules/alsa/alsa-mixer.c:2553 src/modules/alsa/alsa-mixer.c:2637 msgid "Internal Microphone" msgstr "內建麥克風" -#: ../src/modules/alsa/alsa-mixer.c:2388 ../src/modules/alsa/alsa-mixer.c:2468 +#: src/modules/alsa/alsa-mixer.c:2554 src/modules/alsa/alsa-mixer.c:2640 msgid "Radio" msgstr "無線電" -#: ../src/modules/alsa/alsa-mixer.c:2389 ../src/modules/alsa/alsa-mixer.c:2469 +#: src/modules/alsa/alsa-mixer.c:2555 src/modules/alsa/alsa-mixer.c:2641 msgid "Video" msgstr "視訊" -#: ../src/modules/alsa/alsa-mixer.c:2390 +#: src/modules/alsa/alsa-mixer.c:2556 msgid "Automatic Gain Control" msgstr "自動增益控制" -#: ../src/modules/alsa/alsa-mixer.c:2391 +#: src/modules/alsa/alsa-mixer.c:2557 msgid "No Automatic Gain Control" msgstr "無自動增益控制" -#: ../src/modules/alsa/alsa-mixer.c:2392 +#: src/modules/alsa/alsa-mixer.c:2558 msgid "Boost" msgstr "增強" -#: ../src/modules/alsa/alsa-mixer.c:2393 +#: src/modules/alsa/alsa-mixer.c:2559 msgid "No Boost" msgstr "無增強" -#: ../src/modules/alsa/alsa-mixer.c:2394 +#: src/modules/alsa/alsa-mixer.c:2560 msgid "Amplifier" msgstr "擴大器" -#: ../src/modules/alsa/alsa-mixer.c:2395 +#: src/modules/alsa/alsa-mixer.c:2561 msgid "No Amplifier" msgstr "無擴大器" -#: ../src/modules/alsa/alsa-mixer.c:2396 +#: src/modules/alsa/alsa-mixer.c:2562 msgid "Bass Boost" msgstr "低音增強" -#: ../src/modules/alsa/alsa-mixer.c:2397 +#: src/modules/alsa/alsa-mixer.c:2563 msgid "No Bass Boost" msgstr "無低音增強" -#: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez5-device.c:1780 +#: src/modules/alsa/alsa-mixer.c:2564 +#: src/modules/bluetooth/module-bluez5-device.c:1795 msgid "Speaker" msgstr "喇叭" -#: ../src/modules/alsa/alsa-mixer.c:2399 ../src/modules/alsa/alsa-mixer.c:2471 +#: src/modules/alsa/alsa-mixer.c:2565 src/modules/alsa/alsa-mixer.c:2643 msgid "Headphones" msgstr "頭戴式耳機" -#: ../src/modules/alsa/alsa-mixer.c:2460 +#: src/modules/alsa/alsa-mixer.c:2632 msgid "Analog Input" msgstr "類比輸入" -#: ../src/modules/alsa/alsa-mixer.c:2464 +#: src/modules/alsa/alsa-mixer.c:2636 msgid "Dock Microphone" msgstr "臺座麥克風" -#: ../src/modules/alsa/alsa-mixer.c:2466 +#: src/modules/alsa/alsa-mixer.c:2638 msgid "Headset Microphone" msgstr "耳麥麥克風" -#: ../src/modules/alsa/alsa-mixer.c:2470 +#: src/modules/alsa/alsa-mixer.c:2642 msgid "Analog Output" msgstr "類比輸出" -#: ../src/modules/alsa/alsa-mixer.c:2472 +#: src/modules/alsa/alsa-mixer.c:2644 msgid "Headphones Mono Output" msgstr "頭戴式耳機單聲道輸出" -#: ../src/modules/alsa/alsa-mixer.c:2473 +#: src/modules/alsa/alsa-mixer.c:2645 msgid "LFE on Separate Mono Output" msgstr "LFE 於分隔單聲道輸出" -#: ../src/modules/alsa/alsa-mixer.c:2474 +#: src/modules/alsa/alsa-mixer.c:2646 msgid "Line Out" msgstr "線路輸出" -#: ../src/modules/alsa/alsa-mixer.c:2475 +#: src/modules/alsa/alsa-mixer.c:2647 msgid "Analog Mono Output" msgstr "類比單聲道輸出" -#: ../src/modules/alsa/alsa-mixer.c:2476 +#: src/modules/alsa/alsa-mixer.c:2648 msgid "Speakers" msgstr "喇叭" -#: ../src/modules/alsa/alsa-mixer.c:2477 +#: src/modules/alsa/alsa-mixer.c:2649 msgid "HDMI / DisplayPort" msgstr "HDMI / DisplayPort" -#: ../src/modules/alsa/alsa-mixer.c:2478 +#: src/modules/alsa/alsa-mixer.c:2650 msgid "Digital Output (S/PDIF)" msgstr "數位輸出 (S/PDIF)" -#: ../src/modules/alsa/alsa-mixer.c:2479 +#: src/modules/alsa/alsa-mixer.c:2651 msgid "Digital Input (S/PDIF)" msgstr "數位輸入 (S/PDIF)" -#: ../src/modules/alsa/alsa-mixer.c:2480 +#: src/modules/alsa/alsa-mixer.c:2652 msgid "Digital Passthrough (S/PDIF)" msgstr "數位通透 (S/PDIF)" -#: ../src/modules/alsa/alsa-mixer.c:2481 +#: src/modules/alsa/alsa-mixer.c:2653 msgid "Multichannel Input" msgstr "多聲道輸入" -#: ../src/modules/alsa/alsa-mixer.c:2482 +#: src/modules/alsa/alsa-mixer.c:2654 msgid "Multichannel Output" msgstr "多聲道輸出" -#: ../src/modules/alsa/alsa-mixer.c:3991 +#: src/modules/alsa/alsa-mixer.c:2655 +#| msgid "%s Output" +msgid "Game Output" +msgstr "遊戲輸出" + +#: src/modules/alsa/alsa-mixer.c:2656 +#| msgid "%s Output" +msgid "Chat Output" +msgstr "聊天輸出" + +#: src/modules/alsa/alsa-mixer.c:4225 msgid "Analog Mono" msgstr "類比單聲道" -#. Note: Not translated to "Analog Stereo Input", because the source -#. * name gets "Input" appended to it automatically, so adding "Input" -#. * here would lead to the source name to become "Analog Stereo Input -#. * Input". The same logic applies to analog-stereo-output, -#. * multichannel-input and multichannel-output. -#: ../src/modules/alsa/alsa-mixer.c:3992 ../src/modules/alsa/alsa-mixer.c:3998 -#: ../src/modules/alsa/alsa-mixer.c:3999 +#: src/modules/alsa/alsa-mixer.c:4226 src/modules/alsa/alsa-mixer.c:4234 +#: src/modules/alsa/alsa-mixer.c:4235 msgid "Analog Stereo" msgstr "類比立體聲" -#: ../src/modules/alsa/alsa-mixer.c:4000 ../src/modules/alsa/alsa-mixer.c:4001 +#: src/modules/alsa/alsa-mixer.c:4227 src/pulse/channelmap.c:103 +#: src/pulse/channelmap.c:771 +msgid "Mono" +msgstr "單聲道" + +#: src/modules/alsa/alsa-mixer.c:4228 src/pulse/channelmap.c:775 +msgid "Stereo" +msgstr "立體聲" + +#: src/modules/alsa/alsa-mixer.c:4236 src/modules/alsa/alsa-mixer.c:4237 msgid "Multichannel" msgstr "多聲道" -#: ../src/modules/alsa/alsa-mixer.c:4002 +#: src/modules/alsa/alsa-mixer.c:4238 msgid "Analog Surround 2.1" msgstr "類比環繞聲 2.1" -#: ../src/modules/alsa/alsa-mixer.c:4003 +#: src/modules/alsa/alsa-mixer.c:4239 msgid "Analog Surround 3.0" msgstr "類比環繞聲 3.0" -#: ../src/modules/alsa/alsa-mixer.c:4004 +#: src/modules/alsa/alsa-mixer.c:4240 msgid "Analog Surround 3.1" msgstr "類比環繞聲 3.1" -#: ../src/modules/alsa/alsa-mixer.c:4005 +#: src/modules/alsa/alsa-mixer.c:4241 msgid "Analog Surround 4.0" msgstr "類比環繞聲 4.0" -#: ../src/modules/alsa/alsa-mixer.c:4006 +#: src/modules/alsa/alsa-mixer.c:4242 msgid "Analog Surround 4.1" msgstr "類比環繞聲 4.1" -#: ../src/modules/alsa/alsa-mixer.c:4007 +#: src/modules/alsa/alsa-mixer.c:4243 msgid "Analog Surround 5.0" msgstr "類比環繞聲 5.0" -#: ../src/modules/alsa/alsa-mixer.c:4008 +#: src/modules/alsa/alsa-mixer.c:4244 msgid "Analog Surround 5.1" msgstr "類比環繞聲 5.1" -#: ../src/modules/alsa/alsa-mixer.c:4009 +#: src/modules/alsa/alsa-mixer.c:4245 msgid "Analog Surround 6.0" msgstr "類比環繞聲 6.0" -#: ../src/modules/alsa/alsa-mixer.c:4010 +#: src/modules/alsa/alsa-mixer.c:4246 msgid "Analog Surround 6.1" msgstr "類比環繞聲 6.1" -#: ../src/modules/alsa/alsa-mixer.c:4011 +#: src/modules/alsa/alsa-mixer.c:4247 msgid "Analog Surround 7.0" msgstr "類比環繞聲 7.0" -#: ../src/modules/alsa/alsa-mixer.c:4012 +#: src/modules/alsa/alsa-mixer.c:4248 msgid "Analog Surround 7.1" msgstr "類比環繞聲 7.1" -#: ../src/modules/alsa/alsa-mixer.c:4013 +#: src/modules/alsa/alsa-mixer.c:4249 msgid "Digital Stereo (IEC958)" msgstr "數位立體聲 (IEC958)" -#: ../src/modules/alsa/alsa-mixer.c:4014 -msgid "Digital Passthrough (IEC958)" +#: src/modules/alsa/alsa-mixer.c:4250 +#| msgid "Digital Passthrough (IEC958)" +msgid "Digital Passthrough (IEC958)" msgstr "數位通透 (IEC958)" -#: ../src/modules/alsa/alsa-mixer.c:4015 +#: src/modules/alsa/alsa-mixer.c:4251 msgid "Digital Surround 4.0 (IEC958/AC3)" msgstr "數位環繞聲 4.0 (IEC958/AC3)" -#: ../src/modules/alsa/alsa-mixer.c:4016 +#: src/modules/alsa/alsa-mixer.c:4252 msgid "Digital Surround 5.1 (IEC958/AC3)" msgstr "數位環繞聲 5.1 (IEC958/AC3)" -#: ../src/modules/alsa/alsa-mixer.c:4017 +#: src/modules/alsa/alsa-mixer.c:4253 msgid "Digital Surround 5.1 (IEC958/DTS)" msgstr "數位環繞聲 5.1 (IEC958/DTS)" -#: ../src/modules/alsa/alsa-mixer.c:4018 +#: src/modules/alsa/alsa-mixer.c:4254 msgid "Digital Stereo (HDMI)" msgstr "數位立體聲 (HDMI)" -#: ../src/modules/alsa/alsa-mixer.c:4019 +#: src/modules/alsa/alsa-mixer.c:4255 msgid "Digital Surround 5.1 (HDMI)" msgstr "數位環繞聲 5.1 (HDMI)" -#: ../src/modules/alsa/alsa-mixer.c:4020 ../src/pulse/channelmap.c:775 -msgid "Stereo" -msgstr "立體聲" - -#: ../src/modules/alsa/alsa-mixer.c:4153 +#: src/modules/alsa/alsa-mixer.c:4388 msgid "Analog Mono Duplex" msgstr "類比單聲道雙工" -#: ../src/modules/alsa/alsa-mixer.c:4154 +#: src/modules/alsa/alsa-mixer.c:4389 msgid "Analog Stereo Duplex" msgstr "類比立體聲雙工" -#: ../src/modules/alsa/alsa-mixer.c:4155 +#: src/modules/alsa/alsa-mixer.c:4390 msgid "Digital Stereo Duplex (IEC958)" msgstr "數位立體聲雙工 (IEC958)" -#: ../src/modules/alsa/alsa-mixer.c:4156 +#: src/modules/alsa/alsa-mixer.c:4391 msgid "Multichannel Duplex" msgstr "多聲道雙工" -#: ../src/modules/alsa/alsa-mixer.c:4157 +#: src/modules/alsa/alsa-mixer.c:4392 msgid "Stereo Duplex" msgstr "立體聲雙工" -#: ../src/modules/alsa/alsa-mixer.c:4158 -#: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez5-device.c:2028 +#: src/modules/alsa/alsa-mixer.c:4393 src/modules/alsa/module-alsa-card.c:188 +#: src/modules/bluetooth/module-bluez5-device.c:2043 msgid "Off" msgstr "關閉" -#: ../src/modules/alsa/alsa-mixer.c:4257 +#: src/modules/alsa/alsa-mixer.c:4492 #, c-format msgid "%s Output" msgstr "%s 輸出" -#: ../src/modules/alsa/alsa-mixer.c:4265 +#: src/modules/alsa/alsa-mixer.c:4500 #, c-format msgid "%s Input" msgstr "%s 輸入" -#: ../src/modules/alsa/alsa-sink.c:572 +#: src/modules/alsa/alsa-sink.c:652 src/modules/alsa/alsa-sink.c:842 #, c-format msgid "" "ALSA woke us up to write new data to the device, but there was actually " @@ -831,22 +931,7 @@ msgstr "" "我們被 POLLOUT 設定喚醒 -- 然而後續的 snd_pcm_avail() 傳回 0 或另一個值 < " "min_avail。" -#: ../src/modules/alsa/alsa-sink.c:756 -#, c-format -msgid "" -"ALSA woke us up to write new data to the device, but there was actually " -"nothing to write!\n" -"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " -"to the ALSA developers.\n" -"We were woken up with POLLOUT set -- however a subsequent snd_pcm_avail() " -"returned 0 or another value < min_avail." -msgstr "" -"ALSA 喚醒我們以寫入新資料至該裝置,但實際上沒有要寫入的資料!\n" -"這很可能是 ALSA 驅動程式「%s」的臭蟲。請回報此問題給 ALSA 開發者。\n" -"我們被 POLLOUT 設定喚醒 -- 然而後續的 snd_pcm_avail() 傳回 0 或另一個值 < " -"min_avail。" - -#: ../src/modules/alsa/alsa-source.c:529 +#: src/modules/alsa/alsa-source.c:611 src/modules/alsa/alsa-source.c:777 #, c-format msgid "" "ALSA woke us up to read new data from the device, but there was actually " @@ -861,44 +946,49 @@ msgstr "" "我們被 POLLIN 設定喚醒 -- 然而後續的 snd_pcm_avail() 傳回 0 或另一個值 < " "min_avail。" -#: ../src/modules/alsa/alsa-source.c:680 +#: src/modules/alsa/alsa-util.c:1183 src/modules/alsa/alsa-util.c:1277 #, c-format +#| msgid "" +#| "snd_pcm_avail() returned a value that is exceptionally large: %lu bytes " +#| "(%lu ms).\n" +#| "Most likely this is a bug in the ALSA driver '%s'. Please report this " +#| "issue to the ALSA developers." msgid "" -"ALSA woke us up to read new data from the device, but there was actually " -"nothing to read!\n" +"snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu " +"ms).\n" "Most likely this is a bug in the ALSA driver '%s'. Please report this issue " -"to the ALSA developers.\n" -"We were woken up with POLLIN set -- however a subsequent snd_pcm_avail() " -"returned 0 or another value < min_avail." -msgstr "" -"ALSA 喚醒我們從該裝置讀取新資料,但實際上沒有可讀取的資料!\n" -"這很可能是 ALSA 驅動程式「%s」的臭蟲。請回報此問題給 ALSA 開發者。\n" -"我們被 POLLIN 設定喚醒 -- 然而後續的 snd_pcm_avail() 傳回 0 或另一個值 < " -"min_avail。" - -#: ../src/modules/alsa/alsa-util.c:1168 ../src/modules/alsa/alsa-util.c:1243 -#, c-format -msgid "" +"to the ALSA developers." +msgid_plural "" "snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu " "ms).\n" "Most likely this is a bug in the ALSA driver '%s'. Please report this issue " "to the ALSA developers." -msgstr "" +msgstr[0] "" "snd_pcm_avail() 傳回超出預期的大值:%lu bytes (%lu ms)。\n" "這很能是 ALSA 驅動程式「%s」的臭蟲。請回報這個問題給 ALSA 開發者。" -#: ../src/modules/alsa/alsa-util.c:1218 +#: src/modules/alsa/alsa-util.c:1249 #, c-format +#| msgid "" +#| "snd_pcm_delay() returned a value that is exceptionally large: %li bytes " +#| "(%s%lu ms).\n" +#| "Most likely this is a bug in the ALSA driver '%s'. Please report this " +#| "issue to the ALSA developers." msgid "" +"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s" +"%lu ms).\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers." +msgid_plural "" "snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s" "%lu ms).\n" "Most likely this is a bug in the ALSA driver '%s'. Please report this issue " "to the ALSA developers." -msgstr "" +msgstr[0] "" "snd_pcm_delay() 傳回超出預期的大值:%li bytes (%s%lu ms)。\n" "這很能是 ALSA 驅動程式「%s」的臭蟲。請回報這個問題給 ALSA 開發者。" -#: ../src/modules/alsa/alsa-util.c:1259 +#: src/modules/alsa/alsa-util.c:1296 #, c-format msgid "" "snd_pcm_avail_delay() returned strange values: delay %lu is less than avail " @@ -909,75 +999,85 @@ msgstr "" "snd_pcm_avail_delay() 傳回超出預期的大值:延遲 %lu 少於可用的 %lu。\n" "這很能是 ALSA 驅動程式「%s」的臭蟲。請回報這個問題給 ALSA 開發者。" -#: ../src/modules/alsa/alsa-util.c:1302 +#: src/modules/alsa/alsa-util.c:1339 #, c-format +#| msgid "" +#| "snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu " +#| "bytes (%lu ms).\n" +#| "Most likely this is a bug in the ALSA driver '%s'. Please report this " +#| "issue to the ALSA developers." msgid "" +"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte " +"(%lu ms).\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers." +msgid_plural "" "snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes " "(%lu ms).\n" "Most likely this is a bug in the ALSA driver '%s'. Please report this issue " "to the ALSA developers." -msgstr "" +msgstr[0] "" "snd_pcm_mmap_begin() 傳回超出預期的大值:%lu bytes (%lu ms)。\n" "這很能是 ALSA 驅動程式「%s」的臭蟲。請回報這個問題給 ALSA 開發者。" -#: ../src/modules/bluetooth/module-bluez5-device.c:1763 +#: src/modules/bluetooth/module-bluez5-device.c:1772 +#: src/modules/bluetooth/module-bluez5-device.c:1794 +#: src/modules/bluetooth/module-bluez5-device.c:1800 +#: src/modules/bluetooth/module-bluez5-device.c:1826 +msgid "Bluetooth Input" +msgstr "藍牙輸入" + +#: src/modules/bluetooth/module-bluez5-device.c:1773 +#: src/modules/bluetooth/module-bluez5-device.c:1789 +#: src/modules/bluetooth/module-bluez5-device.c:1827 +msgid "Bluetooth Output" +msgstr "藍牙輸出" + +#: src/modules/bluetooth/module-bluez5-device.c:1778 msgid "Headset" msgstr "耳麥" -#: ../src/modules/bluetooth/module-bluez5-device.c:1768 +#: src/modules/bluetooth/module-bluez5-device.c:1783 msgid "Handsfree" msgstr "免持裝置" -#: ../src/modules/bluetooth/module-bluez5-device.c:1786 +#: src/modules/bluetooth/module-bluez5-device.c:1801 msgid "Headphone" msgstr "頭戴式耳機" -#: ../src/modules/bluetooth/module-bluez5-device.c:1791 +#: src/modules/bluetooth/module-bluez5-device.c:1806 msgid "Portable" msgstr "可攜裝置" -#: ../src/modules/bluetooth/module-bluez5-device.c:1796 +#: src/modules/bluetooth/module-bluez5-device.c:1811 msgid "Car" msgstr "汽車" -#: ../src/modules/bluetooth/module-bluez5-device.c:1801 +#: src/modules/bluetooth/module-bluez5-device.c:1816 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez5-device.c:1806 +#: src/modules/bluetooth/module-bluez5-device.c:1821 msgid "Phone" msgstr "手機" -#: ../src/modules/bluetooth/module-bluez5-device.c:1758 -#: ../src/modules/bluetooth/module-bluez5-device.c:1774 -#: ../src/modules/bluetooth/module-bluez5-device.c:1812 -msgid "Bluetooth Output" -msgstr "藍牙輸出" - -#: ../src/modules/bluetooth/module-bluez5-device.c:1757 -#: ../src/modules/bluetooth/module-bluez5-device.c:1779 -#: ../src/modules/bluetooth/module-bluez5-device.c:1785 -#: ../src/modules/bluetooth/module-bluez5-device.c:1811 -msgid "Bluetooth Input" -msgstr "藍牙輸入" - -#: ../src/modules/bluetooth/module-bluez5-device.c:1853 +#: src/modules/bluetooth/module-bluez5-device.c:1868 msgid "High Fidelity Playback (A2DP Sink)" msgstr "高傳真播放裝置 (A2DP Sink)" -#: ../src/modules/bluetooth/module-bluez5-device.c:1865 +#: src/modules/bluetooth/module-bluez5-device.c:1880 msgid "High Fidelity Capture (A2DP Source)" msgstr "高傳真擷取裝置 (A2DP Source)" -#: ../src/modules/bluetooth/module-bluez5-device.c:1877 +#: src/modules/bluetooth/module-bluez5-device.c:1892 msgid "Headset Head Unit (HSP/HFP)" msgstr "耳機麥克風頭部 (HSP/HFP)" -#: ../src/modules/bluetooth/module-bluez5-device.c:1890 +#: src/modules/bluetooth/module-bluez5-device.c:1905 msgid "Headset Audio Gateway (HSP/HFP)" msgstr "耳機麥克風音訊閘道 (HSP/HFP)" -#: ../src/modules/echo-cancel/module-echo-cancel.c:61 +#: src/modules/echo-cancel/module-echo-cancel.c:59 msgid "" "source_name=<name for the source> source_properties=<properties for the " "source> source_master=<name of source to filter> sink_name=<name for the " @@ -999,29 +1099,28 @@ msgstr "" "定此模組是否要被自動載入> use_volume_sharing=<是或否> use_master_format=<是或" "否> " -#. add on profile -#: ../src/modules/macosx/module-coreaudio-device.c:811 +#: src/modules/macosx/module-coreaudio-device.c:824 msgid "On" msgstr "開" -#: ../src/modules/module-allow-passthrough.c:73 -#: ../src/modules/module-always-sink.c:82 +#: src/modules/module-allow-passthrough.c:71 +#: src/modules/module-always-sink.c:80 msgid "Dummy Output" msgstr "Dummy Output" -#: ../src/modules/module-always-sink.c:36 +#: src/modules/module-always-sink.c:34 msgid "Always keeps at least one sink loaded even if it's a null one" msgstr "即使 sink 為空的,也總是維持至少載入一個 sink" -#: ../src/modules/module-always-source.c:37 +#: src/modules/module-always-source.c:35 msgid "Always keeps at least one source loaded even if it's a null one" msgstr "即使來源是空的,也總是維持至少載入一個來源" -#: ../src/modules/module-equalizer-sink.c:70 +#: src/modules/module-equalizer-sink.c:68 msgid "General Purpose Equalizer" msgstr "通用等化器" -#: ../src/modules/module-equalizer-sink.c:74 +#: src/modules/module-equalizer-sink.c:72 msgid "" "sink_name=<name of the sink> sink_properties=<properties for the sink> " "sink_master=<sink to connect to> format=<sample format> rate=<sample rate> " @@ -1032,81 +1131,95 @@ msgstr "" "sink> format=<取樣格式> rate=<取樣率> channels=<聲道數> channel_map=<聲道對應" "表> autoloaded=<設定此模組是否正被自動載入> use_volume_sharing=<yes 或 no> " -#: ../src/modules/module-equalizer-sink.c:1091 -#: ../src/modules/module-equalizer-sink.c:1214 +#: src/modules/module-equalizer-sink.c:1094 +#: src/modules/module-equalizer-sink.c:1217 #, c-format msgid "FFT based equalizer on %s" msgstr "FFT 基礎等化器於 %s" -#: ../src/modules/module-filter-apply.c:49 +#: src/modules/module-filter-apply.c:47 msgid "autoclean=<automatically unload unused filters?>" msgstr "autoclean=<是否自動取消未使用過濾器的載入?>" -#: ../src/modules/module-ladspa-sink.c:51 +#: src/modules/module-ladspa-sink.c:50 msgid "Virtual LADSPA sink" msgstr "虛擬 LADSPA sink" -#: ../src/modules/module-ladspa-sink.c:55 +#: src/modules/module-ladspa-sink.c:54 +#| msgid "" +#| "sink_name=<name for the sink> sink_properties=<properties for the sink> " +#| "master=<name of sink to filter> sink_master=<name of sink to filter> " +#| "format=<sample format> rate=<sample rate> channels=<number of channels> " +#| "channel_map=<input channel map> plugin=<ladspa plugin name> label=<ladspa " +#| "plugin label> control=<comma separated list of input control values> " +#| "input_ladspaport_map=<comma separated list of input LADSPA port names> " +#| "output_ladspaport_map=<comma separated list of output LADSPA port names> " +#| "autoloaded=<set if this module is being loaded automatically> " msgid "" "sink_name=<name for the sink> sink_properties=<properties for the sink> " -"master=<name of sink to filter> sink_master=<name of sink to filter> " -"format=<sample format> rate=<sample rate> channels=<number of channels> " -"channel_map=<input channel map> plugin=<ladspa plugin name> label=<ladspa " -"plugin label> control=<comma separated list of input control values> " -"input_ladspaport_map=<comma separated list of input LADSPA port names> " -"output_ladspaport_map=<comma separated list of output LADSPA port names> " -"autoloaded=<set if this module is being loaded automatically> " +"sink_input_properties=<properties for the sink input> master=<name of sink " +"to filter> sink_master=<name of sink to filter> format=<sample format> " +"rate=<sample rate> channels=<number of channels> channel_map=<input channel " +"map> plugin=<ladspa plugin name> label=<ladspa plugin label> control=<comma " +"separated list of input control values> input_ladspaport_map=<comma " +"separated list of input LADSPA port names> output_ladspaport_map=<comma " +"separated list of output LADSPA port names> autoloaded=<set if this module " +"is being loaded automatically> " msgstr "" -"sink_name=<sink 名稱> sink_properties=<sink 屬性> master=<要過濾的 sink 名稱" +"sink_name=<sink 名稱> sink_properties=<sink 屬性> " +"sink_input_properties=<sink 輸入屬性> master=<要過濾的 sink 名稱" "> sink_master=<要過濾的 sink 名稱> format=<取樣格式> rate=<取樣率> " "channel_map=<輸入聲道映射表> plugin=<ladspa 插件名稱> label=<ladspa 插件標籤" "> control=<輸入控制值的半形逗號分隔清單> input_ladspaport_map=<輸入 LADSPA 連" "接埠名稱的半形逗號分隔清單> output_ladspaport_map=<輸出 LADSPA 連接埠名稱的半" "形逗號分隔清單> autoloaded=<設定此模組是否要被自動載入> " -#: ../src/modules/module-null-sink.c:47 +#: src/modules/module-null-sink.c:46 msgid "Clocked NULL sink" msgstr "Clocked Null sink" -#: ../src/modules/module-null-sink.c:284 +#: src/modules/module-null-sink.c:333 msgid "Null Output" msgstr "Null Output" -#: ../src/modules/module-rygel-media-server.c:508 -#: ../src/modules/module-rygel-media-server.c:546 -#: ../src/modules/module-rygel-media-server.c:905 +#: src/modules/module-null-sink.c:345 src/utils/pactl.c:1058 +#, c-format +msgid "Failed to set format: invalid format string %s" +msgstr "未能設定格式:無效的格式字串 %s" + +#: src/modules/module-rygel-media-server.c:506 +#: src/modules/module-rygel-media-server.c:544 +#: src/modules/module-rygel-media-server.c:903 msgid "Output Devices" msgstr "輸出裝置" -#: ../src/modules/module-rygel-media-server.c:509 -#: ../src/modules/module-rygel-media-server.c:547 -#: ../src/modules/module-rygel-media-server.c:906 +#: src/modules/module-rygel-media-server.c:507 +#: src/modules/module-rygel-media-server.c:545 +#: src/modules/module-rygel-media-server.c:904 msgid "Input Devices" msgstr "輸入裝置" -#: ../src/modules/module-rygel-media-server.c:1063 +#: src/modules/module-rygel-media-server.c:1061 msgid "Audio on @HOSTNAME@" msgstr "音效位於 @HOSTNAME@" -#. TODO: old tunnel put here the remote sink_name into stream name e.g. 'Null Output for lynxis@lazus' -#. TODO: old tunnel put here the remote source_name into stream name e.g. 'Null Output for lynxis@lazus' -#: ../src/modules/module-tunnel-sink-new.c:309 -#: ../src/modules/module-tunnel-source-new.c:307 +#: src/modules/module-tunnel-sink-new.c:307 +#: src/modules/module-tunnel-source-new.c:305 #, c-format msgid "Tunnel for %s@%s" msgstr "%s@%s 的穿隧道" -#: ../src/modules/module-tunnel-sink-new.c:532 -#: ../src/modules/module-tunnel-source-new.c:528 +#: src/modules/module-tunnel-sink-new.c:544 +#: src/modules/module-tunnel-source-new.c:540 #, c-format msgid "Tunnel to %s/%s" msgstr "前往 %s/%s 的穿隧道" -#: ../src/modules/module-virtual-surround-sink.c:47 +#: src/modules/module-virtual-surround-sink.c:45 msgid "Virtual surround sink" msgstr "虛擬環繞聲 sink" -#: ../src/modules/module-virtual-surround-sink.c:51 +#: src/modules/module-virtual-surround-sink.c:49 msgid "" "sink_name=<name for the sink> sink_properties=<properties for the sink> " "master=<name of sink to filter> sink_master=<name of sink to filter> " @@ -1121,641 +1234,648 @@ msgstr "" "force_flat_volume=<是或否> hrir=/path/to/left_hrir.wav autoloaded=<設定此模組" "是否自動被載入> " -#: ../src/modules/reserve-wrap.c:149 +#: src/modules/raop/module-raop-discover.c:295 +#| msgid "Unknown error code" +msgid "Unknown device model" +msgstr "未知裝置型號" + +#: src/modules/raop/raop-sink.c:653 +msgid "RAOP standard profile" +msgstr "RAOP 標準設定檔" + +#: src/modules/reserve-wrap.c:149 msgid "PulseAudio Sound Server" msgstr "PulseAudio 音效伺服器" -#: ../src/pulse/channelmap.c:103 ../src/pulse/channelmap.c:771 -msgid "Mono" -msgstr "單聲道" - -#: ../src/pulse/channelmap.c:105 +#: src/pulse/channelmap.c:105 msgid "Front Center" msgstr "正前方" -#: ../src/pulse/channelmap.c:106 +#: src/pulse/channelmap.c:106 msgid "Front Left" msgstr "左前方" -#: ../src/pulse/channelmap.c:107 +#: src/pulse/channelmap.c:107 msgid "Front Right" msgstr "右前方" -#: ../src/pulse/channelmap.c:109 +#: src/pulse/channelmap.c:109 msgid "Rear Center" msgstr "正後方" -#: ../src/pulse/channelmap.c:110 +#: src/pulse/channelmap.c:110 msgid "Rear Left" msgstr "左後方" -#: ../src/pulse/channelmap.c:111 +#: src/pulse/channelmap.c:111 msgid "Rear Right" msgstr "右後方" -#: ../src/pulse/channelmap.c:113 +#: src/pulse/channelmap.c:113 msgid "Subwoofer" msgstr "超低音喇叭" -#: ../src/pulse/channelmap.c:115 +#: src/pulse/channelmap.c:115 msgid "Front Left-of-center" msgstr "前方中央偏左" -#: ../src/pulse/channelmap.c:116 +#: src/pulse/channelmap.c:116 msgid "Front Right-of-center" msgstr "前方中央偏右" -#: ../src/pulse/channelmap.c:118 +#: src/pulse/channelmap.c:118 msgid "Side Left" msgstr "左側" -#: ../src/pulse/channelmap.c:119 +#: src/pulse/channelmap.c:119 msgid "Side Right" msgstr "右側" -#: ../src/pulse/channelmap.c:121 +#: src/pulse/channelmap.c:121 msgid "Auxiliary 0" msgstr "輔助 0" -#: ../src/pulse/channelmap.c:122 +#: src/pulse/channelmap.c:122 msgid "Auxiliary 1" msgstr "輔助 1" -#: ../src/pulse/channelmap.c:123 +#: src/pulse/channelmap.c:123 msgid "Auxiliary 2" msgstr "輔助 2" -#: ../src/pulse/channelmap.c:124 +#: src/pulse/channelmap.c:124 msgid "Auxiliary 3" msgstr "輔助 3" -#: ../src/pulse/channelmap.c:125 +#: src/pulse/channelmap.c:125 msgid "Auxiliary 4" msgstr "輔助 4" -#: ../src/pulse/channelmap.c:126 +#: src/pulse/channelmap.c:126 msgid "Auxiliary 5" msgstr "輔助 5" -#: ../src/pulse/channelmap.c:127 +#: src/pulse/channelmap.c:127 msgid "Auxiliary 6" msgstr "輔助 6" -#: ../src/pulse/channelmap.c:128 +#: src/pulse/channelmap.c:128 msgid "Auxiliary 7" msgstr "輔助 7" -#: ../src/pulse/channelmap.c:129 +#: src/pulse/channelmap.c:129 msgid "Auxiliary 8" msgstr "輔助 8" -#: ../src/pulse/channelmap.c:130 +#: src/pulse/channelmap.c:130 msgid "Auxiliary 9" msgstr "輔助 9" -#: ../src/pulse/channelmap.c:131 +#: src/pulse/channelmap.c:131 msgid "Auxiliary 10" msgstr "輔助 10" -#: ../src/pulse/channelmap.c:132 +#: src/pulse/channelmap.c:132 msgid "Auxiliary 11" msgstr "輔助 11" -#: ../src/pulse/channelmap.c:133 +#: src/pulse/channelmap.c:133 msgid "Auxiliary 12" msgstr "輔助 12" -#: ../src/pulse/channelmap.c:134 +#: src/pulse/channelmap.c:134 msgid "Auxiliary 13" msgstr "輔助 13" -#: ../src/pulse/channelmap.c:135 +#: src/pulse/channelmap.c:135 msgid "Auxiliary 14" msgstr "輔助 14" -#: ../src/pulse/channelmap.c:136 +#: src/pulse/channelmap.c:136 msgid "Auxiliary 15" msgstr "輔助 15" -#: ../src/pulse/channelmap.c:137 +#: src/pulse/channelmap.c:137 msgid "Auxiliary 16" msgstr "輔助 16" -#: ../src/pulse/channelmap.c:138 +#: src/pulse/channelmap.c:138 msgid "Auxiliary 17" msgstr "輔助 17" -#: ../src/pulse/channelmap.c:139 +#: src/pulse/channelmap.c:139 msgid "Auxiliary 18" msgstr "輔助 18" -#: ../src/pulse/channelmap.c:140 +#: src/pulse/channelmap.c:140 msgid "Auxiliary 19" msgstr "輔助 19" -#: ../src/pulse/channelmap.c:141 +#: src/pulse/channelmap.c:141 msgid "Auxiliary 20" msgstr "輔助 20" -#: ../src/pulse/channelmap.c:142 +#: src/pulse/channelmap.c:142 msgid "Auxiliary 21" msgstr "輔助 21" -#: ../src/pulse/channelmap.c:143 +#: src/pulse/channelmap.c:143 msgid "Auxiliary 22" msgstr "輔助 22" -#: ../src/pulse/channelmap.c:144 +#: src/pulse/channelmap.c:144 msgid "Auxiliary 23" msgstr "輔助 23" -#: ../src/pulse/channelmap.c:145 +#: src/pulse/channelmap.c:145 msgid "Auxiliary 24" msgstr "輔助 24" -#: ../src/pulse/channelmap.c:146 +#: src/pulse/channelmap.c:146 msgid "Auxiliary 25" msgstr "輔助 25" -#: ../src/pulse/channelmap.c:147 +#: src/pulse/channelmap.c:147 msgid "Auxiliary 26" msgstr "輔助 26" -#: ../src/pulse/channelmap.c:148 +#: src/pulse/channelmap.c:148 msgid "Auxiliary 27" msgstr "輔助 27" -#: ../src/pulse/channelmap.c:149 +#: src/pulse/channelmap.c:149 msgid "Auxiliary 28" msgstr "輔助 28" -#: ../src/pulse/channelmap.c:150 +#: src/pulse/channelmap.c:150 msgid "Auxiliary 29" msgstr "輔助 29" -#: ../src/pulse/channelmap.c:151 +#: src/pulse/channelmap.c:151 msgid "Auxiliary 30" msgstr "輔助 30" -#: ../src/pulse/channelmap.c:152 +#: src/pulse/channelmap.c:152 msgid "Auxiliary 31" msgstr "輔助 31" -#: ../src/pulse/channelmap.c:154 +#: src/pulse/channelmap.c:154 msgid "Top Center" msgstr "正上方" -#: ../src/pulse/channelmap.c:156 +#: src/pulse/channelmap.c:156 msgid "Top Front Center" msgstr "頂端正上方" -#: ../src/pulse/channelmap.c:157 +#: src/pulse/channelmap.c:157 msgid "Top Front Left" msgstr "頂端左前方" -#: ../src/pulse/channelmap.c:158 +#: src/pulse/channelmap.c:158 msgid "Top Front Right" msgstr "頂端右前方" -#: ../src/pulse/channelmap.c:160 +#: src/pulse/channelmap.c:160 msgid "Top Rear Center" msgstr "頂端正後方" -#: ../src/pulse/channelmap.c:161 +#: src/pulse/channelmap.c:161 msgid "Top Rear Left" msgstr "頂端左後方" -#: ../src/pulse/channelmap.c:162 +#: src/pulse/channelmap.c:162 msgid "Top Rear Right" msgstr "頂端右後方" -#: ../src/pulse/channelmap.c:479 ../src/pulse/format.c:121 -#: ../src/pulse/sample.c:177 ../src/pulse/volume.c:306 -#: ../src/pulse/volume.c:332 ../src/pulse/volume.c:352 -#: ../src/pulse/volume.c:384 ../src/pulse/volume.c:424 -#: ../src/pulse/volume.c:443 +#: src/pulse/channelmap.c:479 src/pulse/format.c:123 src/pulse/sample.c:177 +#: src/pulse/volume.c:306 src/pulse/volume.c:332 src/pulse/volume.c:352 +#: src/pulse/volume.c:384 src/pulse/volume.c:424 src/pulse/volume.c:443 msgid "(invalid)" msgstr "(無效)" -#: ../src/pulse/channelmap.c:780 +#: src/pulse/channelmap.c:780 msgid "Surround 4.0" msgstr "環繞聲 4.0" -#: ../src/pulse/channelmap.c:786 +#: src/pulse/channelmap.c:786 msgid "Surround 4.1" msgstr "環繞聲 4.1" -#: ../src/pulse/channelmap.c:792 +#: src/pulse/channelmap.c:792 msgid "Surround 5.0" msgstr "環繞聲 5.0" -#: ../src/pulse/channelmap.c:798 +#: src/pulse/channelmap.c:798 msgid "Surround 5.1" msgstr "環繞聲 5.1" -#: ../src/pulse/channelmap.c:805 +#: src/pulse/channelmap.c:805 msgid "Surround 7.1" msgstr "環繞聲 7.1" -#: ../src/pulse/client-conf-x11.c:53 ../src/utils/pax11publish.c:97 +#: src/pulse/client-conf-x11.c:61 src/utils/pax11publish.c:97 msgid "xcb_connect() failed" msgstr "xcb_connect() 失敗" -#: ../src/pulse/client-conf-x11.c:58 ../src/utils/pax11publish.c:102 +#: src/pulse/client-conf-x11.c:66 src/utils/pax11publish.c:102 msgid "xcb_connection_has_error() returned true" msgstr "xcb_connection_has_error() 傳回真值" -#: ../src/pulse/client-conf-x11.c:94 +#: src/pulse/client-conf-x11.c:102 msgid "Failed to parse cookie data" msgstr "未能解析 cookie 資料" -#: ../src/pulse/context.c:702 +#: src/pulse/context.c:706 #, c-format msgid "fork(): %s" msgstr "fork():%s" -#: ../src/pulse/context.c:757 +#: src/pulse/context.c:761 #, c-format msgid "waitpid(): %s" msgstr "waitpid():%s" -#: ../src/pulse/context.c:1463 +#: src/pulse/context.c:1467 #, c-format msgid "Received message for unknown extension '%s'" msgstr "已接收到未知擴展功能的訊息「%s」" -#: ../src/pulse/direction.c:37 +#: src/pulse/direction.c:37 msgid "input" msgstr "輸入" -#: ../src/pulse/direction.c:39 +#: src/pulse/direction.c:39 msgid "output" msgstr "輸出" -#: ../src/pulse/direction.c:41 +#: src/pulse/direction.c:41 msgid "bidirectional" msgstr "雙向" -#: ../src/pulse/direction.c:43 +#: src/pulse/direction.c:43 msgid "invalid" msgstr "無效" -#: ../src/pulsecore/core-util.c:1856 +#: src/pulsecore/core-util.c:1712 #, c-format +#| msgid "" +#| "XDG_RUNTIME_DIR (%s) is not owned by us (uid %d), but by uid %d! (This " +#| "could e g happen if you try to connect to a non-root PulseAudio as a root " +#| "user, over the native protocol. Don't do that.)" msgid "" "XDG_RUNTIME_DIR (%s) is not owned by us (uid %d), but by uid %d! (This could " -"e g happen if you try to connect to a non-root PulseAudio as a root user, " +"e.g. happen if you try to connect to a non-root PulseAudio as a root user, " "over the native protocol. Don't do that.)" msgstr "" "XDG_RUNTIME_DIR (%s) 並非為我們 (uid %d) 所有,擁有者實為 uid %d!(如果您試圖" "以 root 使用者身份、透過原生協定連接到非 root PulseAudio 的話有可能發生這種狀" "況。請不要這麼做。)" -#: ../src/pulsecore/core-util.h:97 +#: src/pulsecore/core-util.h:96 msgid "yes" msgstr "是" -#: ../src/pulsecore/core-util.h:97 +#: src/pulsecore/core-util.h:96 msgid "no" msgstr "否" -#: ../src/pulsecore/lock-autospawn.c:141 ../src/pulsecore/lock-autospawn.c:227 +#: src/pulsecore/lock-autospawn.c:141 src/pulsecore/lock-autospawn.c:227 msgid "Cannot access autospawn lock." msgstr "無法存取 autospawn 鎖。" -#: ../src/pulsecore/log.c:165 +#: src/pulsecore/log.c:165 #, c-format msgid "Failed to open target file '%s'." msgstr "無法開啟目標檔「%s」。" -#: ../src/pulsecore/log.c:188 +#: src/pulsecore/log.c:188 #, c-format msgid "" "Tried to open target file '%s', '%s.1', '%s.2' ... '%s.%d', but all failed." msgstr "試圖開啟目標檔「%s」、「%s.1」、「%s.2」...「%s.%d」,但全都失敗。" -#: ../src/pulsecore/log.c:651 +#: src/pulsecore/log.c:651 msgid "Invalid log target." msgstr "無效的紀錄目標。" -#: ../src/pulsecore/sink.c:3490 +#: src/pulsecore/sink.c:3524 msgid "Built-in Audio" msgstr "內部音效" -#: ../src/pulsecore/sink.c:3495 +#: src/pulsecore/sink.c:3529 msgid "Modem" msgstr "數據機" -#: ../src/pulse/error.c:38 +#: src/pulse/error.c:38 msgid "OK" msgstr "確定" -#: ../src/pulse/error.c:39 +#: src/pulse/error.c:39 msgid "Access denied" msgstr "拒絕存取" -#: ../src/pulse/error.c:40 +#: src/pulse/error.c:40 msgid "Unknown command" msgstr "未知指令" -#: ../src/pulse/error.c:41 +#: src/pulse/error.c:41 msgid "Invalid argument" msgstr "無效的參數" -#: ../src/pulse/error.c:42 +#: src/pulse/error.c:42 msgid "Entity exists" msgstr "實體存在" -#: ../src/pulse/error.c:43 +#: src/pulse/error.c:43 msgid "No such entity" msgstr "無此實體" -#: ../src/pulse/error.c:44 +#: src/pulse/error.c:44 msgid "Connection refused" msgstr "拒絕連線" -#: ../src/pulse/error.c:45 +#: src/pulse/error.c:45 msgid "Protocol error" msgstr "協定錯誤" -#: ../src/pulse/error.c:46 +#: src/pulse/error.c:46 msgid "Timeout" msgstr "逾時" -#: ../src/pulse/error.c:47 +#: src/pulse/error.c:47 msgid "No authentication key" msgstr "無認證金鑰" -#: ../src/pulse/error.c:48 +#: src/pulse/error.c:48 msgid "Internal error" msgstr "內部錯誤" -#: ../src/pulse/error.c:49 +#: src/pulse/error.c:49 msgid "Connection terminated" msgstr "連線已終止" -#: ../src/pulse/error.c:50 +#: src/pulse/error.c:50 msgid "Entity killed" msgstr "實體已結束" -#: ../src/pulse/error.c:51 +#: src/pulse/error.c:51 msgid "Invalid server" msgstr "無效的伺服器" -#: ../src/pulse/error.c:52 +#: src/pulse/error.c:52 msgid "Module initialization failed" msgstr "模組初始化失敗" -#: ../src/pulse/error.c:53 +#: src/pulse/error.c:53 msgid "Bad state" msgstr "不良狀態" -#: ../src/pulse/error.c:54 +#: src/pulse/error.c:54 msgid "No data" msgstr "無資料" -#: ../src/pulse/error.c:55 +#: src/pulse/error.c:55 msgid "Incompatible protocol version" msgstr "不相容的協定版本" -#: ../src/pulse/error.c:56 +#: src/pulse/error.c:56 msgid "Too large" msgstr "過大" -#: ../src/pulse/error.c:57 +#: src/pulse/error.c:57 msgid "Not supported" msgstr "不支援" -#: ../src/pulse/error.c:58 +#: src/pulse/error.c:58 msgid "Unknown error code" msgstr "未知的錯誤碼" -#: ../src/pulse/error.c:59 +#: src/pulse/error.c:59 msgid "No such extension" msgstr "無此擴展功能" -#: ../src/pulse/error.c:60 +#: src/pulse/error.c:60 msgid "Obsolete functionality" msgstr "淘汰的功能" -#: ../src/pulse/error.c:61 +#: src/pulse/error.c:61 msgid "Missing implementation" msgstr "遺失的實作" -#: ../src/pulse/error.c:62 +#: src/pulse/error.c:62 msgid "Client forked" msgstr "客戶端已分支" -#: ../src/pulse/error.c:63 +#: src/pulse/error.c:63 msgid "Input/Output error" msgstr "輸入/輸出 錯誤" -#: ../src/pulse/error.c:64 +#: src/pulse/error.c:64 msgid "Device or resource busy" msgstr "裝置或資源忙碌" -#: ../src/pulse/sample.c:179 +#: src/pulse/sample.c:179 #, c-format msgid "%s %uch %uHz" msgstr "%s %uch %uHz" -#: ../src/pulse/sample.c:191 +#: src/pulse/sample.c:191 #, c-format msgid "%0.1f GiB" msgstr "%0.1f GiB" -#: ../src/pulse/sample.c:193 +#: src/pulse/sample.c:193 #, c-format msgid "%0.1f MiB" msgstr "%0.1f MiB" -#: ../src/pulse/sample.c:195 +#: src/pulse/sample.c:195 #, c-format msgid "%0.1f KiB" msgstr "%0.1f KiB" -#: ../src/pulse/sample.c:197 +#: src/pulse/sample.c:197 #, c-format msgid "%u B" msgstr "%u B" -#: ../src/utils/pacat.c:134 +#: src/utils/pacat.c:134 #, c-format msgid "Failed to drain stream: %s" msgstr "未能排出串流:%s" -#: ../src/utils/pacat.c:139 +#: src/utils/pacat.c:139 msgid "Playback stream drained." msgstr "播放控制串流已排出。" -#: ../src/utils/pacat.c:150 +#: src/utils/pacat.c:150 msgid "Draining connection to server." msgstr "正在排出連線到伺服器。" -#: ../src/utils/pacat.c:163 +#: src/utils/pacat.c:163 #, c-format msgid "pa_stream_drain(): %s" msgstr "pa_stream_drain():%s" -#: ../src/utils/pacat.c:194 ../src/utils/pacat.c:543 +#: src/utils/pacat.c:194 src/utils/pacat.c:543 #, c-format msgid "pa_stream_begin_write() failed: %s" msgstr "pa_stream_begin_write() 失敗:%s" -#: ../src/utils/pacat.c:244 ../src/utils/pacat.c:274 +#: src/utils/pacat.c:244 src/utils/pacat.c:274 #, c-format msgid "pa_stream_peek() failed: %s" msgstr "pa_stream_peek() 失敗:%s" -#: ../src/utils/pacat.c:324 +#: src/utils/pacat.c:324 msgid "Stream successfully created." msgstr "已成功建立串流。" -#: ../src/utils/pacat.c:327 +#: src/utils/pacat.c:327 #, c-format msgid "pa_stream_get_buffer_attr() failed: %s" msgstr "pa_stream_get_buffer_attr() 失敗:%s" -#: ../src/utils/pacat.c:331 +#: src/utils/pacat.c:331 #, c-format msgid "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u" msgstr "緩衝矩陣:maxlength=%u, tlength=%u, prebuf=%u, minreq=%u" -#: ../src/utils/pacat.c:334 +#: src/utils/pacat.c:334 #, c-format msgid "Buffer metrics: maxlength=%u, fragsize=%u" msgstr "緩衝矩陣:maxlength=%u, fragsize=%u" -#: ../src/utils/pacat.c:338 +#: src/utils/pacat.c:338 #, c-format msgid "Using sample spec '%s', channel map '%s'." msgstr "使用取樣規格「%s」,聲道對應表「%s」" -#: ../src/utils/pacat.c:342 +#: src/utils/pacat.c:342 #, c-format msgid "Connected to device %s (index: %u, suspended: %s)." msgstr "已連接到裝置 %s(索引:%u,已暫停:%s)。" -#: ../src/utils/pacat.c:352 +#: src/utils/pacat.c:352 #, c-format msgid "Stream error: %s" msgstr "串流錯誤:%s" -#: ../src/utils/pacat.c:362 +#: src/utils/pacat.c:362 #, c-format msgid "Stream device suspended.%s" msgstr "串流裝置已暫停。%s" -#: ../src/utils/pacat.c:364 +#: src/utils/pacat.c:364 #, c-format msgid "Stream device resumed.%s" msgstr "串流裝置已恢復。%s" -#: ../src/utils/pacat.c:372 +#: src/utils/pacat.c:372 #, c-format msgid "Stream underrun.%s" msgstr "串流欠載運行。%s" -#: ../src/utils/pacat.c:379 +#: src/utils/pacat.c:379 #, c-format msgid "Stream overrun.%s" msgstr "串流超載運行。%s" -#: ../src/utils/pacat.c:386 +#: src/utils/pacat.c:386 #, c-format msgid "Stream started.%s" msgstr "串流已開始。%s" -#: ../src/utils/pacat.c:393 +#: src/utils/pacat.c:393 #, c-format msgid "Stream moved to device %s (%u, %ssuspended).%s" msgstr "串流移至裝置 %s(%u,%s已暫停)。%s" -#: ../src/utils/pacat.c:393 +#: src/utils/pacat.c:393 msgid "not " msgstr "不是" -#: ../src/utils/pacat.c:400 +#: src/utils/pacat.c:400 #, c-format msgid "Stream buffer attributes changed.%s" msgstr "串流緩衝特徵已變更。%s" -#: ../src/utils/pacat.c:415 +#: src/utils/pacat.c:415 msgid "Cork request stack is empty: corking stream" msgstr "Cork 請求堆疊為空:corking 串流" -#: ../src/utils/pacat.c:421 +#: src/utils/pacat.c:421 msgid "Cork request stack is empty: uncorking stream" msgstr "Cork 請求堆疊為空:uncorking 串流" -#: ../src/utils/pacat.c:425 +#: src/utils/pacat.c:425 msgid "Warning: Received more uncork requests than cork requests." msgstr "警告:已接收到多於 cork 請求的 uncork 請求。" -#: ../src/utils/pacat.c:450 +#: src/utils/pacat.c:450 #, c-format msgid "Connection established.%s" msgstr "連線已建立。%s" -#: ../src/utils/pacat.c:453 +#: src/utils/pacat.c:453 #, c-format msgid "pa_stream_new() failed: %s" msgstr "pa_stream_new() 失敗:%s" -#: ../src/utils/pacat.c:491 +#: src/utils/pacat.c:491 #, c-format msgid "pa_stream_connect_playback() failed: %s" msgstr "pa_stream_connect_playback() 失敗:%s" -#: ../src/utils/pacat.c:497 +#: src/utils/pacat.c:497 #, c-format msgid "Failed to set monitor stream: %s" msgstr "無法設定監聽器串流:%s" -#: ../src/utils/pacat.c:501 +#: src/utils/pacat.c:501 #, c-format msgid "pa_stream_connect_record() failed: %s" msgstr "pa_stream_connect_record() 失敗:%s" -#: ../src/utils/pacat.c:514 ../src/utils/pactl.c:1446 +#: src/utils/pacat.c:514 src/utils/pactl.c:1454 #, c-format msgid "Connection failure: %s" msgstr "連線失敗:%s" -#: ../src/utils/pacat.c:557 +#: src/utils/pacat.c:557 msgid "Got EOF." msgstr "已取得 EOF。" -#: ../src/utils/pacat.c:581 +#: src/utils/pacat.c:581 #, c-format msgid "pa_stream_write() failed: %s" msgstr "pa_stream_write() failed:%s" -#: ../src/utils/pacat.c:605 +#: src/utils/pacat.c:605 #, c-format msgid "write() failed: %s" msgstr "write() 失敗:%s" -#: ../src/utils/pacat.c:626 +#: src/utils/pacat.c:626 msgid "Got signal, exiting." msgstr "已取得訊號,正在退出。" -#: ../src/utils/pacat.c:640 +#: src/utils/pacat.c:640 #, c-format msgid "Failed to get latency: %s" msgstr "未能取得傳輸延遲:%s" -#: ../src/utils/pacat.c:645 +#: src/utils/pacat.c:645 #, c-format msgid "Time: %0.3f sec; Latency: %0.0f usec." msgstr "時間:%0.3f 秒;延遲:%0.0f 微秒。" -#: ../src/utils/pacat.c:666 +#: src/utils/pacat.c:666 #, c-format msgid "pa_stream_update_timing_info() failed: %s" msgstr "pa_stream_update_timing_info() 失敗:%s" -#: ../src/utils/pacat.c:676 +#: src/utils/pacat.c:676 #, c-format msgid "" "%s [options]\n" @@ -1868,28 +1988,28 @@ msgstr "" " --list-file-formats 列出可用的檔案格式。\n" " --monitor-stream=INDEX 從 sink 輸入以索引 INDEX 錄製。\n" -#: ../src/utils/pacat.c:793 +#: src/utils/pacat.c:793 msgid "Play back encoded audio files on a PulseAudio sound server." msgstr "在 PulseAudio 音效伺服器回放編碼音訊檔案。" -#: ../src/utils/pacat.c:797 +#: src/utils/pacat.c:797 msgid "" "Capture audio data from a PulseAudio sound server and write it to a file." msgstr "從 PulseAudio 音效伺服器捕捉音訊資料並寫入檔案中。" -#: ../src/utils/pacat.c:801 +#: src/utils/pacat.c:801 msgid "" "Capture audio data from a PulseAudio sound server and write it to STDOUT or " "the specified file." msgstr "從 PulseAudio 音效伺服器捕捉音訊資料並寫入 STDOUT 或指定檔案中。" -#: ../src/utils/pacat.c:805 +#: src/utils/pacat.c:805 msgid "" "Play back audio data from STDIN or the specified file on a PulseAudio sound " "server." msgstr "在 PulseAudio 音效伺服器回放取自 STDIN 的音訊資料或指定的檔案。" -#: ../src/utils/pacat.c:819 +#: src/utils/pacat.c:819 #, c-format msgid "" "pacat %s\n" @@ -1900,226 +2020,226 @@ msgstr "" "以 libpulse %s 編譯\n" "以 libpulse %s 連結\n" -#: ../src/utils/pacat.c:852 ../src/utils/pactl.c:1648 +#: src/utils/pacat.c:852 src/utils/pactl.c:1656 #, c-format msgid "Invalid client name '%s'" msgstr "無效的客戶端名稱「%s」" -#: ../src/utils/pacat.c:867 +#: src/utils/pacat.c:867 #, c-format msgid "Invalid stream name '%s'" msgstr "無效的串流名稱「%s」" -#: ../src/utils/pacat.c:904 +#: src/utils/pacat.c:904 #, c-format msgid "Invalid channel map '%s'" msgstr "無效的聲道對應表「%s」" -#: ../src/utils/pacat.c:933 ../src/utils/pacat.c:947 +#: src/utils/pacat.c:933 src/utils/pacat.c:947 #, c-format msgid "Invalid latency specification '%s'" msgstr "無效的延遲規格「%s」" -#: ../src/utils/pacat.c:940 ../src/utils/pacat.c:954 +#: src/utils/pacat.c:940 src/utils/pacat.c:954 #, c-format msgid "Invalid process time specification '%s'" msgstr "無效的程序時間規格「%s」" -#: ../src/utils/pacat.c:966 +#: src/utils/pacat.c:966 #, c-format msgid "Invalid property '%s'" msgstr "無效的屬性「%s」" -#: ../src/utils/pacat.c:985 +#: src/utils/pacat.c:985 #, c-format msgid "Unknown file format %s." msgstr "未知檔案格式 %s。" -#: ../src/utils/pacat.c:1000 +#: src/utils/pacat.c:1000 msgid "Failed to parse the argument for --monitor-stream" msgstr "無法解析 --monitor-stream 的引數" -#: ../src/utils/pacat.c:1011 +#: src/utils/pacat.c:1011 msgid "Invalid sample specification" msgstr "無效的取樣規格" -#: ../src/utils/pacat.c:1021 +#: src/utils/pacat.c:1021 #, c-format msgid "open(): %s" msgstr "open():%s" -#: ../src/utils/pacat.c:1026 +#: src/utils/pacat.c:1026 #, c-format msgid "dup2(): %s" msgstr "dup2():%s" -#: ../src/utils/pacat.c:1033 +#: src/utils/pacat.c:1033 msgid "Too many arguments." msgstr "太多參數。" -#: ../src/utils/pacat.c:1044 +#: src/utils/pacat.c:1044 msgid "Failed to generate sample specification for file." msgstr "未能替檔案產生取樣規格。" -#: ../src/utils/pacat.c:1070 +#: src/utils/pacat.c:1070 msgid "Failed to open audio file." msgstr "未能開啟音效檔。" -#: ../src/utils/pacat.c:1076 +#: src/utils/pacat.c:1076 msgid "" "Warning: specified sample specification will be overwritten with " "specification from file." msgstr "警告:指定的取樣規格將會覆寫從檔案得到的規格。" -#: ../src/utils/pacat.c:1079 ../src/utils/pactl.c:1712 +#: src/utils/pacat.c:1079 src/utils/pactl.c:1720 msgid "Failed to determine sample specification from file." msgstr "未能從檔案得知取樣規格。" -#: ../src/utils/pacat.c:1088 +#: src/utils/pacat.c:1088 msgid "Warning: Failed to determine channel map from file." msgstr "警告:未能從檔案取得聲道對應表。" -#: ../src/utils/pacat.c:1099 +#: src/utils/pacat.c:1099 msgid "Channel map doesn't match sample specification" msgstr "聲道對應表與取樣規格不符" -#: ../src/utils/pacat.c:1110 +#: src/utils/pacat.c:1110 msgid "Warning: failed to write channel map to file." msgstr "警告:未能將聲道對應表寫入檔案。" -#: ../src/utils/pacat.c:1125 +#: src/utils/pacat.c:1125 #, c-format msgid "" "Opening a %s stream with sample specification '%s' and channel map '%s'." msgstr "正在開啟一道 %s 串流,取樣規格為「%s」,聲道對應表為「%s」。" -#: ../src/utils/pacat.c:1126 +#: src/utils/pacat.c:1126 msgid "recording" msgstr "錄製中" -#: ../src/utils/pacat.c:1126 +#: src/utils/pacat.c:1126 msgid "playback" msgstr "播放控制" -#: ../src/utils/pacat.c:1150 +#: src/utils/pacat.c:1150 msgid "Failed to set media name." msgstr "未能設定媒體名稱。" -#: ../src/utils/pacat.c:1160 ../src/utils/pactl.c:2062 +#: src/utils/pacat.c:1160 src/utils/pactl.c:2070 msgid "pa_mainloop_new() failed." msgstr "pa_mainloop_new() 失敗。" -#: ../src/utils/pacat.c:1183 +#: src/utils/pacat.c:1183 msgid "io_new() failed." msgstr "io_new() 失敗。" -#: ../src/utils/pacat.c:1190 ../src/utils/pactl.c:2074 +#: src/utils/pacat.c:1190 src/utils/pactl.c:2082 msgid "pa_context_new() failed." msgstr "pa_context_new() 失敗。" -#: ../src/utils/pacat.c:1198 ../src/utils/pactl.c:2080 +#: src/utils/pacat.c:1198 src/utils/pactl.c:2088 #, c-format msgid "pa_context_connect() failed: %s" msgstr "pa_context_connect() 失敗:%s" -#: ../src/utils/pacat.c:1204 +#: src/utils/pacat.c:1204 msgid "pa_context_rttime_new() failed." msgstr "pa_context_rttime_new() 失敗。" -#: ../src/utils/pacat.c:1211 ../src/utils/pactl.c:2085 +#: src/utils/pacat.c:1211 src/utils/pactl.c:2093 msgid "pa_mainloop_run() failed." msgstr "pa_mainloop_run() 失敗。" -#: ../src/utils/pacmd.c:51 ../src/utils/pactl.c:1570 +#: src/utils/pacmd.c:51 src/utils/pactl.c:1578 msgid "NAME [ARGS ...]" msgstr "NAME [ARGS ...]" -#: ../src/utils/pacmd.c:52 ../src/utils/pacmd.c:60 ../src/utils/pactl.c:1571 +#: src/utils/pacmd.c:52 src/utils/pacmd.c:60 src/utils/pactl.c:1579 msgid "NAME|#N" msgstr "NAME|#N" -#: ../src/utils/pacmd.c:53 ../src/utils/pacmd.c:63 ../src/utils/pactl.c:1569 -#: ../src/utils/pactl.c:1575 +#: src/utils/pacmd.c:53 src/utils/pacmd.c:63 src/utils/pactl.c:1577 +#: src/utils/pactl.c:1583 msgid "NAME" msgstr "NAME" -#: ../src/utils/pacmd.c:54 +#: src/utils/pacmd.c:54 msgid "NAME|#N VOLUME" msgstr "NAME|#N VOLUME" -#: ../src/utils/pacmd.c:55 +#: src/utils/pacmd.c:55 msgid "#N VOLUME" msgstr "#N VOLUME" -#: ../src/utils/pacmd.c:56 ../src/utils/pacmd.c:70 ../src/utils/pactl.c:1573 +#: src/utils/pacmd.c:56 src/utils/pacmd.c:70 src/utils/pactl.c:1581 msgid "NAME|#N 1|0" msgstr "NAME|#N 1|0" -#: ../src/utils/pacmd.c:57 +#: src/utils/pacmd.c:57 msgid "#N 1|0" msgstr "#N 1|0" -#: ../src/utils/pacmd.c:58 +#: src/utils/pacmd.c:58 msgid "NAME|#N KEY=VALUE" msgstr "NAME|#N KEY=VALUE" -#: ../src/utils/pacmd.c:59 +#: src/utils/pacmd.c:59 msgid "#N KEY=VALUE" msgstr "#N KEY=VALUE" -#: ../src/utils/pacmd.c:61 +#: src/utils/pacmd.c:61 msgid "#N" msgstr "#N" -#: ../src/utils/pacmd.c:62 +#: src/utils/pacmd.c:62 msgid "NAME SINK|#N" msgstr "NAME SINK|#N" -#: ../src/utils/pacmd.c:64 ../src/utils/pacmd.c:65 +#: src/utils/pacmd.c:64 src/utils/pacmd.c:65 msgid "NAME FILENAME" msgstr "NAME FILENAME" -#: ../src/utils/pacmd.c:66 +#: src/utils/pacmd.c:66 msgid "PATHNAME" msgstr "PATHNAME" -#: ../src/utils/pacmd.c:67 +#: src/utils/pacmd.c:67 msgid "FILENAME SINK|#N" msgstr "FILENAME SINK|#N" -#: ../src/utils/pacmd.c:69 ../src/utils/pactl.c:1572 +#: src/utils/pacmd.c:69 src/utils/pactl.c:1580 msgid "#N SINK|SOURCE" msgstr "#N SINK|SOURCE" -#: ../src/utils/pacmd.c:71 ../src/utils/pacmd.c:77 ../src/utils/pacmd.c:78 +#: src/utils/pacmd.c:71 src/utils/pacmd.c:77 src/utils/pacmd.c:78 msgid "1|0" msgstr "1|0" -#: ../src/utils/pacmd.c:72 ../src/utils/pactl.c:1574 +#: src/utils/pacmd.c:72 src/utils/pactl.c:1582 msgid "CARD PROFILE" msgstr "CARD PROFILE" -#: ../src/utils/pacmd.c:73 ../src/utils/pactl.c:1576 +#: src/utils/pacmd.c:73 src/utils/pactl.c:1584 msgid "NAME|#N PORT" msgstr "NAME|#N PORT" -#: ../src/utils/pacmd.c:74 ../src/utils/pactl.c:1582 +#: src/utils/pacmd.c:74 src/utils/pactl.c:1590 msgid "CARD-NAME|CARD-#N PORT OFFSET" msgstr "CARD-NAME|CARD-#N PORT OFFSET" -#: ../src/utils/pacmd.c:75 +#: src/utils/pacmd.c:75 msgid "TARGET" msgstr "TARGET" -#: ../src/utils/pacmd.c:76 +#: src/utils/pacmd.c:76 msgid "NUMERIC-LEVEL" msgstr "NUMERIC-LEVEL" -#: ../src/utils/pacmd.c:79 +#: src/utils/pacmd.c:79 msgid "FRAMES" msgstr "FRAMES" -#: ../src/utils/pacmd.c:81 +#: src/utils/pacmd.c:81 #, c-format msgid "" "\n" @@ -2132,7 +2252,7 @@ msgstr "" " --version 顯示版本\n" "當沒有給予指令時,pacmd 會以互動模式啟動。\n" -#: ../src/utils/pacmd.c:128 +#: src/utils/pacmd.c:128 #, c-format msgid "" "pacmd %s\n" @@ -2143,69 +2263,75 @@ msgstr "" "配合 libpulse %s 編譯\n" "已與 libpulse %s 連結\n" -#: ../src/utils/pacmd.c:142 +#: src/utils/pacmd.c:142 msgid "No PulseAudio daemon running, or not running as session daemon." msgstr "無 PulseAudio 幕後程式正執行中,或者未以作業階段幕後程式執行中。" -#: ../src/utils/pacmd.c:147 +#: src/utils/pacmd.c:147 #, c-format msgid "socket(PF_UNIX, SOCK_STREAM, 0): %s" msgstr "socket(PF_UNIX, SOCK_STREAM, 0):%s" -#: ../src/utils/pacmd.c:164 +#: src/utils/pacmd.c:164 #, c-format msgid "connect(): %s" msgstr "connect():%s" -#: ../src/utils/pacmd.c:172 +#: src/utils/pacmd.c:172 msgid "Failed to kill PulseAudio daemon." msgstr "未能終止 PulseAudio 幕後程式。" -#: ../src/utils/pacmd.c:180 +#: src/utils/pacmd.c:180 msgid "Daemon not responding." msgstr "幕後程式沒有回應。" -#: ../src/utils/pacmd.c:212 ../src/utils/pacmd.c:321 ../src/utils/pacmd.c:339 +#: src/utils/pacmd.c:212 src/utils/pacmd.c:321 src/utils/pacmd.c:339 #, c-format msgid "write(): %s" msgstr "write():%s" -#: ../src/utils/pacmd.c:268 +#: src/utils/pacmd.c:268 #, c-format msgid "poll(): %s" msgstr "poll():%s" -#: ../src/utils/pacmd.c:279 ../src/utils/pacmd.c:299 +#: src/utils/pacmd.c:279 src/utils/pacmd.c:299 #, c-format msgid "read(): %s" msgstr "read():%s" -#: ../src/utils/pactl.c:164 +#: src/utils/pactl.c:164 #, c-format msgid "Failed to get statistics: %s" msgstr "未能取得統計:%s" -#: ../src/utils/pactl.c:170 +#: src/utils/pactl.c:170 #, c-format -msgid "Currently in use: %u blocks containing %s bytes total.\n" -msgstr "目前使用中:%u 個區塊共包含 %s bytes。\n" +#| msgid "Currently in use: %u blocks containing %s bytes total.\n" +msgid "Currently in use: %u block containing %s bytes total.\n" +msgid_plural "Currently in use: %u blocks containing %s bytes total.\n" +msgstr[0] "目前使用中:%u 個區塊共包含 %s bytes。\n" -#: ../src/utils/pactl.c:173 +#: src/utils/pactl.c:176 #, c-format -msgid "Allocated during whole lifetime: %u blocks containing %s bytes total.\n" -msgstr "在整個生命週期間分配:%u 個區塊共包含 %s bytes。\n" +#| msgid "" +#| "Allocated during whole lifetime: %u blocks containing %s bytes total.\n" +msgid "Allocated during whole lifetime: %u block containing %s bytes total.\n" +msgid_plural "" +"Allocated during whole lifetime: %u blocks containing %s bytes total.\n" +msgstr[0] "在整個生命週期間分配:%u 個區塊共包含 %s bytes。\n" -#: ../src/utils/pactl.c:176 +#: src/utils/pactl.c:182 #, c-format msgid "Sample cache size: %s\n" msgstr "取樣快取大小:%s\n" -#: ../src/utils/pactl.c:185 +#: src/utils/pactl.c:191 #, c-format msgid "Failed to get server information: %s" msgstr "未能取得伺服器資訊:%s" -#: ../src/utils/pactl.c:190 +#: src/utils/pactl.c:196 #, c-format msgid "" "Server String: %s\n" @@ -2222,7 +2348,7 @@ msgstr "" "客戶端索引:%u\n" "Tile 大小:%zu\n" -#: ../src/utils/pactl.c:206 +#: src/utils/pactl.c:212 #, c-format msgid "" "User Name: %s\n" @@ -2245,12 +2371,12 @@ msgstr "" "預設來源:%s\n" "Cookie:%04x:%04x\n" -#: ../src/utils/pactl.c:255 ../src/utils/pactl.c:900 ../src/utils/pactl.c:978 +#: src/utils/pactl.c:261 src/utils/pactl.c:908 src/utils/pactl.c:986 #, c-format msgid "Failed to get sink information: %s" msgstr "未能取得 sink 資訊:%s" -#: ../src/utils/pactl.c:281 +#: src/utils/pactl.c:287 #, c-format msgid "" "Sink #%u\n" @@ -2289,27 +2415,27 @@ msgstr "" "\t屬性:\n" "\t\t%s\n" -#: ../src/utils/pactl.c:325 ../src/utils/pactl.c:431 ../src/utils/pactl.c:592 +#: src/utils/pactl.c:331 src/utils/pactl.c:437 src/utils/pactl.c:598 #, c-format msgid "\tPorts:\n" msgstr "\t連接埠:\n" -#: ../src/utils/pactl.c:332 ../src/utils/pactl.c:438 +#: src/utils/pactl.c:338 src/utils/pactl.c:444 #, c-format msgid "\tActive Port: %s\n" msgstr "\t使用中連接埠:%s\n" -#: ../src/utils/pactl.c:338 ../src/utils/pactl.c:444 +#: src/utils/pactl.c:344 src/utils/pactl.c:450 #, c-format msgid "\tFormats:\n" msgstr "\t格式:\n" -#: ../src/utils/pactl.c:362 ../src/utils/pactl.c:920 ../src/utils/pactl.c:993 +#: src/utils/pactl.c:368 src/utils/pactl.c:928 src/utils/pactl.c:1001 #, c-format msgid "Failed to get source information: %s" msgstr "未能取得來源資訊:%s" -#: ../src/utils/pactl.c:388 +#: src/utils/pactl.c:394 #, c-format msgid "" "Source #%u\n" @@ -2348,20 +2474,20 @@ msgstr "" "\t屬性:\n" "\t\t%s\n" -#: ../src/utils/pactl.c:416 ../src/utils/pactl.c:486 ../src/utils/pactl.c:529 -#: ../src/utils/pactl.c:571 ../src/utils/pactl.c:669 ../src/utils/pactl.c:670 -#: ../src/utils/pactl.c:681 ../src/utils/pactl.c:739 ../src/utils/pactl.c:740 -#: ../src/utils/pactl.c:751 ../src/utils/pactl.c:802 ../src/utils/pactl.c:803 -#: ../src/utils/pactl.c:809 +#: src/utils/pactl.c:422 src/utils/pactl.c:492 src/utils/pactl.c:535 +#: src/utils/pactl.c:577 src/utils/pactl.c:675 src/utils/pactl.c:676 +#: src/utils/pactl.c:687 src/utils/pactl.c:745 src/utils/pactl.c:746 +#: src/utils/pactl.c:757 src/utils/pactl.c:808 src/utils/pactl.c:809 +#: src/utils/pactl.c:815 msgid "n/a" msgstr "n/a" -#: ../src/utils/pactl.c:455 ../src/utils/pactl.c:859 +#: src/utils/pactl.c:461 src/utils/pactl.c:865 #, c-format msgid "Failed to get module information: %s" msgstr "未能取得模組資訊:%s" -#: ../src/utils/pactl.c:478 +#: src/utils/pactl.c:484 #, c-format msgid "" "Module #%u\n" @@ -2378,12 +2504,12 @@ msgstr "" "\t屬性:\n" "\t\t%s\n" -#: ../src/utils/pactl.c:497 +#: src/utils/pactl.c:503 #, c-format msgid "Failed to get client information: %s" msgstr "未能取得客戶端資訊:%s" -#: ../src/utils/pactl.c:523 +#: src/utils/pactl.c:529 #, c-format msgid "" "Client #%u\n" @@ -2398,12 +2524,12 @@ msgstr "" "\t屬性:\n" "\t\t%s\n" -#: ../src/utils/pactl.c:540 +#: src/utils/pactl.c:546 #, c-format msgid "Failed to get card information: %s" msgstr "未能取得音效卡資訊:%s" -#: ../src/utils/pactl.c:563 +#: src/utils/pactl.c:569 #, c-format msgid "" "Card #%u\n" @@ -2420,22 +2546,22 @@ msgstr "" "\t屬性:\n" "\t\t%s\n" -#: ../src/utils/pactl.c:579 +#: src/utils/pactl.c:585 #, c-format msgid "\tProfiles:\n" msgstr "\t個人設定檔:\n" -#: ../src/utils/pactl.c:581 +#: src/utils/pactl.c:587 #, c-format msgid "\t\t%s: %s (sinks: %u, sources: %u, priority: %u, available: %s)\n" msgstr "\t\t%s: %s (sink:%u,來源:%u,優先序:%u,可用:%s)\n" -#: ../src/utils/pactl.c:586 +#: src/utils/pactl.c:592 #, c-format msgid "\tActive Profile: %s\n" msgstr "\t啟用的個人設定檔:%s\n" -#: ../src/utils/pactl.c:600 +#: src/utils/pactl.c:606 #, c-format msgid "" "\t\t\tProperties:\n" @@ -2444,17 +2570,17 @@ msgstr "" "\t\t\t屬性:\n" "\t\t\t\t%s\n" -#: ../src/utils/pactl.c:605 +#: src/utils/pactl.c:611 #, c-format msgid "\t\t\tPart of profile(s): %s" msgstr "\t\t\t個人設定檔之部分:%s" -#: ../src/utils/pactl.c:622 ../src/utils/pactl.c:940 ../src/utils/pactl.c:1008 +#: src/utils/pactl.c:628 src/utils/pactl.c:948 src/utils/pactl.c:1016 #, c-format msgid "Failed to get sink input information: %s" msgstr "未能取得 sink 輸入資訊:%s" -#: ../src/utils/pactl.c:651 +#: src/utils/pactl.c:657 #, c-format msgid "" "Sink Input #%u\n" @@ -2493,12 +2619,12 @@ msgstr "" "\t屬性:\n" "\t\t%s\n" -#: ../src/utils/pactl.c:692 ../src/utils/pactl.c:960 ../src/utils/pactl.c:1023 +#: src/utils/pactl.c:698 src/utils/pactl.c:968 src/utils/pactl.c:1031 #, c-format msgid "Failed to get source output information: %s" msgstr "未能取得來源輸出資訊:%s" -#: ../src/utils/pactl.c:721 +#: src/utils/pactl.c:727 #, c-format msgid "" "Source Output #%u\n" @@ -2537,12 +2663,12 @@ msgstr "" "\t屬性:\n" "\t\t%s\n" -#: ../src/utils/pactl.c:762 +#: src/utils/pactl.c:768 #, c-format msgid "Failed to get sample information: %s" msgstr "未能取得取樣資訊:%s" -#: ../src/utils/pactl.c:789 +#: src/utils/pactl.c:795 #, c-format msgid "" "Sample #%u\n" @@ -2571,161 +2697,158 @@ msgstr "" "\t屬性:\n" "\t\t%s\n" -#: ../src/utils/pactl.c:817 ../src/utils/pactl.c:827 +#: src/utils/pactl.c:823 src/utils/pactl.c:833 #, c-format msgid "Failure: %s" msgstr "失敗:%s" -#: ../src/utils/pactl.c:866 +#: src/utils/pactl.c:872 #, c-format msgid "Failed to unload module: Module %s not loaded" msgstr "無法取消模組載入:%s 模組無法載入" -#: ../src/utils/pactl.c:884 +#: src/utils/pactl.c:890 #, c-format +#| msgid "" +#| "Failed to set volume: You tried to set volumes for %d channels, whereas " +#| "channel/s supported = %d\n" msgid "" +"Failed to set volume: You tried to set volumes for %d channel, whereas " +"channel(s) supported = %d\n" +msgid_plural "" "Failed to set volume: You tried to set volumes for %d channels, whereas " -"channel/s supported = %d\n" -msgstr "無法設定音量:您試圖設定 %d 個聲道的音量,而支援的聲道數為 = %d\n" +"channel(s) supported = %d\n" +msgstr[0] "無法設定音量:您試圖設定 %d 個聲道的音量,而支援的聲道數為 = %d\n" -#: ../src/utils/pactl.c:1050 -#, c-format -msgid "Failed to set format: invalid format string %s" -msgstr "未能設定格式:無效的格式字串 %s" - -#: ../src/utils/pactl.c:1093 +#: src/utils/pactl.c:1101 #, c-format msgid "Failed to upload sample: %s" msgstr "未能上傳樣本:%s" -#: ../src/utils/pactl.c:1110 +#: src/utils/pactl.c:1118 msgid "Premature end of file" msgstr "未完成的檔案結尾" -#: ../src/utils/pactl.c:1130 +#: src/utils/pactl.c:1138 msgid "new" msgstr "新增" -#: ../src/utils/pactl.c:1133 +#: src/utils/pactl.c:1141 msgid "change" msgstr "變更" -#: ../src/utils/pactl.c:1136 +#: src/utils/pactl.c:1144 msgid "remove" msgstr "移除" -#: ../src/utils/pactl.c:1139 ../src/utils/pactl.c:1174 +#: src/utils/pactl.c:1147 src/utils/pactl.c:1182 msgid "unknown" msgstr "未知" -#: ../src/utils/pactl.c:1147 +#: src/utils/pactl.c:1155 msgid "sink" msgstr "sink" -#: ../src/utils/pactl.c:1150 +#: src/utils/pactl.c:1158 msgid "source" msgstr "source" -#: ../src/utils/pactl.c:1153 +#: src/utils/pactl.c:1161 msgid "sink-input" msgstr "sink-input" -#: ../src/utils/pactl.c:1156 +#: src/utils/pactl.c:1164 msgid "source-output" msgstr "source-output" -#: ../src/utils/pactl.c:1159 +#: src/utils/pactl.c:1167 msgid "module" msgstr "module" -#: ../src/utils/pactl.c:1162 +#: src/utils/pactl.c:1170 msgid "client" msgstr "client" -#: ../src/utils/pactl.c:1165 +#: src/utils/pactl.c:1173 msgid "sample-cache" msgstr "sample-cache" -#: ../src/utils/pactl.c:1168 +#: src/utils/pactl.c:1176 msgid "server" msgstr "server" -#: ../src/utils/pactl.c:1171 +#: src/utils/pactl.c:1179 msgid "card" msgstr "card" -#: ../src/utils/pactl.c:1180 +#: src/utils/pactl.c:1188 #, c-format msgid "Event '%s' on %s #%u\n" msgstr "事件「%s」 於 %s #%u\n" -#: ../src/utils/pactl.c:1452 +#: src/utils/pactl.c:1460 msgid "Got SIGINT, exiting." msgstr "已取得 SIGINT,正在退出。" -#: ../src/utils/pactl.c:1485 +#: src/utils/pactl.c:1493 msgid "Invalid volume specification" msgstr "無效的音量規格" -#: ../src/utils/pactl.c:1508 +#: src/utils/pactl.c:1516 msgid "Volume outside permissible range.\n" msgstr "音量外部可允許範圍。\n" -#: ../src/utils/pactl.c:1521 +#: src/utils/pactl.c:1529 msgid "Invalid number of volume specifications.\n" msgstr "無效的音量規格。\n" -#: ../src/utils/pactl.c:1533 +#: src/utils/pactl.c:1541 msgid "Inconsistent volume specification.\n" msgstr "不一致的音量規格。\n" -#: ../src/utils/pactl.c:1563 ../src/utils/pactl.c:1564 -#: ../src/utils/pactl.c:1565 ../src/utils/pactl.c:1566 -#: ../src/utils/pactl.c:1567 ../src/utils/pactl.c:1568 -#: ../src/utils/pactl.c:1569 ../src/utils/pactl.c:1570 -#: ../src/utils/pactl.c:1571 ../src/utils/pactl.c:1572 -#: ../src/utils/pactl.c:1573 ../src/utils/pactl.c:1574 -#: ../src/utils/pactl.c:1575 ../src/utils/pactl.c:1576 -#: ../src/utils/pactl.c:1577 ../src/utils/pactl.c:1578 -#: ../src/utils/pactl.c:1579 ../src/utils/pactl.c:1580 -#: ../src/utils/pactl.c:1581 ../src/utils/pactl.c:1582 -#: ../src/utils/pactl.c:1583 +#: src/utils/pactl.c:1571 src/utils/pactl.c:1572 src/utils/pactl.c:1573 +#: src/utils/pactl.c:1574 src/utils/pactl.c:1575 src/utils/pactl.c:1576 +#: src/utils/pactl.c:1577 src/utils/pactl.c:1578 src/utils/pactl.c:1579 +#: src/utils/pactl.c:1580 src/utils/pactl.c:1581 src/utils/pactl.c:1582 +#: src/utils/pactl.c:1583 src/utils/pactl.c:1584 src/utils/pactl.c:1585 +#: src/utils/pactl.c:1586 src/utils/pactl.c:1587 src/utils/pactl.c:1588 +#: src/utils/pactl.c:1589 src/utils/pactl.c:1590 src/utils/pactl.c:1591 msgid "[options]" msgstr "[選項]" -#: ../src/utils/pactl.c:1565 +#: src/utils/pactl.c:1573 msgid "[TYPE]" msgstr "[TYPE]" -#: ../src/utils/pactl.c:1567 +#: src/utils/pactl.c:1575 msgid "FILENAME [NAME]" msgstr "FILENAME [NAME]" -#: ../src/utils/pactl.c:1568 +#: src/utils/pactl.c:1576 msgid "NAME [SINK]" msgstr "NAME [SINK]" -#: ../src/utils/pactl.c:1577 +#: src/utils/pactl.c:1585 msgid "NAME|#N VOLUME [VOLUME ...]" msgstr "NAME|#N VOLUME [VOLUME ...]" -#: ../src/utils/pactl.c:1578 +#: src/utils/pactl.c:1586 msgid "#N VOLUME [VOLUME ...]" msgstr "#N VOLUME [VOLUME ...]" -#: ../src/utils/pactl.c:1579 +#: src/utils/pactl.c:1587 msgid "NAME|#N 1|0|toggle" msgstr "NAME|#N 1|0|toggle" -#: ../src/utils/pactl.c:1580 +#: src/utils/pactl.c:1588 msgid "#N 1|0|toggle" msgstr "#N 1|0|toggle" -#: ../src/utils/pactl.c:1581 +#: src/utils/pactl.c:1589 msgid "#N FORMATS" msgstr "#N FORMATS" -#: ../src/utils/pactl.c:1584 +#: src/utils/pactl.c:1592 #, c-format msgid "" "\n" @@ -2736,7 +2859,7 @@ msgstr "" "特殊名稱 @DEFAULT_SINK@、@DEFAULT_SOURCE@ 和 @DEFAULT_MONITOR@\n" "可用來指定預設 sink、source 和 monitor。\n" -#: ../src/utils/pactl.c:1587 +#: src/utils/pactl.c:1595 #, c-format msgid "" "\n" @@ -2755,7 +2878,7 @@ msgstr "" " -s, --server=SERVER 要連接的伺服器名稱\n" " -n, --client-name=NAME 如何稱呼伺服器上的這個客戶端\n" -#: ../src/utils/pactl.c:1628 +#: src/utils/pactl.c:1636 #, c-format msgid "" "pactl %s\n" @@ -2766,202 +2889,212 @@ msgstr "" "以 libpulse %s 編譯\n" "以 libpulse %s 連結\n" -#: ../src/utils/pactl.c:1684 +#: src/utils/pactl.c:1692 #, c-format msgid "Specify nothing, or one of: %s" msgstr "沒有指定,或者為右述之一:%s" -#: ../src/utils/pactl.c:1694 +#: src/utils/pactl.c:1702 msgid "Please specify a sample file to load" msgstr "請指定要載入的取樣檔" -#: ../src/utils/pactl.c:1707 +#: src/utils/pactl.c:1715 msgid "Failed to open sound file." msgstr "未能開啟音效檔。" -#: ../src/utils/pactl.c:1719 +#: src/utils/pactl.c:1727 msgid "Warning: Failed to determine sample specification from file." msgstr "警告:未能從檔案得知取樣規格。" -#: ../src/utils/pactl.c:1729 +#: src/utils/pactl.c:1737 msgid "You have to specify a sample name to play" msgstr "您必須指定一個要播放的樣本名稱" -#: ../src/utils/pactl.c:1741 +#: src/utils/pactl.c:1749 msgid "You have to specify a sample name to remove" msgstr "您必須指定一個要移除的樣本名稱" -#: ../src/utils/pactl.c:1750 +#: src/utils/pactl.c:1758 msgid "You have to specify a sink input index and a sink" msgstr "您必須指定一項 sink 輸入索引與一個 sink" -#: ../src/utils/pactl.c:1760 +#: src/utils/pactl.c:1768 msgid "You have to specify a source output index and a source" msgstr "您必須指定一項來源輸出索引與一個來源" -#: ../src/utils/pactl.c:1775 +#: src/utils/pactl.c:1783 msgid "You have to specify a module name and arguments." msgstr "您必須指定一個模組名稱與一些參數。" -#: ../src/utils/pactl.c:1795 +#: src/utils/pactl.c:1803 msgid "You have to specify a module index or name" msgstr "您必須指定一個模組索引或名稱" -#: ../src/utils/pactl.c:1808 +#: src/utils/pactl.c:1816 msgid "" "You may not specify more than one sink. You have to specify a boolean value." msgstr "您指定的 sink 數不能超過一個。您必須指定一項布林值。" -#: ../src/utils/pactl.c:1813 ../src/utils/pactl.c:1833 +#: src/utils/pactl.c:1821 src/utils/pactl.c:1841 msgid "Invalid suspend specification." msgstr "無效的暫停規格。" -#: ../src/utils/pactl.c:1828 +#: src/utils/pactl.c:1836 msgid "" "You may not specify more than one source. You have to specify a boolean " "value." msgstr "您指定的來源數不能超過一個。您必須指定一項布林值。" -#: ../src/utils/pactl.c:1845 +#: src/utils/pactl.c:1853 msgid "You have to specify a card name/index and a profile name" msgstr "您必須指定一個音效卡名稱/索引,以及設定組合名稱" -#: ../src/utils/pactl.c:1856 +#: src/utils/pactl.c:1864 msgid "You have to specify a sink name/index and a port name" msgstr "您必須指定一個 sink 名稱/索引,以及連接埠名稱" -#: ../src/utils/pactl.c:1867 +#: src/utils/pactl.c:1875 msgid "You have to specify a sink name" msgstr "您必須指定 sink 名稱" -#: ../src/utils/pactl.c:1877 +#: src/utils/pactl.c:1885 msgid "You have to specify a source name/index and a port name" msgstr "您必須指定一個來源名稱/索引,以及連接埠名稱" -#: ../src/utils/pactl.c:1888 +#: src/utils/pactl.c:1896 msgid "You have to specify a source name" msgstr "您必須指定 source 名稱" -#: ../src/utils/pactl.c:1898 +#: src/utils/pactl.c:1906 msgid "You have to specify a sink name/index and a volume" msgstr "您必須指定一個 sink 名稱/索引,以及一項音量" -#: ../src/utils/pactl.c:1911 +#: src/utils/pactl.c:1919 msgid "You have to specify a source name/index and a volume" msgstr "您必須指定一個來源名稱/索引,以及一項音量" -#: ../src/utils/pactl.c:1924 +#: src/utils/pactl.c:1932 msgid "You have to specify a sink input index and a volume" msgstr "您必須指定一個 sink 輸入索引,以及一項音量" -#: ../src/utils/pactl.c:1929 +#: src/utils/pactl.c:1937 msgid "Invalid sink input index" msgstr "無效的 sink 輸入索引" -#: ../src/utils/pactl.c:1940 +#: src/utils/pactl.c:1948 msgid "You have to specify a source output index and a volume" msgstr "您必須指定一個來源輸出索引,以及一項音量" -#: ../src/utils/pactl.c:1945 +#: src/utils/pactl.c:1953 msgid "Invalid source output index" msgstr "無效的來源輸出索引" -#: ../src/utils/pactl.c:1956 +#: src/utils/pactl.c:1964 msgid "" "You have to specify a sink name/index and a mute action (0, 1, or 'toggle')" msgstr "您必須指定 sink 名稱/索引與靜音動作(0, 1, 或「toggle」)" -#: ../src/utils/pactl.c:1961 ../src/utils/pactl.c:1976 -#: ../src/utils/pactl.c:1996 ../src/utils/pactl.c:2014 +#: src/utils/pactl.c:1969 src/utils/pactl.c:1984 src/utils/pactl.c:2004 +#: src/utils/pactl.c:2022 msgid "Invalid mute specification" msgstr "無效的靜音規格" -#: ../src/utils/pactl.c:1971 +#: src/utils/pactl.c:1979 msgid "" "You have to specify a source name/index and a mute action (0, 1, or 'toggle')" msgstr "您必須指定來源名稱/索引與靜音動作(0, 1, 或「toggle」)" -#: ../src/utils/pactl.c:1986 +#: src/utils/pactl.c:1994 msgid "" "You have to specify a sink input index and a mute action (0, 1, or 'toggle')" msgstr "您必須指定 sink 輸入索引與靜音動作(0, 1, 或「toggle」)" -#: ../src/utils/pactl.c:1991 +#: src/utils/pactl.c:1999 msgid "Invalid sink input index specification" msgstr "無效的 sink 輸入索引規格" -#: ../src/utils/pactl.c:2004 +#: src/utils/pactl.c:2012 msgid "" "You have to specify a source output index and a mute action (0, 1, or " "'toggle')" msgstr "您必須指定來源輸出索引與靜音動作(0, 1, 或「toggle」)" -#: ../src/utils/pactl.c:2009 +#: src/utils/pactl.c:2017 msgid "Invalid source output index specification" msgstr "無效的來源輸出索引規格" -#: ../src/utils/pactl.c:2026 +#: src/utils/pactl.c:2034 msgid "" "You have to specify a sink index and a semicolon-separated list of supported " "formats" msgstr "您必須指定一個 sink 索引,以及一份以半形分號分隔、列有支援格式的清單" -#: ../src/utils/pactl.c:2038 +#: src/utils/pactl.c:2046 msgid "You have to specify a card name/index, a port name and a latency offset" msgstr "您必須指定音效卡名稱/索引、連接埠名稱和延遲偏移" -#: ../src/utils/pactl.c:2045 +#: src/utils/pactl.c:2053 msgid "Could not parse latency offset" msgstr "無法解析延遲偏移" -#: ../src/utils/pactl.c:2057 +#: src/utils/pactl.c:2065 msgid "No valid command specified." msgstr "沒有指定有效的命令。" -#: ../src/utils/pasuspender.c:79 +#: src/utils/pasuspender.c:79 #, c-format msgid "fork(): %s\n" msgstr "fork():%s\n" -#: ../src/utils/pasuspender.c:92 +#: src/utils/pasuspender.c:92 #, c-format msgid "execvp(): %s\n" msgstr "execvp():%s\n" -#: ../src/utils/pasuspender.c:111 +#: src/utils/pasuspender.c:111 #, c-format msgid "Failure to resume: %s\n" msgstr "未能恢復:%s\n" -#: ../src/utils/pasuspender.c:145 +#: src/utils/pasuspender.c:145 #, c-format msgid "Failure to suspend: %s\n" msgstr "未能暫停:%s\n" -#: ../src/utils/pasuspender.c:170 +#: src/utils/pasuspender.c:170 #, c-format msgid "WARNING: Sound server is not local, not suspending.\n" msgstr "警告:音效伺服器並非本機,不會暫停。\n" -#: ../src/utils/pasuspender.c:183 +#: src/utils/pasuspender.c:183 #, c-format msgid "Connection failure: %s\n" msgstr "連線失敗:%s\n" -#: ../src/utils/pasuspender.c:201 +#: src/utils/pasuspender.c:201 #, c-format msgid "Got SIGINT, exiting.\n" msgstr "已取得 SIGINT,正在退出。\n" -#: ../src/utils/pasuspender.c:219 +#: src/utils/pasuspender.c:219 #, c-format msgid "WARNING: Child process terminated by signal %u\n" msgstr "警告:子代程序已被訊號 %u 所終止\n" -#: ../src/utils/pasuspender.c:228 +#: src/utils/pasuspender.c:228 #, 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" msgid "" -"%s [options] ... \n" +"%s [options] -- PROGRAM [ARGUMENTS ...]\n" +"\n" +"Temporarily suspend PulseAudio while PROGRAM runs.\n" "\n" " -h, --help Show this help\n" " --version Show version\n" @@ -2969,14 +3102,16 @@ msgid "" "to\n" "\n" msgstr "" -"%s [選項] ... \n" +"%s [選項] -- 程式 [參數 ...]\n" "\n" -" -h, --help 顯示此幫助\n" +"<程式> 執行時,暫時暫停 PulseAudio。" +"\n" +" -h, --help 顯示此說明\n" " --version 顯示版本\n" -" -s, --server=SERVER 要連接的伺服器名稱\n" +" -s, --server=SERVER 要連線的伺服器名稱\n" "\n" -#: ../src/utils/pasuspender.c:266 +#: src/utils/pasuspender.c:267 #, c-format msgid "" "pasuspender %s\n" @@ -2987,22 +3122,22 @@ msgstr "" "以 libpulse %s 編譯\n" "以 libpulse %s 連結\n" -#: ../src/utils/pasuspender.c:295 +#: src/utils/pasuspender.c:296 #, c-format msgid "pa_mainloop_new() failed.\n" msgstr "pa_mainloop_new() 失敗。\n" -#: ../src/utils/pasuspender.c:308 +#: src/utils/pasuspender.c:309 #, c-format msgid "pa_context_new() failed.\n" msgstr "pa_context_new() 失敗。\n" -#: ../src/utils/pasuspender.c:320 +#: src/utils/pasuspender.c:321 #, c-format msgid "pa_mainloop_run() failed.\n" msgstr "pa_mainloop_run() 失敗。\n" -#: ../src/utils/pax11publish.c:58 +#: src/utils/pax11publish.c:58 #, c-format msgid "" "%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n" @@ -3020,56 +3155,87 @@ msgstr "" " -i 從 X11 顯示匯入 PulseAudio 資料至本地端環境變數與 cookie 檔案。\n" " -r 從 X11 顯示移除 PulseAudio 資料\n" -#: ../src/utils/pax11publish.c:91 +#: src/utils/pax11publish.c:91 #, c-format msgid "Failed to parse command line.\n" msgstr "未能解析命令列。\n" -#: ../src/utils/pax11publish.c:110 +#: src/utils/pax11publish.c:110 #, c-format msgid "Server: %s\n" msgstr "伺服器:%s\n" -#: ../src/utils/pax11publish.c:112 +#: src/utils/pax11publish.c:112 #, c-format msgid "Source: %s\n" msgstr "來源:%s\n" -#: ../src/utils/pax11publish.c:114 +#: src/utils/pax11publish.c:114 #, c-format msgid "Sink: %s\n" msgstr "Sink:%s\n" -#: ../src/utils/pax11publish.c:116 +#: src/utils/pax11publish.c:116 #, c-format msgid "Cookie: %s\n" msgstr "Cookie:%s\n" -#: ../src/utils/pax11publish.c:134 +#: src/utils/pax11publish.c:134 #, c-format msgid "Failed to parse cookie data\n" msgstr "未能解析 cookie 資料\n" -#: ../src/utils/pax11publish.c:139 +#: src/utils/pax11publish.c:139 #, c-format msgid "Failed to save cookie data\n" msgstr "未能儲存 cookie 資料\n" -#: ../src/utils/pax11publish.c:168 +#: src/utils/pax11publish.c:168 #, c-format msgid "Failed to get FQDN.\n" msgstr "未能取得 FQDN。\n" -#: ../src/utils/pax11publish.c:188 +#: src/utils/pax11publish.c:188 #, c-format msgid "Failed to load cookie data\n" msgstr "未能載入 cookie 資料\n" -#: ../src/utils/pax11publish.c:206 +#: src/utils/pax11publish.c:206 #, c-format msgid "Not yet implemented.\n" msgstr "尚未實作。\n" +#~ msgid "Failed to initialize daemon." +#~ msgstr "未能初始化幕後程式。" + +#, c-format +#~ msgid "" +#~ "ALSA woke us up to write new data to the device, but there was actually " +#~ "nothing to write!\n" +#~ "Most likely this is a bug in the ALSA driver '%s'. Please report this " +#~ "issue to the ALSA developers.\n" +#~ "We were woken up with POLLOUT set -- however a subsequent snd_pcm_avail() " +#~ "returned 0 or another value < min_avail." +#~ msgstr "" +#~ "ALSA 喚醒我們以寫入新資料至該裝置,但實際上沒有要寫入的資料!\n" +#~ "這很可能是 ALSA 驅動程式「%s」的臭蟲。請回報此問題給 ALSA 開發者。\n" +#~ "我們被 POLLOUT 設定喚醒 -- 然而後續的 snd_pcm_avail() 傳回 0 或另一個值 < " +#~ "min_avail。" + +#, c-format +#~ msgid "" +#~ "ALSA woke us up to read new data from the device, but there was actually " +#~ "nothing to read!\n" +#~ "Most likely this is a bug in the ALSA driver '%s'. Please report this " +#~ "issue to the ALSA developers.\n" +#~ "We were woken up with POLLIN set -- however a subsequent snd_pcm_avail() " +#~ "returned 0 or another value < min_avail." +#~ msgstr "" +#~ "ALSA 喚醒我們從該裝置讀取新資料,但實際上沒有可讀取的資料!\n" +#~ "這很可能是 ALSA 驅動程式「%s」的臭蟲。請回報此問題給 ALSA 開發者。\n" +#~ "我們被 POLLIN 設定喚醒 -- 然而後續的 snd_pcm_avail() 傳回 0 或另一個值 < " +#~ "min_avail。" + #~ msgid "" #~ "sink_name=<name for the sink> sink_properties=<properties for the sink> " #~ "master=<name of sink to filter> format=<sample format> rate=<sample rate> " diff --git a/scripts/Dockerfile b/scripts/Dockerfile deleted file mode 100644 index e75dbbd..0000000 --- a/scripts/Dockerfile +++ /dev/null @@ -1,65 +0,0 @@ -# Start with current Ubuntu LTS -FROM ubuntu:18.04 - -# Add a PulseAudio's dependencies -RUN apt-get update && apt-get install -y \ - autoconf \ - automake \ - autopoint \ - bash-completion \ - check \ - dbus-x11 \ - g++ \ - gcc \ - gettext \ - git-core \ - libasound2-dev \ - libasyncns-dev \ - libavahi-client-dev \ - libbluetooth-dev \ - libcap-dev \ - libfftw3-dev \ - libglib2.0-dev \ - libgtk-3-dev \ - libice-dev \ - libjack-dev \ - liblircclient-dev \ - libltdl-dev \ - liborc-0.4-dev \ - libsbc-dev \ - libsndfile1-dev \ - libsoxr-dev \ - libspeexdsp-dev \ - libssl-dev \ - libsystemd-dev \ - libtdb-dev \ - libudev-dev \ - libwebrtc-audio-processing-dev \ - libwrap0-dev \ - libx11-xcb-dev \ - libxcb1-dev \ - libxml-parser-perl \ - libxml2-utils \ - libxtst-dev \ - make \ - ninja-build \ - python3-setuptools \ - systemd - -# Install meson from upstream tarball -ARG MESON_VERSION=0.50.0 -RUN apt-get install -y wget && \ - wget -q https://github.com/mesonbuild/meson/releases/download/${MESON_VERSION}/meson-${MESON_VERSION}.tar.gz && \ - tar -xf meson-${MESON_VERSION}.tar.gz && \ - cd meson-${MESON_VERSION} && \ - python3 setup.py install - -# Add a user and set as default for the build. This is safer, in general, and -# allows us to avoid having to explicitly allow running as root in the -# check-daemon stage. -RUN groupadd -g 1000 a_group && \ - useradd a_user -u 1000 -g a_group -m -USER a_user:a_group - -# And make sure subsequent commands are run in the user's home directory -WORKDIR /home/a_user diff --git a/shell-completion/bash/meson.build b/shell-completion/bash/meson.build index b5b00f1..db4b00b 100644 --- a/shell-completion/bash/meson.build +++ b/shell-completion/bash/meson.build @@ -1,18 +1,20 @@ -aliases = [ - 'pacat', - 'pacmd', - 'pactl', - 'padsp', - 'paplay', - 'parec', - 'parecord', - 'pasuspender', -] +if bashcompletiondir != 'no' + aliases = [ + 'pacat', + 'pacmd', + 'pactl', + 'padsp', + 'paplay', + 'parec', + 'parecord', + 'pasuspender', + ] -install_data('pulseaudio', install_dir : bashcompletiondir) + install_data('pulseaudio', install_dir : bashcompletiondir) -foreach alias : aliases - dst = join_paths(bashcompletiondir, alias) - cmd = 'ln -fs @0@ $DESTDIR@1@'.format('pulseaudio', dst) - meson.add_install_script('sh', '-c', cmd) -endforeach + foreach alias : aliases + dst = join_paths(bashcompletiondir, alias) + cmd = 'ln -fs @0@ $DESTDIR@1@'.format('pulseaudio', dst) + meson.add_install_script('sh', '-c', cmd) + endforeach +endif diff --git a/shell-completion/bash/pulseaudio b/shell-completion/bash/pulseaudio index e473b9c..08f247e 100644 --- a/shell-completion/bash/pulseaudio +++ b/shell-completion/bash/pulseaudio @@ -37,7 +37,7 @@ __source_outputs () { } __ports () { - pactl list cards 2> /dev/null | awk -e \ + pactl list cards 2> /dev/null | awk -- \ '/^\tPorts:/ { flag=1; next } @@ -57,7 +57,7 @@ __ports () { } __profiles () { - pactl list cards 2> /dev/null | awk -e \ + pactl list cards 2> /dev/null | awk -- \ '/^\tProfiles:/ { flag=1; next } @@ -116,11 +116,12 @@ _pactl() { modules samples clients' local commands=(stat info list exit upload-sample play-sample remove-sample load-module unload-module move-sink-input move-source-output - suspend-sink suspend-source set-card-profile set-sink-port - set-source-port set-sink-volume set-source-volume - set-sink-input-volume set-source-output-volume set-sink-mute - set-source-mute set-sink-input-mute set-source-output-mute - set-sink-formats set-port-latency-offset subscribe help) + suspend-sink suspend-source set-card-profile set-default-sink + set-sink-port set-default-source set-source-port set-sink-volume + set-source-volume set-sink-input-volume set-source-output-volume + set-sink-mute set-source-mute set-sink-input-mute + set-source-output-mute set-sink-formats set-port-latency-offset + subscribe help) _init_completion -n = || return preprev=${words[$cword-2]} diff --git a/shell-completion/zsh/meson.build b/shell-completion/zsh/meson.build index 88c3355..489be56 100644 --- a/shell-completion/zsh/meson.build +++ b/shell-completion/zsh/meson.build @@ -1 +1,3 @@ -install_data('_pulseaudio', install_dir : zshcompletiondir) +if zshcompletiondir != 'no' + install_data('_pulseaudio', install_dir : zshcompletiondir) +endif diff --git a/src/Makefile.am b/src/Makefile.am index 437311d..0f1ded7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1176,13 +1176,21 @@ libprotocol_esound_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libp endif librtp_la_SOURCES = \ - modules/rtp/rtp.c modules/rtp/rtp.h \ + modules/rtp/rtp-common.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_CFLAGS = $(AM_CFLAGS) librtp_la_LDFLAGS = $(AM_LDFLAGS) $(AM_LIBLDFLAGS) -avoid-version librtp_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la +if HAVE_GSTREAMER +librtp_la_SOURCES += modules/rtp/rtp-gstreamer.c +librtp_la_CFLAGS += $(GSTREAMER_CFLAGS) +librtp_la_LIBADD += $(GSTREAMER_LIBS) +else +librtp_la_SOURCES += modules/rtp/rtp-native.c +endif libraop_la_SOURCES = \ modules/raop/raop-util.c modules/raop/raop-util.h \ @@ -1345,8 +1353,8 @@ dist_alsaprofilesets_DATA = \ modules/alsa/mixer/profile-sets/native-instruments-korecontroller.conf \ modules/alsa/mixer/profile-sets/kinect-audio.conf \ modules/alsa/mixer/profile-sets/sb-omni-surround-5.1.conf \ - modules/alsa/mixer/profile-sets/steelseries-arctis-5-usb-audio.conf \ - modules/alsa/mixer/profile-sets/steelseries-arctis-7-usb-audio.conf \ + modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf \ + modules/alsa/mixer/profile-sets/usb-gaming-headset.conf \ modules/alsa/mixer/profile-sets/dell-dock-tb16-usb-audio.conf \ modules/alsa/mixer/profile-sets/cmedia-high-speed-true-hdaudio.conf @@ -1391,11 +1399,11 @@ dist_alsapaths_DATA = \ modules/alsa/mixer/paths/hdmi-output-5.conf \ modules/alsa/mixer/paths/hdmi-output-6.conf \ modules/alsa/mixer/paths/hdmi-output-7.conf \ - modules/alsa/mixer/paths/steelseries-arctis-5-output-chat.conf \ - modules/alsa/mixer/paths/steelseries-arctis-5-output-game.conf \ - modules/alsa/mixer/paths/steelseries-arctis-7-input.conf \ - modules/alsa/mixer/paths/steelseries-arctis-7-output-mono.conf \ - modules/alsa/mixer/paths/steelseries-arctis-7-output-stereo.conf + modules/alsa/mixer/paths/steelseries-arctis-output-chat-common.conf \ + modules/alsa/mixer/paths/steelseries-arctis-output-game-common.conf \ + modules/alsa/mixer/paths/usb-gaming-headset-input.conf \ + modules/alsa/mixer/paths/usb-gaming-headset-output-mono.conf \ + modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf endif @@ -1734,9 +1742,9 @@ module_tunnel_sink_la_LDFLAGS = $(MODULE_LDFLAGS) module_tunnel_sink_la_LIBADD = $(MODULE_LIBADD) $(X11_LIBS) module_tunnel_source_la_SOURCES = modules/module-tunnel.c -module_tunnel_source_la_LDFLAGS = $(MODULE_LDFLAGS) $(X11_CFLAGS) +module_tunnel_source_la_LDFLAGS = $(MODULE_LDFLAGS) module_tunnel_source_la_LIBADD = $(MODULE_LIBADD) $(X11_LIBS) -module_tunnel_source_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_tunnel_source +module_tunnel_source_la_CFLAGS = $(AM_CFLAGS) $(X11_CFLAGS) -DPA_MODULE_NAME=module_tunnel_source module_loopback_la_SOURCES = modules/module-loopback.c module_loopback_la_LDFLAGS = $(MODULE_LDFLAGS) @@ -2049,12 +2057,12 @@ endif module_rtp_send_la_SOURCES = modules/rtp/module-rtp-send.c module_rtp_send_la_LDFLAGS = $(MODULE_LDFLAGS) module_rtp_send_la_LIBADD = $(MODULE_LIBADD) librtp.la -module_rtp_send_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_rtp_send +module_rtp_send_la_CFLAGS = $(AM_CFLAGS) $(GSTREAMER_CFLAGS) -DPA_MODULE_NAME=module_rtp_send module_rtp_recv_la_SOURCES = modules/rtp/module-rtp-recv.c module_rtp_recv_la_LDFLAGS = $(MODULE_LDFLAGS) module_rtp_recv_la_LIBADD = $(MODULE_LIBADD) librtp.la -module_rtp_recv_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_rtp_recv +module_rtp_recv_la_CFLAGS = $(AM_CFLAGS) $(GSTREAMER_CFLAGS) -DPA_MODULE_NAME=module_rtp_recv # JACK diff --git a/src/Makefile.in b/src/Makefile.in index ab5ac17..5b7d99d 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -288,122 +288,126 @@ bin_PROGRAMS = pulseaudio$(EXEEXT) pacat$(EXEEXT) pactl$(EXEEXT) \ @HAVE_DBUS_TRUE@am__append_82 = $(DBUS_CFLAGS) @HAVE_DBUS_TRUE@am__append_83 = $(DBUS_LIBS) +@HAVE_GSTREAMER_TRUE@am__append_84 = modules/rtp/rtp-gstreamer.c +@HAVE_GSTREAMER_TRUE@am__append_85 = $(GSTREAMER_CFLAGS) +@HAVE_GSTREAMER_TRUE@am__append_86 = $(GSTREAMER_LIBS) +@HAVE_GSTREAMER_FALSE@am__append_87 = modules/rtp/rtp-native.c ################################### # Plug-in libraries # ################################### # Serveral module (e.g. libalsa-util.la) -@HAVE_DBUS_TRUE@am__append_84 = \ +@HAVE_DBUS_TRUE@am__append_88 = \ @HAVE_DBUS_TRUE@ module-console-kit.la -@HAVE_ESOUND_TRUE@am__append_85 = \ +@HAVE_ESOUND_TRUE@am__append_89 = \ @HAVE_ESOUND_TRUE@ module-esound-protocol-tcp.la \ @HAVE_ESOUND_TRUE@ module-esound-sink.la # See comment at librtp.la above -@OS_IS_WIN32_FALSE@am__append_86 = \ +@OS_IS_WIN32_FALSE@am__append_90 = \ @OS_IS_WIN32_FALSE@ module-rtp-send.la \ @OS_IS_WIN32_FALSE@ module-rtp-recv.la -@HAVE_AF_UNIX_TRUE@am__append_87 = \ +@HAVE_AF_UNIX_TRUE@am__append_91 = \ @HAVE_AF_UNIX_TRUE@ module-cli-protocol-unix.la \ @HAVE_AF_UNIX_TRUE@ module-simple-protocol-unix.la \ @HAVE_AF_UNIX_TRUE@ module-http-protocol-unix.la \ @HAVE_AF_UNIX_TRUE@ module-native-protocol-unix.la -@HAVE_AF_UNIX_TRUE@@HAVE_ESOUND_TRUE@am__append_88 = \ +@HAVE_AF_UNIX_TRUE@@HAVE_ESOUND_TRUE@am__append_92 = \ @HAVE_AF_UNIX_TRUE@@HAVE_ESOUND_TRUE@ module-esound-protocol-unix.la -@HAVE_MKFIFO_TRUE@am__append_89 = \ +@HAVE_MKFIFO_TRUE@am__append_93 = \ @HAVE_MKFIFO_TRUE@ module-pipe-sink.la \ @HAVE_MKFIFO_TRUE@ module-pipe-source.la -@HAVE_ESOUND_TRUE@@OS_IS_WIN32_FALSE@am__append_90 = \ +@HAVE_ESOUND_TRUE@@OS_IS_WIN32_FALSE@am__append_94 = \ @HAVE_ESOUND_TRUE@@OS_IS_WIN32_FALSE@ module-esound-compat-spawnfd.la \ @HAVE_ESOUND_TRUE@@OS_IS_WIN32_FALSE@ module-esound-compat-spawnpid.la -@HAVE_REGEX_TRUE@am__append_91 = \ +@HAVE_REGEX_TRUE@am__append_95 = \ @HAVE_REGEX_TRUE@ module-match.la -@HAVE_X11_TRUE@am__append_92 = \ +@HAVE_X11_TRUE@am__append_96 = \ @HAVE_X11_TRUE@ module-x11-bell.la \ @HAVE_X11_TRUE@ module-x11-publish.la \ @HAVE_X11_TRUE@ module-x11-xsmp.la \ @HAVE_X11_TRUE@ module-x11-cork-request.la -@HAVE_OSS_OUTPUT_TRUE@am__append_93 = \ +@HAVE_OSS_OUTPUT_TRUE@am__append_97 = \ @HAVE_OSS_OUTPUT_TRUE@ liboss-util.la \ @HAVE_OSS_OUTPUT_TRUE@ module-oss.la -@HAVE_COREAUDIO_TRUE@am__append_94 = \ +@HAVE_COREAUDIO_TRUE@am__append_98 = \ @HAVE_COREAUDIO_TRUE@ module-coreaudio-detect.la \ @HAVE_COREAUDIO_TRUE@ module-coreaudio-device.la pulselibexec_PROGRAMS = $(am__EXEEXT_16) $(am__EXEEXT_17) -@HAVE_ALSA_TRUE@am__append_95 = \ +@HAVE_ALSA_TRUE@am__append_99 = \ @HAVE_ALSA_TRUE@ libalsa-util.la \ @HAVE_ALSA_TRUE@ module-alsa-sink.la \ @HAVE_ALSA_TRUE@ module-alsa-source.la \ @HAVE_ALSA_TRUE@ module-alsa-card.la -@HAVE_SOLARIS_TRUE@am__append_96 = \ +@HAVE_SOLARIS_TRUE@am__append_100 = \ @HAVE_SOLARIS_TRUE@ module-solaris.la -@HAVE_AVAHI_TRUE@am__append_97 = \ +@HAVE_AVAHI_TRUE@am__append_101 = \ @HAVE_AVAHI_TRUE@ module-zeroconf-publish.la \ @HAVE_AVAHI_TRUE@ module-zeroconf-discover.la -@HAVE_BONJOUR_TRUE@am__append_98 = \ +@HAVE_BONJOUR_TRUE@am__append_102 = \ @HAVE_BONJOUR_TRUE@ module-bonjour-publish.la -@HAVE_LIRC_TRUE@am__append_99 = \ +@HAVE_LIRC_TRUE@am__append_103 = \ @HAVE_LIRC_TRUE@ module-lirc.la -@HAVE_EVDEV_TRUE@am__append_100 = \ +@HAVE_EVDEV_TRUE@am__append_104 = \ @HAVE_EVDEV_TRUE@ module-mmkbd-evdev.la -@HAVE_JACK_TRUE@am__append_101 = \ +@HAVE_JACK_TRUE@am__append_105 = \ @HAVE_JACK_TRUE@ module-jack-sink.la \ @HAVE_JACK_TRUE@ module-jack-source.la -@HAVE_DBUS_TRUE@@HAVE_JACK_TRUE@am__append_102 = \ +@HAVE_DBUS_TRUE@@HAVE_JACK_TRUE@am__append_106 = \ @HAVE_DBUS_TRUE@@HAVE_JACK_TRUE@ module-jackdbus-detect.la -@HAVE_GCONF_TRUE@am__append_103 = \ +@HAVE_GCONF_TRUE@am__append_107 = \ @HAVE_GCONF_TRUE@ module-gconf.la -@HAVE_GCONF_TRUE@am__append_104 = \ +@HAVE_GCONF_TRUE@am__append_108 = \ @HAVE_GCONF_TRUE@ gconf-helper -@HAVE_GSETTINGS_TRUE@am__append_105 = \ +@HAVE_GSETTINGS_TRUE@am__append_109 = \ @HAVE_GSETTINGS_TRUE@ module-gsettings.la -@HAVE_GSETTINGS_TRUE@am__append_106 = \ +@HAVE_GSETTINGS_TRUE@am__append_110 = \ @HAVE_GSETTINGS_TRUE@ gsettings-helper -@HAVE_WAVEOUT_TRUE@am__append_107 = \ +@HAVE_WAVEOUT_TRUE@am__append_111 = \ @HAVE_WAVEOUT_TRUE@ module-waveout.la -@HAVE_HAL_COMPAT_TRUE@am__append_108 = \ +@HAVE_HAL_COMPAT_TRUE@am__append_112 = \ @HAVE_HAL_COMPAT_TRUE@ module-hal-detect.la -@HAVE_UDEV_TRUE@am__append_109 = \ +@HAVE_UDEV_TRUE@am__append_113 = \ @HAVE_UDEV_TRUE@ module-udev-detect.la -@HAVE_SYSTEMD_LOGIN_TRUE@am__append_110 = \ +@HAVE_SYSTEMD_LOGIN_TRUE@am__append_114 = \ @HAVE_SYSTEMD_LOGIN_TRUE@ module-systemd-login.la -@HAVE_DBUS_TRUE@am__append_111 = \ +@HAVE_DBUS_TRUE@am__append_115 = \ @HAVE_DBUS_TRUE@ module-rygel-media-server.la \ @HAVE_DBUS_TRUE@ module-dbus-protocol.la -@HAVE_BLUEZ_TRUE@am__append_112 = \ +@HAVE_BLUEZ_TRUE@am__append_116 = \ @HAVE_BLUEZ_TRUE@ module-bluetooth-discover.la \ @HAVE_BLUEZ_TRUE@ module-bluetooth-policy.la -@HAVE_BLUEZ_5_TRUE@am__append_113 = \ +@HAVE_BLUEZ_5_TRUE@am__append_117 = \ @HAVE_BLUEZ_5_TRUE@ libbluez5-util.la \ @HAVE_BLUEZ_5_TRUE@ module-bluez5-discover.la \ @HAVE_BLUEZ_5_TRUE@ module-bluez5-device.la @@ -411,46 +415,46 @@ pulselibexec_PROGRAMS = $(am__EXEEXT_16) $(am__EXEEXT_17) # RAOP depends on RTP, and we don't support RTP on Windows, see comment at # librtp.la above. -@HAVE_OPENSSL_TRUE@@OS_IS_WIN32_FALSE@am__append_114 = \ +@HAVE_OPENSSL_TRUE@@OS_IS_WIN32_FALSE@am__append_118 = \ @HAVE_OPENSSL_TRUE@@OS_IS_WIN32_FALSE@ libraop.la \ @HAVE_OPENSSL_TRUE@@OS_IS_WIN32_FALSE@ module-raop-sink.la -@HAVE_AVAHI_TRUE@@HAVE_OPENSSL_TRUE@@OS_IS_WIN32_FALSE@am__append_115 = \ +@HAVE_AVAHI_TRUE@@HAVE_OPENSSL_TRUE@@OS_IS_WIN32_FALSE@am__append_119 = \ @HAVE_AVAHI_TRUE@@HAVE_OPENSSL_TRUE@@OS_IS_WIN32_FALSE@ module-raop-discover.la -@HAVE_DBUS_TRUE@@HAVE_FFTW_TRUE@am__append_116 = \ +@HAVE_DBUS_TRUE@@HAVE_FFTW_TRUE@am__append_120 = \ @HAVE_DBUS_TRUE@@HAVE_FFTW_TRUE@ module-equalizer-sink.la -@HAVE_DBUS_TRUE@@HAVE_FFTW_TRUE@am__append_117 = utils/qpaeq -@HAVE_DBUS_TRUE@am__append_118 = $(DBUS_CFLAGS) -@HAVE_DBUS_TRUE@am__append_119 = $(DBUS_LIBS) -@HAVE_UDEV_TRUE@am__append_120 = modules/udev-util.h modules/udev-util.c -@HAVE_UDEV_TRUE@am__append_121 = $(UDEV_LIBS) -@HAVE_UDEV_TRUE@am__append_122 = $(UDEV_CFLAGS) -@HAVE_DBUS_TRUE@am__append_123 = modules/reserve.h modules/reserve.c modules/reserve-monitor.h modules/reserve-monitor.c -@HAVE_DBUS_TRUE@am__append_124 = $(DBUS_LIBS) -@HAVE_DBUS_TRUE@am__append_125 = $(DBUS_CFLAGS) -@HAVE_DBUS_TRUE@am__append_126 = $(DBUS_LIBS) -@HAVE_DBUS_TRUE@am__append_127 = $(DBUS_CFLAGS) +@HAVE_DBUS_TRUE@@HAVE_FFTW_TRUE@am__append_121 = utils/qpaeq +@HAVE_DBUS_TRUE@am__append_122 = $(DBUS_CFLAGS) +@HAVE_DBUS_TRUE@am__append_123 = $(DBUS_LIBS) +@HAVE_UDEV_TRUE@am__append_124 = modules/udev-util.h modules/udev-util.c +@HAVE_UDEV_TRUE@am__append_125 = $(UDEV_LIBS) +@HAVE_UDEV_TRUE@am__append_126 = $(UDEV_CFLAGS) +@HAVE_DBUS_TRUE@am__append_127 = modules/reserve.h modules/reserve.c modules/reserve-monitor.h modules/reserve-monitor.c @HAVE_DBUS_TRUE@am__append_128 = $(DBUS_LIBS) @HAVE_DBUS_TRUE@am__append_129 = $(DBUS_CFLAGS) -@HAVE_ADRIAN_EC_TRUE@am__append_130 = \ +@HAVE_DBUS_TRUE@am__append_130 = $(DBUS_LIBS) +@HAVE_DBUS_TRUE@am__append_131 = $(DBUS_CFLAGS) +@HAVE_DBUS_TRUE@am__append_132 = $(DBUS_LIBS) +@HAVE_DBUS_TRUE@am__append_133 = $(DBUS_CFLAGS) +@HAVE_ADRIAN_EC_TRUE@am__append_134 = \ @HAVE_ADRIAN_EC_TRUE@ modules/echo-cancel/adrian-aec.c modules/echo-cancel/adrian-aec.h \ @HAVE_ADRIAN_EC_TRUE@ modules/echo-cancel/adrian.c modules/echo-cancel/adrian.h -@HAVE_ADRIAN_EC_TRUE@am__append_131 = -DHAVE_ADRIAN_EC=1 -@HAVE_ADRIAN_EC_TRUE@am__append_132 = modules/echo-cancel/adrian-aec -@HAVE_ADRIAN_EC_TRUE@@HAVE_ORC_TRUE@am__append_133 = $(ORC_LIBS) -@HAVE_ADRIAN_EC_TRUE@@HAVE_ORC_TRUE@am__append_134 = $(ORC_CFLAGS) -I$(top_builddir)/src/modules/echo-cancel -@HAVE_SPEEX_TRUE@am__append_135 = modules/echo-cancel/speex.c -@HAVE_SPEEX_TRUE@am__append_136 = $(LIBSPEEX_CFLAGS) -@HAVE_SPEEX_TRUE@am__append_137 = $(LIBSPEEX_LIBS) -@HAVE_WEBRTC_TRUE@am__append_138 = -DHAVE_WEBRTC=1 -@HAVE_WEBRTC_TRUE@am__append_139 = libwebrtc-util.la -@HAVE_BLUEZ_5_OFONO_HEADSET_TRUE@am__append_140 = \ +@HAVE_ADRIAN_EC_TRUE@am__append_135 = -DHAVE_ADRIAN_EC=1 +@HAVE_ADRIAN_EC_TRUE@am__append_136 = modules/echo-cancel/adrian-aec +@HAVE_ADRIAN_EC_TRUE@@HAVE_ORC_TRUE@am__append_137 = $(ORC_LIBS) +@HAVE_ADRIAN_EC_TRUE@@HAVE_ORC_TRUE@am__append_138 = $(ORC_CFLAGS) -I$(top_builddir)/src/modules/echo-cancel +@HAVE_SPEEX_TRUE@am__append_139 = modules/echo-cancel/speex.c +@HAVE_SPEEX_TRUE@am__append_140 = $(LIBSPEEX_CFLAGS) +@HAVE_SPEEX_TRUE@am__append_141 = $(LIBSPEEX_LIBS) +@HAVE_WEBRTC_TRUE@am__append_142 = -DHAVE_WEBRTC=1 +@HAVE_WEBRTC_TRUE@am__append_143 = libwebrtc-util.la +@HAVE_BLUEZ_5_OFONO_HEADSET_TRUE@am__append_144 = \ @HAVE_BLUEZ_5_OFONO_HEADSET_TRUE@ modules/bluetooth/backend-ofono.c -@HAVE_BLUEZ_5_NATIVE_HEADSET_TRUE@am__append_141 = \ +@HAVE_BLUEZ_5_NATIVE_HEADSET_TRUE@am__append_145 = \ @HAVE_BLUEZ_5_NATIVE_HEADSET_TRUE@ modules/bluetooth/backend-native.c subdir = src @@ -1132,16 +1136,30 @@ libraop_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(CFLAGS) $(libraop_la_LDFLAGS) $(LDFLAGS) -o $@ @HAVE_OPENSSL_TRUE@@OS_IS_WIN32_FALSE@am_libraop_la_rpath = -rpath \ @HAVE_OPENSSL_TRUE@@OS_IS_WIN32_FALSE@ $(modlibexecdir) +@HAVE_GSTREAMER_TRUE@am__DEPENDENCIES_13 = $(am__DEPENDENCIES_1) librtp_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \ libpulsecore-@PA_MAJORMINOR@.la \ - libpulsecommon-@PA_MAJORMINOR@.la libpulse.la -am_librtp_la_OBJECTS = modules/rtp/rtp.lo modules/rtp/sdp.lo \ - modules/rtp/sap.lo modules/rtp/rtsp_client.lo \ - modules/rtp/headerlist.lo + libpulsecommon-@PA_MAJORMINOR@.la libpulse.la \ + $(am__DEPENDENCIES_13) +am__librtp_la_SOURCES_DIST = modules/rtp/rtp-common.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 modules/rtp/rtp-gstreamer.c \ + modules/rtp/rtp-native.c +@HAVE_GSTREAMER_TRUE@am__objects_23 = \ +@HAVE_GSTREAMER_TRUE@ modules/rtp/librtp_la-rtp-gstreamer.lo +@HAVE_GSTREAMER_FALSE@am__objects_24 = \ +@HAVE_GSTREAMER_FALSE@ modules/rtp/librtp_la-rtp-native.lo +am_librtp_la_OBJECTS = modules/rtp/librtp_la-rtp-common.lo \ + modules/rtp/librtp_la-sdp.lo modules/rtp/librtp_la-sap.lo \ + modules/rtp/librtp_la-rtsp_client.lo \ + modules/rtp/librtp_la-headerlist.lo $(am__objects_23) \ + $(am__objects_24) librtp_la_OBJECTS = $(am_librtp_la_OBJECTS) librtp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(librtp_la_LDFLAGS) $(LDFLAGS) -o $@ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(librtp_la_CFLAGS) \ + $(CFLAGS) $(librtp_la_LDFLAGS) $(LDFLAGS) -o $@ @OS_IS_WIN32_FALSE@am_librtp_la_rpath = -rpath $(modlibexecdir) @HAVE_WEBRTC_TRUE@libwebrtc_util_la_DEPENDENCIES = \ @HAVE_WEBRTC_TRUE@ libpulsecore-@PA_MAJORMINOR@.la \ @@ -1412,23 +1430,23 @@ module_device_restore_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(module_device_restore_la_CFLAGS) $(CFLAGS) \ $(module_device_restore_la_LDFLAGS) $(LDFLAGS) -o $@ -@HAVE_ADRIAN_EC_TRUE@@HAVE_ORC_TRUE@am__DEPENDENCIES_13 = \ +@HAVE_ADRIAN_EC_TRUE@@HAVE_ORC_TRUE@am__DEPENDENCIES_14 = \ @HAVE_ADRIAN_EC_TRUE@@HAVE_ORC_TRUE@ $(am__DEPENDENCIES_1) module_echo_cancel_la_DEPENDENCIES = $(am__DEPENDENCIES_3) \ - $(am__DEPENDENCIES_13) $(am__DEPENDENCIES_10) \ - $(am__append_139) + $(am__DEPENDENCIES_14) $(am__DEPENDENCIES_10) \ + $(am__append_143) am__module_echo_cancel_la_SOURCES_DIST = \ modules/echo-cancel/module-echo-cancel.c \ modules/echo-cancel/null.c modules/echo-cancel/echo-cancel.h \ modules/echo-cancel/adrian-aec.c \ modules/echo-cancel/adrian-aec.h modules/echo-cancel/adrian.c \ modules/echo-cancel/adrian.h modules/echo-cancel/speex.c -@HAVE_ADRIAN_EC_TRUE@am__objects_23 = modules/echo-cancel/module_echo_cancel_la-adrian-aec.lo \ +@HAVE_ADRIAN_EC_TRUE@am__objects_25 = modules/echo-cancel/module_echo_cancel_la-adrian-aec.lo \ @HAVE_ADRIAN_EC_TRUE@ modules/echo-cancel/module_echo_cancel_la-adrian.lo -@HAVE_SPEEX_TRUE@am__objects_24 = modules/echo-cancel/module_echo_cancel_la-speex.lo +@HAVE_SPEEX_TRUE@am__objects_26 = modules/echo-cancel/module_echo_cancel_la-speex.lo am_module_echo_cancel_la_OBJECTS = modules/echo-cancel/module_echo_cancel_la-module-echo-cancel.lo \ modules/echo-cancel/module_echo_cancel_la-null.lo \ - $(am__objects_23) $(am__objects_24) + $(am__objects_25) $(am__objects_26) @HAVE_ADRIAN_EC_TRUE@@HAVE_ORC_TRUE@nodist_module_echo_cancel_la_OBJECTS = modules/echo-cancel/module_echo_cancel_la-adrian-aec-orc-gen.lo module_echo_cancel_la_OBJECTS = $(am_module_echo_cancel_la_OBJECTS) \ $(nodist_module_echo_cancel_la_OBJECTS) @@ -2236,20 +2254,20 @@ am__echo_cancel_test_SOURCES_DIST = \ modules/echo-cancel/adrian-aec.c \ modules/echo-cancel/adrian-aec.h modules/echo-cancel/adrian.c \ modules/echo-cancel/adrian.h modules/echo-cancel/speex.c -@HAVE_ADRIAN_EC_TRUE@am__objects_25 = modules/echo-cancel/echo_cancel_test-adrian-aec.$(OBJEXT) \ +@HAVE_ADRIAN_EC_TRUE@am__objects_27 = modules/echo-cancel/echo_cancel_test-adrian-aec.$(OBJEXT) \ @HAVE_ADRIAN_EC_TRUE@ modules/echo-cancel/echo_cancel_test-adrian.$(OBJEXT) -@HAVE_SPEEX_TRUE@am__objects_26 = modules/echo-cancel/echo_cancel_test-speex.$(OBJEXT) -am__objects_27 = modules/echo-cancel/echo_cancel_test-module-echo-cancel.$(OBJEXT) \ +@HAVE_SPEEX_TRUE@am__objects_28 = modules/echo-cancel/echo_cancel_test-speex.$(OBJEXT) +am__objects_29 = modules/echo-cancel/echo_cancel_test-module-echo-cancel.$(OBJEXT) \ modules/echo-cancel/echo_cancel_test-null.$(OBJEXT) \ - $(am__objects_25) $(am__objects_26) -am_echo_cancel_test_OBJECTS = $(am__objects_27) -@HAVE_ADRIAN_EC_TRUE@@HAVE_ORC_TRUE@am__objects_28 = modules/echo-cancel/echo_cancel_test-adrian-aec-orc-gen.$(OBJEXT) -nodist_echo_cancel_test_OBJECTS = $(am__objects_28) + $(am__objects_27) $(am__objects_28) +am_echo_cancel_test_OBJECTS = $(am__objects_29) +@HAVE_ADRIAN_EC_TRUE@@HAVE_ORC_TRUE@am__objects_30 = modules/echo-cancel/echo_cancel_test-adrian-aec-orc-gen.$(OBJEXT) +nodist_echo_cancel_test_OBJECTS = $(am__objects_30) echo_cancel_test_OBJECTS = $(am_echo_cancel_test_OBJECTS) \ $(nodist_echo_cancel_test_OBJECTS) -am__DEPENDENCIES_14 = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_13) \ - $(am__DEPENDENCIES_10) $(am__append_139) -echo_cancel_test_DEPENDENCIES = $(am__DEPENDENCIES_14) +am__DEPENDENCIES_15 = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_14) \ + $(am__DEPENDENCIES_10) $(am__append_143) +echo_cancel_test_DEPENDENCIES = $(am__DEPENDENCIES_15) echo_cancel_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(echo_cancel_test_CFLAGS) $(CFLAGS) \ @@ -2385,12 +2403,12 @@ mainloop_test_DEPENDENCIES = $(am__DEPENDENCIES_2) libpulse.la \ mainloop_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(mainloop_test_CFLAGS) \ $(CFLAGS) $(mainloop_test_LDFLAGS) $(LDFLAGS) -o $@ -am__objects_29 = tests/mainloop_test_glib-mainloop-test.$(OBJEXT) -am_mainloop_test_glib_OBJECTS = $(am__objects_29) +am__objects_31 = tests/mainloop_test_glib-mainloop-test.$(OBJEXT) +am_mainloop_test_glib_OBJECTS = $(am__objects_31) mainloop_test_glib_OBJECTS = $(am_mainloop_test_glib_OBJECTS) -am__DEPENDENCIES_15 = $(am__DEPENDENCIES_2) libpulse.la \ +am__DEPENDENCIES_16 = $(am__DEPENDENCIES_2) libpulse.la \ libpulsecommon-@PA_MAJORMINOR@.la -mainloop_test_glib_DEPENDENCIES = $(am__DEPENDENCIES_15) \ +mainloop_test_glib_DEPENDENCIES = $(am__DEPENDENCIES_16) \ $(am__DEPENDENCIES_1) libpulse-mainloop-glib.la mainloop_test_glib_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ @@ -2521,7 +2539,7 @@ am__pulseaudio_SOURCES_DIST = daemon/caps.c daemon/caps.h \ daemon/dumpmodules.c daemon/dumpmodules.h \ daemon/ltdl-bind-now.c daemon/ltdl-bind-now.h daemon/main.c \ daemon/server-lookup.c daemon/server-lookup.h -@HAVE_DBUS_TRUE@am__objects_30 = \ +@HAVE_DBUS_TRUE@am__objects_32 = \ @HAVE_DBUS_TRUE@ daemon/pulseaudio-server-lookup.$(OBJEXT) am_pulseaudio_OBJECTS = daemon/pulseaudio-caps.$(OBJEXT) \ daemon/pulseaudio-cmdline.$(OBJEXT) \ @@ -2529,7 +2547,7 @@ am_pulseaudio_OBJECTS = daemon/pulseaudio-caps.$(OBJEXT) \ daemon/pulseaudio-daemon-conf.$(OBJEXT) \ daemon/pulseaudio-dumpmodules.$(OBJEXT) \ daemon/pulseaudio-ltdl-bind-now.$(OBJEXT) \ - daemon/pulseaudio-main.$(OBJEXT) $(am__objects_30) + daemon/pulseaudio-main.$(OBJEXT) $(am__objects_32) pulseaudio_OBJECTS = $(am_pulseaudio_OBJECTS) pulseaudio_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(pulseaudio_CFLAGS) \ @@ -2837,12 +2855,15 @@ am__depfiles_remade = daemon/$(DEPDIR)/cpulimit_test-cpulimit.Po \ modules/raop/$(DEPDIR)/libraop_la-raop-util.Plo \ modules/raop/$(DEPDIR)/module_raop_discover_la-module-raop-discover.Plo \ modules/raop/$(DEPDIR)/module_raop_sink_la-module-raop-sink.Plo \ - modules/rtp/$(DEPDIR)/headerlist.Plo \ + modules/rtp/$(DEPDIR)/librtp_la-headerlist.Plo \ + modules/rtp/$(DEPDIR)/librtp_la-rtp-common.Plo \ + modules/rtp/$(DEPDIR)/librtp_la-rtp-gstreamer.Plo \ + modules/rtp/$(DEPDIR)/librtp_la-rtp-native.Plo \ + modules/rtp/$(DEPDIR)/librtp_la-rtsp_client.Plo \ + modules/rtp/$(DEPDIR)/librtp_la-sap.Plo \ + modules/rtp/$(DEPDIR)/librtp_la-sdp.Plo \ modules/rtp/$(DEPDIR)/module_rtp_recv_la-module-rtp-recv.Plo \ modules/rtp/$(DEPDIR)/module_rtp_send_la-module-rtp-send.Plo \ - modules/rtp/$(DEPDIR)/rtp.Plo \ - modules/rtp/$(DEPDIR)/rtsp_client.Plo \ - modules/rtp/$(DEPDIR)/sap.Plo modules/rtp/$(DEPDIR)/sdp.Plo \ modules/x11/$(DEPDIR)/module_x11_bell_la-module-x11-bell.Plo \ modules/x11/$(DEPDIR)/module_x11_cork_request_la-module-x11-cork-request.Plo \ modules/x11/$(DEPDIR)/module_x11_publish_la-module-x11-publish.Plo \ @@ -3283,7 +3304,8 @@ DIST_SOURCES = $(am__libalsa_util_la_SOURCES_DIST) \ $(am__libpulsecore_remap_neon_la_SOURCES_DIST) \ $(am__libpulsecore_sconv_neon_la_SOURCES_DIST) \ $(libpulsedsp_la_SOURCES) $(libraop_la_SOURCES) \ - $(librtp_la_SOURCES) $(am__libwebrtc_util_la_SOURCES_DIST) \ + $(am__librtp_la_SOURCES_DIST) \ + $(am__libwebrtc_util_la_SOURCES_DIST) \ $(module_allow_passthrough_la_SOURCES) \ $(module_alsa_card_la_SOURCES) $(module_alsa_sink_la_SOURCES) \ $(module_alsa_source_la_SOURCES) \ @@ -3439,11 +3461,11 @@ am__dist_alsapaths_DATA_DIST = \ modules/alsa/mixer/paths/hdmi-output-5.conf \ modules/alsa/mixer/paths/hdmi-output-6.conf \ modules/alsa/mixer/paths/hdmi-output-7.conf \ - modules/alsa/mixer/paths/steelseries-arctis-5-output-chat.conf \ - modules/alsa/mixer/paths/steelseries-arctis-5-output-game.conf \ - modules/alsa/mixer/paths/steelseries-arctis-7-input.conf \ - modules/alsa/mixer/paths/steelseries-arctis-7-output-mono.conf \ - modules/alsa/mixer/paths/steelseries-arctis-7-output-stereo.conf + modules/alsa/mixer/paths/steelseries-arctis-output-chat-common.conf \ + modules/alsa/mixer/paths/steelseries-arctis-output-game-common.conf \ + modules/alsa/mixer/paths/usb-gaming-headset-input.conf \ + modules/alsa/mixer/paths/usb-gaming-headset-output-mono.conf \ + modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf am__dist_alsaprofilesets_DATA_DIST = \ modules/alsa/mixer/profile-sets/default.conf \ modules/alsa/mixer/profile-sets/force-speaker.conf \ @@ -3458,8 +3480,8 @@ am__dist_alsaprofilesets_DATA_DIST = \ modules/alsa/mixer/profile-sets/native-instruments-korecontroller.conf \ modules/alsa/mixer/profile-sets/kinect-audio.conf \ modules/alsa/mixer/profile-sets/sb-omni-surround-5.1.conf \ - modules/alsa/mixer/profile-sets/steelseries-arctis-5-usb-audio.conf \ - modules/alsa/mixer/profile-sets/steelseries-arctis-7-usb-audio.conf \ + modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf \ + modules/alsa/mixer/profile-sets/usb-gaming-headset.conf \ modules/alsa/mixer/profile-sets/dell-dock-tb16-usb-audio.conf \ modules/alsa/mixer/profile-sets/cmedia-high-speed-true-hdaudio.conf am__dist_udevrules_DATA_DIST = modules/alsa/90-pulseaudio.rules @@ -3744,6 +3766,8 @@ GREP = @GREP@ GSETTINGS_CFLAGS = @GSETTINGS_CFLAGS@ GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ GSETTINGS_LIBS = @GSETTINGS_LIBS@ +GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@ +GSTREAMER_LIBS = @GSTREAMER_LIBS@ GTK30_CFLAGS = @GTK30_CFLAGS@ GTK30_LIBS = @GTK30_LIBS@ HAVE_AF_UNIX = @HAVE_AF_UNIX@ @@ -3954,7 +3978,6 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pulseconfdir = @pulseconfdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -4049,7 +4072,7 @@ CLEANFILES = $(am__append_7) $(am__append_50) \ @HAVE_ORC_TRUE@cp_v_gen = $(cp_v_gen_$(V)) @HAVE_ORC_TRUE@cp_v_gen_ = $(cp_v_gen_$(AM_DEFAULT_VERBOSITY)) @HAVE_ORC_TRUE@cp_v_gen_0 = @echo " CP $@"; -ORC_SOURCE = pulsecore/svolume $(am__append_132) +ORC_SOURCE = pulsecore/svolume $(am__append_136) pulseaudio_SOURCES = daemon/caps.c daemon/caps.h daemon/cmdline.c \ daemon/cmdline.h daemon/cpulimit.c daemon/cpulimit.h \ daemon/daemon-conf.c daemon/daemon-conf.h daemon/dumpmodules.c \ @@ -4078,7 +4101,7 @@ pulseaudio_DEPENDENCIES = libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJ # Utility programs # ################################### bin_SCRIPTS = utils/pa-info $(am__append_13) $(am__append_17) \ - $(am__append_49) $(am__append_117) + $(am__append_49) $(am__append_121) pacat_SOURCES = utils/pacat.c pacat_LDADD = $(AM_LDADD) libpulse.la libpulsecommon-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) pacat_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) @@ -4622,7 +4645,7 @@ libpulsecore_foreign_la_CFLAGS = $(AM_CFLAGS) $(FOREIGN_CFLAGS) modlibexec_LTLIBRARIES = libcli.la libprotocol-cli.la \ libprotocol-simple.la libprotocol-http.la \ libprotocol-native.la $(am__append_78) $(am__append_79) \ - $(am__append_80) $(am__append_81) $(am__append_84) \ + $(am__append_80) $(am__append_81) $(am__append_88) \ module-cli.la module-cli-protocol-tcp.la \ module-simple-protocol-tcp.la module-null-sink.la \ module-null-source.la module-sine-source.la module-detect.la \ @@ -4644,16 +4667,16 @@ modlibexec_LTLIBRARIES = libcli.la libprotocol-cli.la \ module-switch-on-connect.la module-switch-on-port-available.la \ module-filter-apply.la module-filter-heuristics.la \ module-role-ducking.la module-allow-passthrough.la \ - $(am__append_85) $(am__append_86) $(am__append_87) \ - $(am__append_88) $(am__append_89) $(am__append_90) \ - $(am__append_91) $(am__append_92) $(am__append_93) \ - $(am__append_94) $(am__append_95) $(am__append_96) \ - $(am__append_97) $(am__append_98) $(am__append_99) \ - $(am__append_100) $(am__append_101) $(am__append_102) \ - $(am__append_103) $(am__append_105) $(am__append_107) \ - $(am__append_108) $(am__append_109) $(am__append_110) \ - $(am__append_111) $(am__append_112) $(am__append_113) \ - $(am__append_114) $(am__append_115) $(am__append_116) + $(am__append_89) $(am__append_90) $(am__append_91) \ + $(am__append_92) $(am__append_93) $(am__append_94) \ + $(am__append_95) $(am__append_96) $(am__append_97) \ + $(am__append_98) $(am__append_99) $(am__append_100) \ + $(am__append_101) $(am__append_102) $(am__append_103) \ + $(am__append_104) $(am__append_105) $(am__append_106) \ + $(am__append_107) $(am__append_109) $(am__append_111) \ + $(am__append_112) $(am__append_113) $(am__append_114) \ + $(am__append_115) $(am__append_116) $(am__append_117) \ + $(am__append_118) $(am__append_119) $(am__append_120) libprotocol_simple_la_SOURCES = pulsecore/protocol-simple.c pulsecore/protocol-simple.h libprotocol_simple_la_LDFLAGS = $(AM_LDFLAGS) $(AM_LIBLDFLAGS) -avoid-version libprotocol_simple_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la @@ -4676,15 +4699,15 @@ libprotocol_native_la_LIBADD = $(AM_LIBADD) \ @HAVE_ESOUND_TRUE@libprotocol_esound_la_SOURCES = pulsecore/protocol-esound.c pulsecore/protocol-esound.h pulsecore/esound.h @HAVE_ESOUND_TRUE@libprotocol_esound_la_LDFLAGS = $(AM_LDFLAGS) $(AM_LIBLDFLAGS) -avoid-version @HAVE_ESOUND_TRUE@libprotocol_esound_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.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_SOURCES = modules/rtp/rtp-common.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 $(am__append_84) $(am__append_87) +librtp_la_CFLAGS = $(AM_CFLAGS) $(am__append_85) librtp_la_LDFLAGS = $(AM_LDFLAGS) $(AM_LIBLDFLAGS) -avoid-version -librtp_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la +librtp_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la \ + libpulsecommon-@PA_MAJORMINOR@.la libpulse.la $(am__append_86) libraop_la_SOURCES = \ modules/raop/raop-util.c modules/raop/raop-util.h \ modules/raop/raop-crypto.c modules/raop/raop-crypto.h \ @@ -4715,8 +4738,8 @@ libavahi_wrap_la_LIBADD = $(AM_LIBADD) $(AVAHI_CFLAGS) libpulsecore-@PA_MAJORMIN @HAVE_ALSA_TRUE@ modules/alsa/mixer/profile-sets/native-instruments-korecontroller.conf \ @HAVE_ALSA_TRUE@ modules/alsa/mixer/profile-sets/kinect-audio.conf \ @HAVE_ALSA_TRUE@ modules/alsa/mixer/profile-sets/sb-omni-surround-5.1.conf \ -@HAVE_ALSA_TRUE@ modules/alsa/mixer/profile-sets/steelseries-arctis-5-usb-audio.conf \ -@HAVE_ALSA_TRUE@ modules/alsa/mixer/profile-sets/steelseries-arctis-7-usb-audio.conf \ +@HAVE_ALSA_TRUE@ modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf \ +@HAVE_ALSA_TRUE@ modules/alsa/mixer/profile-sets/usb-gaming-headset.conf \ @HAVE_ALSA_TRUE@ modules/alsa/mixer/profile-sets/dell-dock-tb16-usb-audio.conf \ @HAVE_ALSA_TRUE@ modules/alsa/mixer/profile-sets/cmedia-high-speed-true-hdaudio.conf @@ -4759,11 +4782,11 @@ libavahi_wrap_la_LIBADD = $(AM_LIBADD) $(AVAHI_CFLAGS) libpulsecore-@PA_MAJORMIN @HAVE_ALSA_TRUE@ modules/alsa/mixer/paths/hdmi-output-5.conf \ @HAVE_ALSA_TRUE@ modules/alsa/mixer/paths/hdmi-output-6.conf \ @HAVE_ALSA_TRUE@ modules/alsa/mixer/paths/hdmi-output-7.conf \ -@HAVE_ALSA_TRUE@ modules/alsa/mixer/paths/steelseries-arctis-5-output-chat.conf \ -@HAVE_ALSA_TRUE@ modules/alsa/mixer/paths/steelseries-arctis-5-output-game.conf \ -@HAVE_ALSA_TRUE@ modules/alsa/mixer/paths/steelseries-arctis-7-input.conf \ -@HAVE_ALSA_TRUE@ modules/alsa/mixer/paths/steelseries-arctis-7-output-mono.conf \ -@HAVE_ALSA_TRUE@ modules/alsa/mixer/paths/steelseries-arctis-7-output-stereo.conf +@HAVE_ALSA_TRUE@ modules/alsa/mixer/paths/steelseries-arctis-output-chat-common.conf \ +@HAVE_ALSA_TRUE@ modules/alsa/mixer/paths/steelseries-arctis-output-game-common.conf \ +@HAVE_ALSA_TRUE@ modules/alsa/mixer/paths/usb-gaming-headset-input.conf \ +@HAVE_ALSA_TRUE@ modules/alsa/mixer/paths/usb-gaming-headset-output-mono.conf \ +@HAVE_ALSA_TRUE@ modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf @HAVE_GSETTINGS_TRUE@gsettingsdataconvert_DATA = \ @HAVE_GSETTINGS_TRUE@ modules/gsettings/pulseaudio.convert @@ -4921,10 +4944,10 @@ module_remap_source_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_remap_sourc 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) $(SERVER_CFLAGS) \ - -DPA_MODULE_NAME=module_ladspa_sink $(am__append_118) + -DPA_MODULE_NAME=module_ladspa_sink $(am__append_122) module_ladspa_sink_la_LDFLAGS = $(MODULE_LDFLAGS) module_ladspa_sink_la_LIBADD = $(MODULE_LIBADD) $(LIBLTDL) \ - $(am__append_119) + $(am__append_123) module_equalizer_sink_la_SOURCES = modules/module-equalizer-sink.c module_equalizer_sink_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS) $(DBUS_CFLAGS) $(FFTW_CFLAGS) -DPA_MODULE_NAME=module_equalizer_sink module_equalizer_sink_la_LDFLAGS = $(MODULE_LDFLAGS) @@ -4946,9 +4969,9 @@ module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS) $(X11_CFLAGS) -DPA_M module_tunnel_sink_la_LDFLAGS = $(MODULE_LDFLAGS) module_tunnel_sink_la_LIBADD = $(MODULE_LIBADD) $(X11_LIBS) module_tunnel_source_la_SOURCES = modules/module-tunnel.c -module_tunnel_source_la_LDFLAGS = $(MODULE_LDFLAGS) $(X11_CFLAGS) +module_tunnel_source_la_LDFLAGS = $(MODULE_LDFLAGS) module_tunnel_source_la_LIBADD = $(MODULE_LIBADD) $(X11_LIBS) -module_tunnel_source_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_tunnel_source +module_tunnel_source_la_CFLAGS = $(AM_CFLAGS) $(X11_CFLAGS) -DPA_MODULE_NAME=module_tunnel_source module_loopback_la_SOURCES = modules/module-loopback.c module_loopback_la_LDFLAGS = $(MODULE_LDFLAGS) module_loopback_la_LIBADD = $(MODULE_LIBADD) @@ -5016,12 +5039,12 @@ libalsa_util_la_SOURCES = modules/alsa/alsa-util.c \ modules/alsa/alsa-mixer.h modules/alsa/alsa-sink.c \ modules/alsa/alsa-sink.h modules/alsa/alsa-source.c \ modules/alsa/alsa-source.h modules/reserve-wrap.c \ - modules/reserve-wrap.h $(am__append_120) $(am__append_123) + modules/reserve-wrap.h $(am__append_124) $(am__append_127) libalsa_util_la_LDFLAGS = -avoid-version libalsa_util_la_LIBADD = $(MODULE_LIBADD) $(ASOUNDLIB_LIBS) \ - $(am__append_121) $(am__append_124) + $(am__append_125) $(am__append_128) libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS) \ - $(ASOUNDLIB_CFLAGS) $(am__append_122) $(am__append_125) + $(ASOUNDLIB_CFLAGS) $(am__append_126) $(am__append_129) module_alsa_sink_la_SOURCES = modules/alsa/module-alsa-sink.c module_alsa_sink_la_LDFLAGS = $(MODULE_LDFLAGS) module_alsa_sink_la_LIBADD = $(MODULE_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la @@ -5128,17 +5151,17 @@ module_device_manager_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_device_ma module_device_restore_la_SOURCES = modules/module-device-restore.c module_device_restore_la_LDFLAGS = $(MODULE_LDFLAGS) module_device_restore_la_LIBADD = $(MODULE_LIBADD) \ - libprotocol-native.la $(am__append_126) + libprotocol-native.la $(am__append_130) module_device_restore_la_CFLAGS = $(AM_CFLAGS) \ - -DPA_MODULE_NAME=module_device_restore $(am__append_127) + -DPA_MODULE_NAME=module_device_restore $(am__append_131) # Stream volume/muted/device restore module module_stream_restore_la_SOURCES = modules/module-stream-restore.c module_stream_restore_la_LDFLAGS = $(MODULE_LDFLAGS) module_stream_restore_la_LIBADD = $(MODULE_LIBADD) \ - libprotocol-native.la $(am__append_128) + libprotocol-native.la $(am__append_132) module_stream_restore_la_CFLAGS = $(AM_CFLAGS) \ - -DPA_MODULE_NAME=module_stream_restore $(am__append_129) + -DPA_MODULE_NAME=module_stream_restore $(am__append_133) # Card profile restore module module_card_restore_la_SOURCES = modules/module-card-restore.c @@ -5186,13 +5209,13 @@ module_suspend_on_idle_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_suspend_ module_echo_cancel_la_SOURCES = \ modules/echo-cancel/module-echo-cancel.c \ modules/echo-cancel/null.c modules/echo-cancel/echo-cancel.h \ - $(am__append_130) $(am__append_135) + $(am__append_134) $(am__append_139) module_echo_cancel_la_LDFLAGS = $(MODULE_LDFLAGS) -module_echo_cancel_la_LIBADD = $(MODULE_LIBADD) $(am__append_133) \ - $(am__append_137) $(am__append_139) +module_echo_cancel_la_LIBADD = $(MODULE_LIBADD) $(am__append_137) \ + $(am__append_141) $(am__append_143) module_echo_cancel_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS) \ - -DPA_MODULE_NAME=module_echo_cancel $(am__append_131) \ - $(am__append_134) $(am__append_136) $(am__append_138) + -DPA_MODULE_NAME=module_echo_cancel $(am__append_135) \ + $(am__append_138) $(am__append_140) $(am__append_142) @HAVE_ADRIAN_EC_TRUE@@HAVE_ORC_TRUE@nodist_module_echo_cancel_la_SOURCES = \ @HAVE_ADRIAN_EC_TRUE@@HAVE_ORC_TRUE@ modules/echo-cancel/adrian-aec-orc-gen.c \ @HAVE_ADRIAN_EC_TRUE@@HAVE_ORC_TRUE@ modules/echo-cancel/adrian-aec-orc-gen.h @@ -5209,11 +5232,11 @@ module_echo_cancel_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS) \ module_rtp_send_la_SOURCES = modules/rtp/module-rtp-send.c module_rtp_send_la_LDFLAGS = $(MODULE_LDFLAGS) module_rtp_send_la_LIBADD = $(MODULE_LIBADD) librtp.la -module_rtp_send_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_rtp_send +module_rtp_send_la_CFLAGS = $(AM_CFLAGS) $(GSTREAMER_CFLAGS) -DPA_MODULE_NAME=module_rtp_send module_rtp_recv_la_SOURCES = modules/rtp/module-rtp-recv.c module_rtp_recv_la_LDFLAGS = $(MODULE_LDFLAGS) module_rtp_recv_la_LIBADD = $(MODULE_LIBADD) librtp.la -module_rtp_recv_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_rtp_recv +module_rtp_recv_la_CFLAGS = $(AM_CFLAGS) $(GSTREAMER_CFLAGS) -DPA_MODULE_NAME=module_rtp_recv # JACK module_jackdbus_detect_la_SOURCES = modules/jack/module-jackdbus-detect.c @@ -5291,7 +5314,7 @@ libbluez5_util_la_SOURCES = modules/bluetooth/bluez5-util.c \ modules/bluetooth/a2dp-codec-util.c \ modules/bluetooth/a2dp-codec-util.h \ modules/bluetooth/a2dp-codecs.h modules/bluetooth/rtp.h \ - $(am__append_140) $(am__append_141) \ + $(am__append_144) $(am__append_145) \ modules/bluetooth/a2dp-codec-sbc.c libbluez5_util_la_LDFLAGS = -avoid-version libbluez5_util_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS) $(SBC_LIBS) @@ -6276,15 +6299,19 @@ modules/rtp/$(am__dirstamp): modules/rtp/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) modules/rtp/$(DEPDIR) @: > modules/rtp/$(DEPDIR)/$(am__dirstamp) -modules/rtp/rtp.lo: modules/rtp/$(am__dirstamp) \ +modules/rtp/librtp_la-rtp-common.lo: modules/rtp/$(am__dirstamp) \ modules/rtp/$(DEPDIR)/$(am__dirstamp) -modules/rtp/sdp.lo: modules/rtp/$(am__dirstamp) \ +modules/rtp/librtp_la-sdp.lo: modules/rtp/$(am__dirstamp) \ modules/rtp/$(DEPDIR)/$(am__dirstamp) -modules/rtp/sap.lo: modules/rtp/$(am__dirstamp) \ +modules/rtp/librtp_la-sap.lo: modules/rtp/$(am__dirstamp) \ modules/rtp/$(DEPDIR)/$(am__dirstamp) -modules/rtp/rtsp_client.lo: modules/rtp/$(am__dirstamp) \ +modules/rtp/librtp_la-rtsp_client.lo: modules/rtp/$(am__dirstamp) \ modules/rtp/$(DEPDIR)/$(am__dirstamp) -modules/rtp/headerlist.lo: modules/rtp/$(am__dirstamp) \ +modules/rtp/librtp_la-headerlist.lo: modules/rtp/$(am__dirstamp) \ + modules/rtp/$(DEPDIR)/$(am__dirstamp) +modules/rtp/librtp_la-rtp-gstreamer.lo: modules/rtp/$(am__dirstamp) \ + modules/rtp/$(DEPDIR)/$(am__dirstamp) +modules/rtp/librtp_la-rtp-native.lo: modules/rtp/$(am__dirstamp) \ modules/rtp/$(DEPDIR)/$(am__dirstamp) librtp.la: $(librtp_la_OBJECTS) $(librtp_la_DEPENDENCIES) $(EXTRA_librtp_la_DEPENDENCIES) @@ -7546,13 +7573,15 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@modules/raop/$(DEPDIR)/libraop_la-raop-util.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@modules/raop/$(DEPDIR)/module_raop_discover_la-module-raop-discover.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@modules/raop/$(DEPDIR)/module_raop_sink_la-module-raop-sink.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/headerlist.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/librtp_la-headerlist.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/librtp_la-rtp-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/librtp_la-rtp-gstreamer.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/librtp_la-rtp-native.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/librtp_la-rtsp_client.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/librtp_la-sap.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/librtp_la-sdp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/module_rtp_recv_la-module-rtp-recv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/module_rtp_send_la-module-rtp-send.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/rtp.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/rtsp_client.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/sap.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@modules/rtp/$(DEPDIR)/sdp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@modules/x11/$(DEPDIR)/module_x11_bell_la-module-x11-bell.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@modules/x11/$(DEPDIR)/module_x11_cork_request_la-module-x11-cork-request.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@modules/x11/$(DEPDIR)/module_x11_publish_la-module-x11-publish.Plo@am__quote@ # am--include-marker @@ -9237,6 +9266,55 @@ modules/raop/libraop_la-raop-sink.lo: modules/raop/raop-sink.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libraop_la_CFLAGS) $(CFLAGS) -c -o modules/raop/libraop_la-raop-sink.lo `test -f 'modules/raop/raop-sink.c' || echo '$(srcdir)/'`modules/raop/raop-sink.c +modules/rtp/librtp_la-rtp-common.lo: modules/rtp/rtp-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -MT modules/rtp/librtp_la-rtp-common.lo -MD -MP -MF modules/rtp/$(DEPDIR)/librtp_la-rtp-common.Tpo -c -o modules/rtp/librtp_la-rtp-common.lo `test -f 'modules/rtp/rtp-common.c' || echo '$(srcdir)/'`modules/rtp/rtp-common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) modules/rtp/$(DEPDIR)/librtp_la-rtp-common.Tpo modules/rtp/$(DEPDIR)/librtp_la-rtp-common.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='modules/rtp/rtp-common.c' object='modules/rtp/librtp_la-rtp-common.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -c -o modules/rtp/librtp_la-rtp-common.lo `test -f 'modules/rtp/rtp-common.c' || echo '$(srcdir)/'`modules/rtp/rtp-common.c + +modules/rtp/librtp_la-sdp.lo: modules/rtp/sdp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -MT modules/rtp/librtp_la-sdp.lo -MD -MP -MF modules/rtp/$(DEPDIR)/librtp_la-sdp.Tpo -c -o modules/rtp/librtp_la-sdp.lo `test -f 'modules/rtp/sdp.c' || echo '$(srcdir)/'`modules/rtp/sdp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) modules/rtp/$(DEPDIR)/librtp_la-sdp.Tpo modules/rtp/$(DEPDIR)/librtp_la-sdp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='modules/rtp/sdp.c' object='modules/rtp/librtp_la-sdp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -c -o modules/rtp/librtp_la-sdp.lo `test -f 'modules/rtp/sdp.c' || echo '$(srcdir)/'`modules/rtp/sdp.c + +modules/rtp/librtp_la-sap.lo: modules/rtp/sap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -MT modules/rtp/librtp_la-sap.lo -MD -MP -MF modules/rtp/$(DEPDIR)/librtp_la-sap.Tpo -c -o modules/rtp/librtp_la-sap.lo `test -f 'modules/rtp/sap.c' || echo '$(srcdir)/'`modules/rtp/sap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) modules/rtp/$(DEPDIR)/librtp_la-sap.Tpo modules/rtp/$(DEPDIR)/librtp_la-sap.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='modules/rtp/sap.c' object='modules/rtp/librtp_la-sap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -c -o modules/rtp/librtp_la-sap.lo `test -f 'modules/rtp/sap.c' || echo '$(srcdir)/'`modules/rtp/sap.c + +modules/rtp/librtp_la-rtsp_client.lo: modules/rtp/rtsp_client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -MT modules/rtp/librtp_la-rtsp_client.lo -MD -MP -MF modules/rtp/$(DEPDIR)/librtp_la-rtsp_client.Tpo -c -o modules/rtp/librtp_la-rtsp_client.lo `test -f 'modules/rtp/rtsp_client.c' || echo '$(srcdir)/'`modules/rtp/rtsp_client.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) modules/rtp/$(DEPDIR)/librtp_la-rtsp_client.Tpo modules/rtp/$(DEPDIR)/librtp_la-rtsp_client.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='modules/rtp/rtsp_client.c' object='modules/rtp/librtp_la-rtsp_client.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -c -o modules/rtp/librtp_la-rtsp_client.lo `test -f 'modules/rtp/rtsp_client.c' || echo '$(srcdir)/'`modules/rtp/rtsp_client.c + +modules/rtp/librtp_la-headerlist.lo: modules/rtp/headerlist.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -MT modules/rtp/librtp_la-headerlist.lo -MD -MP -MF modules/rtp/$(DEPDIR)/librtp_la-headerlist.Tpo -c -o modules/rtp/librtp_la-headerlist.lo `test -f 'modules/rtp/headerlist.c' || echo '$(srcdir)/'`modules/rtp/headerlist.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) modules/rtp/$(DEPDIR)/librtp_la-headerlist.Tpo modules/rtp/$(DEPDIR)/librtp_la-headerlist.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='modules/rtp/headerlist.c' object='modules/rtp/librtp_la-headerlist.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -c -o modules/rtp/librtp_la-headerlist.lo `test -f 'modules/rtp/headerlist.c' || echo '$(srcdir)/'`modules/rtp/headerlist.c + +modules/rtp/librtp_la-rtp-gstreamer.lo: modules/rtp/rtp-gstreamer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -MT modules/rtp/librtp_la-rtp-gstreamer.lo -MD -MP -MF modules/rtp/$(DEPDIR)/librtp_la-rtp-gstreamer.Tpo -c -o modules/rtp/librtp_la-rtp-gstreamer.lo `test -f 'modules/rtp/rtp-gstreamer.c' || echo '$(srcdir)/'`modules/rtp/rtp-gstreamer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) modules/rtp/$(DEPDIR)/librtp_la-rtp-gstreamer.Tpo modules/rtp/$(DEPDIR)/librtp_la-rtp-gstreamer.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='modules/rtp/rtp-gstreamer.c' object='modules/rtp/librtp_la-rtp-gstreamer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -c -o modules/rtp/librtp_la-rtp-gstreamer.lo `test -f 'modules/rtp/rtp-gstreamer.c' || echo '$(srcdir)/'`modules/rtp/rtp-gstreamer.c + +modules/rtp/librtp_la-rtp-native.lo: modules/rtp/rtp-native.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -MT modules/rtp/librtp_la-rtp-native.lo -MD -MP -MF modules/rtp/$(DEPDIR)/librtp_la-rtp-native.Tpo -c -o modules/rtp/librtp_la-rtp-native.lo `test -f 'modules/rtp/rtp-native.c' || echo '$(srcdir)/'`modules/rtp/rtp-native.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) modules/rtp/$(DEPDIR)/librtp_la-rtp-native.Tpo modules/rtp/$(DEPDIR)/librtp_la-rtp-native.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='modules/rtp/rtp-native.c' object='modules/rtp/librtp_la-rtp-native.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librtp_la_CFLAGS) $(CFLAGS) -c -o modules/rtp/librtp_la-rtp-native.lo `test -f 'modules/rtp/rtp-native.c' || echo '$(srcdir)/'`modules/rtp/rtp-native.c + modules/module_allow_passthrough_la-module-allow-passthrough.lo: modules/module-allow-passthrough.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(module_allow_passthrough_la_CFLAGS) $(CFLAGS) -MT modules/module_allow_passthrough_la-module-allow-passthrough.lo -MD -MP -MF modules/$(DEPDIR)/module_allow_passthrough_la-module-allow-passthrough.Tpo -c -o modules/module_allow_passthrough_la-module-allow-passthrough.lo `test -f 'modules/module-allow-passthrough.c' || echo '$(srcdir)/'`modules/module-allow-passthrough.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) modules/$(DEPDIR)/module_allow_passthrough_la-module-allow-passthrough.Tpo modules/$(DEPDIR)/module_allow_passthrough_la-module-allow-passthrough.Plo @@ -12121,13 +12199,15 @@ distclean: distclean-am -rm -f modules/raop/$(DEPDIR)/libraop_la-raop-util.Plo -rm -f modules/raop/$(DEPDIR)/module_raop_discover_la-module-raop-discover.Plo -rm -f modules/raop/$(DEPDIR)/module_raop_sink_la-module-raop-sink.Plo - -rm -f modules/rtp/$(DEPDIR)/headerlist.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-headerlist.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-rtp-common.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-rtp-gstreamer.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-rtp-native.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-rtsp_client.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-sap.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-sdp.Plo -rm -f modules/rtp/$(DEPDIR)/module_rtp_recv_la-module-rtp-recv.Plo -rm -f modules/rtp/$(DEPDIR)/module_rtp_send_la-module-rtp-send.Plo - -rm -f modules/rtp/$(DEPDIR)/rtp.Plo - -rm -f modules/rtp/$(DEPDIR)/rtsp_client.Plo - -rm -f modules/rtp/$(DEPDIR)/sap.Plo - -rm -f modules/rtp/$(DEPDIR)/sdp.Plo -rm -f modules/x11/$(DEPDIR)/module_x11_bell_la-module-x11-bell.Plo -rm -f modules/x11/$(DEPDIR)/module_x11_cork_request_la-module-x11-cork-request.Plo -rm -f modules/x11/$(DEPDIR)/module_x11_publish_la-module-x11-publish.Plo @@ -12580,13 +12660,15 @@ maintainer-clean: maintainer-clean-am -rm -f modules/raop/$(DEPDIR)/libraop_la-raop-util.Plo -rm -f modules/raop/$(DEPDIR)/module_raop_discover_la-module-raop-discover.Plo -rm -f modules/raop/$(DEPDIR)/module_raop_sink_la-module-raop-sink.Plo - -rm -f modules/rtp/$(DEPDIR)/headerlist.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-headerlist.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-rtp-common.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-rtp-gstreamer.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-rtp-native.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-rtsp_client.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-sap.Plo + -rm -f modules/rtp/$(DEPDIR)/librtp_la-sdp.Plo -rm -f modules/rtp/$(DEPDIR)/module_rtp_recv_la-module-rtp-recv.Plo -rm -f modules/rtp/$(DEPDIR)/module_rtp_send_la-module-rtp-send.Plo - -rm -f modules/rtp/$(DEPDIR)/rtp.Plo - -rm -f modules/rtp/$(DEPDIR)/rtsp_client.Plo - -rm -f modules/rtp/$(DEPDIR)/sap.Plo - -rm -f modules/rtp/$(DEPDIR)/sdp.Plo -rm -f modules/x11/$(DEPDIR)/module_x11_bell_la-module-x11-bell.Plo -rm -f modules/x11/$(DEPDIR)/module_x11_cork_request_la-module-x11-cork-request.Plo -rm -f modules/x11/$(DEPDIR)/module_x11_publish_la-module-x11-publish.Plo diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 33cf7a7..bcf7329 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -68,7 +68,8 @@ static const pa_daemon_conf default_conf = { .realtime_priority = 5, /* Half of JACK's default rtprio */ .disallow_module_loading = false, .disallow_exit = false, - .flat_volumes = true, + .flat_volumes = false, + .rescue_streams = true, .exit_idle_time = 20, .scache_idle_time = 20, .script_commands = NULL, @@ -84,7 +85,8 @@ static const pa_daemon_conf default_conf = { .avoid_resampling = false, .disable_remixing = false, .remixing_use_all_sink_channels = true, - .disable_lfe_remixing = true, + .remixing_produce_lfe = false, + .remixing_consume_lfe = false, .lfe_crossover_freq = 0, .config_file = NULL, .use_pid_file = true, @@ -496,6 +498,48 @@ static int parse_rtprio(pa_config_parser_state *state) { return 0; } +static int parse_disable_lfe_remix(pa_config_parser_state *state) { + pa_daemon_conf *c; + int k; + + pa_assert(state); + c = state->data; + + if ((k = pa_parse_boolean(state->rvalue)) < 0) { + pa_log("[%s:%u] Failed to parse boolean value: %s", state->filename, state->lineno, state->rvalue); + return -1; + } + + c->remixing_produce_lfe = c->remixing_consume_lfe = !k; + + pa_log("[%s:%u] Deprecated option 'disable-lfe-remixing' found.", state->filename, state->lineno); + pa_log("[%s:%u] Please migrate to 'remixing-produce-lfe' and 'remixing-consume-lfe', set both to '%s'.", + state->filename, state->lineno, pa_yes_no(c->remixing_produce_lfe)); + + return 0; +} + +static int parse_enable_lfe_remix(pa_config_parser_state *state) { + pa_daemon_conf *c; + int k; + + pa_assert(state); + c = state->data; + + if ((k = pa_parse_boolean(state->rvalue)) < 0) { + pa_log("[%s:%u] Failed to parse boolean value: %s", state->filename, state->lineno, state->rvalue); + return -1; + } + + c->remixing_produce_lfe = c->remixing_consume_lfe = k; + + pa_log("[%s:%u] Deprecated option 'enable-lfe-remixing' found.", state->filename, state->lineno); + pa_log("[%s:%u] Please migrate to 'remixing-produce-lfe' and 'remixing-consume-lfe', set both to '%s'.", + state->filename, state->lineno, pa_yes_no(c->remixing_produce_lfe)); + + return 0; +} + #ifdef HAVE_DBUS static int parse_server_type(pa_config_parser_state *state) { pa_daemon_conf *c; @@ -537,6 +581,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "enable-shm", pa_config_parse_not_bool, &c->disable_shm, NULL }, { "enable-memfd", pa_config_parse_not_bool, &c->disable_memfd, NULL }, { "flat-volumes", pa_config_parse_bool, &c->flat_volumes, NULL }, + { "rescue-streams", pa_config_parse_bool, &c->rescue_streams, NULL }, { "lock-memory", pa_config_parse_bool, &c->lock_memory, NULL }, { "enable-deferred-volume", pa_config_parse_bool, &c->deferred_volume, NULL }, { "exit-idle-time", pa_config_parse_int, &c->exit_idle_time, NULL }, @@ -565,8 +610,10 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "enable-remixing", pa_config_parse_not_bool, &c->disable_remixing, NULL }, { "remixing-use-all-sink-channels", pa_config_parse_bool, &c->remixing_use_all_sink_channels, NULL }, - { "disable-lfe-remixing", pa_config_parse_bool, &c->disable_lfe_remixing, NULL }, - { "enable-lfe-remixing", pa_config_parse_not_bool, &c->disable_lfe_remixing, NULL }, + { "disable-lfe-remixing", parse_disable_lfe_remix, c, NULL }, + { "enable-lfe-remixing", parse_enable_lfe_remix, c, NULL }, + { "remixing-produce-lfe", pa_config_parse_bool, &c->remixing_produce_lfe, NULL }, + { "remixing-consume-lfe", pa_config_parse_bool, &c->remixing_consume_lfe, NULL }, { "lfe-crossover-freq", pa_config_parse_unsigned, &c->lfe_crossover_freq, NULL }, { "load-default-script-file", pa_config_parse_bool, &c->load_default_script_file, NULL }, { "shm-size-bytes", pa_config_parse_size, &c->shm_size, NULL }, @@ -749,6 +796,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "cpu-limit = %s\n", pa_yes_no(!c->no_cpu_limit)); pa_strbuf_printf(s, "enable-shm = %s\n", pa_yes_no(!c->disable_shm)); pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes)); + pa_strbuf_printf(s, "rescue-streams = %s\n", pa_yes_no(c->rescue_streams)); pa_strbuf_printf(s, "lock-memory = %s\n", pa_yes_no(c->lock_memory)); pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time); pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time); @@ -761,7 +809,8 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "avoid-resampling = %s\n", pa_yes_no(c->avoid_resampling)); pa_strbuf_printf(s, "enable-remixing = %s\n", pa_yes_no(!c->disable_remixing)); pa_strbuf_printf(s, "remixing-use-all-sink-channels = %s\n", pa_yes_no(c->remixing_use_all_sink_channels)); - pa_strbuf_printf(s, "enable-lfe-remixing = %s\n", pa_yes_no(!c->disable_lfe_remixing)); + pa_strbuf_printf(s, "remixing-produce-lfe = %s\n", pa_yes_no(c->remixing_produce_lfe)); + pa_strbuf_printf(s, "remixing-consume-lfe = %s\n", pa_yes_no(c->remixing_consume_lfe)); pa_strbuf_printf(s, "lfe-crossover-freq = %u\n", c->lfe_crossover_freq); 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); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index 953ea33..fa713b9 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -70,12 +70,14 @@ typedef struct pa_daemon_conf { avoid_resampling, disable_remixing, remixing_use_all_sink_channels, - disable_lfe_remixing, + remixing_produce_lfe, + remixing_consume_lfe, load_default_script_file, disallow_exit, log_meta, log_time, flat_volumes, + rescue_streams, lock_memory, deferred_volume; pa_server_type_t local_server_type; diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index a955523..7409976 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -57,10 +57,13 @@ ifelse(@HAVE_DBUS@, 1, [dnl ; avoid-resampling = false ; enable-remixing = yes ; remixing-use-all-sink-channels = yes -; enable-lfe-remixing = no +; remixing-produce-lfe = no +; remixing-consume-lfe = no ; lfe-crossover-freq = 0 -; flat-volumes = yes +; flat-volumes = no + +; rescue-streams = yes ifelse(@HAVE_SYS_RESOURCE_H@, 1, [dnl ; rlimit-fsize = -1 diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index 14b6a6f..030334f 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -138,10 +138,6 @@ load-module module-gconf ### that look up the default sink/source get the right value load-module module-default-device-restore -### Automatically move streams to the default sink if the sink they are -### connected to dies, similar for sources -load-module module-rescue-streams - ### Make sure we always have a sink around, even if it is a null sink. load-module module-always-sink diff --git a/src/daemon/main.c b/src/daemon/main.c index e96c86d..f1810c5 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -1056,11 +1056,13 @@ int main(int argc, char *argv[]) { c->avoid_resampling = conf->avoid_resampling; c->disable_remixing = conf->disable_remixing; c->remixing_use_all_sink_channels = conf->remixing_use_all_sink_channels; - c->disable_lfe_remixing = conf->disable_lfe_remixing; + c->remixing_produce_lfe = conf->remixing_produce_lfe; + c->remixing_consume_lfe = conf->remixing_consume_lfe; c->deferred_volume = conf->deferred_volume; c->running_as_daemon = conf->daemonize; c->disallow_exit = conf->disallow_exit; c->flat_volumes = conf->flat_volumes; + c->rescue_streams = conf->rescue_streams; #ifdef HAVE_DBUS c->server_type = conf->local_server_type; #endif diff --git a/src/daemon/meson.build b/src/daemon/meson.build index 9bc3bf1..9c9f807 100644 --- a/src/daemon/meson.build +++ b/src/daemon/meson.build @@ -31,7 +31,7 @@ executable('pulseaudio', include_directories : [configinc, topinc], link_args : ['-ffast-math'], link_with : [libpulsecore, libpulsecommon, libpulse], - dependencies : [ltdl_dep, cap_dep, dbus_dep, libsystemd_dep, dl_dep], + dependencies : [ltdl_dep, cap_dep, dbus_dep, libsystemd_dep, dl_dep, libintl_dep], c_args : pa_c_args, ) diff --git a/src/daemon/start-pulseaudio-x11.in b/src/daemon/start-pulseaudio-x11.in index 1b5f429..0e84315 100755 --- a/src/daemon/start-pulseaudio-x11.in +++ b/src/daemon/start-pulseaudio-x11.in @@ -19,17 +19,19 @@ set -e if [ x"$DISPLAY" != x ] ; then - @PACTL_BINARY@ load-module module-x11-publish "display=$DISPLAY" > /dev/null - @PACTL_BINARY@ load-module module-x11-cork-request "display=$DISPLAY" > /dev/null + @PACTL_BINARY@ load-module module-x11-publish "display=$DISPLAY xauthority=$XAUTHORITY" > /dev/null + @PACTL_BINARY@ load-module module-x11-cork-request "display=$DISPLAY xauthority=$XAUTHORITY" > /dev/null + # KDE plasma versions older than 5.17.0 use module-device-manager's routing API. + # Check for current plasma version and load module if it's necessary. if [ x"$KDE_FULL_SESSION" = x"true" ]; then - plasmaversion=`grep "X-KDE-PluginInfo-Version" $DESKTOP_SESSION.desktop | cut -d "=" -f2 | cut -d "." -f1,2 | tr -d "."` - if [ "$plasmaversion" -lt "517" ]; then + plasmaversion="$(plasmashell -v 2>/dev/null | sed -n 's/^plasmashell \([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\)/\1*1000000+\2*1000+\3/p' | head -1)" + if [ -n "$plasmaversion" ] && [ "$(($plasmaversion))" -lt "5017000" ]; then @PACTL_BINARY@ load-module module-device-manager "do_routing=1" > /dev/null fi fi if [ x"$SESSION_MANAGER" != x ] ; then - @PACTL_BINARY@ load-module module-x11-xsmp "display=$DISPLAY session_manager=$SESSION_MANAGER" > /dev/null + @PACTL_BINARY@ load-module module-x11-xsmp "display=$DISPLAY xauthority=$XAUTHORITY session_manager=$SESSION_MANAGER" > /dev/null fi fi diff --git a/src/daemon/system.pa.in b/src/daemon/system.pa.in index b1a4a5c..73e39ec 100755 --- a/src/daemon/system.pa.in +++ b/src/daemon/system.pa.in @@ -52,10 +52,6 @@ load-module module-native-protocol-unix ### that look up the default sink/source get the right value load-module module-default-device-restore -### Automatically move streams to the default sink if the sink they are -### connected to dies, similar for sources -load-module module-rescue-streams - ### Make sure we always have a sink around, even if it is a null sink. load-module module-always-sink diff --git a/src/meson.build b/src/meson.build index c9b71a4..832c0de 100644 --- a/src/meson.build +++ b/src/meson.build @@ -183,7 +183,7 @@ libpulsecommon = shared_library('pulsecommon-' + pa_version_major_minor, install_dir : privlibdir, dependencies : [ libm_dep, thread_dep, dl_dep, shm_dep, iconv_dep, sndfile_dep, dbus_dep, - x11_dep, libsystemd_dep, glib_dep, gtk_dep, asyncns_dep + x11_dep, libsystemd_dep, glib_dep, gtk_dep, asyncns_dep, libintl_dep, ], implicit_include_directories : false) diff --git a/src/modules/alsa/90-pulseaudio.rules b/src/modules/alsa/90-pulseaudio.rules index d857639..fa43cb8 100644 --- a/src/modules/alsa/90-pulseaudio.rules +++ b/src/modules/alsa/90-pulseaudio.rules @@ -109,15 +109,23 @@ ATTRS{idVendor}=="0763", ATTRS{idProduct}=="2012", ENV{PULSE_PROFILE_SET}="maudi ATTRS{idVendor}=="045e", ATTRS{idProduct}=="02bb", ENV{PULSE_PROFILE_SET}="kinect-audio.conf" ATTRS{idVendor}=="041e", ATTRS{idProduct}=="322c", ENV{PULSE_PROFILE_SET}="sb-omni-surround-5.1.conf" ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="4014", ENV{PULSE_PROFILE_SET}="dell-dock-tb16-usb-audio.conf" -ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1250", ENV{PULSE_PROFILE_SET}="steelseries-arctis-5-usb-audio.conf" + # ID 1038:12ad is for the 2018 refresh of the Arctis 7. -# ID 1038:1294 is for Arctis Pro Wireless (which works with the Arctis 7 -# configuration). -ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1260", ENV{PULSE_PROFILE_SET}="steelseries-arctis-7-usb-audio.conf" -ATTRS{idVendor}=="1038", ATTRS{idProduct}=="12ad", ENV{PULSE_PROFILE_SET}="steelseries-arctis-7-usb-audio.conf" -ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1294", ENV{PULSE_PROFILE_SET}="steelseries-arctis-7-usb-audio.conf" -ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1730", ENV{PULSE_PROFILE_SET}="steelseries-arctis-7-usb-audio.conf" +# ID 1038:1294 is for Arctis Pro Wireless (which works with the Arctis 7 configuration). +ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1260", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf" +ATTRS{idVendor}=="1038", ATTRS{idProduct}=="12ad", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf" +ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1294", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf" +ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1730", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf" +# Lucidsound LS31 +ATTRS{idVendor}=="2f12", ATTRS{idProduct}=="0109", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf" + +# ID 1038:1250 is for the Arctis 5 +# ID 1037:12aa is for the Arctis 5 2019 +# ID 1038:1252 is for the Arctis Pro 2019 edition +ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1250", ENV{PULSE_PROFILE_SET}="steelseries-arctis-common-usb-audio.conf" +ATTRS{idVendor}=="1038", ATTRS{idProduct}=="12aa", ENV{PULSE_PROFILE_SET}="steelseries-arctis-common-usb-audio.conf" +ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1252", ENV{PULSE_PROFILE_SET}="steelseries-arctis-common-usb-audio.conf" ATTRS{idVendor}=="147a", ATTRS{idProduct}=="e055", ENV{PULSE_PROFILE_SET}="cmedia-high-speed-true-hdaudio.conf" diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index cd99a75..d184aec 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -107,13 +107,54 @@ struct description_map { const char *description; }; -pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *name) { +static char *alsa_id_str(char *dst, size_t dst_len, pa_alsa_mixer_id *id) { + if (id->index > 0) { + snprintf(dst, dst_len, "'%s',%d", id->name, id->index); + } else { + snprintf(dst, dst_len, "'%s'", id->name); + } + return dst; +} + +static int alsa_id_decode(const char *src, char *name, int *index) { + char *idx, c; + int i; + + *index = 0; + c = src[0]; + /* Strip quotes in entries such as 'Speaker',1 or "Speaker",1 */ + if (c == '\'' || c == '"') { + strcpy(name, src + 1); + for (i = 0; name[i] != '\0' && name[i] != c; i++); + idx = NULL; + if (name[i]) { + name[i] = '\0'; + idx = strchr(name + i + 1, ','); + } + } else { + strcpy(name, src); + idx = strchr(name, ','); + } + if (idx == NULL) + return 0; + *idx = '\0'; + idx++; + if (*idx < '0' || *idx > '9') { + pa_log("Element %s: index value is invalid", src); + return 1; + } + *index = atoi(idx); + return 0; +} + +pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name) { pa_alsa_jack *jack; pa_assert(name); jack = pa_xnew0(pa_alsa_jack, 1); jack->path = path; + jack->mixer_device_name = pa_xstrdup(mixer_device_name); jack->name = pa_xstrdup(name); jack->alsa_name = pa_sprintf_malloc("%s Jack", name); jack->state_unplugged = PA_AVAILABLE_NO; @@ -132,6 +173,7 @@ void pa_alsa_jack_free(pa_alsa_jack *jack) { pa_xfree(jack->alsa_name); pa_xfree(jack->name); + pa_xfree(jack->mixer_device_name); pa_xfree(jack); } @@ -467,7 +509,7 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) { unsigned short revents = 0; int err, ret = 0; - pd = pa_rtpoll_item_get_userdata(i); + pd = pa_rtpoll_item_get_work_userdata(i); pa_assert_fp(pd); pa_assert_fp(i == pd->poll_item); @@ -547,8 +589,7 @@ int pa_alsa_set_mixer_rtpoll(struct pa_alsa_mixer_pdata *pd, snd_mixer_t *mixer, pd->poll_item = i; pd->mixer = mixer; - pa_rtpoll_item_set_userdata(i, pd); - pa_rtpoll_item_set_work_callback(i, rtpoll_work_cb); + pa_rtpoll_item_set_work_callback(i, rtpoll_work_cb, pd); return 0; } @@ -642,6 +683,7 @@ static void decibel_fix_free(pa_alsa_decibel_fix *db_fix) { pa_xfree(db_fix->name); pa_xfree(db_fix->db_values); + pa_xfree(db_fix->key); pa_xfree(db_fix); } @@ -657,7 +699,7 @@ static void element_free(pa_alsa_element *e) { if (e->db_fix) decibel_fix_free(e->db_fix); - pa_xfree(e->alsa_name); + pa_xfree(e->alsa_id.name); pa_xfree(e); } @@ -699,6 +741,12 @@ void pa_alsa_path_set_free(pa_alsa_path_set *ps) { pa_xfree(ps); } +int pa_alsa_path_set_is_empty(pa_alsa_path_set *ps) { + if (ps && !pa_hashmap_isempty(ps->paths)) + return 0; + return 1; +} + static long to_alsa_dB(pa_volume_t v) { return lround(pa_sw_volume_to_dB(v) * 100.0); } @@ -718,11 +766,11 @@ static pa_volume_t from_alsa_volume(long v, long min, long max) { return (pa_volume_t) round(((double) (v - min) * PA_VOLUME_NORM) / (double) (max - min)); } -#define SELEM_INIT(sid, name) \ - do { \ - snd_mixer_selem_id_alloca(&(sid)); \ - snd_mixer_selem_id_set_name((sid), (name)); \ - snd_mixer_selem_id_set_index((sid), 0); \ +#define SELEM_INIT(sid, aid) \ + do { \ + snd_mixer_selem_id_alloca(&(sid)); \ + snd_mixer_selem_id_set_name((sid), (aid)->name); \ + snd_mixer_selem_id_set_index((sid), (aid)->index); \ } while(false) static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v) { @@ -730,6 +778,7 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann snd_mixer_elem_t *me; snd_mixer_selem_channel_id_t c; pa_channel_position_mask_t mask = 0; + char buf[64]; unsigned k; pa_assert(m); @@ -737,9 +786,10 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann pa_assert(cm); pa_assert(v); - SELEM_INIT(sid, e->alsa_name); + SELEM_INIT(sid, &e->alsa_id); if (!(me = snd_mixer_find_selem(m, sid))) { - pa_log_warn("Element %s seems to have disappeared.", e->alsa_name); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Element %s seems to have disappeared.", buf); return -1; } @@ -764,14 +814,16 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann if (value < e->db_fix->min_step) { value = e->db_fix->min_step; snd_mixer_selem_set_playback_volume(me, c, value); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); pa_log_debug("Playback volume for element %s channel %i was below the dB fix limit. " - "Volume reset to %0.2f dB.", e->alsa_name, c, + "Volume reset to %0.2f dB.", buf, c, e->db_fix->db_values[value - e->db_fix->min_step] / 100.0); } else if (value > e->db_fix->max_step) { value = e->db_fix->max_step; snd_mixer_selem_set_playback_volume(me, c, value); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); pa_log_debug("Playback volume for element %s channel %i was over the dB fix limit. " - "Volume reset to %0.2f dB.", e->alsa_name, c, + "Volume reset to %0.2f dB.", buf, c, e->db_fix->db_values[value - e->db_fix->min_step] / 100.0); } @@ -792,14 +844,16 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann if (value < e->db_fix->min_step) { value = e->db_fix->min_step; snd_mixer_selem_set_capture_volume(me, c, value); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); pa_log_debug("Capture volume for element %s channel %i was below the dB fix limit. " - "Volume reset to %0.2f dB.", e->alsa_name, c, + "Volume reset to %0.2f dB.", buf, c, e->db_fix->db_values[value - e->db_fix->min_step] / 100.0); } else if (value > e->db_fix->max_step) { value = e->db_fix->max_step; snd_mixer_selem_set_capture_volume(me, c, value); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); pa_log_debug("Capture volume for element %s channel %i was over the dB fix limit. " - "Volume reset to %0.2f dB.", e->alsa_name, c, + "Volume reset to %0.2f dB.", buf, c, e->db_fix->db_values[value - e->db_fix->min_step] / 100.0); } @@ -897,14 +951,16 @@ static int element_get_switch(pa_alsa_element *e, snd_mixer_t *m, bool *b) { snd_mixer_selem_id_t *sid; snd_mixer_elem_t *me; snd_mixer_selem_channel_id_t c; + char buf[64]; pa_assert(m); pa_assert(e); pa_assert(b); - SELEM_INIT(sid, e->alsa_name); + SELEM_INIT(sid, &e->alsa_id); if (!(me = snd_mixer_find_selem(m, sid))) { - pa_log_warn("Element %s seems to have disappeared.", e->alsa_name); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Element %s seems to have disappeared.", buf); return -1; } @@ -1058,6 +1114,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann snd_mixer_elem_t *me; snd_mixer_selem_channel_id_t c; pa_channel_position_mask_t mask = 0; + char buf[64]; unsigned k; pa_assert(m); @@ -1066,9 +1123,10 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann pa_assert(v); pa_assert(pa_cvolume_compatible_with_channel_map(v, cm)); - SELEM_INIT(sid, e->alsa_name); + SELEM_INIT(sid, &e->alsa_id); if (!(me = snd_mixer_find_selem(m, sid))) { - pa_log_warn("Element %s seems to have disappeared.", e->alsa_name); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Element %s seems to have disappeared.", buf); return -1; } @@ -1251,14 +1309,16 @@ int pa_alsa_path_set_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_ma static int element_set_switch(pa_alsa_element *e, snd_mixer_t *m, bool b) { snd_mixer_elem_t *me; snd_mixer_selem_id_t *sid; + char buf[64]; int r; pa_assert(m); pa_assert(e); - SELEM_INIT(sid, e->alsa_name); + SELEM_INIT(sid, &e->alsa_id); if (!(me = snd_mixer_find_selem(m, sid))) { - pa_log_warn("Element %s seems to have disappeared.", e->alsa_name); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Element %s seems to have disappeared.", buf); return -1; } @@ -1267,8 +1327,10 @@ static int element_set_switch(pa_alsa_element *e, snd_mixer_t *m, bool b) { else r = snd_mixer_selem_set_capture_switch_all(me, b); - if (r < 0) - pa_log_warn("Failed to set switch of %s: %s", e->alsa_name, pa_alsa_strerror(errno)); + if (r < 0) { + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Failed to set switch of %s: %s", buf, pa_alsa_strerror(errno)); + } return r; } @@ -1303,13 +1365,15 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) { int r = 0; long volume = -1; bool volume_set = false; + char buf[64]; pa_assert(m); pa_assert(e); - SELEM_INIT(sid, e->alsa_name); + SELEM_INIT(sid, &e->alsa_id); if (!(me = snd_mixer_find_selem(m, sid))) { - pa_log_warn("Element %s seems to have disappeared.", e->alsa_name); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Element %s seems to have disappeared.", buf); return -1; } @@ -1352,8 +1416,10 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) { r = snd_mixer_selem_set_capture_dB_all(me, 0, -1); } - if (r < 0) - pa_log_warn("Failed to set volume of %s: %s", e->alsa_name, pa_alsa_strerror(errno)); + if (r < 0) { + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Failed to set volume of %s: %s", buf, pa_alsa_strerror(errno)); + } return r; } @@ -1531,6 +1597,7 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) { int r; bool is_mono; pa_channel_position_t p; + char buf[64]; if (e->direction == PA_ALSA_DIRECTION_OUTPUT) { if (!snd_mixer_selem_has_playback_volume(me)) { @@ -1556,29 +1623,33 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) { r = snd_mixer_selem_get_capture_volume_range(me, &e->min_volume, &e->max_volume); if (r < 0) { - pa_log_warn("Failed to get volume range of %s: %s", e->alsa_name, pa_alsa_strerror(r)); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Failed to get volume range of %s: %s", buf, pa_alsa_strerror(r)); return false; } if (e->min_volume >= e->max_volume) { - pa_log_warn("Your kernel driver is broken: it reports a volume range from %li to %li which makes no sense.", - e->min_volume, e->max_volume); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Your kernel driver is broken for element %s: it reports a volume range from %li to %li which makes no sense.", + buf, e->min_volume, e->max_volume); return false; } if (e->volume_use == PA_ALSA_VOLUME_CONSTANT && (e->min_volume > e->constant_volume || e->max_volume < e->constant_volume)) { + alsa_id_str(buf, sizeof(buf), &e->alsa_id); pa_log_warn("Constant volume %li configured for element %s, but the available range is from %li to %li.", - e->constant_volume, e->alsa_name, e->min_volume, e->max_volume); + e->constant_volume, buf, e->min_volume, e->max_volume); return false; } if (e->db_fix && ((e->min_volume > e->db_fix->min_step) || (e->max_volume < e->db_fix->max_step))) { - pa_log_warn("The step range of the decibel fix for element %s (%li-%li) doesn't fit to the " - "real hardware range (%li-%li). Disabling the decibel fix.", e->alsa_name, - e->db_fix->min_step, e->db_fix->max_step, e->min_volume, e->max_volume); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("The step range of the decibel fix for element %s (%li-%li) doesn't fit to the " + "real hardware range (%li-%li). Disabling the decibel fix.", buf, + e->db_fix->min_step, e->db_fix->max_step, e->min_volume, e->max_volume); - decibel_fix_free(e->db_fix); - e->db_fix = NULL; + decibel_fix_free(e->db_fix); + e->db_fix = NULL; } if (e->db_fix) { @@ -1599,19 +1670,22 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) { long max_dB_checked = 0; if (element_ask_vol_dB(me, e->direction, e->min_volume, &min_dB_checked) < 0) { - pa_log_warn("Failed to query the dB value for %s at volume level %li", e->alsa_name, e->min_volume); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Failed to query the dB value for %s at volume level %li", buf, e->min_volume); return false; } if (element_ask_vol_dB(me, e->direction, e->max_volume, &max_dB_checked) < 0) { - pa_log_warn("Failed to query the dB value for %s at volume level %li", e->alsa_name, e->max_volume); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Failed to query the dB value for %s at volume level %li", buf, e->max_volume); return false; } if (min_dB != min_dB_checked || max_dB != max_dB_checked) { + alsa_id_str(buf, sizeof(buf), &e->alsa_id); pa_log_warn("Your kernel driver is broken: the reported dB range for %s (from %0.2f dB to %0.2f dB) " "doesn't match the dB values at minimum and maximum volume levels: %0.2f dB at level %li, " - "%0.2f dB at level %li.", e->alsa_name, min_dB / 100.0, max_dB / 100.0, + "%0.2f dB at level %li.", buf, min_dB / 100.0, max_dB / 100.0, min_dB_checked / 100.0, e->min_volume, max_dB_checked / 100.0, e->max_volume); return false; } @@ -1630,11 +1704,12 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) { } if (e->volume_limit >= 0) { - if (e->volume_limit <= e->min_volume || e->volume_limit > e->max_volume) + if (e->volume_limit <= e->min_volume || e->volume_limit > e->max_volume) { + alsa_id_str(buf, sizeof(buf), &e->alsa_id); pa_log_warn("Volume limit for element %s of path %s is invalid: %li isn't within the valid range " "%li-%li. The volume limit is ignored.", - e->alsa_name, e->path->name, e->volume_limit, e->min_volume + 1, e->max_volume); - else { + buf, e->path->name, e->volume_limit, e->min_volume + 1, e->max_volume); + } else { e->max_volume = e->volume_limit; if (e->has_dB) { @@ -1642,7 +1717,8 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) { e->db_fix->max_step = e->max_volume; e->max_dB = ((double) e->db_fix->db_values[e->db_fix->max_step - e->db_fix->min_step]) / 100.0; } else if (element_ask_vol_dB(me, e->direction, e->max_volume, &max_dB) < 0) { - pa_log_warn("Failed to get dB value of %s: %s", e->alsa_name, pa_alsa_strerror(r)); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Failed to get dB value of %s: %s", buf, pa_alsa_strerror(r)); e->has_dB = false; } else e->max_dB = ((double) max_dB) / 100.0; @@ -1682,7 +1758,8 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) { } if (e->n_channels <= 0) { - pa_log_warn("Volume element %s with no channels?", e->alsa_name); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Volume element %s with no channels?", buf); return false; } else if (e->n_channels > 2) { /* FIXME: In some places code like this is used: @@ -1696,7 +1773,8 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) { * Since the array size is fixed at 2, we obviously * don't support elements with more than two * channels... */ - pa_log_warn("Volume element %s has %u channels. That's too much! I can't handle that!", e->alsa_name, e->n_channels); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Volume element %s has %u channels. That's too much! I can't handle that!", buf, e->n_channels); return false; } @@ -1734,7 +1812,7 @@ static int element_probe(pa_alsa_element *e, snd_mixer_t *m) { pa_assert(e); pa_assert(e->path); - SELEM_INIT(sid, e->alsa_name); + SELEM_INIT(sid, &e->alsa_id); if (!(me = snd_mixer_find_selem(m, sid))) { @@ -1837,7 +1915,7 @@ static int jack_probe(pa_alsa_jack *j, pa_alsa_mapping *mapping, snd_mixer_t *m) j->append_pcm_to_name = false; } - has_control = pa_alsa_mixer_find(m, j->alsa_name, 0) != NULL; + has_control = pa_alsa_mixer_find_card(m, j->alsa_name, 0) != NULL; pa_alsa_jack_set_has_control(j, has_control); if (j->has_control) { @@ -1853,8 +1931,10 @@ static int jack_probe(pa_alsa_jack *j, pa_alsa_mapping *mapping, snd_mixer_t *m) return 0; } -static pa_alsa_element* element_get(pa_alsa_path *p, const char *section, bool prefixed) { +pa_alsa_element * pa_alsa_element_get(pa_alsa_path *p, const char *section, bool prefixed) { pa_alsa_element *e; + char *name; + int index; pa_assert(p); pa_assert(section); @@ -1870,16 +1950,22 @@ static pa_alsa_element* element_get(pa_alsa_path *p, const char *section, bool p if (strchr(section, ':')) return NULL; - if (p->last_element && pa_streq(p->last_element->alsa_name, section)) + name = alloca(strlen(section) + 1); + if (alsa_id_decode(section, name, &index)) + return NULL; + + if (p->last_element && pa_streq(p->last_element->alsa_id.name, name) && + p->last_element->alsa_id.index == index) return p->last_element; PA_LLIST_FOREACH(e, p->elements) - if (pa_streq(e->alsa_name, section)) + if (pa_streq(e->alsa_id.name, name) && e->alsa_id.index == index) goto finish; e = pa_xnew0(pa_alsa_element, 1); e->path = p; - e->alsa_name = pa_xstrdup(section); + e->alsa_id.name = pa_xstrdup(name); + e->alsa_id.index = index; e->direction = p->direction; e->volume_limit = -1; @@ -1904,7 +1990,7 @@ static pa_alsa_jack* jack_get(pa_alsa_path *p, const char *section) { if (pa_streq(j->name, section)) goto finish; - j = pa_alsa_jack_new(p, section); + j = pa_alsa_jack_new(p, NULL, section); PA_LLIST_INSERT_AFTER(pa_alsa_jack, p->jacks, p->last_jack, j); finish: @@ -1913,10 +1999,12 @@ finish: } static pa_alsa_option* option_get(pa_alsa_path *p, const char *section) { - char *en; + char *en, *name; const char *on; pa_alsa_option *o; pa_alsa_element *e; + size_t len; + int index; if (!pa_startswith(section, "Option ")) return NULL; @@ -1927,18 +2015,25 @@ static pa_alsa_option* option_get(pa_alsa_path *p, const char *section) { if (!(on = strchr(section, ':'))) return NULL; - en = pa_xstrndup(section, on - section); + len = on - section; + en = alloca(len + 1); + strncpy(en, section, len); + en[len] = '\0'; + + name = alloca(strlen(en) + 1); + if (alsa_id_decode(en, name, &index)) + return NULL; + on++; if (p->last_option && - pa_streq(p->last_option->element->alsa_name, en) && + pa_streq(p->last_option->element->alsa_id.name, name) && + p->last_option->element->alsa_id.index == index && pa_streq(p->last_option->alsa_name, on)) { - pa_xfree(en); return p->last_option; } - pa_assert_se(e = element_get(p, en, false)); - pa_xfree(en); + pa_assert_se(e = pa_alsa_element_get(p, en, false)); PA_LLIST_FOREACH(o, e->options) if (pa_streq(o->alsa_name, on)) @@ -1967,7 +2062,7 @@ static int element_parse_switch(pa_config_parser_state *state) { p = state->userdata; - if (!(e = element_get(p, state->section, true))) { + if (!(e = pa_alsa_element_get(p, state->section, true))) { pa_log("[%s:%u] Switch makes no sense in '%s'", state->filename, state->lineno, state->section); return -1; } @@ -1998,7 +2093,7 @@ static int element_parse_volume(pa_config_parser_state *state) { p = state->userdata; - if (!(e = element_get(p, state->section, true))) { + if (!(e = pa_alsa_element_get(p, state->section, true))) { pa_log("[%s:%u] Volume makes no sense in '%s'", state->filename, state->lineno, state->section); return -1; } @@ -2034,7 +2129,7 @@ static int element_parse_enumeration(pa_config_parser_state *state) { p = state->userdata; - if (!(e = element_get(p, state->section, true))) { + if (!(e = pa_alsa_element_get(p, state->section, true))) { pa_log("[%s:%u] Enumeration makes no sense in '%s'", state->filename, state->lineno, state->section); return -1; } @@ -2126,7 +2221,7 @@ static int element_parse_required(pa_config_parser_state *state) { p = state->userdata; - e = element_get(p, state->section, true); + e = pa_alsa_element_get(p, state->section, true); o = option_get(p, state->section); j = jack_get(p, state->section); if (!e && !o && !j) { @@ -2192,7 +2287,7 @@ static int element_parse_direction(pa_config_parser_state *state) { p = state->userdata; - if (!(e = element_get(p, state->section, true))) { + if (!(e = pa_alsa_element_get(p, state->section, true))) { pa_log("[%s:%u] Direction makes no sense in '%s'", state->filename, state->lineno, state->section); return -1; } @@ -2218,7 +2313,7 @@ static int element_parse_direction_try_other(pa_config_parser_state *state) { p = state->userdata; - if (!(e = element_get(p, state->section, true))) { + if (!(e = pa_alsa_element_get(p, state->section, true))) { pa_log("[%s:%u] Direction makes no sense in '%s'", state->filename, state->lineno, state->section); return -1; } @@ -2241,7 +2336,7 @@ static int element_parse_volume_limit(pa_config_parser_state *state) { p = state->userdata; - if (!(e = element_get(p, state->section, true))) { + if (!(e = pa_alsa_element_get(p, state->section, true))) { pa_log("[%s:%u] volume-limit makes no sense in '%s'", state->filename, state->lineno, state->section); return -1; } @@ -2299,7 +2394,7 @@ static int element_parse_override_map(pa_config_parser_state *state) { p = state->userdata; - if (!(e = element_get(p, state->section, true))) { + if (!(e = pa_alsa_element_get(p, state->section, true))) { pa_log("[%s:%u] Override map makes no sense in '%s'", state->filename, state->lineno, state->section); return -1; } @@ -2394,14 +2489,16 @@ static int jack_parse_append_pcm_to_name(pa_config_parser_state *state) { static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx) { snd_mixer_selem_id_t *sid; snd_mixer_elem_t *me; + char buf[64]; int r; pa_assert(e); pa_assert(m); - SELEM_INIT(sid, e->alsa_name); + SELEM_INIT(sid, &e->alsa_id); if (!(me = snd_mixer_find_selem(m, sid))) { - pa_log_warn("Element %s seems to have disappeared.", e->alsa_name); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Element %s seems to have disappeared.", buf); return -1; } @@ -2412,14 +2509,18 @@ static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx) else r = snd_mixer_selem_set_capture_switch_all(me, alsa_idx); - if (r < 0) - pa_log_warn("Failed to set switch of %s: %s", e->alsa_name, pa_alsa_strerror(errno)); + if (r < 0) { + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Failed to set switch of %s: %s", buf, pa_alsa_strerror(errno)); + } } else { pa_assert(e->enumeration_use == PA_ALSA_ENUMERATION_SELECT); - if ((r = snd_mixer_selem_set_enum_item(me, 0, alsa_idx)) < 0) - pa_log_warn("Failed to set enumeration of %s: %s", e->alsa_name, pa_alsa_strerror(errno)); + if ((r = snd_mixer_selem_set_enum_item(me, 0, alsa_idx)) < 0) { + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Failed to set enumeration of %s: %s", buf, pa_alsa_strerror(errno)); + } } return r; @@ -2463,6 +2564,7 @@ static int option_verify(pa_alsa_option *o) { { "output-speaker", N_("Speaker") }, { "output-headphones", N_("Headphones") } }; + char buf[64]; pa_assert(o); @@ -2473,14 +2575,16 @@ static int option_verify(pa_alsa_option *o) { if (o->element->enumeration_use != PA_ALSA_ENUMERATION_SELECT && o->element->switch_use != PA_ALSA_SWITCH_SELECT) { - pa_log("Element %s of option %s not set for select.", o->element->alsa_name, o->name); + alsa_id_str(buf, sizeof(buf), &o->element->alsa_id); + pa_log("Element %s of option %s not set for select.", buf, o->name); return -1; } if (o->element->switch_use == PA_ALSA_SWITCH_SELECT && !pa_streq(o->alsa_name, "on") && !pa_streq(o->alsa_name, "off")) { - pa_log("Switch %s options need be named off or on ", o->element->alsa_name); + alsa_id_str(buf, sizeof(buf), &o->element->alsa_id); + pa_log("Switch %s options need be named off or on ", buf); return -1; } @@ -2496,6 +2600,7 @@ static int option_verify(pa_alsa_option *o) { static int element_verify(pa_alsa_element *e) { pa_alsa_option *o; + char buf[64]; pa_assert(e); @@ -2504,12 +2609,14 @@ static int element_verify(pa_alsa_element *e) { (e->required_any != PA_ALSA_REQUIRED_IGNORE && e->required_any == e->required_absent) || (e->required_absent == PA_ALSA_REQUIRED_ANY && e->required_any != PA_ALSA_REQUIRED_IGNORE) || (e->required_absent == PA_ALSA_REQUIRED_ANY && e->required != PA_ALSA_REQUIRED_IGNORE)) { - pa_log("Element %s cannot be required and absent at the same time.", e->alsa_name); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log("Element %s cannot be required and absent at the same time.", buf); return -1; } if (e->switch_use == PA_ALSA_SWITCH_SELECT && e->enumeration_use == PA_ALSA_ENUMERATION_SELECT) { - pa_log("Element %s cannot set select for both switch and enumeration.", e->alsa_name); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log("Element %s cannot set select for both switch and enumeration.", buf); return -1; } @@ -2661,9 +2768,15 @@ fail: pa_alsa_path *pa_alsa_path_synthesize(const char *element, pa_alsa_direction_t direction) { pa_alsa_path *p; pa_alsa_element *e; + char *name; + int index; pa_assert(element); + name = alloca(strlen(element) + 1); + if (alsa_id_decode(element, name, &index)) + return NULL; + p = pa_xnew0(pa_alsa_path, 1); p->name = pa_xstrdup(element); p->direction = direction; @@ -2671,7 +2784,8 @@ pa_alsa_path *pa_alsa_path_synthesize(const char *element, pa_alsa_direction_t d e = pa_xnew0(pa_alsa_element, 1); e->path = p; - e->alsa_name = pa_xstrdup(element); + e->alsa_id.name = pa_xstrdup(name); + e->alsa_id.index = index; e->direction = direction; e->volume_limit = -1; @@ -2821,6 +2935,7 @@ int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m double min_dB[PA_CHANNEL_POSITION_MAX], max_dB[PA_CHANNEL_POSITION_MAX]; pa_channel_position_t t; pa_channel_position_mask_t path_volume_channels = 0; + char buf[64]; pa_assert(p); pa_assert(m); @@ -2844,12 +2959,13 @@ int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m } PA_LLIST_FOREACH(e, p->elements) { + alsa_id_str(buf, sizeof(buf), &e->alsa_id); if (element_probe(e, m) < 0) { p->supported = false; - pa_log_debug("Probe of element '%s' failed.", e->alsa_name); + pa_log_debug("Probe of element %s failed.", buf); return -1; } - pa_log_debug("Probe of element '%s' succeeded (volume=%d, switch=%d, enumeration=%d).", e->alsa_name, e->volume_use, e->switch_use, e->enumeration_use); + pa_log_debug("Probe of element %s succeeded (volume=%d, switch=%d, enumeration=%d).", buf, e->volume_use, e->switch_use, e->enumeration_use); if (ignore_dB) e->has_dB = false; @@ -2885,13 +3001,13 @@ int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m * which cannot do dB volumes, so we we need * to 'neutralize' this slider */ e->volume_use = PA_ALSA_VOLUME_ZERO; - pa_log_info("Zeroing volume of '%s' on path '%s'", e->alsa_name, p->name); + pa_log_info("Zeroing volume of %s on path '%s'", buf, p->name); } } } else if (p->has_volume) { /* We can't use this volume, so let's ignore it */ e->volume_use = PA_ALSA_VOLUME_IGNORE; - pa_log_info("Ignoring volume of '%s' on path '%s' (missing dB info)", e->alsa_name, p->name); + pa_log_info("Ignoring volume of %s on path '%s' (missing dB info)", buf, p->name); } p->has_volume = true; } @@ -2955,11 +3071,14 @@ void pa_alsa_option_dump(pa_alsa_option *o) { } void pa_alsa_element_dump(pa_alsa_element *e) { + char buf[64]; + pa_alsa_option *o; pa_assert(e); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); pa_log_debug("Element %s, direction=%i, switch=%i, volume=%i, volume_limit=%li, enumeration=%i, required=%i, required_any=%i, required_absent=%i, mask=0x%llx, n_channels=%u, override_map=%s", - e->alsa_name, + buf, e->direction, e->switch_use, e->volume_use, @@ -3009,14 +3128,16 @@ void pa_alsa_path_dump(pa_alsa_path *p) { static void element_set_callback(pa_alsa_element *e, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata) { snd_mixer_selem_id_t *sid; snd_mixer_elem_t *me; + char buf[64]; pa_assert(e); pa_assert(m); pa_assert(cb); - SELEM_INIT(sid, e->alsa_name); + SELEM_INIT(sid, &e->alsa_id); if (!(me = snd_mixer_find_selem(m, sid))) { - pa_log_warn("Element %s seems to have disappeared.", e->alsa_name); + alsa_id_str(buf, sizeof(buf), &e->alsa_id); + pa_log_warn("Element %s seems to have disappeared.", buf); return; } @@ -3082,6 +3203,8 @@ pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t d char **pn = NULL, **en = NULL, **ie; pa_alsa_decibel_fix *db_fix; void *state, *state2; + char name[64]; + int index; pa_assert(m); pa_assert(m->profile_set); @@ -3161,9 +3284,18 @@ pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t d if (je == ie) continue; + if (strlen(*je) + 1 >= sizeof(name)) { + pa_log("Element identifier %s is too long!", *je); + continue; + } + + if (alsa_id_decode(*je, name, &index)) + continue; + e = pa_xnew0(pa_alsa_element, 1); e->path = p; - e->alsa_name = pa_xstrdup(*je); + e->alsa_id.name = pa_xstrdup(name); + e->alsa_id.index = index; e->direction = direction; e->required_absent = PA_ALSA_REQUIRED_ANY; e->volume_limit = -1; @@ -3184,7 +3316,8 @@ finish: pa_alsa_element *e; PA_LLIST_FOREACH(e, p->elements) { - if (e->volume_use != PA_ALSA_VOLUME_IGNORE && pa_streq(db_fix->name, e->alsa_name)) { + if (e->volume_use != PA_ALSA_VOLUME_IGNORE && pa_streq(db_fix->name, e->alsa_id.name) && + db_fix->index == e->alsa_id.index) { /* The profile set that contains the dB fix may be freed * before the element, so we have to copy the dB fix * object. */ @@ -3257,6 +3390,8 @@ static bool enumeration_is_subset(pa_alsa_option *a_options, pa_alsa_option *b_o * Compares two elements to see if a is a subset of b */ static bool element_is_subset(pa_alsa_element *a, pa_alsa_element *b, snd_mixer_t *m) { + char buf[64]; + pa_assert(a); pa_assert(b); pa_assert(m); @@ -3294,9 +3429,10 @@ static bool element_is_subset(pa_alsa_element *a, pa_alsa_element *b, snd_mixer_ snd_mixer_selem_id_t *sid; snd_mixer_elem_t *me; - SELEM_INIT(sid, a->alsa_name); + SELEM_INIT(sid, &a->alsa_id); if (!(me = snd_mixer_find_selem(m, sid))) { - pa_log_warn("Element %s seems to have disappeared.", a->alsa_name); + alsa_id_str(buf, sizeof(buf), &a->alsa_id); + pa_log_warn("Element %s seems to have disappeared.", buf); return false; } @@ -3326,8 +3462,9 @@ static bool element_is_subset(pa_alsa_element *a, pa_alsa_element *b, snd_mixer_ return false; for (s = 0; s <= SND_MIXER_SCHN_LAST; s++) if (a->masks[s][a->n_channels-1] != b->masks[s][b->n_channels-1]) { + alsa_id_str(buf, sizeof(buf), &a->alsa_id); pa_log_debug("Element %s is not a subset - mask a: 0x%" PRIx64 ", mask b: 0x%" PRIx64 ", at channel %d", - a->alsa_name, a->masks[s][a->n_channels-1], b->masks[s][b->n_channels-1], s); + buf, a->masks[s][a->n_channels-1], b->masks[s][b->n_channels-1], s); return false; } } @@ -3424,7 +3561,8 @@ static void path_set_condense(pa_alsa_path_set *ps, snd_mixer_t *m) { break; PA_LLIST_FOREACH(eb, p2->elements) { - if (pa_streq(ea->alsa_name, eb->alsa_name)) { + if (pa_streq(ea->alsa_id.name, eb->alsa_id.name) && + ea->alsa_id.index == eb->alsa_id.index) { found_matching_element = true; is_subset = element_is_subset(ea, eb, m); break; @@ -3601,22 +3739,30 @@ static pa_alsa_profile *profile_get(pa_alsa_profile_set *ps, const char *name) { return p; } -static pa_alsa_decibel_fix *decibel_fix_get(pa_alsa_profile_set *ps, const char *name) { +static pa_alsa_decibel_fix *decibel_fix_get(pa_alsa_profile_set *ps, const char *alsa_id) { pa_alsa_decibel_fix *db_fix; + char *name; + int index; - if (!pa_startswith(name, "DecibelFix ")) + if (!pa_startswith(alsa_id, "DecibelFix ")) return NULL; - name += 11; + alsa_id += 11; - if ((db_fix = pa_hashmap_get(ps->decibel_fixes, name))) + if ((db_fix = pa_hashmap_get(ps->decibel_fixes, alsa_id))) return db_fix; + name = alloca(strlen(alsa_id) + 1); + if (alsa_id_decode(alsa_id, name, &index)) + return NULL; + db_fix = pa_xnew0(pa_alsa_decibel_fix, 1); db_fix->profile_set = ps; db_fix->name = pa_xstrdup(name); + db_fix->index = index; + db_fix->key = pa_xstrdup(alsa_id); - pa_hashmap_put(ps->decibel_fixes, db_fix->name, db_fix); + pa_hashmap_put(ps->decibel_fixes, db_fix->key, db_fix); return db_fix; } @@ -3840,6 +3986,24 @@ static int mapping_parse_fallback(pa_config_parser_state *state) { return 0; } +static int mapping_parse_intended_roles(pa_config_parser_state *state) { + pa_alsa_profile_set *ps; + pa_alsa_mapping *m; + + pa_assert(state); + + ps = state->userdata; + + if (!(m = pa_alsa_mapping_get(ps, state->section))) { + pa_log("[%s:%u] %s invalid in section %s", state->filename, state->lineno, state->lvalue, state->section); + return -1; + } + + pa_proplist_sets(m->proplist, PA_PROP_DEVICE_INTENDED_ROLES, state->rvalue); + + return 0; +} + static int profile_parse_mappings(pa_config_parser_state *state) { pa_alsa_profile_set *ps; @@ -4004,7 +4168,8 @@ fail: } static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile, - pa_alsa_direction_t direction, pa_hashmap *used_paths) { + pa_alsa_direction_t direction, pa_hashmap *used_paths, + pa_hashmap *mixers) { pa_alsa_path *p; void *state; @@ -4029,7 +4194,7 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile, pa_assert(pcm_handle); - mixer_handle = pa_alsa_open_mixer_for_pcm(pcm_handle, NULL); + mixer_handle = pa_alsa_open_mixer_for_pcm(mixers, pcm_handle, true); if (!mixer_handle) { /* Cannot open mixer, remove all entries */ pa_hashmap_remove_all(ps->paths); @@ -4047,9 +4212,6 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile, path_set_condense(ps, mixer_handle); path_set_make_path_descriptions_unique(ps); - if (mixer_handle) - snd_mixer_close(mixer_handle); - PA_HASHMAP_FOREACH(p, ps->paths, state) pa_hashmap_put(used_paths, p, p); @@ -4431,6 +4593,7 @@ pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel { "element-output", mapping_parse_element, NULL, NULL }, { "direction", mapping_parse_direction, NULL, NULL }, { "exact-channels", mapping_parse_exact_channels, NULL, NULL }, + { "intended-roles", mapping_parse_intended_roles, NULL, NULL }, /* Shared by [Mapping ...] and [Profile ...] */ { "description", mapping_parse_description, NULL, NULL }, @@ -4628,6 +4791,7 @@ static void mapping_query_hw_device(pa_alsa_mapping *mapping, snd_pcm_t *pcm) { void pa_alsa_profile_set_probe( pa_alsa_profile_set *ps, + pa_hashmap *mixers, const char *dev_id, const pa_sample_spec *ss, unsigned default_n_fragments, @@ -4757,14 +4921,14 @@ void pa_alsa_profile_set_probe( PA_IDXSET_FOREACH(m, p->output_mappings, idx) if (m->output_pcm) { found_output |= !p->fallback_output; - mapping_paths_probe(m, p, PA_ALSA_DIRECTION_OUTPUT, used_paths); + mapping_paths_probe(m, p, PA_ALSA_DIRECTION_OUTPUT, used_paths, mixers); } if (p->input_mappings) PA_IDXSET_FOREACH(m, p->input_mappings, idx) if (m->input_pcm) { found_input |= !p->fallback_input; - mapping_paths_probe(m, p, PA_ALSA_DIRECTION_INPUT, used_paths); + mapping_paths_probe(m, p, PA_ALSA_DIRECTION_INPUT, used_paths, mixers); } } diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h index 65b0711..df739cc 100644 --- a/src/modules/alsa/alsa-mixer.h +++ b/src/modules/alsa/alsa-mixer.h @@ -32,8 +32,10 @@ #include <pulsecore/rtpoll.h> typedef struct pa_alsa_fdlist pa_alsa_fdlist; +typedef struct pa_alsa_mixer pa_alsa_mixer; typedef struct pa_alsa_mixer_pdata pa_alsa_mixer_pdata; typedef struct pa_alsa_setting pa_alsa_setting; +typedef struct pa_alsa_mixer_id pa_alsa_mixer_id; typedef struct pa_alsa_option pa_alsa_option; typedef struct pa_alsa_element pa_alsa_element; typedef struct pa_alsa_jack pa_alsa_jack; @@ -97,6 +99,20 @@ struct pa_alsa_setting { unsigned priority; }; +/* An entry for one ALSA mixer */ +struct pa_alsa_mixer { + snd_mixer_t *mixer_handle; + int card_index; + pa_alsa_fdlist *fdl; + bool used_for_probe_only:1; +}; + +/* ALSA mixer element identifier */ +struct pa_alsa_mixer_id { + char *name; + int index; +}; + /* An option belongs to an element and refers to one enumeration item * of the element is an enumeration item, or a switch status if the * element is a switch item. */ @@ -123,7 +139,7 @@ struct pa_alsa_element { pa_alsa_path *path; PA_LLIST_FIELDS(pa_alsa_element); - char *alsa_name; + struct pa_alsa_mixer_id alsa_id; pa_alsa_direction_t direction; pa_alsa_switch_use_t switch_use; @@ -158,6 +174,9 @@ struct pa_alsa_jack { pa_alsa_path *path; PA_LLIST_FIELDS(pa_alsa_jack); + snd_mixer_t *mixer_handle; + char *mixer_device_name; + char *name; /* E g "Headphone" */ char *alsa_name; /* E g "Headphone Jack" */ bool has_control; /* is the jack itself present? */ @@ -175,7 +194,7 @@ struct pa_alsa_jack { bool append_pcm_to_name; }; -pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *name); +pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name); void pa_alsa_jack_free(pa_alsa_jack *jack); void pa_alsa_jack_set_has_control(pa_alsa_jack *jack, bool has_control); void pa_alsa_jack_set_plugged_in(pa_alsa_jack *jack, bool plugged_in); @@ -194,6 +213,7 @@ struct pa_alsa_path { char *description; unsigned priority; bool autodetect_eld_device; + pa_alsa_mixer *eld_mixer_handle; int eld_device; pa_proplist *proplist; @@ -237,6 +257,7 @@ void pa_alsa_element_dump(pa_alsa_element *e); pa_alsa_path *pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction); pa_alsa_path *pa_alsa_path_synthesize(const char *element, pa_alsa_direction_t direction); +pa_alsa_element *pa_alsa_element_get(pa_alsa_path *p, const char *section, bool prefixed); int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m, bool ignore_dB); void pa_alsa_path_dump(pa_alsa_path *p); int pa_alsa_path_get_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v); @@ -251,6 +272,7 @@ pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t d void pa_alsa_path_set_dump(pa_alsa_path_set *s); void pa_alsa_path_set_set_callback(pa_alsa_path_set *ps, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata); void pa_alsa_path_set_free(pa_alsa_path_set *s); +int pa_alsa_path_set_is_empty(pa_alsa_path_set *s); struct pa_alsa_mapping { pa_alsa_profile_set *profile_set; @@ -315,9 +337,12 @@ struct pa_alsa_profile { }; struct pa_alsa_decibel_fix { + char *key; + pa_alsa_profile_set *profile_set; char *name; /* Alsa volume element name. */ + int index; /* Alsa volume element index. */ long min_step; long max_step; @@ -348,13 +373,11 @@ void pa_alsa_decibel_fix_dump(pa_alsa_decibel_fix *db_fix); pa_alsa_mapping *pa_alsa_mapping_get(pa_alsa_profile_set *ps, const char *name); pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus); -void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss, unsigned default_n_fragments, unsigned default_fragment_size_msec); +void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, pa_hashmap *mixers, const char *dev_id, const pa_sample_spec *ss, unsigned default_n_fragments, unsigned default_fragment_size_msec); void pa_alsa_profile_set_free(pa_alsa_profile_set *s); void pa_alsa_profile_set_dump(pa_alsa_profile_set *s); void pa_alsa_profile_set_drop_unsupported(pa_alsa_profile_set *s); -snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device); - pa_alsa_fdlist *pa_alsa_fdlist_new(void); void pa_alsa_fdlist_free(pa_alsa_fdlist *fdl); int pa_alsa_fdlist_set_handle(pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, snd_hctl_t *hctl_handle, pa_mainloop_api* m); diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 4b46708..042d4df 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -105,6 +105,7 @@ struct userdata { char *paths_dir; pa_alsa_fdlist *mixer_fdl; pa_alsa_mixer_pdata *mixer_pd; + pa_hashmap *mixers; snd_mixer_t *mixer_handle; pa_alsa_path_set *mixer_path_set; pa_alsa_path *mixer_path; @@ -1266,7 +1267,7 @@ static void sync_mixer(struct userdata *u, pa_device_port *port) { /* port may be NULL, because if we use a synthesized mixer path, then the * sink has no ports. */ - if (port) { + if (port && !u->ucm_context) { pa_alsa_port_data *data; data = PA_DEVICE_PORT_DATA(port); @@ -1598,7 +1599,7 @@ static void sink_set_mute_cb(pa_sink *s) { static void mixer_volume_init(struct userdata *u) { pa_assert(u); - if (!u->mixer_path->has_volume) { + if (!u->mixer_path || !u->mixer_path->has_volume) { pa_sink_set_write_volume_callback(u->sink, NULL); pa_sink_set_get_volume_callback(u->sink, NULL); pa_sink_set_set_volume_callback(u->sink, NULL); @@ -1633,7 +1634,7 @@ static void mixer_volume_init(struct userdata *u) { pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->mixer_path->has_dB ? "supported" : "not supported"); } - if (!u->mixer_path->has_mute) { + if (!u->mixer_path || !u->mixer_path->has_mute) { pa_sink_set_get_mute_callback(u->sink, NULL); pa_sink_set_set_mute_callback(u->sink, NULL); pa_log_info("Driver does not support hardware mute control, falling back to software mute control."); @@ -1646,11 +1647,21 @@ static void mixer_volume_init(struct userdata *u) { static int sink_set_port_ucm_cb(pa_sink *s, pa_device_port *p) { struct userdata *u = s->userdata; + pa_alsa_ucm_port_data *data; pa_assert(u); pa_assert(p); pa_assert(u->ucm_context); + data = PA_DEVICE_PORT_DATA(p); + pa_assert_se(u->mixer_path = data->path); + mixer_volume_init(u); + + if (s->flags & PA_SINK_DEFERRED_VOLUME) + pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_SYNC_MIXER, p, 0, NULL); + else + sync_mixer(u, p); + return pa_alsa_ucm_set_port(u->ucm_context, p, true); } @@ -1661,6 +1672,7 @@ static int sink_set_port_cb(pa_sink *s, pa_device_port *p) { pa_assert(u); pa_assert(p); pa_assert(u->mixer_handle); + pa_assert(!u->ucm_context); data = PA_DEVICE_PORT_DATA(p); pa_assert_se(u->mixer_path = data->path); @@ -2071,10 +2083,24 @@ static void set_sink_name(pa_sink_new_data *data, pa_modargs *ma, const char *de } static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char *element, bool ignore_dB) { + const char *mdev; + if (!mapping && !element) return; - if (!(u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device))) { + if (!element && mapping && pa_alsa_path_set_is_empty(mapping->output_path_set)) + return; + + u->mixers = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, + NULL, (pa_free_cb_t) pa_alsa_mixer_free); + + mdev = pa_proplist_gets(mapping->proplist, "alsa.mixer_device"); + if (mdev) { + u->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, mdev, true); + } else { + u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->mixers, u->pcm_handle, true); + } + if (!u->mixer_handle) { pa_log_info("Failed to find a working mixer device."); return; } @@ -2089,8 +2115,9 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char pa_log_debug("Probed mixer path %s:", u->mixer_path->name); pa_alsa_path_dump(u->mixer_path); - } else if (!(u->mixer_path_set = mapping->output_path_set)) - goto fail; + } else { + u->mixer_path_set = mapping->output_path_set; + } return; @@ -2101,10 +2128,9 @@ fail: u->mixer_path = NULL; } - if (u->mixer_handle) { - snd_mixer_close(u->mixer_handle); - u->mixer_handle = NULL; - } + u->mixer_handle = NULL; + pa_hashmap_free(u->mixers); + u->mixers = NULL; } static int setup_mixer(struct userdata *u, bool ignore_dB) { @@ -2116,16 +2142,31 @@ static int setup_mixer(struct userdata *u, bool ignore_dB) { return 0; if (u->sink->active_port) { - pa_alsa_port_data *data; + if (!u->ucm_context) { + pa_alsa_port_data *data; + + /* We have a list of supported paths, so let's activate the + * one that has been chosen as active */ - /* We have a list of supported paths, so let's activate the - * one that has been chosen as active */ + data = PA_DEVICE_PORT_DATA(u->sink->active_port); + u->mixer_path = data->path; - data = PA_DEVICE_PORT_DATA(u->sink->active_port); - u->mixer_path = data->path; + pa_alsa_path_select(data->path, data->setting, u->mixer_handle, u->sink->muted); + } else { + pa_alsa_ucm_port_data *data; + + /* First activate the port on the UCM side */ + if (pa_alsa_ucm_set_port(u->ucm_context, u->sink->active_port, true) < 0) + return -1; - pa_alsa_path_select(data->path, data->setting, u->mixer_handle, u->sink->muted); + data = PA_DEVICE_PORT_DATA(u->sink->active_port); + /* Now activate volume controls, if any */ + if (data->path) { + u->mixer_path = data->path; + pa_alsa_path_select(u->mixer_path, NULL, u->mixer_handle, u->sink->muted); + } + } } else { if (!u->mixer_path && u->mixer_path_set) @@ -2135,7 +2176,6 @@ static int setup_mixer(struct userdata *u, bool ignore_dB) { /* Hmm, we have only a single path, then let's activate it */ pa_alsa_path_select(u->mixer_path, u->mixer_path->settings, u->mixer_handle, u->sink->muted); - } else return 0; } @@ -2466,8 +2506,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca /* ALSA might tweak the sample spec, so recalculate the frame size */ frame_size = pa_frame_size(&ss); - if (!u->ucm_context) - find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB); + find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB); pa_sink_new_data_init(&data); data.driver = driver; @@ -2523,10 +2562,14 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca goto fail; } - if (u->ucm_context) - pa_alsa_ucm_add_ports(&data.ports, data.proplist, u->ucm_context, true, card); - else if (u->mixer_path_set) - pa_alsa_add_ports(&data, u->mixer_path_set, card); + if (u->ucm_context) { + pa_alsa_ucm_add_ports(&data.ports, data.proplist, u->ucm_context, true, card, u->pcm_handle, ignore_dB); + find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB); + } else { + find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB); + if (u->mixer_path_set) + pa_alsa_add_ports(&data, u->mixer_path_set, card); + } u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE | PA_SINK_LATENCY | (u->use_tsched ? PA_SINK_DYNAMIC_LATENCY : 0) | (set_formats ? PA_SINK_SET_FORMATS : 0)); @@ -2598,10 +2641,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca if (update_sw_params(u, false) < 0) goto fail; - if (u->ucm_context) { - if (u->sink->active_port && pa_alsa_ucm_set_port(u->ucm_context, u->sink->active_port, true) < 0) - goto fail; - } else if (setup_mixer(u, ignore_dB) < 0) + if (setup_mixer(u, ignore_dB) < 0) goto fail; pa_alsa_dump(PA_LOG_DEBUG, u->pcm_handle); @@ -2666,7 +2706,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca * pa_sink_suspend() between pa_sink_new() and pa_sink_put() would * otherwise work, but currently pa_sink_suspend() will crash if * pa_sink_put() hasn't been called. */ - if (u->sink->active_port) { + if (u->sink->active_port && !u->ucm_context) { pa_alsa_port_data *port_data; port_data = PA_DEVICE_PORT_DATA(u->sink->active_port); @@ -2725,11 +2765,12 @@ static void userdata_free(struct userdata *u) { if (u->mixer_fdl) pa_alsa_fdlist_free(u->mixer_fdl); - if (u->mixer_path && !u->mixer_path_set) + /* Only free the mixer_path if the sink owns it */ + if (u->mixer_path && !u->mixer_path_set && !u->ucm_context) pa_alsa_path_free(u->mixer_path); - if (u->mixer_handle) - snd_mixer_close(u->mixer_handle); + if (u->mixers) + pa_hashmap_free(u->mixers); if (u->smoother) pa_smoother_free(u->smoother); diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index c8bf649..104de4e 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -93,6 +93,7 @@ struct userdata { char *paths_dir; pa_alsa_fdlist *mixer_fdl; pa_alsa_mixer_pdata *mixer_pd; + pa_hashmap *mixers; snd_mixer_t *mixer_handle; pa_alsa_path_set *mixer_path_set; pa_alsa_path *mixer_path; @@ -1137,7 +1138,7 @@ static void sync_mixer(struct userdata *u, pa_device_port *port) { /* port may be NULL, because if we use a synthesized mixer path, then the * source has no ports. */ - if (port) { + if (port && !u->ucm_context) { pa_alsa_port_data *data; data = PA_DEVICE_PORT_DATA(port); @@ -1469,7 +1470,7 @@ static void source_set_mute_cb(pa_source *s) { static void mixer_volume_init(struct userdata *u) { pa_assert(u); - if (!u->mixer_path->has_volume) { + if (!u->mixer_path || !u->mixer_path->has_volume) { pa_source_set_write_volume_callback(u->source, NULL); pa_source_set_get_volume_callback(u->source, NULL); pa_source_set_set_volume_callback(u->source, NULL); @@ -1504,7 +1505,7 @@ static void mixer_volume_init(struct userdata *u) { pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->mixer_path->has_dB ? "supported" : "not supported"); } - if (!u->mixer_path->has_mute) { + if (!u->mixer_path || !u->mixer_path->has_mute) { pa_source_set_get_mute_callback(u->source, NULL); pa_source_set_set_mute_callback(u->source, NULL); pa_log_info("Driver does not support hardware mute control, falling back to software mute control."); @@ -1517,11 +1518,21 @@ static void mixer_volume_init(struct userdata *u) { static int source_set_port_ucm_cb(pa_source *s, pa_device_port *p) { struct userdata *u = s->userdata; + pa_alsa_ucm_port_data *data; pa_assert(u); pa_assert(p); pa_assert(u->ucm_context); + data = PA_DEVICE_PORT_DATA(p); + pa_assert_se(u->mixer_path = data->path); + mixer_volume_init(u); + + if (s->flags & PA_SOURCE_DEFERRED_VOLUME) + pa_asyncmsgq_send(u->source->asyncmsgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_SYNC_MIXER, p, 0, NULL); + else + sync_mixer(u, p); + return pa_alsa_ucm_set_port(u->ucm_context, p, false); } @@ -1532,6 +1543,7 @@ static int source_set_port_cb(pa_source *s, pa_device_port *p) { pa_assert(u); pa_assert(p); pa_assert(u->mixer_handle); + pa_assert(!u->ucm_context); data = PA_DEVICE_PORT_DATA(p); pa_assert_se(u->mixer_path = data->path); @@ -1777,10 +1789,24 @@ static void set_source_name(pa_source_new_data *data, pa_modargs *ma, const char } static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char *element, bool ignore_dB) { + const char *mdev; + if (!mapping && !element) return; - if (!(u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device))) { + if (!element && mapping && pa_alsa_path_set_is_empty(mapping->input_path_set)) + return; + + u->mixers = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, + NULL, (pa_free_cb_t) pa_alsa_mixer_free); + + mdev = pa_proplist_gets(mapping->proplist, "alsa.mixer_device"); + if (mdev) { + u->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, mdev, false); + } else { + u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->mixers, u->pcm_handle, false); + } + if (!u->mixer_handle) { pa_log_info("Failed to find a working mixer device."); return; } @@ -1795,8 +1821,9 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char pa_log_debug("Probed mixer path %s:", u->mixer_path->name); pa_alsa_path_dump(u->mixer_path); - } else if (!(u->mixer_path_set = mapping->input_path_set)) - goto fail; + } else { + u->mixer_path_set = mapping->input_path_set; + } return; @@ -1807,10 +1834,9 @@ fail: u->mixer_path = NULL; } - if (u->mixer_handle) { - snd_mixer_close(u->mixer_handle); - u->mixer_handle = NULL; - } + u->mixer_handle = NULL; + pa_hashmap_free(u->mixers); + u->mixers = NULL; } static int setup_mixer(struct userdata *u, bool ignore_dB) { @@ -1822,16 +1848,31 @@ static int setup_mixer(struct userdata *u, bool ignore_dB) { return 0; if (u->source->active_port) { - pa_alsa_port_data *data; + if (!u->ucm_context) { + pa_alsa_port_data *data; - /* We have a list of supported paths, so let's activate the - * one that has been chosen as active */ + /* We have a list of supported paths, so let's activate the + * one that has been chosen as active */ - data = PA_DEVICE_PORT_DATA(u->source->active_port); - u->mixer_path = data->path; + data = PA_DEVICE_PORT_DATA(u->source->active_port); + u->mixer_path = data->path; - pa_alsa_path_select(data->path, data->setting, u->mixer_handle, u->source->muted); + pa_alsa_path_select(data->path, data->setting, u->mixer_handle, u->source->muted); + } else { + pa_alsa_ucm_port_data *data; + /* First activate the port on the UCM side */ + if (pa_alsa_ucm_set_port(u->ucm_context, u->source->active_port, false) < 0) + return -1; + + data = PA_DEVICE_PORT_DATA(u->source->active_port); + + /* Now activate volume controls, if any */ + if (data->path) { + u->mixer_path = data->path; + pa_alsa_path_select(u->mixer_path, NULL, u->mixer_handle, u->source->muted); + } + } } else { if (!u->mixer_path && u->mixer_path_set) @@ -2152,8 +2193,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p /* ALSA might tweak the sample spec, so recalculate the frame size */ frame_size = pa_frame_size(&ss); - if (!u->ucm_context) - find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB); + find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB); pa_source_new_data_init(&data); data.driver = driver; @@ -2210,7 +2250,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p } if (u->ucm_context) - pa_alsa_ucm_add_ports(&data.ports, data.proplist, u->ucm_context, false, card); + pa_alsa_ucm_add_ports(&data.ports, data.proplist, u->ucm_context, false, card, u->pcm_handle, ignore_dB); else if (u->mixer_path_set) pa_alsa_add_ports(&data, u->mixer_path_set, card); @@ -2276,10 +2316,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p if (update_sw_params(u) < 0) goto fail; - if (u->ucm_context) { - if (u->source->active_port && pa_alsa_ucm_set_port(u->ucm_context, u->source->active_port, false) < 0) - goto fail; - } else if (setup_mixer(u, ignore_dB) < 0) + if (setup_mixer(u, ignore_dB) < 0) goto fail; pa_alsa_dump(PA_LOG_DEBUG, u->pcm_handle); @@ -2368,11 +2405,12 @@ static void userdata_free(struct userdata *u) { if (u->mixer_fdl) pa_alsa_fdlist_free(u->mixer_fdl); - if (u->mixer_path && !u->mixer_path_set) + /* Only free the mixer_path if the sink owns it */ + if (u->mixer_path && !u->mixer_path_set && !u->ucm_context) pa_alsa_path_free(u->mixer_path); - if (u->mixer_handle) - snd_mixer_close(u->mixer_handle); + if (u->mixers) + pa_hashmap_free(u->mixers); if (u->smoother) pa_smoother_free(u->smoother); diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c index 0a40ca8..a57be6d 100644 --- a/src/modules/alsa/alsa-ucm.c +++ b/src/modules/alsa/alsa-ucm.c @@ -81,34 +81,37 @@ static void device_add_hw_mute_jack(pa_alsa_ucm_device *device, pa_alsa_jack *ja static pa_alsa_ucm_device *verb_find_device(pa_alsa_ucm_verb *verb, const char *device_name); -struct ucm_port { - pa_alsa_ucm_config *ucm; - pa_device_port *core_port; - - /* A single port will be associated with multiple devices if it represents - * a combination of devices. */ - pa_dynarray *devices; /* pa_alsa_ucm_device */ -}; -static void ucm_port_init(struct ucm_port *port, pa_alsa_ucm_config *ucm, pa_device_port *core_port, - pa_alsa_ucm_device **devices, unsigned n_devices); -static void ucm_port_free(pa_device_port *port); -static void ucm_port_update_available(struct ucm_port *port); +static void ucm_port_data_init(pa_alsa_ucm_port_data *port, pa_alsa_ucm_config *ucm, pa_device_port *core_port, + pa_alsa_ucm_device **devices, unsigned n_devices); +static void ucm_port_data_free(pa_device_port *port); +static void ucm_port_update_available(pa_alsa_ucm_port_data *port); static struct ucm_items item[] = { {"PlaybackPCM", PA_ALSA_PROP_UCM_SINK}, {"CapturePCM", PA_ALSA_PROP_UCM_SOURCE}, + {"PlaybackCTL", PA_ALSA_PROP_UCM_PLAYBACK_CTL_DEVICE}, {"PlaybackVolume", PA_ALSA_PROP_UCM_PLAYBACK_VOLUME}, {"PlaybackSwitch", PA_ALSA_PROP_UCM_PLAYBACK_SWITCH}, + {"PlaybackMixer", PA_ALSA_PROP_UCM_PLAYBACK_MIXER_DEVICE}, + {"PlaybackMixerElem", PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM}, + {"PlaybackMasterElem", PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ELEM}, + {"PlaybackMasterType", PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE}, {"PlaybackPriority", PA_ALSA_PROP_UCM_PLAYBACK_PRIORITY}, {"PlaybackRate", PA_ALSA_PROP_UCM_PLAYBACK_RATE}, {"PlaybackChannels", PA_ALSA_PROP_UCM_PLAYBACK_CHANNELS}, + {"CaptureCTL", PA_ALSA_PROP_UCM_CAPTURE_CTL_DEVICE}, {"CaptureVolume", PA_ALSA_PROP_UCM_CAPTURE_VOLUME}, {"CaptureSwitch", PA_ALSA_PROP_UCM_CAPTURE_SWITCH}, + {"CaptureMixer", PA_ALSA_PROP_UCM_CAPTURE_MIXER_DEVICE}, + {"CaptureMixerElem", PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM}, + {"CaptureMasterElem", PA_ALSA_PROP_UCM_CAPTURE_MASTER_ELEM}, + {"CaptureMasterType", PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE}, {"CapturePriority", PA_ALSA_PROP_UCM_CAPTURE_PRIORITY}, {"CaptureRate", PA_ALSA_PROP_UCM_CAPTURE_RATE}, {"CaptureChannels", PA_ALSA_PROP_UCM_CAPTURE_CHANNELS}, {"TQ", PA_ALSA_PROP_UCM_QOS}, + {"JackCTL", PA_ALSA_PROP_UCM_JACK_DEVICE}, {"JackControl", PA_ALSA_PROP_UCM_JACK_CONTROL}, {"JackHWMute", PA_ALSA_PROP_UCM_JACK_HW_MUTE}, {NULL, NULL}, @@ -143,29 +146,25 @@ static struct ucm_info dev_info[] = { {NULL, 0} }; -/* UCM profile properties - The verb data is store so it can be used to fill - * the new profiles properties */ -static int ucm_get_property(pa_alsa_ucm_verb *verb, snd_use_case_mgr_t *uc_mgr, const char *verb_name) { - const char *value; - char *id; - int i; - - for (i = 0; item[i].id; i++) { - int err; - - id = pa_sprintf_malloc("=%s//%s", item[i].id, verb_name); - err = snd_use_case_get(uc_mgr, id, &value); - pa_xfree(id); - if (err < 0) - continue; - pa_log_debug("Got %s for verb %s: %s", item[i].id, verb_name, value); - pa_proplist_sets(verb->proplist, item[i].property, value); - free((void*)value); - } +static char *ucm_verb_value( + snd_use_case_mgr_t *uc_mgr, + const char *verb_name, + const char *id) { - return 0; -}; + const char *value; + char *_id = pa_sprintf_malloc("=%s//%s", id, verb_name); + int err = snd_use_case_get(uc_mgr, _id, &value); + pa_xfree(_id); + if (err < 0) + return NULL; + pa_log_debug("Got %s for verb %s: %s", id, verb_name, value); + /* Use the cast here to allow free() call without casting for callers. + * The snd_use_case_get() returns mallocated string. + * See the Note: in use-case.h for snd_use_case_get(). + */ + return (char *)value; +} static int ucm_device_exists(pa_idxset *idxset, pa_alsa_ucm_device *dev) { pa_alsa_ucm_device *d; @@ -202,6 +201,139 @@ static void ucm_add_devices_to_idxset( } } +/* Split a string into words. Like pa_split_spaces() but handle '' and "". */ +static char *ucm_split_devnames(const char *c, const char **state) { + const char *current = *state ? *state : c; + char h; + size_t l; + + if (!*current || *c == 0) + return NULL; + + current += strspn(current, "\n\r \t"); + h = *current; + if (h == '\'' || h =='"') { + c = ++current; + for (l = 0; *c && *c != h; l++) c++; + if (*c != h) + return NULL; + *state = c + 1; + } else { + l = strcspn(current, "\n\r \t"); + *state = current+l; + } + + return pa_xstrndup(current, l); +} + + +static void ucm_volume_free(pa_alsa_ucm_volume *vol) { + pa_assert(vol); + pa_xfree(vol->mixer_elem); + pa_xfree(vol->master_elem); + pa_xfree(vol->master_type); + pa_xfree(vol); +} + +/* Get the volume identifier */ +static char *ucm_get_mixer_id( + pa_alsa_ucm_device *device, + const char *mprop, + const char *cprop, + const char *cid) +{ +#if SND_LIB_VERSION >= 0x10201 /* alsa-lib-1.2.1+ check */ + snd_ctl_elem_id_t *ctl; + int err; +#endif + const char *value; + char *value2; + int index; + + /* mixer element as first, if it's found, return it without modifications */ + value = pa_proplist_gets(device->proplist, mprop); + if (value) + return pa_xstrdup(value); + /* fallback, get the control element identifier */ + /* and try to do some heuristic to determine the mixer element name */ + value = pa_proplist_gets(device->proplist, cprop); + if (value == NULL) + return NULL; +#if SND_LIB_VERSION >= 0x10201 /* alsa-lib-1.2.1+ check */ + /* The new parser may return also element index. */ + snd_ctl_elem_id_alloca(&ctl); + err = snd_use_case_parse_ctl_elem_id(ctl, cid, value); + if (err < 0) + return NULL; + value = snd_ctl_elem_id_get_name(ctl); + index = snd_ctl_elem_id_get_index(ctl); +#else +#warning "Upgrade to alsa-lib 1.2.1!" + index = 0; +#endif + if (!(value2 = pa_str_strip_suffix(value, " Playback Volume"))) + if (!(value2 = pa_str_strip_suffix(value, " Capture Volume"))) + if (!(value2 = pa_str_strip_suffix(value, " Volume"))) + value2 = pa_xstrdup(value); + if (index > 0) { + char *mix = pa_sprintf_malloc("'%s',%d", value2, index); + pa_xfree(value2); + return mix; + } + return value2; +} + +/* Get the volume identifier */ +static pa_alsa_ucm_volume *ucm_get_mixer_volume( + pa_alsa_ucm_device *device, + const char *mprop, + const char *cprop, + const char *cid, + const char *masterid, + const char *mastertype) +{ + pa_alsa_ucm_volume *vol; + char *mixer_elem; + + mixer_elem = ucm_get_mixer_id(device, mprop, cprop, cid); + if (mixer_elem == NULL) + return NULL; + vol = pa_xnew0(pa_alsa_ucm_volume, 1); + if (vol == NULL) { + pa_xfree(mixer_elem); + return NULL; + } + vol->mixer_elem = mixer_elem; + vol->master_elem = pa_xstrdup(pa_proplist_gets(device->proplist, masterid)); + vol->master_type = pa_xstrdup(pa_proplist_gets(device->proplist, mastertype)); + return vol; +} + +/* Get the ALSA mixer device for the UCM device */ +static const char *get_mixer_device(pa_alsa_ucm_device *dev, bool is_sink) +{ + const char *dev_name; + + if (is_sink) { + dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_PLAYBACK_MIXER_DEVICE); + if (!dev_name) + dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_PLAYBACK_CTL_DEVICE); + } else { + dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_CAPTURE_MIXER_DEVICE); + if (!dev_name) + dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_CAPTURE_CTL_DEVICE); + } + return dev_name; +} + +/* Get the ALSA mixer device for the UCM jack */ +static const char *get_jack_mixer_device(pa_alsa_ucm_device *dev, bool is_sink) { + const char *dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_JACK_DEVICE); + if (!dev_name) + return get_mixer_device(dev, is_sink); + return dev_name; +} + /* Create a property list for this ucm device */ static int ucm_get_device_property( pa_alsa_ucm_device *device, @@ -216,9 +348,10 @@ static int ucm_get_device_property( int err; uint32_t ui; int n_confdev, n_suppdev; + pa_alsa_ucm_volume *vol; for (i = 0; item[i].id; i++) { - id = pa_sprintf_malloc("=%s/%s", item[i].id, device_name); + id = pa_sprintf_malloc("%s/%s", item[i].id, device_name); err = snd_use_case_get(uc_mgr, id, &value); pa_xfree(id); if (err < 0) @@ -240,14 +373,8 @@ static int ucm_get_device_property( /* get pcm */ value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_SINK); - if (!value) { /* take pcm from verb playback default */ - value = pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_SINK); - if (value) { - pa_log_debug("UCM playback device %s fetch pcm from verb default %s", device_name, value); - pa_proplist_sets(device->proplist, PA_ALSA_PROP_UCM_SINK, value); - } else - pa_log("UCM playback device %s fetch pcm failed", device_name); - } + if (!value) /* take pcm from verb playback default */ + pa_log("UCM playback device %s fetch pcm failed", device_name); } value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_CAPTURE_CHANNELS); @@ -260,14 +387,8 @@ static int ucm_get_device_property( /* get pcm */ value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_SOURCE); - if (!value) { /* take pcm from verb capture default */ - value = pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_SOURCE); - if (value) { - pa_log_debug("UCM capture device %s fetch pcm from verb default %s", device_name, value); - pa_proplist_sets(device->proplist, PA_ALSA_PROP_UCM_SOURCE, value); - } else - pa_log("UCM capture device %s fetch pcm failed", device_name); - } + if (!value) /* take pcm from verb capture default */ + pa_log("UCM capture device %s fetch pcm failed", device_name); } if (device->playback_channels == 0 && device->capture_channels == 0) { @@ -280,8 +401,7 @@ static int ucm_get_device_property( /* get rate and priority of device */ if (device->playback_channels) { /* sink device */ /* get rate */ - if ((value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_PLAYBACK_RATE)) || - (value = pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_PLAYBACK_RATE))) { + if ((value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_PLAYBACK_RATE))) { if (pa_atou(value, &ui) == 0 && pa_sample_rate_valid(ui)) { pa_log_debug("UCM playback device %s rate %d", device_name, ui); device->playback_rate = ui; @@ -297,12 +417,20 @@ static int ucm_get_device_property( else pa_log_debug("UCM playback priority %s for device %s error", value, device_name); } + + vol = ucm_get_mixer_volume(device, + PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM, + PA_ALSA_PROP_UCM_PLAYBACK_VOLUME, + "PlaybackVolume", + PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ELEM, + PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE); + if (vol) + pa_hashmap_put(device->playback_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), vol); } if (device->capture_channels) { /* source device */ /* get rate */ - if ((value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_CAPTURE_RATE)) || - (value = pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_CAPTURE_RATE))) { + if ((value = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_CAPTURE_RATE))) { if (pa_atou(value, &ui) == 0 && pa_sample_rate_valid(ui)) { pa_log_debug("UCM capture device %s rate %d", device_name, ui); device->capture_rate = ui; @@ -318,6 +446,15 @@ static int ucm_get_device_property( else pa_log_debug("UCM capture priority %s for device %s error", value, device_name); } + + vol = ucm_get_mixer_volume(device, + PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM, + PA_ALSA_PROP_UCM_CAPTURE_VOLUME, + "CaptureVolume", + PA_ALSA_PROP_UCM_CAPTURE_MASTER_ELEM, + PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE); + if (vol) + pa_hashmap_put(device->capture_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), vol); } if (PA_UCM_PLAYBACK_PRIORITY_UNSET(device) || PA_UCM_CAPTURE_PRIORITY_UNSET(device)) { @@ -421,6 +558,11 @@ static int ucm_get_devices(pa_alsa_ucm_verb *verb, snd_use_case_mgr_t *uc_mgr) { d->hw_mute_jacks = pa_dynarray_new(NULL); d->available = PA_AVAILABLE_UNKNOWN; + d->playback_volumes = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, pa_xfree, + (pa_free_cb_t) ucm_volume_free); + d->capture_volumes = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, pa_xfree, + (pa_free_cb_t) ucm_volume_free); + PA_LLIST_PREPEND(pa_alsa_ucm_device, verb->devices, d); } @@ -576,17 +718,25 @@ int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index) { const char **verb_list; int num_verbs, i, err = 0; - /* is UCM available for this card ? */ - err = snd_card_get_name(card_index, &card_name); - if (err < 0) { - pa_log("Card can't get card_name from card_index %d", card_index); - goto name_fail; - } - + /* support multiple card instances, address card directly by index */ + card_name = pa_sprintf_malloc("hw:%i", card_index); + if (card_name == NULL) + return -ENOMEM; err = snd_use_case_mgr_open(&ucm->ucm_mgr, card_name); if (err < 0) { - pa_log_info("UCM not available for card %s", card_name); - goto ucm_mgr_fail; + /* fallback longname: is UCM available for this card ? */ + pa_xfree(card_name); + err = snd_card_get_name(card_index, &card_name); + if (err < 0) { + pa_log("Card can't get card_name from card_index %d", card_index); + goto name_fail; + } + + err = snd_use_case_mgr_open(&ucm->ucm_mgr, card_name); + if (err < 0) { + pa_log_info("UCM not available for card %s", card_name); + goto ucm_mgr_fail; + } } pa_log_info("UCM available for card %s", card_name); @@ -626,7 +776,7 @@ ucm_verb_fail: } ucm_mgr_fail: - free(card_name); + pa_xfree(card_name); name_fail: return err; @@ -636,6 +786,8 @@ int pa_alsa_ucm_get_verb(snd_use_case_mgr_t *uc_mgr, const char *verb_name, cons pa_alsa_ucm_device *d; pa_alsa_ucm_modifier *mod; pa_alsa_ucm_verb *verb; + char *value; + unsigned ui; int err = 0; *p_verb = NULL; @@ -650,6 +802,11 @@ int pa_alsa_ucm_get_verb(snd_use_case_mgr_t *uc_mgr, const char *verb_name, cons pa_proplist_sets(verb->proplist, PA_ALSA_PROP_UCM_NAME, pa_strnull(verb_name)); pa_proplist_sets(verb->proplist, PA_ALSA_PROP_UCM_DESCRIPTION, pa_strna(verb_desc)); + value = ucm_verb_value(uc_mgr, verb_name, "Priority"); + if (value && !pa_atou(value, &ui)) + verb->priority = ui > 10000 ? 10000 : ui; + free(value); + err = ucm_get_devices(verb, uc_mgr); if (err < 0) pa_log("No UCM devices for verb %s", verb_name); @@ -658,9 +815,6 @@ int pa_alsa_ucm_get_verb(snd_use_case_mgr_t *uc_mgr, const char *verb_name, cons if (err < 0) pa_log("No UCM modifiers for verb %s", verb_name); - /* Verb properties */ - ucm_get_property(verb, uc_mgr, verb_name); - PA_LLIST_FOREACH(d, verb->devices) { const char *dev_name = pa_proplist_gets(d->proplist, PA_ALSA_PROP_UCM_NAME); @@ -693,6 +847,86 @@ static int pa_alsa_ucm_device_cmp(const void *a, const void *b) { return strcmp(pa_proplist_gets(d1->proplist, PA_ALSA_PROP_UCM_NAME), pa_proplist_gets(d2->proplist, PA_ALSA_PROP_UCM_NAME)); } +static void set_eld_devices(pa_hashmap *hash) +{ + pa_device_port *port; + pa_alsa_ucm_port_data *data; + pa_alsa_ucm_device *dev; + const char *eld_mixer_device_name; + void *state; + int idx, eld_device; + + PA_HASHMAP_FOREACH(port, hash, state) { + data = PA_DEVICE_PORT_DATA(port); + eld_mixer_device_name = NULL; + eld_device = -1; + PA_DYNARRAY_FOREACH(dev, data->devices, idx) { + if (dev->eld_device >= 0 && dev->eld_mixer_device_name) { + if (eld_device >= 0 && eld_device != dev->eld_device) { + pa_log_error("The ELD device is already set!"); + } else if (eld_mixer_device_name && pa_streq(dev->eld_mixer_device_name, eld_mixer_device_name)) { + pa_log_error("The ELD mixer device is already set (%s, %s)!", dev->eld_mixer_device_name, dev->eld_mixer_device_name); + } else { + eld_mixer_device_name = dev->eld_mixer_device_name; + eld_device = dev->eld_device; + } + } + } + data->eld_device = eld_device; + data->eld_mixer_device_name = pa_xstrdup(eld_mixer_device_name); + } +} + +static void probe_volumes(pa_hashmap *hash, bool is_sink, snd_pcm_t *pcm_handle, pa_hashmap *mixers, bool ignore_dB) { + pa_device_port *port; + pa_alsa_path *path; + pa_alsa_ucm_port_data *data; + pa_alsa_ucm_device *dev; + snd_mixer_t *mixer_handle; + const char *profile, *mdev, *mdev2; + void *state, *state2; + int idx; + + PA_HASHMAP_FOREACH(port, hash, state) { + data = PA_DEVICE_PORT_DATA(port); + + mdev = NULL; + PA_DYNARRAY_FOREACH(dev, data->devices, idx) { + mdev2 = get_mixer_device(dev, is_sink); + if (mdev && !pa_streq(mdev, mdev2)) { + pa_log_error("Two mixer device names found ('%s', '%s'), using s/w volume", mdev, mdev2); + goto fail; + } + mdev = mdev2; + } + + if (!(mixer_handle = pa_alsa_open_mixer_by_name(mixers, mdev, true))) { + pa_log_error("Failed to find a working mixer device (%s).", mdev); + goto fail; + } + + PA_HASHMAP_FOREACH_KV(profile, path, data->paths, state2) { + if (pa_alsa_path_probe(path, NULL, mixer_handle, ignore_dB) < 0) { + pa_log_warn("Could not probe path: %s, using s/w volume", data->path->name); + pa_hashmap_remove(data->paths, profile); + } else if (!path->has_volume) { + pa_log_warn("Path %s is not a volume control", data->path->name); + pa_hashmap_remove(data->paths, profile); + } else + pa_log_debug("Set up h/w volume using '%s' for %s:%s", path->name, profile, port->name); + } + } + + return; + +fail: + /* We could not probe the paths we created. Free them and revert to software volumes. */ + PA_HASHMAP_FOREACH(port, hash, state) { + data = PA_DEVICE_PORT_DATA(port); + pa_hashmap_remove_all(data->paths); + } +} + static void ucm_add_port_combination( pa_hashmap *hash, pa_alsa_ucm_mapping_context *context, @@ -710,7 +944,11 @@ static void ucm_add_port_combination( char *name, *desc; const char *dev_name; const char *direction; + const char *profile; pa_alsa_ucm_device *sorted[num], *dev; + pa_alsa_ucm_port_data *data; + pa_alsa_ucm_volume *vol; + void *state; for (i = 0; i < num; i++) sorted[i] = pdevices[i]; @@ -758,8 +996,6 @@ static void ucm_add_port_combination( port = pa_hashmap_get(ports, name); if (!port) { - struct ucm_port *ucm_port; - pa_device_port_new_data port_data; pa_device_port_new_data_init(&port_data); @@ -767,15 +1003,45 @@ static void ucm_add_port_combination( pa_device_port_new_data_set_description(&port_data, desc); pa_device_port_new_data_set_direction(&port_data, is_sink ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT); - port = pa_device_port_new(core, &port_data, sizeof(struct ucm_port)); - port->impl_free = ucm_port_free; + port = pa_device_port_new(core, &port_data, sizeof(pa_alsa_ucm_port_data)); pa_device_port_new_data_done(&port_data); - ucm_port = PA_DEVICE_PORT_DATA(port); - ucm_port_init(ucm_port, context->ucm, port, pdevices, num); + data = PA_DEVICE_PORT_DATA(port); + ucm_port_data_init(data, context->ucm, port, pdevices, num); + port->impl_free = ucm_port_data_free; pa_hashmap_put(ports, port->name, port); pa_log_debug("Add port %s: %s", port->name, port->description); + + if (num == 1) { + /* To keep things simple and not worry about stacking controls, we only support hardware volumes on non-combination + * ports. */ + data = PA_DEVICE_PORT_DATA(port); + + PA_HASHMAP_FOREACH_KV(profile, vol, is_sink ? dev->playback_volumes : dev->capture_volumes, state) { + pa_alsa_path *path = pa_alsa_path_synthesize(vol->mixer_elem, + is_sink ? PA_ALSA_DIRECTION_OUTPUT : PA_ALSA_DIRECTION_INPUT); + + if (!path) + pa_log_warn("Failed to set up volume control: %s", vol->mixer_elem); + else { + if (vol->master_elem) { + pa_alsa_element *e = pa_alsa_element_get(path, vol->master_elem, false); + e->switch_use = PA_ALSA_SWITCH_MUTE; + e->volume_use = PA_ALSA_VOLUME_MERGE; + } + + pa_hashmap_put(data->paths, pa_xstrdup(profile), path); + + /* Add path also to already created empty path set */ + dev = sorted[0]; + if (is_sink) + pa_hashmap_put(dev->playback_mapping->output_path_set->paths, pa_xstrdup(vol->mixer_elem), path); + else + pa_hashmap_put(dev->capture_mapping->input_path_set->paths, pa_xstrdup(vol->mixer_elem), path); + } + } + } } port->priority = priority; @@ -950,6 +1216,9 @@ void pa_alsa_ucm_add_ports_combination( ucm_add_ports_combination(p, context, is_sink, pdevices, 0, PA_IDXSET_INVALID, ports, cp, core); pa_xfree(pdevices); } + + /* ELD devices */ + set_eld_devices(ports); } void pa_alsa_ucm_add_ports( @@ -957,7 +1226,9 @@ void pa_alsa_ucm_add_ports( pa_proplist *proplist, pa_alsa_ucm_mapping_context *context, bool is_sink, - pa_card *card) { + pa_card *card, + snd_pcm_t *pcm_handle, + bool ignore_dB) { uint32_t idx; char *merged_roles; @@ -972,6 +1243,9 @@ void pa_alsa_ucm_add_ports( /* add ports first */ pa_alsa_ucm_add_ports_combination(*p, context, is_sink, card->ports, NULL, card->core); + /* now set up volume paths if any */ + probe_volumes(*p, is_sink, pcm_handle, context->ucm->mixers, ignore_dB); + /* then set property PA_PROP_DEVICE_INTENDED_ROLES */ merged_roles = pa_xstrdup(pa_proplist_gets(proplist, PA_PROP_DEVICE_INTENDED_ROLES)); PA_IDXSET_FOREACH(dev, context->ucm_devices, idx) { @@ -996,10 +1270,13 @@ void pa_alsa_ucm_add_ports( } /* Change UCM verb and device to match selected card profile */ -int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, const char *new_profile, const char *old_profile) { +int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, pa_card *card, const char *new_profile, const char *old_profile) { int ret = 0; const char *profile; pa_alsa_ucm_verb *verb; + pa_device_port *port; + pa_alsa_ucm_port_data *data; + void *state; if (new_profile == old_profile) return ret; @@ -1028,6 +1305,12 @@ int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, const char *new_profile, co } } + /* select volume controls on ports */ + PA_HASHMAP_FOREACH(port, card->ports, state) { + data = PA_DEVICE_PORT_DATA(port); + data->path = pa_hashmap_get(data->paths, new_profile); + } + return ret; } @@ -1079,23 +1362,35 @@ int pa_alsa_ucm_set_port(pa_alsa_ucm_mapping_context *context, pa_device_port *p static void ucm_add_mapping(pa_alsa_profile *p, pa_alsa_mapping *m) { + pa_alsa_path_set *ps; + + /* create empty path set for the future path additions */ + ps = pa_xnew0(pa_alsa_path_set, 1); + ps->direction = m->direction; + ps->paths = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + switch (m->direction) { case PA_ALSA_DIRECTION_ANY: pa_idxset_put(p->output_mappings, m, NULL); pa_idxset_put(p->input_mappings, m, NULL); + m->output_path_set = ps; + m->input_path_set = ps; break; case PA_ALSA_DIRECTION_OUTPUT: pa_idxset_put(p->output_mappings, m, NULL); + m->output_path_set = ps; break; case PA_ALSA_DIRECTION_INPUT: pa_idxset_put(p->input_mappings, m, NULL); + m->input_path_set = ps; break; } } static void alsa_mapping_add_ucm_device(pa_alsa_mapping *m, pa_alsa_ucm_device *device) { char *cur_desc; - const char *new_desc; + const char *new_desc, *mdev; + bool is_sink = m->direction == PA_ALSA_DIRECTION_OUTPUT; pa_idxset_put(m->ucm_context.ucm_devices, device, NULL); @@ -1111,10 +1406,14 @@ static void alsa_mapping_add_ucm_device(pa_alsa_mapping *m, pa_alsa_ucm_device * m->description = m->description ? m->description : pa_xstrdup(""); /* save mapping to ucm device */ - if (m->direction == PA_ALSA_DIRECTION_OUTPUT) + if (is_sink) device->playback_mapping = m; else device->capture_mapping = m; + + mdev = get_mixer_device(device, is_sink); + if (mdev) + pa_proplist_sets(m->proplist, "alsa.mixer_device", mdev); } static void alsa_mapping_add_ucm_modifier(pa_alsa_mapping *m, pa_alsa_ucm_modifier *modifier) { @@ -1294,6 +1593,7 @@ static pa_alsa_jack* ucm_get_jack(pa_alsa_ucm_config *ucm, pa_alsa_ucm_device *d pa_alsa_jack *j; const char *device_name; const char *jack_control; + const char *mixer_device_name; char *name; pa_assert(ucm); @@ -1303,6 +1603,22 @@ static pa_alsa_jack* ucm_get_jack(pa_alsa_ucm_config *ucm, pa_alsa_ucm_device *d jack_control = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_JACK_CONTROL); if (jack_control) { +#if SND_LIB_VERSION >= 0x10201 + snd_ctl_elem_id_t *ctl; + int err, index; + snd_ctl_elem_id_alloca(&ctl); + err = snd_use_case_parse_ctl_elem_id(ctl, "JackControl", jack_control); + if (err < 0) + return NULL; + jack_control = snd_ctl_elem_id_get_name(ctl); + index = snd_ctl_elem_id_get_index(ctl); + if (index > 0) { + pa_log("[%s] Invalid JackControl index value: \"%s\",%d", device_name, jack_control, index); + return NULL; + } +#else +#warning "Upgrade to alsa-lib 1.2.1!" +#endif if (!pa_endswith(jack_control, " Jack")) { pa_log("[%s] Invalid JackControl value: \"%s\"", device_name, jack_control); return NULL; @@ -1312,16 +1628,22 @@ static pa_alsa_jack* ucm_get_jack(pa_alsa_ucm_config *ucm, pa_alsa_ucm_device *d * end, so drop the trailing " Jack". */ name = pa_xstrndup(jack_control, strlen(jack_control) - 5); } else { - /* The jack control hasn't been explicitly configured - try a jack name - * that is the same as the device name. */ - name = pa_xstrdup(device_name); + /* The jack control hasn't been explicitly configured, fail. */ + return NULL; } PA_LLIST_FOREACH(j, ucm->jacks) if (pa_streq(j->name, name)) goto finish; - j = pa_alsa_jack_new(NULL, name); + mixer_device_name = get_jack_mixer_device(device, true); + if (!mixer_device_name) + mixer_device_name = get_jack_mixer_device(device, false); + if (!mixer_device_name) { + pa_log("[%s] No mixer device name for JackControl \"%s\"", device_name, jack_control); + return NULL; + } + j = pa_alsa_jack_new(NULL, mixer_device_name, name); PA_LLIST_PREPEND(pa_alsa_jack, ucm->jacks, j); finish: @@ -1342,7 +1664,7 @@ static int ucm_create_profile( pa_alsa_ucm_modifier *mod; int i = 0; const char *name, *sink, *source; - char *verb_cmp, *c; + unsigned int priority; pa_assert(ps); @@ -1362,24 +1684,26 @@ static int ucm_create_profile( p->supported = true; pa_hashmap_put(ps->profiles, p->name, p); - /* TODO: get profile priority from ucm info or policy management */ - c = verb_cmp = pa_xstrdup(verb_name); - while (*c) { - if (*c == '_') *c = ' '; - c++; - } + /* TODO: get profile priority from policy management */ + priority = verb->priority; - for (i = 0; verb_info[i].id; i++) { - if (strcasecmp(verb_info[i].id, verb_cmp) == 0) { - p->priority = verb_info[i].priority; - break; + if (priority == 0) { + char *verb_cmp, *c; + c = verb_cmp = pa_xstrdup(verb_name); + while (*c) { + if (*c == '_') *c = ' '; + c++; + } + for (i = 0; verb_info[i].id; i++) { + if (strcasecmp(verb_info[i].id, verb_cmp) == 0) { + priority = verb_info[i].priority; + break; + } } + pa_xfree(verb_cmp); } - pa_xfree(verb_cmp); - - if (verb_info[i].id == NULL) - p->priority = 1000; + p->priority = priority; PA_LLIST_FOREACH(dev, verb->devices) { pa_alsa_jack *jack; @@ -1393,7 +1717,8 @@ static int ucm_create_profile( ucm_create_mapping(ucm, ps, p, dev, verb_name, name, sink, source); jack = ucm_get_jack(ucm, dev); - device_set_jack(dev, jack); + if (jack) + device_set_jack(dev, jack); /* JackHWMute contains a list of device names. Each listed device must * be associated with the jack object that we just created. */ @@ -1402,7 +1727,7 @@ static int ucm_create_profile( char *hw_mute_device_name; const char *state = NULL; - while ((hw_mute_device_name = pa_split_spaces(jack_hw_mute, &state))) { + while ((hw_mute_device_name = ucm_split_devnames(jack_hw_mute, &state))) { pa_alsa_ucm_verb *verb2; bool device_found = false; @@ -1446,6 +1771,33 @@ static int ucm_create_profile( return 0; } +static void mapping_init_eld(pa_alsa_mapping *m, snd_pcm_t *pcm) +{ + pa_alsa_ucm_mapping_context *context = &m->ucm_context; + pa_alsa_ucm_device *dev; + uint32_t idx; + char *mdev; + snd_pcm_info_t *info; + int pcm_card, pcm_device; + + snd_pcm_info_alloca(&info); + if (snd_pcm_info(pcm, info) < 0) + return; + + if ((pcm_card = snd_pcm_info_get_card(info)) < 0) + return; + if ((pcm_device = snd_pcm_info_get_device(info)) < 0) + return; + + PA_IDXSET_FOREACH(dev, context->ucm_devices, idx) { + mdev = pa_sprintf_malloc("hw:%i", pcm_card); + if (mdev == NULL) + continue; + dev->eld_mixer_device_name = mdev; + dev->eld_device = pcm_device; + } +} + static snd_pcm_t* mapping_open_pcm(pa_alsa_ucm_config *ucm, pa_alsa_mapping *m, int mode) { snd_pcm_t* pcm; pa_sample_spec try_ss = ucm->core->default_sample_spec; @@ -1467,8 +1819,11 @@ static snd_pcm_t* mapping_open_pcm(pa_alsa_ucm_config *ucm, pa_alsa_mapping *m, pcm = pa_alsa_open_by_device_string(m->device_strings[0], NULL, &try_ss, &try_map, mode, &try_period_size, &try_buffer_size, 0, NULL, NULL, exact_channels); - if (pcm && !exact_channels) - m->channel_map = try_map; + if (pcm) { + if (!exact_channels) + m->channel_map = try_map; + mapping_init_eld(m, pcm); + } return pcm; } @@ -1500,27 +1855,28 @@ static void profile_finalize_probing(pa_alsa_profile *p) { } } -static void ucm_mapping_jack_probe(pa_alsa_mapping *m) { - snd_pcm_t *pcm_handle; +static void ucm_mapping_jack_probe(pa_alsa_mapping *m, pa_hashmap *mixers) { snd_mixer_t *mixer_handle; pa_alsa_ucm_mapping_context *context = &m->ucm_context; pa_alsa_ucm_device *dev; uint32_t idx; - pcm_handle = m->direction == PA_ALSA_DIRECTION_OUTPUT ? m->output_pcm : m->input_pcm; - mixer_handle = pa_alsa_open_mixer_for_pcm(pcm_handle, NULL); - if (!mixer_handle) - return; - PA_IDXSET_FOREACH(dev, context->ucm_devices, idx) { bool has_control; - has_control = pa_alsa_mixer_find(mixer_handle, dev->jack->alsa_name, 0) != NULL; + if (!dev->jack || !dev->jack->mixer_device_name) + continue; + + mixer_handle = pa_alsa_open_mixer_by_name(mixers, dev->jack->mixer_device_name, true); + if (!mixer_handle) { + pa_log_error("Unable to determine open mixer device '%s' for jack %s", dev->jack->mixer_device_name, dev->jack->name); + continue; + } + + has_control = pa_alsa_mixer_find_card(mixer_handle, dev->jack->alsa_name, 0) != NULL; pa_alsa_jack_set_has_control(dev->jack, has_control); pa_log_info("UCM jack %s has_control=%d", dev->jack->name, dev->jack->has_control); } - - snd_mixer_close(mixer_handle); } static void ucm_probe_profile_set(pa_alsa_ucm_config *ucm, pa_alsa_profile_set *ps) { @@ -1578,11 +1934,11 @@ static void ucm_probe_profile_set(pa_alsa_ucm_config *ucm, pa_alsa_profile_set * PA_IDXSET_FOREACH(m, p->output_mappings, idx) if (!PA_UCM_IS_MODIFIER_MAPPING(m)) - ucm_mapping_jack_probe(m); + ucm_mapping_jack_probe(m, ucm->mixers); PA_IDXSET_FOREACH(m, p->input_mappings, idx) if (!PA_UCM_IS_MODIFIER_MAPPING(m)) - ucm_mapping_jack_probe(m); + ucm_mapping_jack_probe(m, ucm->mixers); profile_finalize_probing(p); } @@ -1636,11 +1992,20 @@ static void free_verb(pa_alsa_ucm_verb *verb) { if (di->ucm_ports) pa_dynarray_free(di->ucm_ports); + if (di->playback_volumes) + pa_hashmap_free(di->playback_volumes); + if (di->capture_volumes) + pa_hashmap_free(di->capture_volumes); + pa_proplist_free(di->proplist); + if (di->conflicting_devices) pa_idxset_free(di->conflicting_devices, NULL); if (di->supported_devices) pa_idxset_free(di->supported_devices, NULL); + + pa_xfree(di->eld_mixer_device_name); + pa_xfree(di); } @@ -1771,7 +2136,7 @@ void pa_alsa_ucm_roled_stream_end(pa_alsa_ucm_config *ucm, const char *role, pa_ } } -static void device_add_ucm_port(pa_alsa_ucm_device *device, struct ucm_port *port) { +static void device_add_ucm_port(pa_alsa_ucm_device *device, pa_alsa_ucm_port_data *port) { pa_assert(device); pa_assert(port); @@ -1799,7 +2164,7 @@ static void device_add_hw_mute_jack(pa_alsa_ucm_device *device, pa_alsa_jack *ja } static void device_set_available(pa_alsa_ucm_device *device, pa_available_t available) { - struct ucm_port *port; + pa_alsa_ucm_port_data *port; unsigned idx; pa_assert(device); @@ -1833,8 +2198,8 @@ void pa_alsa_ucm_device_update_available(pa_alsa_ucm_device *device) { device_set_available(device, available); } -static void ucm_port_init(struct ucm_port *port, pa_alsa_ucm_config *ucm, pa_device_port *core_port, - pa_alsa_ucm_device **devices, unsigned n_devices) { +static void ucm_port_data_init(pa_alsa_ucm_port_data *port, pa_alsa_ucm_config *ucm, pa_device_port *core_port, + pa_alsa_ucm_device **devices, unsigned n_devices) { unsigned i; pa_assert(ucm); @@ -1844,17 +2209,21 @@ static void ucm_port_init(struct ucm_port *port, pa_alsa_ucm_config *ucm, pa_dev port->ucm = ucm; port->core_port = core_port; port->devices = pa_dynarray_new(NULL); + port->eld_device = -1; for (i = 0; i < n_devices; i++) { pa_dynarray_append(port->devices, devices[i]); device_add_ucm_port(devices[i], port); } + port->paths = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, pa_xfree, + (pa_free_cb_t) pa_alsa_path_free); + ucm_port_update_available(port); } -static void ucm_port_free(pa_device_port *port) { - struct ucm_port *ucm_port; +static void ucm_port_data_free(pa_device_port *port) { + pa_alsa_ucm_port_data *ucm_port; pa_assert(port); @@ -1862,9 +2231,14 @@ static void ucm_port_free(pa_device_port *port) { if (ucm_port->devices) pa_dynarray_free(ucm_port->devices); + + if (ucm_port->paths) + pa_hashmap_free(ucm_port->paths); + + pa_xfree(ucm_port->eld_mixer_device_name); } -static void ucm_port_update_available(struct ucm_port *port) { +static void ucm_port_update_available(pa_alsa_ucm_port_data *port) { pa_alsa_ucm_device *device; unsigned idx; pa_available_t available = PA_AVAILABLE_YES; @@ -1896,7 +2270,7 @@ pa_alsa_profile_set* pa_alsa_ucm_add_profile_set(pa_alsa_ucm_config *ucm, pa_cha return NULL; } -int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, const char *new_profile, const char *old_profile) { +int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, pa_card *card, const char *new_profile, const char *old_profile) { return -1; } @@ -1909,7 +2283,9 @@ void pa_alsa_ucm_add_ports( pa_proplist *proplist, pa_alsa_ucm_mapping_context *context, bool is_sink, - pa_card *card) { + pa_card *card, + snd_pcm_t *pcm_handle, + bool ignore_dB) { } void pa_alsa_ucm_add_ports_combination( diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h index c926f3c..e7a795c 100644 --- a/src/modules/alsa/alsa-ucm.h +++ b/src/modules/alsa/alsa-ucm.h @@ -45,12 +45,33 @@ typedef void snd_use_case_mgr_t; /** For devices: Playback roles */ #define PA_ALSA_PROP_UCM_PLAYBACK_ROLES "alsa.ucm.playback.roles" +/** For devices: Playback control device name */ +#define PA_ALSA_PROP_UCM_PLAYBACK_CTL_DEVICE "alsa.ucm.playback.ctldev" + /** For devices: Playback control volume ID string. e.g PlaybackVolume */ #define PA_ALSA_PROP_UCM_PLAYBACK_VOLUME "alsa.ucm.playback.volume" /** For devices: Playback switch e.g PlaybackSwitch */ #define PA_ALSA_PROP_UCM_PLAYBACK_SWITCH "alsa.ucm.playback.switch" +/** For devices: Playback mixer device name */ +#define PA_ALSA_PROP_UCM_PLAYBACK_MIXER_DEVICE "alsa.ucm.playback.mixer.device" + +/** For devices: Playback mixer identifier */ +#define PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM "alsa.ucm.playback.mixer.element" + +/** For devices: Playback mixer master identifier */ +#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ELEM "alsa.ucm.playback.master.element" + +/** For devices: Playback mixer master type */ +#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE "alsa.ucm.playback.master.type" + +/** For devices: Playback mixer master identifier */ +#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ID "alsa.ucm.playback.master.id" + +/** For devices: Playback mixer master type */ +#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE "alsa.ucm.playback.master.type" + /** For devices: Playback priority */ #define PA_ALSA_PROP_UCM_PLAYBACK_PRIORITY "alsa.ucm.playback.priority" @@ -63,12 +84,33 @@ typedef void snd_use_case_mgr_t; /** For devices: Capture roles */ #define PA_ALSA_PROP_UCM_CAPTURE_ROLES "alsa.ucm.capture.roles" +/** For devices: Capture control device name */ +#define PA_ALSA_PROP_UCM_CAPTURE_CTL_DEVICE "alsa.ucm.capture.ctldev" + /** For devices: Capture controls volume ID string. e.g CaptureVolume */ #define PA_ALSA_PROP_UCM_CAPTURE_VOLUME "alsa.ucm.capture.volume" /** For devices: Capture switch e.g CaptureSwitch */ #define PA_ALSA_PROP_UCM_CAPTURE_SWITCH "alsa.ucm.capture.switch" +/** For devices: Capture mixer device name */ +#define PA_ALSA_PROP_UCM_CAPTURE_MIXER_DEVICE "alsa.ucm.capture.mixer.device" + +/** For devices: Capture mixer identifier */ +#define PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM "alsa.ucm.capture.mixer.element" + +/** For devices: Capture mixer identifier */ +#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_ELEM "alsa.ucm.capture.master.element" + +/** For devices: Capture mixer identifier */ +#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE "alsa.ucm.capture.master.type" + +/** For devices: Capture mixer identifier */ +#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_ID "alsa.ucm.capture.master.id" + +/** For devices: Capture mixer identifier */ +#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE "alsa.ucm.capture.master.type" + /** For devices: Capture priority */ #define PA_ALSA_PROP_UCM_CAPTURE_PRIORITY "alsa.ucm.capture.priority" @@ -84,6 +126,9 @@ typedef void snd_use_case_mgr_t; /** For devices: The modifier (if any) that this device corresponds to */ #define PA_ALSA_PROP_UCM_MODIFIER "alsa.ucm.modifier" +/* Corresponds to the "JackCTL" UCM value. */ +#define PA_ALSA_PROP_UCM_JACK_DEVICE "alsa.ucm.jack_device" + /* Corresponds to the "JackControl" UCM value. */ #define PA_ALSA_PROP_UCM_JACK_CONTROL "alsa.ucm.jack_control" @@ -95,10 +140,12 @@ typedef struct pa_alsa_ucm_modifier pa_alsa_ucm_modifier; typedef struct pa_alsa_ucm_device pa_alsa_ucm_device; typedef struct pa_alsa_ucm_config pa_alsa_ucm_config; typedef struct pa_alsa_ucm_mapping_context pa_alsa_ucm_mapping_context; +typedef struct pa_alsa_ucm_port_data pa_alsa_ucm_port_data; +typedef struct pa_alsa_ucm_volume pa_alsa_ucm_volume; int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index); pa_alsa_profile_set* pa_alsa_ucm_add_profile_set(pa_alsa_ucm_config *ucm, pa_channel_map *default_channel_map); -int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, const char *new_profile, const char *old_profile); +int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, pa_card *card, const char *new_profile, const char *old_profile); int pa_alsa_ucm_get_verb(snd_use_case_mgr_t *uc_mgr, const char *verb_name, const char *verb_desc, pa_alsa_ucm_verb **p_verb); @@ -107,7 +154,9 @@ void pa_alsa_ucm_add_ports( pa_proplist *proplist, pa_alsa_ucm_mapping_context *context, bool is_sink, - pa_card *card); + pa_card *card, + snd_pcm_t *pcm_handle, + bool ignore_dB); void pa_alsa_ucm_add_ports_combination( pa_hashmap *hash, pa_alsa_ucm_mapping_context *context, @@ -139,6 +188,11 @@ struct pa_alsa_ucm_device { unsigned playback_channels; unsigned capture_channels; + /* These may be different per verb, so we store this as a hashmap of verb -> volume_control. We might eventually want to + * make this a hashmap of verb -> per-verb-device-properties-struct. */ + pa_hashmap *playback_volumes; + pa_hashmap *capture_volumes; + pa_alsa_mapping *playback_mapping; pa_alsa_mapping *capture_mapping; @@ -153,6 +207,9 @@ struct pa_alsa_ucm_device { pa_alsa_jack *jack; pa_dynarray *hw_mute_jacks; /* pa_alsa_jack */ pa_available_t available; + + char *eld_mixer_device_name; + int eld_device; }; void pa_alsa_ucm_device_update_available(pa_alsa_ucm_device *device); @@ -184,6 +241,7 @@ struct pa_alsa_ucm_verb { PA_LLIST_FIELDS(pa_alsa_ucm_verb); pa_proplist *proplist; + unsigned priority; PA_LLIST_HEAD(pa_alsa_ucm_device, devices); PA_LLIST_HEAD(pa_alsa_ucm_modifier, modifiers); @@ -194,6 +252,7 @@ struct pa_alsa_ucm_config { snd_use_case_mgr_t *ucm_mgr; pa_alsa_ucm_verb *active_verb; + pa_hashmap *mixers; PA_LLIST_HEAD(pa_alsa_ucm_verb, verbs); PA_LLIST_HEAD(pa_alsa_jack, jacks); }; @@ -206,4 +265,28 @@ struct pa_alsa_ucm_mapping_context { pa_idxset *ucm_modifiers; }; +struct pa_alsa_ucm_port_data { + pa_alsa_ucm_config *ucm; + pa_device_port *core_port; + + /* A single port will be associated with multiple devices if it represents + * a combination of devices. */ + pa_dynarray *devices; /* pa_alsa_ucm_device */ + + /* profile name -> pa_alsa_path for volume control */ + pa_hashmap *paths; + /* Current path, set when activating profile */ + pa_alsa_path *path; + + /* ELD info */ + char *eld_mixer_device_name; + int eld_device; /* PCM device number */ +}; + +struct pa_alsa_ucm_volume { + char *mixer_elem; /* mixer element identifier */ + char *master_elem; /* master mixer element identifier */ + char *master_type; +}; + #endif diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c index bd0a47e..d86f43c 100644 --- a/src/modules/alsa/alsa-util.c +++ b/src/modules/alsa/alsa-util.c @@ -1066,6 +1066,7 @@ void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) { int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) { snd_pcm_state_t state; + snd_pcm_hw_params_t *hwparams; int err; pa_assert(pcm); @@ -1103,16 +1104,25 @@ int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) { break; case SND_PCM_STATE_SUSPENDED: - /* Retry resume 3 times before giving up, then fallback to restarting the stream. */ - for (int i = 0; i < 3; i++) { - if ((err = snd_pcm_resume(pcm)) == 0) - return 0; - if (err != -EAGAIN) - break; - pa_msleep(25); + snd_pcm_hw_params_alloca(&hwparams); + + if ((err = snd_pcm_hw_params_any(pcm, hwparams)) < 0) { + pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(err)); + return -1; } - pa_log_warn("Could not recover alsa device from SUSPENDED state, trying to restart PCM"); - /* Fall through */ + + if (snd_pcm_hw_params_can_resume(hwparams)) { + /* Retry resume 3 times before giving up, then fallback to restarting the stream. */ + for (int i = 0; i < 3; i++) { + if ((err = snd_pcm_resume(pcm)) == 0) + return 0; + if (err != -EAGAIN) + break; + pa_msleep(25); + } + pa_log_warn("Could not recover alsa device from SUSPENDED state, trying to restart PCM"); + } + /* Fall through */ default: @@ -1600,7 +1610,11 @@ bool pa_alsa_may_tsched(bool want) { #define SND_MIXER_ELEM_PULSEAUDIO (SND_MIXER_ELEM_LAST + 10) -snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsigned int device) { +static snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, + snd_ctl_elem_iface_t iface, + const char *name, + unsigned int index, + unsigned int device) { snd_mixer_elem_t *elem; for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(elem)) { @@ -1608,8 +1622,12 @@ snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsig if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_PULSEAUDIO) continue; helem = snd_mixer_elem_get_private(elem); + if (snd_hctl_elem_get_interface(helem) != iface) + continue; if (!pa_streq(snd_hctl_elem_get_name(helem), name)) continue; + if (snd_hctl_elem_get_index(helem) != index) + continue; if (snd_hctl_elem_get_device(helem) != device) continue; return elem; @@ -1617,6 +1635,14 @@ snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsig return NULL; } +snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, const char *name, unsigned int device) { + return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, name, 0, device); +} + +snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device) { + return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_PCM, name, 0, device); +} + static int mixer_class_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2) { /* Dummy compare function */ @@ -1700,85 +1726,119 @@ static int prepare_mixer(snd_mixer_t *mixer, const char *dev) { return 0; } -snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device) { +snd_mixer_t *pa_alsa_open_mixer(pa_hashmap *mixers, int alsa_card_index, bool probe) { + char *md = pa_sprintf_malloc("hw:%i", alsa_card_index); + snd_mixer_t *m = pa_alsa_open_mixer_by_name(mixers, md, probe); + pa_xfree(md); + return m; +} + +snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, bool probe) { int err; snd_mixer_t *m; - char *md; - snd_pcm_info_t* info; - snd_pcm_info_alloca(&info); + pa_alsa_mixer *pm; + char *dev2; + void *state; + + pa_assert(mixers); + pa_assert(dev); + + pm = pa_hashmap_get(mixers, dev); + + /* The quick card number/index lookup (hw:#) + * We already know the card number/index, thus use the mixer + * from the cache at first. + */ + if (!pm && pa_strneq(dev, "hw:", 3)) { + const char *s = dev + 3; + int card_index; + while (*s && *s >= 0 && *s <= '9') s++; + if (*s == '\0' && pa_atoi(dev + 3, &card_index) >= 0) { + PA_HASHMAP_FOREACH_KV(dev2, pm, mixers, state) { + if (pm->card_index == card_index) { + dev = dev2; + pm = pa_hashmap_get(mixers, dev); + break; + } + } + } + } + + if (pm) { + if (!probe) + pm->used_for_probe_only = false; + return pm->mixer_handle; + } if ((err = snd_mixer_open(&m, 0)) < 0) { pa_log("Error opening mixer: %s", pa_alsa_strerror(err)); return NULL; } - /* Then, try by card index */ - md = pa_sprintf_malloc("hw:%i", alsa_card_index); - if (prepare_mixer(m, md) >= 0) { - - if (ctl_device) - *ctl_device = md; - else - pa_xfree(md); - - return m; + if (prepare_mixer(m, dev) >= 0) { + pm = pa_xnew0(pa_alsa_mixer, 1); + if (pm) { + snd_hctl_t *hctl; + pm->card_index = -1; + /* determine the ALSA card number (index) and store it to card_index */ + err = snd_mixer_get_hctl(m, dev, &hctl); + if (err >= 0) { + snd_ctl_card_info_t *info; + snd_ctl_card_info_alloca(&info); + err = snd_ctl_card_info(snd_hctl_ctl(hctl), info); + if (err >= 0) + pm->card_index = snd_ctl_card_info_get_card(info); + } + pm->used_for_probe_only = probe; + pm->mixer_handle = m; + pa_hashmap_put(mixers, pa_xstrdup(dev), pm); + return m; + } } - pa_xfree(md); - snd_mixer_close(m); return NULL; } -snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device) { - int err; - snd_mixer_t *m; - const char *dev; +snd_mixer_t *pa_alsa_open_mixer_for_pcm(pa_hashmap *mixers, snd_pcm_t *pcm, bool probe) { snd_pcm_info_t* info; snd_pcm_info_alloca(&info); pa_assert(pcm); - if ((err = snd_mixer_open(&m, 0)) < 0) { - pa_log("Error opening mixer: %s", pa_alsa_strerror(err)); - return NULL; - } - - /* First, try by name */ - if ((dev = snd_pcm_name(pcm))) - if (prepare_mixer(m, dev) >= 0) { - if (ctl_device) - *ctl_device = pa_xstrdup(dev); - - return m; - } - - /* Then, try by card index */ if (snd_pcm_info(pcm, info) >= 0) { - char *md; int card_idx; - if ((card_idx = snd_pcm_info_get_card(info)) >= 0) { - - md = pa_sprintf_malloc("hw:%i", card_idx); - - if (!dev || !pa_streq(dev, md)) - if (prepare_mixer(m, md) >= 0) { + if ((card_idx = snd_pcm_info_get_card(info)) >= 0) + return pa_alsa_open_mixer(mixers, card_idx, probe); + } - if (ctl_device) - *ctl_device = md; - else - pa_xfree(md); + return NULL; +} - return m; - } +void pa_alsa_mixer_set_fdlist(pa_hashmap *mixers, snd_mixer_t *mixer_handle, pa_mainloop_api *ml) +{ + pa_alsa_mixer *pm; + void *state; - pa_xfree(md); + PA_HASHMAP_FOREACH(pm, mixers, state) + if (pm->mixer_handle == mixer_handle) { + pm->used_for_probe_only = false; + if (!pm->fdl) { + pm->fdl = pa_alsa_fdlist_new(); + if (pm->fdl) + pa_alsa_fdlist_set_handle(pm->fdl, pm->mixer_handle, NULL, ml); + } } - } +} - snd_mixer_close(m); - return NULL; +void pa_alsa_mixer_free(pa_alsa_mixer *mixer) +{ + if (mixer->fdl) + pa_alsa_fdlist_free(mixer->fdl); + if (mixer->mixer_handle) + snd_mixer_close(mixer->mixer_handle); + pa_xfree(mixer); } int pa_alsa_get_hdmi_eld(snd_hctl_elem_t *elem, pa_hdmi_eld *eld) { diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h index 4ceaa06..0d3d5af 100644 --- a/src/modules/alsa/alsa-util.h +++ b/src/modules/alsa/alsa-util.h @@ -141,9 +141,14 @@ const char* pa_alsa_strerror(int errnum); bool pa_alsa_may_tsched(bool want); -snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsigned int device); - -snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device); +snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, const char *name, unsigned int device); +snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device); + +snd_mixer_t *pa_alsa_open_mixer(pa_hashmap *mixers, int alsa_card_index, bool probe); +snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, bool probe); +snd_mixer_t *pa_alsa_open_mixer_for_pcm(pa_hashmap *mixers, snd_pcm_t *pcm, bool probe); +void pa_alsa_mixer_set_fdlist(pa_hashmap *mixers, snd_mixer_t *mixer, pa_mainloop_api *ml); +void pa_alsa_mixer_free(pa_alsa_mixer *mixer); typedef struct pa_hdmi_eld pa_hdmi_eld; struct pa_hdmi_eld { diff --git a/src/modules/alsa/meson.build b/src/modules/alsa/meson.build index 5309dc1..f31eeb5 100644 --- a/src/modules/alsa/meson.build +++ b/src/modules/alsa/meson.build @@ -32,7 +32,7 @@ libalsa_util = shared_library('alsa-util', c_args : [pa_c_args, server_c_args], link_args : [nodelete_link_args], include_directories : [configinc, topinc], - dependencies : [libpulse_dep, libpulsecommon_dep, libpulsecore_dep, alsa_dep, dbus_dep, libatomic_ops_dep, libm_dep, udev_dep], + dependencies : [libpulse_dep, libpulsecommon_dep, libpulsecore_dep, alsa_dep, dbus_dep, libatomic_ops_dep, libm_dep, udev_dep, libintl_dep], install : true, install_rpath : privlibdir, install_dir : modlibexecdir, diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker.conf b/src/modules/alsa/mixer/paths/analog-output-speaker.conf index 9f4dac4..6f9968e 100644 --- a/src/modules/alsa/mixer/paths/analog-output-speaker.conf +++ b/src/modules/alsa/mixer/paths/analog-output-speaker.conf @@ -56,6 +56,9 @@ state.unplugged = unknown state.plugged = no state.unplugged = unknown +[Jack Speaker] +required-any = any + [Jack Speaker Phantom] required-any = any state.plugged = unknown diff --git a/src/modules/alsa/mixer/paths/analog-output.conf.common b/src/modules/alsa/mixer/paths/analog-output.conf.common index e52830d..7bf3463 100644 --- a/src/modules/alsa/mixer/paths/analog-output.conf.common +++ b/src/modules/alsa/mixer/paths/analog-output.conf.common @@ -85,7 +85,8 @@ ; required-any = ignore | enumeration | any # In this element, either this or another option must exist (or an element) ; required-absent = ignore | enumeration | any # In this element, this option must not exist or the path will be invalid ; -; [Element ...] # For each element that we shall control +; [Element ...] # For each element that we shall control. The "..." here is the element name, +; # or name and index separated by a comma. ; required = ignore | switch | volume | enumeration | any # If set, require this element to be of this kind and available, ; # otherwise don't consider this path valid for the card ; required-any = ignore | switch | volume | enumeration | any # If set, at least one of the elements or jacks with required-any in this diff --git a/src/modules/alsa/mixer/paths/steelseries-arctis-5-output-chat.conf b/src/modules/alsa/mixer/paths/steelseries-arctis-output-chat-common.conf index 5842bfe..5842bfe 100644 --- a/src/modules/alsa/mixer/paths/steelseries-arctis-5-output-chat.conf +++ b/src/modules/alsa/mixer/paths/steelseries-arctis-output-chat-common.conf diff --git a/src/modules/alsa/mixer/paths/steelseries-arctis-5-output-game.conf b/src/modules/alsa/mixer/paths/steelseries-arctis-output-game-common.conf index b758a6f..b758a6f 100644 --- a/src/modules/alsa/mixer/paths/steelseries-arctis-5-output-game.conf +++ b/src/modules/alsa/mixer/paths/steelseries-arctis-output-game-common.conf diff --git a/src/modules/alsa/mixer/paths/steelseries-arctis-7-input.conf b/src/modules/alsa/mixer/paths/usb-gaming-headset-input.conf index 3fa36e9..9fa7fe9 100644 --- a/src/modules/alsa/mixer/paths/steelseries-arctis-7-input.conf +++ b/src/modules/alsa/mixer/paths/usb-gaming-headset-input.conf @@ -13,8 +13,16 @@ # You should have received a copy of the GNU Lesser General Public License # along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. -; Steelseries Arctis 7 USB headset microphone path. Works also with Arctis Pro -; Wireless. +; USB gaming headset microphone input path. These headsets usually have two +; output devices. The first one is mono, meant for voice audio, and the second +; one is stereo, meant for everything else. The purpose of this unusual design +; is to provide separate volume controls for voice and other audio, which can +; be useful in gaming. +; +; Works with: +; Steelseries Arctis 7 +; Steelseries Arctis Pro Wireless. +; Lucidsound LS31 [General] description-key = analog-input-microphone-headset diff --git a/src/modules/alsa/mixer/paths/steelseries-arctis-7-output-mono.conf b/src/modules/alsa/mixer/paths/usb-gaming-headset-output-mono.conf index d8b24a2..6df662f 100644 --- a/src/modules/alsa/mixer/paths/steelseries-arctis-7-output-mono.conf +++ b/src/modules/alsa/mixer/paths/usb-gaming-headset-output-mono.conf @@ -13,11 +13,16 @@ # You should have received a copy of the GNU Lesser General Public License # along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. -; Steelseries Arctis 7 USB headset mono output path. Works also with Arctis Pro -; Wireless. The headset has two output devices. The first one is mono, meant -; for voice audio, and the second one is stereo, meant for everything else. The -; purpose of this unusual design is to provide separate volume controls for -; voice and other audio, which can be useful in gaming. +; USB gaming headset mono output path. These headsets usually have two +; output devices. The first one is mono, meant for voice audio, and the second +; one is stereo, meant for everything else. The purpose of this unusual design +; is to provide separate volume controls for voice and other audio, which can +; be useful in gaming. +; +; Works with: +; Steelseries Arctis 7 +; Steelseries Arctis Pro Wireless. +; Lucidsound LS31 [General] description-key = analog-output-headphones-mono diff --git a/src/modules/alsa/mixer/paths/steelseries-arctis-7-output-stereo.conf b/src/modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf index fcc58a0..e3f91cd 100644 --- a/src/modules/alsa/mixer/paths/steelseries-arctis-7-output-stereo.conf +++ b/src/modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf @@ -13,11 +13,16 @@ # You should have received a copy of the GNU Lesser General Public License # along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. -; Steelseries Arctis 7 USB headset stereo output path. Works also with Arctis -; Pro Wireless. The headset has two output devices. The first one is mono, -; meant for voice audio, and the second one is stereo, meant for everything -; else. The purpose of this unusual design is to provide separate volume -; controls for voice and other audio, which can be useful in gaming. +; USB gaming headset mono output path. These headsets usually have two +; output devices. The first one is mono, meant for voice audio, and the second +; one is stereo, meant for everything else. The purpose of this unusual design +; is to provide separate volume controls for voice and other audio, which can +; be useful in gaming. +; +; Works with: +; Steelseries Arctis 7 +; Steelseries Arctis Pro Wireless. +; Lucidsound LS31 ; ; This path doesn't provide hardware volume control, because the stereo ; output is controlled by the PCM element with index 1, and currently diff --git a/src/modules/alsa/mixer/profile-sets/default.conf b/src/modules/alsa/mixer/profile-sets/default.conf index 34c51bc..c73bf5c 100644 --- a/src/modules/alsa/mixer/profile-sets/default.conf +++ b/src/modules/alsa/mixer/profile-sets/default.conf @@ -49,7 +49,8 @@ ; # If multiple are found to be working they will be available as device ports ; paths-output = ... ; element-input = ... # Instead of configuring a full mixer path simply configure a single -; # mixer element for volume/mute handling +; # mixer element for volume/mute handling. The value can be an element +; # name, or name and index separated by a comma. ; element-output = ... ; priority = ... ; direction = any | input | output # Only useful for? @@ -72,7 +73,8 @@ ; [DecibelFix element] # Decibel fixes can be used to work around missing or incorrect dB ; # information from alsa. A decibel fix is a table that maps volume steps ; # to decibel values for one volume element. The "element" part in the -; # section title is the name of the volume element. +; # section title is the name of the volume element (or name and index +; # separated by a comma). ; # ; # NOTE: This feature is meant just as a help for figuring out the correct ; # decibel values. PulseAudio is not the correct place to maintain the diff --git a/src/modules/alsa/mixer/profile-sets/steelseries-arctis-5-usb-audio.conf b/src/modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf index fe353c3..5f11ed1 100644 --- a/src/modules/alsa/mixer/profile-sets/steelseries-arctis-5-usb-audio.conf +++ b/src/modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf @@ -6,13 +6,14 @@ description = Chat device-strings = hw:%f,0,0 channel-map = left,right paths-input = analog-input-mic -paths-output = steelseries-arctis-5-output-chat +paths-output = steelseries-arctis-output-chat-common +intended-roles = phone [Mapping analog-game] description = Game device-strings = hw:%f,1,0 channel-map = left,right -paths-output = steelseries-arctis-5-output-game +paths-output = steelseries-arctis-output-game-common direction = output [Profile output:analog-chat+output:analog-game+input:analog-chat] diff --git a/src/modules/alsa/mixer/profile-sets/steelseries-arctis-7-usb-audio.conf b/src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf index e1394dc..f48b44f 100644 --- a/src/modules/alsa/mixer/profile-sets/steelseries-arctis-7-usb-audio.conf +++ b/src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf @@ -13,12 +13,17 @@ # You should have received a copy of the GNU Lesser General Public License # along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. -; Steelseries Arctis 7 USB and Arctis Pro Wireless USB headset. These headsets -; have a microphone and two output devices. The first output device is mono, -; meant for voice audio, and the second one is stereo, meant for everything -; else. The purpose of this unusual design is to provide separate volume +; USB gaming headset. +; These headsets usually have two output devices. The first one is mono, +; meant for voice audio, and the second one is stereo, meant for everything +; else. The purpose of this unusual design is to provide separate volume ; controls for voice and other audio, which can be useful in gaming. ; +; Works with: +; Steelseries Arctis 7 +; Steelseries Arctis Pro Wireless. +; Lucidsound LS31 +; ; See default.conf for an explanation on the directives used here. [General] @@ -27,13 +32,14 @@ auto-profiles = yes [Mapping analog-mono] device-strings = hw:%f,0,0 channel-map = mono -paths-output = steelseries-arctis-7-output-mono -paths-input = steelseries-arctis-7-input +paths-output = usb-gaming-headset-output-mono +paths-input = usb-gaming-headset-input +intended-roles = phone [Mapping analog-stereo] device-strings = hw:%f,1,0 channel-map = left,right -paths-output = steelseries-arctis-7-output-stereo +paths-output = usb-gaming-headset-output-stereo direction = output [Profile output:analog-mono+output:analog-stereo+input:analog-mono] diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index 1e1090f..c5852b4 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -111,9 +111,8 @@ struct userdata { char *device_id; int alsa_card_index; - snd_mixer_t *mixer_handle; + pa_hashmap *mixers; pa_hashmap *jacks; - pa_alsa_fdlist *mixer_fdl; pa_card *card; @@ -241,7 +240,7 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { /* if UCM is available for this card then update the verb */ if (u->use_ucm) { - if (pa_alsa_ucm_set_profile(&u->ucm, nd->profile ? nd->profile->name : NULL, + if (pa_alsa_ucm_set_profile(&u->ucm, c, nd->profile ? nd->profile->name : NULL, od->profile ? od->profile->name : NULL) < 0) { ret = -1; goto finish; @@ -294,7 +293,7 @@ static void init_profile(struct userdata *u) { if (d->profile && u->use_ucm) { /* Set initial verb */ - if (pa_alsa_ucm_set_profile(ucm, d->profile->name, NULL) < 0) { + if (pa_alsa_ucm_set_profile(ucm, u->card, d->profile->name, NULL) < 0) { pa_log("Failed to set ucm profile %s", d->profile->name); return; } @@ -513,15 +512,24 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) { return 0; } -static pa_device_port* find_port_with_eld_device(pa_hashmap *ports, int device) { +static pa_device_port* find_port_with_eld_device(struct userdata *u, int device) { void *state; pa_device_port *p; - PA_HASHMAP_FOREACH(p, ports, state) { - pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(p); - pa_assert(data->path); - if (device == data->path->eld_device) - return p; + if (u->use_ucm) { + PA_HASHMAP_FOREACH(p, u->card->ports, state) { + pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(p); + pa_assert(data->eld_mixer_device_name); + if (device == data->eld_device) + return p; + } + } else { + PA_HASHMAP_FOREACH(p, u->card->ports, state) { + pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(p); + pa_assert(data->path); + if (device == data->path->eld_device) + return p; + } } return NULL; } @@ -538,7 +546,7 @@ static int hdmi_eld_changed(snd_mixer_elem_t *melem, unsigned int mask) { if (mask == SND_CTL_EVENT_MASK_REMOVE) return 0; - p = find_port_with_eld_device(u->card->ports, device); + p = find_port_with_eld_device(u, device); if (p == NULL) { pa_log_error("Invalid device changed in ALSA: %d", device); return 0; @@ -566,33 +574,46 @@ static void init_eld_ctls(struct userdata *u) { void *state; pa_device_port *port; - if (!u->mixer_handle) - return; - /* The code in this function expects ports to have a pa_alsa_port_data * struct as their data, but in UCM mode ports don't have any data. Hence, * the ELD controls can't currently be used in UCM mode. */ - if (u->use_ucm) - return; - PA_HASHMAP_FOREACH(port, u->card->ports, state) { - pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(port); + snd_mixer_t *mixer_handle; snd_mixer_elem_t* melem; int device; - pa_assert(data->path); - device = data->path->eld_device; - if (device < 0) + if (u->use_ucm) { + pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(port); + device = data->eld_device; + if (device < 0 || !data->eld_mixer_device_name) + continue; + + mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, data->eld_mixer_device_name, true); + } else { + pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(port); + + pa_assert(data->path); + + device = data->path->eld_device; + if (device < 0) + continue; + + mixer_handle = pa_alsa_open_mixer(u->mixers, u->alsa_card_index, true); + } + + if (!mixer_handle) continue; - melem = pa_alsa_mixer_find(u->mixer_handle, "ELD", device); + melem = pa_alsa_mixer_find_pcm(mixer_handle, "ELD", device); if (melem) { + pa_alsa_mixer_set_fdlist(u->mixers, mixer_handle, u->core->mainloop); snd_mixer_elem_set_callback(melem, hdmi_eld_changed); snd_mixer_elem_set_callback_private(melem, u); hdmi_eld_changed(melem, 0); + pa_log_info("ELD device found for port %s (%d).", port->name, device); } else - pa_log_debug("No ELD device found for port %s.", port->name); + pa_log_debug("No ELD device found for port %s (%d).", port->name, device); } } @@ -627,25 +648,31 @@ static void init_jacks(struct userdata *u) { if (pa_hashmap_size(u->jacks) == 0) return; - u->mixer_fdl = pa_alsa_fdlist_new(); - - u->mixer_handle = pa_alsa_open_mixer(u->alsa_card_index, NULL); - if (u->mixer_handle && pa_alsa_fdlist_set_handle(u->mixer_fdl, u->mixer_handle, NULL, u->core->mainloop) >= 0) { - PA_HASHMAP_FOREACH(jack, u->jacks, state) { - jack->melem = pa_alsa_mixer_find(u->mixer_handle, jack->alsa_name, 0); - if (!jack->melem) { - pa_log_warn("Jack '%s' seems to have disappeared.", jack->alsa_name); - pa_alsa_jack_set_has_control(jack, false); - continue; + PA_HASHMAP_FOREACH(jack, u->jacks, state) { + if (!jack->mixer_device_name) { + jack->mixer_handle = pa_alsa_open_mixer(u->mixers, u->alsa_card_index, false); + if (!jack->mixer_handle) { + pa_log("Failed to open mixer for card %d for jack detection", u->alsa_card_index); + continue; + } + } else { + jack->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, jack->mixer_device_name, false); + if (!jack->mixer_handle) { + pa_log("Failed to open mixer '%s' for jack detection", jack->mixer_device_name); + continue; } - snd_mixer_elem_set_callback(jack->melem, report_jack_state); - snd_mixer_elem_set_callback_private(jack->melem, u); - report_jack_state(jack->melem, 0); } - - } else - pa_log("Failed to open mixer for jack detection"); - + pa_alsa_mixer_set_fdlist(u->mixers, jack->mixer_handle, u->core->mainloop); + jack->melem = pa_alsa_mixer_find_card(jack->mixer_handle, jack->alsa_name, 0); + if (!jack->melem) { + pa_log_warn("Jack '%s' seems to have disappeared.", jack->alsa_name); + pa_alsa_jack_set_has_control(jack, false); + continue; + } + snd_mixer_elem_set_callback(jack->melem, report_jack_state); + snd_mixer_elem_set_callback_private(jack->melem, u); + report_jack_state(jack->melem, 0); + } } static void set_card_name(pa_card_new_data *data, pa_modargs *ma, const char *device_id) { @@ -769,6 +796,10 @@ int pa__init(pa_module *m) { u->use_ucm = true; u->ucm.core = m->core; + u->mixers = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, + pa_xfree, (pa_free_cb_t) pa_alsa_mixer_free); + u->ucm.mixers = u->mixers; /* alias */ + if (!(u->modargs = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments."); goto fail; @@ -849,7 +880,7 @@ int pa__init(pa_module *m) { u->profile_set->ignore_dB = ignore_dB; - pa_alsa_profile_set_probe(u->profile_set, u->device_id, &m->core->default_sample_spec, m->core->default_n_fragments, m->core->default_fragment_size_msec); + pa_alsa_profile_set_probe(u->profile_set, u->mixers, u->device_id, &m->core->default_sample_spec, m->core->default_n_fragments, m->core->default_fragment_size_msec); pa_alsa_profile_set_dump(u->profile_set); pa_card_new_data_init(&data); @@ -900,7 +931,8 @@ int pa__init(pa_module *m) { * results in an infinite loop of "fill buffer, handle underrun". To work * around this issue, the suspend_when_unavailable flag is used to stop * playback when the HDMI cable is unplugged. */ - if (pa_safe_streq(pa_proplist_gets(data.proplist, "alsa.driver_name"), "snd_hdmi_lpe_audio")) { + if (!u->use_ucm && + pa_safe_streq(pa_proplist_gets(data.proplist, "alsa.driver_name"), "snd_hdmi_lpe_audio")) { pa_device_port *port; void *state; @@ -948,6 +980,16 @@ int pa__init(pa_module *m) { init_profile(u); init_eld_ctls(u); + /* Remove all probe only mixers */ + if (u->mixers) { + const char *devname; + pa_alsa_mixer *pm; + void *state; + PA_HASHMAP_FOREACH_KV(devname, pm, u->mixers, state) + if (pm->used_for_probe_only) + pa_hashmap_remove_and_free(u->mixers, devname); + } + if (reserve) pa_reserve_wrapper_unref(reserve); @@ -998,10 +1040,8 @@ void pa__done(pa_module*m) { if (!(u = m->userdata)) goto finish; - if (u->mixer_fdl) - pa_alsa_fdlist_free(u->mixer_fdl); - if (u->mixer_handle) - snd_mixer_close(u->mixer_handle); + if (u->mixers) + pa_hashmap_free(u->mixers); if (u->jacks) pa_hashmap_free(u->jacks); diff --git a/src/modules/alsa/module-alsa-sink.c b/src/modules/alsa/module-alsa-sink.c index 4d4beb3..a90c5e4 100644 --- a/src/modules/alsa/module-alsa-sink.c +++ b/src/modules/alsa/module-alsa-sink.c @@ -52,7 +52,7 @@ PA_MODULE_USAGE( "tsched_buffer_size=<buffer size when using timer based scheduling> " "tsched_buffer_watermark=<lower fill watermark> " "ignore_dB=<ignore dB information from the device?> " - "control=<name of mixer control> " + "control=<name of mixer control, or name and index separated by a comma> " "rewind_safeguard=<number of bytes that cannot be rewound> " "deferred_volume=<Synchronize software and hardware volume changes to avoid momentary jumps?> " "deferred_volume_safety_margin=<usec adjustment depending on volume direction> " diff --git a/src/modules/alsa/module-alsa-source.c b/src/modules/alsa/module-alsa-source.c index 747ba93..d152283 100644 --- a/src/modules/alsa/module-alsa-source.c +++ b/src/modules/alsa/module-alsa-source.c @@ -61,7 +61,7 @@ PA_MODULE_USAGE( "tsched_buffer_size=<buffer size when using timer based scheduling> " "tsched_buffer_watermark=<upper fill watermark> " "ignore_dB=<ignore dB information from the device?> " - "control=<name of mixer control>" + "control=<name of mixer control, or name and index separated by a comma>" "deferred_volume=<Synchronize software and hardware volume changes to avoid momentary jumps?> " "deferred_volume_safety_margin=<usec adjustment depending on volume direction> " "deferred_volume_extra_delay=<usec adjustment to HW volume changes> " diff --git a/src/modules/bluetooth/meson.build b/src/modules/bluetooth/meson.build index 7b3de6b..9982cba 100644 --- a/src/modules/bluetooth/meson.build +++ b/src/modules/bluetooth/meson.build @@ -26,7 +26,7 @@ libbluez5_util = shared_library('bluez5-util', c_args : [pa_c_args, server_c_args], link_args : [nodelete_link_args], include_directories : [configinc, topinc], - dependencies : [libpulse_dep, libpulsecommon_dep, libpulsecore_dep, dbus_dep, sbc_dep], + dependencies : [libpulse_dep, libpulsecommon_dep, libpulsecore_dep, dbus_dep, sbc_dep, libintl_dep], install : true, install_rpath : privlibdir, install_dir : modlibexecdir, diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c index cff1cd6..9da5d1a 100644 --- a/src/modules/bluetooth/module-bluez5-device.c +++ b/src/modules/bluetooth/module-bluez5-device.c @@ -395,7 +395,9 @@ static int sco_process_push(struct userdata *u) { } if (!found_tstamp) { - pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!"); + PA_ONCE_BEGIN { + pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!"); + } PA_ONCE_END; tstamp = pa_rtclock_now(); } @@ -548,13 +550,29 @@ static int a2dp_process_push(struct userdata *u) { a2dp_prepare_decoder_buffer(u); for (;;) { + uint8_t aux[1024]; + struct iovec iov; + struct cmsghdr *cm; + struct msghdr m; bool found_tstamp = false; pa_usec_t tstamp; uint8_t *ptr; ssize_t l; size_t processed; - l = pa_read(u->stream_fd, u->decoder_buffer, u->decoder_buffer_size, &u->stream_write_type); + pa_zero(m); + pa_zero(aux); + pa_zero(iov); + + m.msg_iov = &iov; + m.msg_iovlen = 1; + m.msg_control = aux; + m.msg_controllen = sizeof(aux); + + iov.iov_base = u->decoder_buffer; + iov.iov_len = u->decoder_buffer_size; + + l = recvmsg(u->stream_fd, &m, 0); if (l <= 0) { @@ -574,8 +592,21 @@ static int a2dp_process_push(struct userdata *u) { pa_assert((size_t) l <= u->decoder_buffer_size); /* TODO: get timestamp from rtp */ + + for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) { + if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SO_TIMESTAMP) { + struct timeval *tv = (struct timeval*) CMSG_DATA(cm); + pa_rtclock_from_wallclock(tv); + tstamp = pa_timeval_load(tv); + found_tstamp = true; + break; + } + } + if (!found_tstamp) { - /* pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!"); */ + PA_ONCE_BEGIN { + pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!"); + } PA_ONCE_END; tstamp = pa_rtclock_now(); } diff --git a/src/modules/echo-cancel/meson.build b/src/modules/echo-cancel/meson.build index 171a414..641cd35 100644 --- a/src/modules/echo-cancel/meson.build +++ b/src/modules/echo-cancel/meson.build @@ -14,7 +14,7 @@ libwebrtc_util = shared_library('webrtc-util', libwebrtc_util_sources, cpp_args : [pa_c_args, server_c_args], include_directories : [configinc, topinc], - dependencies : [libpulse_dep, libpulsecommon_dep, libpulsecore_dep, libatomic_ops_dep, webrtc_dep], + dependencies : [libpulse_dep, libpulsecommon_dep, libpulsecore_dep, libatomic_ops_dep, webrtc_dep, libintl_dep], link_args : [nodelete_link_args, '-Wl,--unresolved-symbols=ignore-in-object-files'], install : true, install_rpath : privlibdir, diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c index 3a4c8c9..f239492 100644 --- a/src/modules/echo-cancel/module-echo-cancel.c +++ b/src/modules/echo-cancel/module-echo-cancel.c @@ -1466,6 +1466,8 @@ static bool sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) { /* Called from main context. */ static void source_output_moving_cb(pa_source_output *o, pa_source *dest) { struct userdata *u; + uint32_t idx; + pa_source_output *output; pa_source_output_assert_ref(o); pa_assert_ctl_context(); @@ -1477,6 +1479,12 @@ static void source_output_moving_cb(pa_source_output *o, pa_source *dest) { } else pa_source_set_asyncmsgq(u->source, NULL); + /* Propagate asyncmsq change to attached virtual sources */ + PA_IDXSET_FOREACH(output, u->source->outputs, idx) { + if (output->destination_source && output->moving) + output->moving(output, u->source); + } + if (u->source_auto_desc && dest) { const char *y, *z; pa_proplist *pl; diff --git a/src/modules/gsettings/meson.build b/src/modules/gsettings/meson.build index f39fb65..68a72c3 100644 --- a/src/modules/gsettings/meson.build +++ b/src/modules/gsettings/meson.build @@ -29,7 +29,7 @@ install_data('org.freedesktop.pulseaudio.gschema.xml', install_dir : join_paths(datadir, 'glib-2.0', 'schemas') ) -meson.add_install_script('post-install.sh', datadir) +meson.add_install_script('meson_post_install.py', datadir) # Conversion from GConf to GSettings diff --git a/src/modules/gsettings/meson_post_install.py b/src/modules/gsettings/meson_post_install.py new file mode 100644 index 0000000..0ddb70d --- /dev/null +++ b/src/modules/gsettings/meson_post_install.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 + +import os +import subprocess +import sys + +datadir = sys.argv[1] + +# Package managers set this so we don't need to run +if not os.environ.get('DESTDIR'): + schemadir = os.path.join(datadir, 'glib-2.0', 'schemas') + print('Compiling gsettings schemas...') + subprocess.call(['glib-compile-schemas', schemadir]) + diff --git a/src/modules/gsettings/post-install.sh b/src/modules/gsettings/post-install.sh deleted file mode 100755 index cec8b93..0000000 --- a/src/modules/gsettings/post-install.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -set -e -set -u - -DATADIR="$1" - -# Package managers set this so we don't need to run -if [ "${DESTDIR:-}" ]; then exit 0; fi - -echo "Compiling GSettings schemas..." -glib-compile-schemas "$DATADIR/glib-2.0/schemas" diff --git a/src/modules/jack/module-jackdbus-detect.c b/src/modules/jack/module-jackdbus-detect.c index 6628102..63c4307 100644 --- a/src/modules/jack/module-jackdbus-detect.c +++ b/src/modules/jack/module-jackdbus-detect.c @@ -38,6 +38,8 @@ PA_MODULE_LOAD_ONCE(true); PA_MODULE_VERSION(PACKAGE_VERSION); PA_MODULE_USAGE( "channels=<number of channels> " + "source_channels=<number of channels> " + "sink_channels=<number of channels> " "connect=<connect ports?>"); #define JACK_SERVICE_NAME "org.jackaudio.service" @@ -59,6 +61,8 @@ PA_MODULE_USAGE( static const char* const valid_modargs[] = { "channels", + "source_channels", + "sink_channels", "connect", NULL }; @@ -79,7 +83,7 @@ struct userdata { bool filter_added, match_added; bool is_service_started; bool autoconnect_ports; - uint32_t channels; + uint32_t channels[JACK_SS_COUNT]; /* Using index here protects us from module unloading without us knowing */ int jack_module_index[JACK_SS_COUNT]; }; @@ -104,8 +108,8 @@ static void ensure_ports_started(struct userdata* u) { if (!u->jack_module_index[i]) { char* args; pa_module* m; - if (u->channels > 0) { - args = pa_sprintf_malloc("connect=%s channels=%" PRIu32, pa_yes_no(u->autoconnect_ports), u->channels); + if (u->channels[i] > 0) { + args = pa_sprintf_malloc("connect=%s channels=%" PRIu32, pa_yes_no(u->autoconnect_ports), u->channels[i]); } else { args = pa_sprintf_malloc("connect=%s", pa_yes_no(u->autoconnect_ports)); } @@ -213,6 +217,8 @@ int pa__init(pa_module *m) { pa_dbus_connection *connection = NULL; struct userdata *u = NULL; pa_modargs *ma; + uint32_t channels = 0; + int i; pa_assert(m); @@ -227,17 +233,29 @@ int pa__init(pa_module *m) { u->core = m->core; u->module = m; u->autoconnect_ports = true; - u->channels = 0; if (pa_modargs_get_value_boolean(ma, "connect", &u->autoconnect_ports) < 0) { pa_log("Failed to parse connect= argument."); goto fail; } - if (pa_modargs_get_value_u32(ma, "channels", &u->channels) < 0 || !pa_channels_valid(u->channels)) { + if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || (channels > 0 && !pa_channels_valid(channels))) { pa_log("Failed to parse channels= argument."); goto fail; } + for (i = 0; i < JACK_SS_COUNT; i++) { + u->channels[i] = channels; + } + + if (pa_modargs_get_value_u32(ma, "source_channels", &u->channels[JACK_SS_SOURCE]) < 0 || (u->channels[JACK_SS_SOURCE] > 0 && !pa_channels_valid(u->channels[JACK_SS_SOURCE]))) { + pa_log("Failed to parse source_channels= argument."); + goto fail; + } + + if (pa_modargs_get_value_u32(ma, "sink_channels", &u->channels[JACK_SS_SINK]) < 0 || (u->channels[JACK_SS_SINK] > 0 && !pa_channels_valid(u->channels[JACK_SS_SINK]))) { + pa_log("Failed to parse sink_channels= argument."); + goto fail; + } if (!(connection = pa_dbus_bus_get(m->core, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) { diff --git a/src/modules/meson.build b/src/modules/meson.build index 92d5871..5f04371 100644 --- a/src/modules/meson.build +++ b/src/modules/meson.build @@ -55,7 +55,7 @@ all_modules = [ [ 'module-suspend-on-idle', 'module-suspend-on-idle.c' ], [ 'module-switch-on-connect', 'module-switch-on-connect.c' ], [ 'module-switch-on-port-available', 'module-switch-on-port-available.c' ], - [ 'module-tunnel-sink', 'module-tunnel.c', [], [], [x11_dep] ], + [ 'module-tunnel-sink', 'module-tunnel.c', [], ['-DTUNNEL_SINK=1'], [x11_dep] ], [ 'module-tunnel-sink-new', 'module-tunnel-sink-new.c' ], [ 'module-tunnel-source', 'module-tunnel.c', [], [], [x11_dep] ], [ 'module-tunnel-source-new', 'module-tunnel-source-new.c' ], @@ -284,7 +284,7 @@ foreach m : all_modules install : true, install_rpath : rpath_dirs, install_dir : modlibexecdir, - dependencies : [thread_dep, libpulse_dep, libpulsecommon_dep, libpulsecore_dep] + extra_deps, + dependencies : [thread_dep, libpulse_dep, libpulsecommon_dep, libpulsecore_dep, libintl_dep] + extra_deps, link_args : [nodelete_link_args, '-Wl,--no-undefined' ], link_with : extra_libs, name_prefix : '', diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c index 25598f7..6aeef49 100644 --- a/src/modules/module-card-restore.c +++ b/src/modules/module-card-restore.c @@ -55,7 +55,8 @@ PA_MODULE_USAGE( #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC) static const char* const valid_modargs[] = { - "restore_bluetooth_profile=<boolean>" + "restore_bluetooth_profile", + NULL }; struct userdata { diff --git a/src/modules/module-device-manager.c b/src/modules/module-device-manager.c index 15fdaaa..308ef0b 100644 --- a/src/modules/module-device-manager.c +++ b/src/modules/module-device-manager.c @@ -656,14 +656,14 @@ static void route_sink_input(struct userdata *u, pa_sink_input *si) { pa_assert(u); pa_assert(u->do_routing); - /* Don't override user or application routing requests. */ - if (si->save_sink || si->sink_requested_by_application) - return; - /* Skip this if it is already in the process of being moved anyway */ if (!si->sink) return; + /* Don't override user or application routing requests. */ + if (pa_safe_streq(si->sink->name, si->preferred_sink) || si->sink_requested_by_application) + return; + auto_filtered_prop = pa_proplist_gets(si->proplist, "module-device-manager.auto_filtered"); if (auto_filtered_prop) auto_filtered = (pa_parse_boolean(auto_filtered_prop) == 1); @@ -728,10 +728,6 @@ static void route_source_output(struct userdata *u, pa_source_output *so) { pa_assert(u); pa_assert(u->do_routing); - /* Don't override user or application routing requests. */ - if (so->save_source || so->source_requested_by_application) - return; - if (so->direct_on_input) return; @@ -739,6 +735,10 @@ static void route_source_output(struct userdata *u, pa_source_output *so) { if (!so->source) return; + /* Don't override user or application routing requests. */ + if (pa_safe_streq(so->source->name, so->preferred_source) || so->source_requested_by_application) + return; + auto_filtered_prop = pa_proplist_gets(so->proplist, "module-device-manager.auto_filtered"); if (auto_filtered_prop) auto_filtered = (pa_parse_boolean(auto_filtered_prop) == 1); @@ -1596,7 +1596,7 @@ int pa__init(pa_module*m) { } if (on_rescue) { - /* A little bit later than module-stream-restore, a little bit earlier than module-intended-roles, module-rescue-streams, ... */ + /* A little bit later than module-stream-restore, a little bit earlier than module-intended-roles, ... */ u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) sink_unlink_hook_callback, u); u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) source_unlink_hook_callback, u); } diff --git a/src/modules/module-filter-apply.c b/src/modules/module-filter-apply.c index faeedcb..c9f3f39 100644 --- a/src/modules/module-filter-apply.c +++ b/src/modules/module-filter-apply.c @@ -687,8 +687,7 @@ static pa_hook_result_t sink_unlink_cb(pa_core *core, pa_sink *sink, struct user uint32_t idx; /* Attempt to rescue any streams to the parent sink as this is likely - * the best course of action (as opposed to a generic rescue via - * module-rescue-streams */ + * the best course of action */ if (filter->sink == sink) { pa_sink_input *i; @@ -769,8 +768,7 @@ static pa_hook_result_t source_unlink_cb(pa_core *core, pa_source *source, struc uint32_t idx; /* Attempt to rescue any streams to the parent source as this is likely - * the best course of action (as opposed to a generic rescue via - * module-rescue-streams */ + * the best course of action */ if (filter->source == source) { pa_source_output *o; diff --git a/src/modules/module-intended-roles.c b/src/modules/module-intended-roles.c index adee51c..2269c0d 100644 --- a/src/modules/module-intended-roles.c +++ b/src/modules/module-intended-roles.c @@ -175,14 +175,14 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct if (si->sink == sink) continue; - if (si->save_sink) - continue; - /* Skip this if it is already in the process of being moved * anyway */ if (!si->sink) continue; + if (pa_safe_streq(si->sink->name, si->preferred_sink)) + continue; + /* It might happen that a stream and a sink are set up at the same time, in which case we want to make sure we don't interfere with that */ @@ -222,9 +222,6 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, if (so->source == source) continue; - if (so->save_source) - continue; - if (so->direct_on_input) continue; @@ -233,6 +230,9 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, if (!so->source) continue; + if (pa_safe_streq(so->source->name, so->preferred_source)) + continue; + /* It might happen that a stream and a source are set up at the same time, in which case we want to make sure we don't interfere with that */ @@ -398,7 +398,7 @@ int pa__init(pa_module*m) { } if (on_rescue) { - /* A little bit later than module-stream-restore, a little bit earlier than module-rescue-streams, ... */ + /* A little bit later than module-stream-restore, ... */ u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+10, (pa_hook_cb_t) sink_unlink_hook_callback, u); u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+10, (pa_hook_cb_t) source_unlink_hook_callback, u); } diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index ac57882..336676b 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -360,7 +360,7 @@ int pa__init(pa_module*m) { goto fail; } - u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY); + u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY | PA_SINK_DYNAMIC_LATENCY | PA_SINK_SET_FORMATS); pa_sink_new_data_done(&data); if (!u->sink) { diff --git a/src/modules/module-remap-source.c b/src/modules/module-remap-source.c index cad04af..281f413 100644 --- a/src/modules/module-remap-source.c +++ b/src/modules/module-remap-source.c @@ -252,6 +252,8 @@ static void source_output_state_change_cb(pa_source_output *o, pa_source_output_ /* Called from main thread */ static void source_output_moving_cb(pa_source_output *o, pa_source *dest) { struct userdata *u; + uint32_t idx; + pa_source_output *output; pa_source_output_assert_ref(o); pa_assert_ctl_context(); @@ -263,6 +265,12 @@ static void source_output_moving_cb(pa_source_output *o, pa_source *dest) { } else pa_source_set_asyncmsgq(u->source, NULL); + /* Propagate asyncmsq change to attached virtual sources */ + PA_IDXSET_FOREACH(output, u->source->outputs, idx) { + if (output->destination_source && output->moving) + output->moving(output, u->source); + } + if (u->auto_desc && dest) { const char *k; pa_proplist *pl; diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c index 0d8b1be..ac95896 100644 --- a/src/modules/module-rescue-streams.c +++ b/src/modules/module-rescue-streams.c @@ -24,332 +24,23 @@ #include <pulse/xmalloc.h> #include <pulsecore/core.h> -#include <pulsecore/sink-input.h> -#include <pulsecore/source-output.h> -#include <pulsecore/modargs.h> #include <pulsecore/log.h> #include <pulsecore/namereg.h> #include <pulsecore/core-util.h> PA_MODULE_AUTHOR("Lennart Poettering"); -PA_MODULE_DESCRIPTION("When a sink/source is removed, try to move its streams to the default sink/source"); +PA_MODULE_DESCRIPTION("This module is obsolete, please remove it from your configuration."); PA_MODULE_VERSION(PACKAGE_VERSION); PA_MODULE_LOAD_ONCE(true); -static const char* const valid_modargs[] = { - NULL, -}; - -struct userdata { - pa_hook_slot - *sink_unlink_slot, - *source_unlink_slot, - *sink_input_move_fail_slot, - *source_output_move_fail_slot; -}; - -static pa_source* find_source_from_port(pa_core *c, pa_device_port *port) { - pa_source *target; - uint32_t idx; - void *state; - pa_device_port *p; - - if (!port) - return NULL; - - PA_IDXSET_FOREACH(target, c->sources, idx) - PA_HASHMAP_FOREACH(p, target->ports, state) - if (port == p) - return target; - - return NULL; -} - -static pa_sink* find_sink_from_port(pa_core *c, pa_device_port *port) { - pa_sink *target; - uint32_t idx; - void *state; - pa_device_port *p; - - if (!port) - return NULL; - - PA_IDXSET_FOREACH(target, c->sinks, idx) - PA_HASHMAP_FOREACH(p, target->ports, state) - if (port == p) - return target; - - return NULL; -} - -static void build_group_ports(pa_hashmap *g_ports, pa_hashmap *s_ports) { - void *state; - pa_device_port *p; - - if (!g_ports || !s_ports) - return; - - PA_HASHMAP_FOREACH(p, s_ports, state) - pa_hashmap_put(g_ports, p, p); -} - -static pa_sink* find_evacuation_sink(pa_core *c, pa_sink_input *i, pa_sink *skip) { - pa_sink *target, *fb_sink = NULL; - uint32_t idx; - pa_hashmap *all_ports; - pa_device_port *best_port; - - pa_assert(c); - pa_assert(i); - - if (c->default_sink && c->default_sink != skip && pa_sink_input_may_move_to(i, c->default_sink)) - return c->default_sink; - - all_ports = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); - - PA_IDXSET_FOREACH(target, c->sinks, idx) { - if (target == c->default_sink) - continue; - - if (target == skip) - continue; - - if (!PA_SINK_IS_LINKED(target->state)) - continue; - - if (!pa_sink_input_may_move_to(i, target)) - continue; - - if (!fb_sink) - fb_sink = target; - - build_group_ports(all_ports, target->ports); - } - - best_port = pa_device_port_find_best(all_ports); - - pa_hashmap_free(all_ports); - - if (best_port) - target = find_sink_from_port(c, best_port); - else - target = fb_sink; - - if (!target) - pa_log_debug("No evacuation sink found."); - - return target; -} - -static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, void* userdata) { - pa_sink_input *i; - uint32_t idx; - - pa_assert(c); - pa_assert(sink); - - /* There's no point in doing anything if the core is shut down anyway */ - if (c->state == PA_CORE_SHUTDOWN) - return PA_HOOK_OK; - - if (pa_idxset_size(sink->inputs) <= 0) { - pa_log_debug("No sink inputs to move away."); - return PA_HOOK_OK; - } - - PA_IDXSET_FOREACH(i, sink->inputs, idx) { - pa_sink *target; - - if (!(target = find_evacuation_sink(c, i, sink))) - continue; - - if (pa_sink_input_move_to(i, target, false) < 0) - pa_log_info("Failed to move sink input %u \"%s\" to %s.", i->index, - pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name); - else - pa_log_info("Successfully moved sink input %u \"%s\" to %s.", i->index, - pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name); - } - - return PA_HOOK_OK; -} - -static pa_hook_result_t sink_input_move_fail_hook_callback(pa_core *c, pa_sink_input *i, void *userdata) { - pa_sink *target; - - pa_assert(c); - pa_assert(i); - - /* There's no point in doing anything if the core is shut down anyway */ - if (c->state == PA_CORE_SHUTDOWN) - return PA_HOOK_OK; - - if (!(target = find_evacuation_sink(c, i, NULL))) - return PA_HOOK_OK; - - if (pa_sink_input_finish_move(i, target, false) < 0) { - pa_log_info("Failed to move sink input %u \"%s\" to %s.", i->index, - pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name); - return PA_HOOK_OK; - - } else { - pa_log_info("Successfully moved sink input %u \"%s\" to %s.", i->index, - pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name); - return PA_HOOK_STOP; - } -} - -static pa_source* find_evacuation_source(pa_core *c, pa_source_output *o, pa_source *skip) { - pa_source *target, *fb_source = NULL; - uint32_t idx; - pa_hashmap *all_ports; - pa_device_port *best_port; - - pa_assert(c); - pa_assert(o); - - if (c->default_source && c->default_source != skip && pa_source_output_may_move_to(o, c->default_source)) - return c->default_source; - - all_ports = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); - - PA_IDXSET_FOREACH(target, c->sources, idx) { - if (target == c->default_source) - continue; - - if (target == skip) - continue; - - /* We only move to a monitor source if we're already on one */ - if (skip && !target->monitor_of != !skip->monitor_of) - continue; - - if (!PA_SOURCE_IS_LINKED(target->state)) - continue; - - if (!pa_source_output_may_move_to(o, target)) - continue; - - if (!fb_source) - fb_source = target; - - build_group_ports(all_ports, target->ports); - } - - best_port = pa_device_port_find_best(all_ports); - - pa_hashmap_free(all_ports); - - if (best_port) - target = find_source_from_port(c, best_port); - else - target = fb_source; - - if (!target) - pa_log_debug("No evacuation source found."); - - return target; -} - -static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, void* userdata) { - pa_source_output *o; - uint32_t idx; - - pa_assert(c); - pa_assert(source); - - /* There's no point in doing anything if the core is shut down anyway */ - if (c->state == PA_CORE_SHUTDOWN) - return PA_HOOK_OK; - - if (pa_idxset_size(source->outputs) <= 0) { - pa_log_debug("No source outputs to move away."); - return PA_HOOK_OK; - } - - PA_IDXSET_FOREACH(o, source->outputs, idx) { - pa_source *target; - - if (!(target = find_evacuation_source(c, o, source))) - continue; - - if (pa_source_output_move_to(o, target, false) < 0) - pa_log_info("Failed to move source output %u \"%s\" to %s.", o->index, - pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), target->name); - else - pa_log_info("Successfully moved source output %u \"%s\" to %s.", o->index, - pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), target->name); - } - - return PA_HOOK_OK; -} - -static pa_hook_result_t source_output_move_fail_hook_callback(pa_core *c, pa_source_output *i, void *userdata) { - pa_source *target; - - pa_assert(c); - pa_assert(i); - - /* There's no point in doing anything if the core is shut down anyway */ - if (c->state == PA_CORE_SHUTDOWN) - return PA_HOOK_OK; - - if (!(target = find_evacuation_source(c, i, NULL))) - return PA_HOOK_OK; - - if (pa_source_output_finish_move(i, target, false) < 0) { - pa_log_info("Failed to move source output %u \"%s\" to %s.", i->index, - pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name); - return PA_HOOK_OK; - - } else { - pa_log_info("Successfully moved source output %u \"%s\" to %s.", i->index, - pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name); - return PA_HOOK_STOP; - } -} int pa__init(pa_module*m) { - pa_modargs *ma; - struct userdata *u; pa_assert(m); - if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("Failed to parse module arguments"); - return -1; - } - - m->userdata = u = pa_xnew(struct userdata, 1); - - /* A little bit later than module-stream-restore, module-intended-roles... */ - u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+20, (pa_hook_cb_t) sink_unlink_hook_callback, u); - u->source_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+20, (pa_hook_cb_t) source_unlink_hook_callback, u); + pa_log("module-rescue-stream is obsolete and should no longer be loaded. Please remove it from your configuration."); - u->sink_input_move_fail_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], PA_HOOK_LATE+20, (pa_hook_cb_t) sink_input_move_fail_hook_callback, u); - u->source_output_move_fail_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FAIL], PA_HOOK_LATE+20, (pa_hook_cb_t) source_output_move_fail_hook_callback, u); + pa_module_unload_request(m, false); - pa_modargs_free(ma); return 0; } - -void pa__done(pa_module*m) { - struct userdata *u; - - pa_assert(m); - - if (!(u = m->userdata)) - return; - - if (u->sink_unlink_slot) - pa_hook_slot_free(u->sink_unlink_slot); - if (u->source_unlink_slot) - pa_hook_slot_free(u->source_unlink_slot); - - if (u->sink_input_move_fail_slot) - pa_hook_slot_free(u->sink_input_move_fail_slot); - if (u->source_output_move_fail_slot) - pa_hook_slot_free(u->source_output_move_fail_slot); - - pa_xfree(u); -} diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index cbef478..6a42466 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -64,8 +64,8 @@ PA_MODULE_USAGE( "restore_device=<Save/restore sinks/sources?> " "restore_volume=<Save/restore volumes?> " "restore_muted=<Save/restore muted states?> " - "on_hotplug=<When new device becomes available, recheck streams?> " - "on_rescue=<When device becomes unavailable, recheck streams?> " + "on_hotplug=<This argument is obsolete, please remove it from configuration> " + "on_rescue=<This argument is obsolete, please remove it from configuration> " "fallback_table=<filename>"); #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC) @@ -95,10 +95,6 @@ struct userdata { *sink_input_fixate_hook_slot, *source_output_new_hook_slot, *source_output_fixate_hook_slot, - *sink_put_hook_slot, - *source_put_hook_slot, - *sink_unlink_hook_slot, - *source_unlink_hook_slot, *connection_unlink_hook_slot; pa_time_event *save_time_event; pa_database* database; @@ -106,8 +102,6 @@ struct userdata { bool restore_device:1; bool restore_volume:1; bool restore_muted:1; - bool on_hotplug:1; - bool on_rescue:1; pa_native_protocol *protocol; pa_idxset *subscribed; @@ -1311,19 +1305,24 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 mute_updated = !created_new_entry && (!old->muted_valid || entry->muted != old->muted); } - if (sink_input->save_sink) { + if (sink_input->preferred_sink != NULL || !created_new_entry) { + pa_sink *s = NULL; + pa_xfree(entry->device); - entry->device = pa_xstrdup(sink_input->sink->name); + entry->device = pa_xstrdup(sink_input->preferred_sink); entry->device_valid = true; - - device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry->device, old->device)); - if (sink_input->sink->card) { - pa_xfree(entry->card); - entry->card = pa_xstrdup(sink_input->sink->card->name); + if (!entry->device) + entry->device_valid = false; + + device_updated = !created_new_entry && !pa_safe_streq(entry->device, old->device); + pa_xfree(entry->card); + entry->card = NULL; + entry->card_valid = false; + if (entry->device_valid && (s = pa_namereg_get(c, entry->device, PA_NAMEREG_SINK)) && s->card) { + entry->card = pa_xstrdup(s->card->name); entry->card_valid = true; } } - } else { pa_source_output *source_output; @@ -1366,16 +1365,22 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 mute_updated = !created_new_entry && (!old->muted_valid || entry->muted != old->muted); } - if (source_output->save_source) { + if (source_output->preferred_source != NULL || !created_new_entry) { + pa_source *s = NULL; + pa_xfree(entry->device); - entry->device = pa_xstrdup(source_output->source->name); + entry->device = pa_xstrdup(source_output->preferred_source); entry->device_valid = true; - device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry->device, old->device)); + if (!entry->device) + entry->device_valid = false; - if (source_output->source->card) { - pa_xfree(entry->card); - entry->card = pa_xstrdup(source_output->source->card->name); + device_updated = !created_new_entry && !pa_safe_streq(entry->device, old->device); + pa_xfree(entry->card); + entry->card = NULL; + entry->card_valid = false; + if (entry->device_valid && (s = pa_namereg_get(c, entry->device, PA_NAMEREG_SOURCE)) && s->card) { + entry->card = pa_xstrdup(s->card->name); entry->card_valid = true; } } @@ -1634,209 +1639,6 @@ static pa_hook_result_t source_output_fixate_hook_callback(pa_core *c, pa_source return PA_HOOK_OK; } -static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) { - pa_sink_input *si; - uint32_t idx; - - pa_assert(c); - pa_assert(sink); - pa_assert(u); - pa_assert(u->on_hotplug && u->restore_device); - - PA_IDXSET_FOREACH(si, c->sink_inputs, idx) { - char *name; - struct entry *e; - - if (si->sink == sink) - continue; - - if (si->save_sink) - continue; - - /* Skip this if it is already in the process of being moved - * anyway */ - if (!si->sink) - continue; - - /* Skip this sink input if it is connecting a filter sink to - * the master */ - if (si->origin_sink) - continue; - - /* It might happen that a stream and a sink are set up at the - same time, in which case we want to make sure we don't - interfere with that */ - if (!PA_SINK_INPUT_IS_LINKED(si->state)) - continue; - - if (!(name = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY))) - continue; - - if ((e = entry_read(u, name))) { - if (e->device_valid && pa_streq(e->device, sink->name)) - pa_sink_input_move_to(si, sink, true); - - entry_free(e); - } - - pa_xfree(name); - } - - return PA_HOOK_OK; -} - -static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, struct userdata *u) { - pa_source_output *so; - uint32_t idx; - - pa_assert(c); - pa_assert(source); - pa_assert(u); - pa_assert(u->on_hotplug && u->restore_device); - - PA_IDXSET_FOREACH(so, c->source_outputs, idx) { - char *name; - struct entry *e; - - if (so->source == source) - continue; - - if (so->save_source) - continue; - - if (so->direct_on_input) - continue; - - /* Skip this if it is already in the process of being moved anyway */ - if (!so->source) - continue; - - /* Skip this source output if it is connecting a filter source to - * the master */ - if (so->destination_source) - continue; - - /* It might happen that a stream and a source are set up at the - same time, in which case we want to make sure we don't - interfere with that */ - if (!PA_SOURCE_OUTPUT_IS_LINKED(so->state)) - continue; - - if (!(name = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY))) - continue; - - if ((e = entry_read(u, name))) { - if (e->device_valid && pa_streq(e->device, source->name)) - pa_source_output_move_to(so, source, true); - - entry_free(e); - } - - pa_xfree(name); - } - - return PA_HOOK_OK; -} - -static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) { - pa_sink_input *si; - uint32_t idx; - - pa_assert(c); - pa_assert(sink); - pa_assert(u); - pa_assert(u->on_rescue && u->restore_device); - - /* There's no point in doing anything if the core is shut down anyway */ - if (c->state == PA_CORE_SHUTDOWN) - return PA_HOOK_OK; - - PA_IDXSET_FOREACH(si, sink->inputs, idx) { - char *name; - struct entry *e; - - if (!si->sink) - continue; - - /* Skip this sink input if it is connecting a filter sink to - * the master */ - if (si->origin_sink) - continue; - - if (!(name = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY))) - continue; - - if ((e = entry_read(u, name))) { - - if (e->device_valid) { - pa_sink *d; - - if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) && - d != sink && - PA_SINK_IS_LINKED(d->state)) - pa_sink_input_move_to(si, d, true); - } - - entry_free(e); - } - - pa_xfree(name); - } - - return PA_HOOK_OK; -} - -static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) { - pa_source_output *so; - uint32_t idx; - - pa_assert(c); - pa_assert(source); - pa_assert(u); - pa_assert(u->on_rescue && u->restore_device); - - /* There's no point in doing anything if the core is shut down anyway */ - if (c->state == PA_CORE_SHUTDOWN) - return PA_HOOK_OK; - - PA_IDXSET_FOREACH(so, source->outputs, idx) { - char *name; - struct entry *e; - - if (so->direct_on_input) - continue; - - if (!so->source) - continue; - - /* Skip this source output if it is connecting a filter source to - * the master */ - if (so->destination_source) - continue; - - if (!(name = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY))) - continue; - - if ((e = entry_read(u, name))) { - - if (e->device_valid) { - pa_source *d; - - if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) && - d != source && - PA_SOURCE_IS_LINKED(d->state)) - pa_source_output_move_to(so, d, true); - } - - entry_free(e); - } - - pa_xfree(name); - } - - return PA_HOOK_OK; -} - static int fill_db(struct userdata *u, const char *filename) { FILE *f; int n = 0; @@ -1951,21 +1753,16 @@ static void entry_apply(struct userdata *u, const char *name, struct entry *e) { if (u->restore_device) { if (!e->device_valid) { - if (si->save_sink) { + if (si->preferred_sink != NULL) { pa_log_info("Ensuring device is not saved for stream %s.", name); /* If the device is not valid we should make sure the - save flag is cleared as the user may have specifically + preferred_sink is cleared as the user may have specifically removed the sink element from the rule. */ - si->save_sink = false; - /* This is cheating a bit. The sink input itself has not changed - but the rules governing its routing have, so we fire this event - such that other routing modules (e.g. module-device-manager) - will pick up the change and reapply their routing */ - pa_subscription_post(si->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, si->index); + pa_sink_input_set_preferred_sink(si, NULL); } } else if ((s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SINK))) { pa_log_info("Restoring device for stream %s.", name); - pa_sink_input_move_to(si, s, true); + pa_sink_input_set_preferred_sink(si, s); } } } @@ -1999,21 +1796,16 @@ static void entry_apply(struct userdata *u, const char *name, struct entry *e) { if (u->restore_device) { if (!e->device_valid) { - if (so->save_source) { + if (so->preferred_source != NULL) { pa_log_info("Ensuring device is not saved for stream %s.", name); /* If the device is not valid we should make sure the - save flag is cleared as the user may have specifically + preferred_source is cleared as the user may have specifically removed the source element from the rule. */ - so->save_source = false; - /* This is cheating a bit. The source output itself has not changed - but the rules governing its routing have, so we fire this event - such that other routing modules (e.g. module-device-manager) - will pick up the change and reapply their routing */ - pa_subscription_post(so->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, so->index); + pa_source_output_set_preferred_source(so, NULL); } } else if ((s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SOURCE))) { pa_log_info("Restoring device for stream %s.", name); - pa_source_output_move_to(so, s, true); + pa_source_output_set_preferred_source(so, s); } } } @@ -2152,7 +1944,7 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio } while (!pa_tagstruct_eof(t)) { - const char *name, *device; + const char *name, *device, *client_name; bool muted; struct entry *entry; #ifdef HAVE_DBUS @@ -2193,7 +1985,20 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio entry_free(entry); goto fail; } - + /* When users select an output device from gnome-control-center, the gnome-control-center will change all entries + * in the database to bind the sink of this output device, this is not correct since at this moment, the sink is + * default_sink and we shouldn't bind a stream to default_sink via preferred_sink or database. This also applies + * to source, default_source and preferred_source. + * After gnome-control-center fix the issue, let us remove this code */ + client_name = pa_strnull(pa_proplist_gets(pa_native_connection_get_client(c)->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)); + if (pa_safe_streq(client_name, "gnome-control-center")) { + if (entry->device_valid && ((m->core->default_sink && pa_safe_streq(device, m->core->default_sink->name)) || + (m->core->default_source && pa_safe_streq(device, m->core->default_source->name)))) { + entry_free(entry); + pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply); + return 0; + } + } #ifdef HAVE_DBUS old = entry_read(u, name); #endif @@ -2415,7 +2220,8 @@ int pa__init(pa_module*m) { pa_sink_input *si; pa_source_output *so; uint32_t idx; - bool restore_device = true, restore_volume = true, restore_muted = true, on_hotplug = true, on_rescue = true; + bool restore_device = true, restore_volume = true, restore_muted = true; + #ifdef HAVE_DBUS pa_datum key; bool done; @@ -2430,13 +2236,15 @@ int pa__init(pa_module*m) { if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 || pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 || - pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 || - pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 || - pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) { - pa_log("restore_device=, restore_volume=, restore_muted=, on_hotplug= and on_rescue= expect boolean arguments"); + pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0) { + pa_log("restore_device=, restore_volume= and restore_muted= expect boolean arguments"); goto fail; } + if (pa_modargs_get_value(ma, "on_hotplug", NULL) != NULL || + pa_modargs_get_value(ma, "on_rescue", NULL) != NULL) + pa_log("on_hotplug and on_rescue are obsolete arguments, please remove them from your configuration"); + if (!restore_muted && !restore_volume && !restore_device) pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring device enabled!"); @@ -2446,8 +2254,6 @@ int pa__init(pa_module*m) { u->restore_device = restore_device; u->restore_volume = restore_volume; u->restore_muted = restore_muted; - u->on_hotplug = on_hotplug; - u->on_rescue = on_rescue; u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); u->protocol = pa_native_protocol_get(m->core); @@ -2463,18 +2269,6 @@ int pa__init(pa_module*m) { pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_new_hook_callback, u); } - if (restore_device && on_hotplug) { - /* A little bit earlier than module-intended-roles ... */ - pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE, (pa_hook_cb_t) sink_put_hook_callback, u); - pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE, (pa_hook_cb_t) source_put_hook_callback, u); - } - - if (restore_device && on_rescue) { - /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */ - pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_unlink_hook_callback, u); - pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) source_unlink_hook_callback, u); - } - if (restore_volume || restore_muted) { pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_fixate_hook_callback, u); pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_fixate_hook_callback, u); diff --git a/src/modules/module-switch-on-connect.c b/src/modules/module-switch-on-connect.c index 9077eae..950ecbe 100644 --- a/src/modules/module-switch-on-connect.c +++ b/src/modules/module-switch-on-connect.c @@ -33,6 +33,12 @@ #include <pulsecore/namereg.h> #include <pulsecore/core-util.h> +/* Ignore HDMI devices by default. HDMI monitors don't necessarily have audio + * output on them, and even if they do, waking up from sleep or changing + * monitor resolution may appear as a plugin event, which causes trouble if the + * user doesn't want to use the monitor for audio. */ +#define DEFAULT_BLACKLIST "hdmi" + PA_MODULE_AUTHOR("Michael Terry"); PA_MODULE_DESCRIPTION("When a sink/source is added, switch to it or conditionally switch to it"); PA_MODULE_VERSION(PACKAGE_VERSION); @@ -40,23 +46,23 @@ PA_MODULE_LOAD_ONCE(true); PA_MODULE_USAGE( "only_from_unavailable=<boolean, only switch from unavailable ports> " "ignore_virtual=<boolean, ignore new virtual sinks and sources, defaults to true> " + "blacklist=<regex, ignore matching devices> " ); static const char* const valid_modargs[] = { "only_from_unavailable", "ignore_virtual", + "blacklist", NULL, }; struct userdata { bool only_from_unavailable; bool ignore_virtual; + char *blacklist; }; static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void* userdata) { - pa_sink_input *i; - uint32_t idx; - pa_sink *old_default_sink; const char *s; struct userdata *u = userdata; @@ -80,6 +86,12 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void* } } + /* Ignore sinks matching the blacklist regex */ + if (u->blacklist && (pa_match(u->blacklist, sink->name) > 0)) { + pa_log_info("Refusing to switch to blacklisted sink %s", sink->name); + return PA_HOOK_OK; + } + /* Ignore virtual sinks if not configured otherwise on the command line */ if (u->ignore_virtual && !(sink->flags & PA_SINK_HARDWARE)) { pa_log_debug("Refusing to switch to virtual sink"); @@ -103,36 +115,13 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void* return PA_HOOK_OK; } - old_default_sink = c->default_sink; - /* Actually do the switch to the new sink */ pa_core_set_configured_default_sink(c, sink->name); - /* Now move all old inputs over */ - if (pa_idxset_size(old_default_sink->inputs) <= 0) { - pa_log_debug("No sink inputs to move away."); - return PA_HOOK_OK; - } - - PA_IDXSET_FOREACH(i, old_default_sink->inputs, idx) { - if (i->save_sink || !PA_SINK_INPUT_IS_LINKED(i->state)) - continue; - - if (pa_sink_input_move_to(i, sink, false) < 0) - pa_log_info("Failed to move sink input %u \"%s\" to %s.", i->index, - pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), sink->name); - else - pa_log_info("Successfully moved sink input %u \"%s\" to %s.", i->index, - pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), sink->name); - } - return PA_HOOK_OK; } static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, void* userdata) { - pa_source_output *o; - uint32_t idx; - pa_source *old_default_source; const char *s; struct userdata *u = userdata; @@ -157,6 +146,12 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, return PA_HOOK_OK; } + /* Ignore sources matching the blacklist regex */ + if (u->blacklist && (pa_match(u->blacklist, source->name) > 0)) { + pa_log_info("Refusing to switch to blacklisted source %s", source->name); + return PA_HOOK_OK; + } + /* Ignore virtual sources if not configured otherwise on the command line */ if (u->ignore_virtual && !(source->flags & PA_SOURCE_HARDWARE)) { pa_log_debug("Refusing to switch to virtual source"); @@ -180,29 +175,9 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, return PA_HOOK_OK; } - old_default_source = c->default_source; - /* Actually do the switch to the new source */ pa_core_set_configured_default_source(c, source->name); - /* Now move all old outputs over */ - if (pa_idxset_size(old_default_source->outputs) <= 0) { - pa_log_debug("No source outputs to move away."); - return PA_HOOK_OK; - } - - PA_IDXSET_FOREACH(o, old_default_source->outputs, idx) { - if (o->save_source || !PA_SOURCE_OUTPUT_IS_LINKED(o->state)) - continue; - - if (pa_source_output_move_to(o, source, false) < 0) - pa_log_info("Failed to move source output %u \"%s\" to %s.", o->index, - pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), source->name); - else - pa_log_info("Successfully moved source output %u \"%s\" to %s.", o->index, - pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), source->name); - } - return PA_HOOK_OK; } @@ -219,7 +194,6 @@ int pa__init(pa_module*m) { m->userdata = u = pa_xnew0(struct userdata, 1); - /* A little bit later than module-rescue-streams... */ pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE+30, (pa_hook_cb_t) sink_put_hook_callback, u); pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE+20, (pa_hook_cb_t) source_put_hook_callback, u); @@ -234,6 +208,20 @@ int pa__init(pa_module*m) { goto fail; } + u->blacklist = pa_xstrdup(pa_modargs_get_value(ma, "blacklist", DEFAULT_BLACKLIST)); + + /* An empty string disables all blacklisting. */ + if (!*u->blacklist) { + pa_xfree(u->blacklist); + u->blacklist = NULL; + } + + if (u->blacklist != NULL && !pa_is_regex_valid(u->blacklist)) { + pa_log_error("A blacklist pattern was provided but is not a valid regex"); + pa_xfree(u->blacklist); + goto fail; + } + pa_modargs_free(ma); return 0; @@ -254,5 +242,8 @@ void pa__done(pa_module*m) { if (!(u = m->userdata)) return; + if (u->blacklist) + pa_xfree(u->blacklist); + pa_xfree(u); } diff --git a/src/modules/module-virtual-source.c b/src/modules/module-virtual-source.c index 0c98178..22566b0 100644 --- a/src/modules/module-virtual-source.c +++ b/src/modules/module-virtual-source.c @@ -152,18 +152,6 @@ static void sink_update_requested_latency_cb(pa_sink *s) { } /* Called from I/O thread context */ -static void sink_request_rewind_cb(pa_sink *s) { - struct userdata *u; - - pa_sink_assert_ref(s); - pa_assert_se(u = s->userdata); - - /* Do nothing */ - pa_sink_process_rewind(u->sink, 0); - -} - -/* Called from I/O thread context */ static int source_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { struct userdata *u = PA_SOURCE(o)->userdata; @@ -458,6 +446,8 @@ static void source_output_kill_cb(pa_source_output *o) { /* Called from main thread */ static void source_output_moving_cb(pa_source_output *o, pa_source *dest) { struct userdata *u; + uint32_t idx; + pa_source_output *output; pa_source_output_assert_ref(o); pa_assert_ctl_context(); @@ -469,6 +459,12 @@ static void source_output_moving_cb(pa_source_output *o, pa_source *dest) { } else pa_source_set_asyncmsgq(u->source, NULL); + /* Propagate asyncmsq change to attached virtual sources */ + PA_IDXSET_FOREACH(output, u->source->outputs, idx) { + if (output->destination_source && output->moving) + output->moving(output, u->source); + } + if (u->auto_desc && dest) { const char *z; pa_proplist *pl; @@ -675,7 +671,6 @@ int pa__init(pa_module*m) { u->sink->parent.process_msg = sink_process_msg_cb; u->sink->update_requested_latency = sink_update_requested_latency_cb; - u->sink->request_rewind = sink_request_rewind_cb; u->sink->set_state_in_main_thread = sink_set_state_in_main_thread_cb; u->sink->userdata = u; @@ -685,7 +680,7 @@ int pa__init(pa_module*m) { /* FIXME: no idea what I am doing here */ u->block_usec = BLOCK_USEC; nbytes = pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec); - pa_sink_set_max_rewind(u->sink, nbytes); + pa_sink_set_max_rewind(u->sink, 0); pa_sink_set_max_request(u->sink, nbytes); pa_sink_put(u->sink); diff --git a/src/modules/module-virtual-surround-sink.c b/src/modules/module-virtual-surround-sink.c index d8e0fd9..c321073 100644 --- a/src/modules/module-virtual-surround-sink.c +++ b/src/modules/module-virtual-surround-sink.c @@ -786,7 +786,7 @@ int pa__init(pa_module*m) { u->sink->input_to_master = u->sink_input; pa_sink_input_get_silence(u->sink_input, &silence); - u->memblockq = pa_memblockq_new("module-virtual-surround-sink memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0, &sink_input_ss, 1, 1, 0, &silence); + u->memblockq = pa_memblockq_new("module-virtual-surround-sink memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0, &ss, 1, 1, 0, &silence); pa_memblock_unref(silence.memblock); /* resample hrir */ diff --git a/src/modules/raop/meson.build b/src/modules/raop/meson.build index e98bb45..533580c 100644 --- a/src/modules/raop/meson.build +++ b/src/modules/raop/meson.build @@ -23,7 +23,7 @@ libraop = shared_library('raop', c_args : [pa_c_args, server_c_args], link_args : [nodelete_link_args], include_directories : [configinc, topinc], - dependencies : [libpulse_dep, libpulsecommon_dep, libpulsecore_dep, librtp_dep, openssl_dep], + dependencies : [libpulse_dep, libpulsecommon_dep, libpulsecore_dep, librtp_dep, openssl_dep, libintl_dep], install : true, install_rpath : rpath_dirs, install_dir : modlibexecdir, diff --git a/src/modules/raop/module-raop-sink.c b/src/modules/raop/module-raop-sink.c index 745b1d0..393341a 100644 --- a/src/modules/raop/module-raop-sink.c +++ b/src/modules/raop/module-raop-sink.c @@ -58,9 +58,11 @@ static const char* const valid_modargs[] = { "format", "rate", "channels", + "channel_map", "username", "password", "latency_msec", + "autoreconnect", NULL }; diff --git a/src/modules/raop/raop-client.c b/src/modules/raop/raop-client.c index 4887e0f..9a026db 100644 --- a/src/modules/raop/raop-client.c +++ b/src/modules/raop/raop-client.c @@ -95,6 +95,7 @@ struct pa_raop_client { pa_rtsp_client *rtsp; char *sci, *sid; char *password; + bool autoreconnect; pa_raop_protocol_t protocol; pa_raop_encryption_t encryption; @@ -362,13 +363,12 @@ static ssize_t send_tcp_audio_packet(pa_raop_client *c, pa_memchunk *block, size ssize_t written = -1; size_t done = 0; - if (!(packet = pa_raop_packet_buffer_retrieve(c->pbuf, c->seq))) - return -1; + packet = pa_raop_packet_buffer_retrieve(c->pbuf, c->seq); - if (packet->length <= 0) { + if (!packet || (packet && packet->length <= 0)) { pa_assert(block->index == offset); - if (!(packet = pa_raop_packet_buffer_prepare(c->pbuf, c->seq + 1, max))) + if (!(packet = pa_raop_packet_buffer_prepare(c->pbuf, c->seq, max))) return -1; packet->index = 0; @@ -1326,10 +1326,11 @@ static void rtsp_auth_cb(pa_rtsp_client *rtsp, pa_rtsp_state_t state, pa_rtsp_st c->password = NULL; } - if (c->state_callback) - c->state_callback((int) PA_RAOP_AUTHENTICATED, c->state_userdata); pa_rtsp_client_free(c->rtsp); c->rtsp = NULL; + /* Ensure everything is cleaned before calling the callback, otherwise it may raise a crash */ + if (c->state_callback) + c->state_callback((int) PA_RAOP_AUTHENTICATED, c->state_userdata); waiting = false; break; @@ -1379,8 +1380,39 @@ static void rtsp_auth_cb(pa_rtsp_client *rtsp, pa_rtsp_state_t state, pa_rtsp_st } } + +void pa_raop_client_disconnect(pa_raop_client *c) { + c->is_recording = false; + + if (c->tcp_sfd >= 0) + pa_close(c->tcp_sfd); + c->tcp_sfd = -1; + + if (c->udp_sfd >= 0) + pa_close(c->udp_sfd); + c->udp_sfd = -1; + + /* Polling sockets will be closed by sink */ + c->udp_cfd = c->udp_tfd = -1; + c->tcp_sfd = -1; + + pa_log_error("RTSP control channel closed (disconnected)"); + + if (c->rtsp) + pa_rtsp_client_free(c->rtsp); + if (c->sid) + pa_xfree(c->sid); + c->rtsp = NULL; + c->sid = NULL; + + if (c->state_callback) + c->state_callback((int) PA_RAOP_DISCONNECTED, c->state_userdata); + +} + + pa_raop_client* pa_raop_client_new(pa_core *core, const char *host, pa_raop_protocol_t protocol, - pa_raop_encryption_t encryption, pa_raop_codec_t codec) { + pa_raop_encryption_t encryption, pa_raop_codec_t codec, bool autoreconnect) { pa_raop_client *c; pa_parsed_address a; @@ -1408,6 +1440,7 @@ pa_raop_client* pa_raop_client_new(pa_core *core, const char *host, pa_raop_prot c->rtsp = NULL; c->sci = c->sid = NULL; c->password = NULL; + c->autoreconnect = autoreconnect; c->protocol = protocol; c->encryption = encryption; @@ -1473,7 +1506,7 @@ int pa_raop_client_authenticate (pa_raop_client *c, const char *password) { c->password = NULL; if (password) c->password = pa_xstrdup(password); - c->rtsp = pa_rtsp_client_new(c->core->mainloop, c->host, c->port, DEFAULT_USER_AGENT); + c->rtsp = pa_rtsp_client_new(c->core->mainloop, c->host, c->port, DEFAULT_USER_AGENT, c->autoreconnect); pa_assert(c->rtsp); @@ -1502,7 +1535,7 @@ int pa_raop_client_announce(pa_raop_client *c) { return 1; } - c->rtsp = pa_rtsp_client_new(c->core->mainloop, c->host, c->port, DEFAULT_USER_AGENT); + c->rtsp = pa_rtsp_client_new(c->core->mainloop, c->host, c->port, DEFAULT_USER_AGENT, c->autoreconnect); pa_assert(c->rtsp); @@ -1545,7 +1578,6 @@ bool pa_raop_client_can_stream(pa_raop_client *c) { pa_assert(c); if (!c->rtsp || !c->sci) { - pa_log_debug("Can't stream, connection not established yet..."); return false; } @@ -1565,6 +1597,10 @@ bool pa_raop_client_can_stream(pa_raop_client *c) { return false; } +bool pa_raop_client_is_recording(pa_raop_client *c) { + return c->is_recording; +} + int pa_raop_client_stream(pa_raop_client *c) { int rv = 0; @@ -1725,6 +1761,10 @@ bool pa_raop_client_register_pollfd(pa_raop_client *c, pa_rtpoll *poll, pa_rtpol return oob; } +bool pa_raop_client_is_timing_fd(pa_raop_client *c, const int fd) { + return fd == c->udp_tfd; +} + pa_volume_t pa_raop_client_adjust_volume(pa_raop_client *c, pa_volume_t volume) { double minv, maxv; diff --git a/src/modules/raop/raop-client.h b/src/modules/raop/raop-client.h index 72e6018..faec01e 100644 --- a/src/modules/raop/raop-client.h +++ b/src/modules/raop/raop-client.h @@ -57,7 +57,7 @@ typedef enum pa_raop_state { } pa_raop_state_t; pa_raop_client* pa_raop_client_new(pa_core *core, const char *host, pa_raop_protocol_t protocol, - pa_raop_encryption_t encryption, pa_raop_codec_t codec); + pa_raop_encryption_t encryption, pa_raop_codec_t codec, bool autoreconnect); void pa_raop_client_free(pa_raop_client *c); int pa_raop_client_authenticate(pa_raop_client *c, const char *password); @@ -65,14 +65,17 @@ bool pa_raop_client_is_authenticated(pa_raop_client *c); int pa_raop_client_announce(pa_raop_client *c); bool pa_raop_client_is_alive(pa_raop_client *c); +bool pa_raop_client_is_recording(pa_raop_client *c); bool pa_raop_client_can_stream(pa_raop_client *c); int pa_raop_client_stream(pa_raop_client *c); int pa_raop_client_set_volume(pa_raop_client *c, pa_volume_t volume); int pa_raop_client_flush(pa_raop_client *c); int pa_raop_client_teardown(pa_raop_client *c); +void pa_raop_client_disconnect(pa_raop_client *c); void pa_raop_client_get_frames_per_block(pa_raop_client *c, size_t *size); bool pa_raop_client_register_pollfd(pa_raop_client *c, pa_rtpoll *poll, pa_rtpoll_item **poll_item); +bool pa_raop_client_is_timing_fd(pa_raop_client *c, const int fd); pa_volume_t pa_raop_client_adjust_volume(pa_raop_client *c, pa_volume_t volume); void pa_raop_client_handle_oob_packet(pa_raop_client *c, const int fd, const uint8_t packet[], ssize_t size); ssize_t pa_raop_client_send_audio_packet(pa_raop_client *c, pa_memchunk *block, size_t offset); diff --git a/src/modules/raop/raop-sink.c b/src/modules/raop/raop-sink.c index d5ce6dc..aa66af2 100644 --- a/src/modules/raop/raop-sink.c +++ b/src/modules/raop/raop-sink.c @@ -59,12 +59,16 @@ #include <pulsecore/thread-mq.h> #include <pulsecore/poll.h> #include <pulsecore/rtpoll.h> +#include <pulsecore/core-rtclock.h> #include <pulsecore/time-smoother.h> #include "raop-sink.h" #include "raop-client.h" #include "raop-util.h" +#define UDP_TIMING_PACKET_LOSS_MAX (30 * PA_USEC_PER_SEC) +#define UDP_TIMING_PACKET_DISCONNECT_CYCLE 3 + struct userdata { pa_core *core; pa_module *module; @@ -78,11 +82,16 @@ struct userdata { bool oob; pa_raop_client *raop; + char *server; pa_raop_protocol_t protocol; pa_raop_encryption_t encryption; pa_raop_codec_t codec; + bool autoreconnect; + /* if true, behaves like a null-sink when disconnected */ + bool autonull; size_t block_size; + pa_usec_t block_usec; pa_memchunk memchunk; pa_usec_t delay; @@ -91,10 +100,13 @@ struct userdata { uint64_t write_count; uint32_t latency; + /* Consider as first I/O thread iteration, can be switched to true in autoreconnect mode */ + bool first; }; enum { - PA_SINK_MESSAGE_SET_RAOP_STATE = PA_SINK_MESSAGE_MAX + PA_SINK_MESSAGE_SET_RAOP_STATE = PA_SINK_MESSAGE_MAX, + PA_SINK_MESSAGE_DISCONNECT_REQUEST }; static void userdata_free(struct userdata *u); @@ -136,10 +148,23 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse pa_assert(u->raop); switch (code) { + /* Exception : for this message, we are in main thread, msg sent from the IO/thread + Done here, as alloc/free of rtsp_client is also done in this thread for other cases */ + case PA_SINK_MESSAGE_DISCONNECT_REQUEST: { + if (u->sink->state == PA_SINK_RUNNING) { + /* Disconnect raop client, and restart the whole chain since + * the authentication token might be outdated */ + pa_raop_client_disconnect(u->raop); + pa_raop_client_authenticate(u->raop, NULL); + } + + return 0; + } + case PA_SINK_MESSAGE_GET_LATENCY: { int64_t r = 0; - if (pa_raop_client_can_stream(u->raop)) + if (u->autonull || pa_raop_client_can_stream(u->raop)) r = sink_get_latency(u); *((int64_t*) data) = r; @@ -154,6 +179,17 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse pa_module_unload_request(u->module, true); } + if (u->autoreconnect && u->sink->state == PA_SINK_RUNNING) { + pa_usec_t now; + now = pa_rtclock_now(); + pa_smoother_reset(u->smoother, now, false); + + if (!pa_raop_client_is_alive(u->raop)) { + /* Connecting will trigger a RECORD and start steaming */ + pa_raop_client_announce(u->raop); + } + } + return 0; } @@ -169,9 +205,10 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse pa_usec_t now; now = pa_rtclock_now(); - pa_rtpoll_set_timer_absolute(u->rtpoll, now); u->write_count = 0; u->start = now; + u->first = true; + pa_rtpoll_set_timer_absolute(u->rtpoll, now); if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { /* Our stream has been suspended so we just flush it... */ @@ -180,6 +217,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse } else { /* Set the initial volume */ sink_set_volume_cb(u->sink); + pa_sink_process_msg(o, PA_SINK_MESSAGE_SET_VOLUME, data, offset, chunk); } return 0; @@ -204,10 +242,22 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse u->rtpoll_item = NULL; } - if (u->sink->thread_info.state == PA_SINK_SUSPENDED) + if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { pa_rtpoll_set_timer_disabled(u->rtpoll); - else if (u->sink->thread_info.state != PA_SINK_IDLE) - pa_module_unload_request(u->module, true); + + return 0; + } + + if (u->autoreconnect) { + if (u->sink->thread_info.state != PA_SINK_IDLE) { + if (!u->autonull) + pa_rtpoll_set_timer_disabled(u->rtpoll); + pa_raop_client_authenticate(u->raop, NULL); + } + } else { + if (u->sink->thread_info.state != PA_SINK_IDLE) + pa_module_unload_request(u->module, true); + } return 0; } @@ -264,10 +314,19 @@ static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, now = pa_rtclock_now(); pa_smoother_reset(u->smoother, now, false); + /* If autonull is enabled, I/O thread is always eating chunks since + * it is emulating a null sink */ + if (u->autonull) { + u->start = now; + u->write_count = 0; + u->first = true; + pa_rtpoll_set_timer_absolute(u->rtpoll, now); + } + if (!pa_raop_client_is_alive(u->raop)) { - /* Connecting will trigger a RECORD and start steaming */ + /* Connecting will trigger a RECORD and start streaming */ pa_raop_client_announce(u->raop); - } else if (!pa_raop_client_can_stream(u->raop)) { + } else if (!pa_raop_client_is_recording(u->raop)) { /* RECORD alredy sent, simply start streaming */ pa_raop_client_stream(u->raop); pa_rtpoll_set_timer_absolute(u->rtpoll, now); @@ -341,6 +400,8 @@ static void sink_set_mute_cb(pa_sink *s) { static void thread_func(void *userdata) { struct userdata *u = userdata; size_t offset = 0; + pa_usec_t last_timing; + uint32_t check_timing_count; pa_assert(u); @@ -356,11 +417,7 @@ static void thread_func(void *userdata) { uint64_t position; size_t index; 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); - } + bool canstream, sendstream, on_timeout; /* Polling (audio data + control socket + timing socket). */ if ((ret = pa_rtpoll_run(u->rtpoll)) < 0) @@ -368,6 +425,12 @@ static void thread_func(void *userdata) { else if (ret == 0) goto finish; + if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) { + if (u->sink->thread_info.rewind_requested) + pa_sink_process_rewind(u->sink, 0); + } + + on_timeout = pa_rtpoll_timer_elapsed(u->rtpoll); if (u->rtpoll_item) { pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, &nbfds); /* If !oob: streaming driven by pollds (POLLOUT) */ @@ -383,12 +446,19 @@ static void thread_func(void *userdata) { } /* if oob: streaming managed by timing, pollfd for oob sockets */ - if (pollfd && u->oob && !pa_rtpoll_timer_elapsed(u->rtpoll)) { + if (pollfd && u->oob && !on_timeout) { uint8_t packet[32]; ssize_t read; for (i = 0; i < nbfds; i++) { if (pollfd->revents & POLLERR) { + if (u->autoreconnect && pa_raop_client_is_alive(u->raop)) { + pollfd->revents = 0; + pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->sink), + PA_SINK_MESSAGE_DISCONNECT_REQUEST, 0, 0, NULL, NULL); + continue; + } + /* one of UDP fds is in faulty state, may have been disconnected, this is fatal */ goto fail; } @@ -396,6 +466,10 @@ static void thread_func(void *userdata) { pollfd->revents = 0; read = pa_read(pollfd->fd, packet, sizeof(packet), NULL); pa_raop_client_handle_oob_packet(u->raop, pollfd->fd, packet, read); + if (pa_raop_client_is_timing_fd(u->raop, pollfd->fd)) { + last_timing = pa_rtclock_now(); + check_timing_count = 1; + } } pollfd++; @@ -405,65 +479,133 @@ static void thread_func(void *userdata) { } } - if (u->sink->thread_info.state != PA_SINK_RUNNING) - continue; - if (!pa_raop_client_can_stream(u->raop)) + if (u->sink->thread_info.state != PA_SINK_RUNNING) { continue; + } - /* This assertion is meant to silence a complaint from Coverity about - * pollfd being possibly NULL when we access it later. That's a false - * positive, because we check pa_raop_client_can_stream() above, and if - * that returns true, it means that the connection is up, and when the - * connection is up, pollfd will be non-NULL. */ - pa_assert(pollfd); + if (u->first) { + last_timing = 0; + check_timing_count = 1; + intvl = 0; + u->first = false; + } - if (u->memchunk.length <= 0) { - if (u->memchunk.memblock) - pa_memblock_unref(u->memchunk.memblock); - pa_memchunk_reset(&u->memchunk); + canstream = pa_raop_client_can_stream(u->raop); + now = pa_rtclock_now(); + + if (u->oob && u->autoreconnect && on_timeout) { + if (!canstream) { + last_timing = 0; + } else if (last_timing != 0) { + pa_usec_t since = now - last_timing; + /* Incoming Timing packets should be received every 3 seconds in UDP mode + according to raop specifications. + Here we disconnect if no packet received since UDP_TIMING_PACKET_LOSS_MAX seconds + We only detect timing packet requests interruptions (we do nothing if no packet received at all), since some clients do not implement RTCP Timing requests at all */ + + if (since > (UDP_TIMING_PACKET_LOSS_MAX/UDP_TIMING_PACKET_DISCONNECT_CYCLE)*check_timing_count) { + if (check_timing_count < UDP_TIMING_PACKET_DISCONNECT_CYCLE) { + uint32_t since_in_sec = since / PA_USEC_PER_SEC; + pa_log_warn( + "UDP Timing Packets Warn #%d/%d- Nothing received since %d seconds from %s", + check_timing_count, + UDP_TIMING_PACKET_DISCONNECT_CYCLE-1, since_in_sec, u->server); + check_timing_count++; + } else { + /* Limit reached, then request disconnect */ + check_timing_count = 1; + last_timing = 0; + if (pa_raop_client_is_alive(u->raop)) { + pa_log_warn("UDP Timing Packets Warn limit reached - Requesting reconnect"); + pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->sink), + PA_SINK_MESSAGE_DISCONNECT_REQUEST, 0, 0, NULL, NULL); + continue; + } + } + } + } + } - /* Grab unencoded audio data from PulseAudio */ - pa_sink_render_full(u->sink, u->block_size, &u->memchunk); - offset = u->memchunk.index; + if (!u->autonull) { + if (!canstream) { + pa_log_debug("Can't stream, connection not established yet..."); + continue; + } + /* This assertion is meant to silence a complaint from Coverity about + * pollfd being possibly NULL when we access it later. That's a false + * positive, because we check pa_raop_client_can_stream() above, and if + * that returns true, it means that the connection is up, and when the + * connection is up, pollfd will be non-NULL. */ + pa_assert(pollfd); } - pa_assert(u->memchunk.length > 0); - - index = u->memchunk.index; - if (pa_raop_client_send_audio_packet(u->raop, &u->memchunk, offset) < 0) { - if (errno == EINTR) { - /* Just try again. */ - pa_log_debug("Failed to write data to FIFO (EINTR), retrying"); - goto fail; - } else if (errno != EAGAIN && !u->oob) { - /* Buffer is full, wait for POLLOUT. */ - pollfd->events = POLLOUT; - pollfd->revents = 0; - } else { - pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno)); - goto fail; + if (u->memchunk.length <= 0) { + if (intvl < now + u->block_usec) { + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + pa_memchunk_reset(&u->memchunk); + + /* Grab unencoded audio data from PulseAudio */ + pa_sink_render_full(u->sink, u->block_size, &u->memchunk); + offset = u->memchunk.index; } - } else { - u->write_count += (uint64_t) u->memchunk.index - (uint64_t) index; - position = u->write_count - pa_usec_to_bytes(u->delay, &u->sink->sample_spec); + } - now = pa_rtclock_now(); - estimated = pa_bytes_to_usec(position, &u->sink->sample_spec); - pa_smoother_put(u->smoother, now, estimated); - - if (u->oob && !pollfd->revents) { - /* Sleep until next packet transmission */ - intvl = u->start + pa_bytes_to_usec(u->write_count, &u->sink->sample_spec); - pa_rtpoll_set_timer_absolute(u->rtpoll, intvl); - } else if (!u->oob) { - if (u->memchunk.length > 0) { - pollfd->events = POLLOUT; - pollfd->revents = 0; + if (u->memchunk.length > 0) { + index = u->memchunk.index; + sendstream = !u->autonull || (u->autonull && canstream); + if (sendstream && pa_raop_client_send_audio_packet(u->raop, &u->memchunk, offset) < 0) { + if (errno == EINTR) { + /* Just try again. */ + pa_log_debug("Failed to write data to FIFO (EINTR), retrying"); + if (u->autoreconnect) { + pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_DISCONNECT_REQUEST, + 0, 0, NULL, NULL); + continue; + } else + goto fail; + } else if (errno != EAGAIN && !u->oob) { + /* Buffer is full, wait for POLLOUT. */ + if (!u->oob) { + pollfd->events = POLLOUT; + pollfd->revents = 0; + } } else { + pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno)); + if (u->autoreconnect) { + pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_DISCONNECT_REQUEST, + 0, 0, NULL, NULL); + continue; + } else + goto fail; + } + } else { + if (sendstream) { + u->write_count += (uint64_t) u->memchunk.index - (uint64_t) index; + } else { + u->write_count += u->memchunk.length; + u->memchunk.length = 0; + } + position = u->write_count - pa_usec_to_bytes(u->delay, &u->sink->sample_spec); + + now = pa_rtclock_now(); + estimated = pa_bytes_to_usec(position, &u->sink->sample_spec); + pa_smoother_put(u->smoother, now, estimated); + + if ((u->autonull && !canstream) || (u->oob && canstream && on_timeout)) { + /* Sleep until next packet transmission */ intvl = u->start + pa_bytes_to_usec(u->write_count, &u->sink->sample_spec); pa_rtpoll_set_timer_absolute(u->rtpoll, intvl); - pollfd->revents = 0; - pollfd->events = 0; + } else if (!u->oob) { + if (u->memchunk.length > 0) { + pollfd->events = POLLOUT; + pollfd->revents = 0; + } else { + intvl = u->start + pa_bytes_to_usec(u->write_count, &u->sink->sample_spec); + pa_rtpoll_set_timer_absolute(u->rtpoll, intvl); + pollfd->revents = 0; + pollfd->events = 0; + } } } } @@ -553,6 +695,7 @@ static pa_card *raop_create_card(pa_module *m, pa_device_port *port, pa_card_pro pa_sink* pa_raop_sink_new(pa_module *m, pa_modargs *ma, const char *driver) { struct userdata *u = NULL; pa_sample_spec ss; + pa_channel_map map; char *thread_name = NULL; const char *server, *protocol, *encryption, *codec; const char /* *username, */ *password; @@ -566,8 +709,10 @@ pa_sink* pa_raop_sink_new(pa_module *m, pa_modargs *ma, const char *driver) { pa_assert(ma); ss = m->core->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log("Failed to parse sample specification"); + map = m->core->default_channel_map; + + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { + pa_log("Invalid sample format specification or channel map"); goto fail; } @@ -588,6 +733,15 @@ pa_sink* pa_raop_sink_new(pa_module *m, pa_modargs *ma, const char *driver) { u->rtpoll = pa_rtpoll_new(); u->rtpoll_item = NULL; u->latency = RAOP_DEFAULT_LATENCY; + u->autoreconnect = false; + u->server = pa_xstrdup(server); + + if (pa_modargs_get_value_boolean(ma, "autoreconnect", &u->autoreconnect) < 0) { + pa_log("Failed to parse autoreconnect argument"); + goto fail; + } + /* Linked for now, potentially ready for additional parameter */ + u->autonull = u->autoreconnect; if (pa_modargs_get_value_u32(ma, "latency_msec", &u->latency) < 0) { pa_log("Failed to parse latency_msec argument"); @@ -667,6 +821,7 @@ pa_sink* pa_raop_sink_new(pa_module *m, pa_modargs *ma, const char *driver) { } pa_sink_new_data_set_sample_spec(&data, &ss); + pa_sink_new_data_set_channel_map(&data, &map); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, server); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_INTENDED_ROLES, "music"); @@ -718,7 +873,7 @@ pa_sink* pa_raop_sink_new(pa_module *m, pa_modargs *ma, const char *driver) { pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); pa_sink_set_rtpoll(u->sink, u->rtpoll); - u->raop = pa_raop_client_new(u->core, server, u->protocol, u->encryption, u->codec); + u->raop = pa_raop_client_new(u->core, server, u->protocol, u->encryption, u->codec, u->autoreconnect); if (!(u->raop)) { pa_log("Failed to create RAOP client object"); @@ -729,6 +884,7 @@ pa_sink* pa_raop_sink_new(pa_module *m, pa_modargs *ma, const char *driver) { pa_raop_client_get_frames_per_block(u->raop, &u->block_size); u->block_size *= pa_frame_size(&ss); pa_sink_set_max_request(u->sink, u->block_size); + u->block_usec = pa_bytes_to_usec(u->block_size, &u->sink->sample_spec); pa_raop_client_set_state_callback(u->raop, raop_state_cb, u); @@ -794,6 +950,8 @@ static void userdata_free(struct userdata *u) { if (u->card) pa_card_free(u->card); + if (u->server) + pa_xfree(u->server); pa_xfree(u); } diff --git a/src/modules/rtp/meson.build b/src/modules/rtp/meson.build index c3efde6..119cf08 100644 --- a/src/modules/rtp/meson.build +++ b/src/modules/rtp/meson.build @@ -1,5 +1,5 @@ librtp_sources = [ - 'rtp.c', + 'rtp-common.c', 'sdp.c', 'sap.c', 'rtsp_client.c', @@ -14,13 +14,19 @@ librtp_headers = [ 'headerlist.h', ] +if have_gstreamer + librtp_sources += 'rtp-gstreamer.c' +else + librtp_sources += 'rtp-native.c' +endif + librtp = shared_library('rtp', librtp_sources, librtp_headers, c_args : [pa_c_args, server_c_args], link_args : [nodelete_link_args], include_directories : [configinc, topinc], - dependencies : [libpulse_dep, libpulsecommon_dep, libpulsecore_dep, libatomic_ops_dep], + dependencies : [libpulse_dep, libpulsecommon_dep, libpulsecore_dep, libatomic_ops_dep, gst_dep, gstapp_dep, gstrtp_dep, gio_dep], install : true, install_rpath : privlibdir, install_dir : modlibexecdir, diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 79e712d..a9b42bb 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -90,12 +90,11 @@ struct session { pa_memblockq *memblockq; bool first_packet; - uint32_t ssrc; uint32_t offset; struct pa_sdp_info sdp_info; - pa_rtp_context rtp_context; + pa_rtp_context *rtp_context; pa_rtpoll_item *rtpoll_item; @@ -205,12 +204,13 @@ static void sink_input_suspend_within_thread(pa_sink_input* i, bool b) { /* Called from I/O thread context */ static int rtpoll_work_cb(pa_rtpoll_item *i) { pa_memchunk chunk; + uint32_t timestamp; int64_t k, j, delta; struct timeval now = { 0, 0 }; struct session *s; struct pollfd *p; - pa_assert_se(s = pa_rtpoll_item_get_userdata(i)); + pa_assert_se(s = pa_rtpoll_item_get_work_userdata(i)); p = pa_rtpoll_item_get_pollfd(i, NULL); @@ -224,40 +224,30 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) { p->revents = 0; - if (pa_rtp_recv(&s->rtp_context, &chunk, s->userdata->module->core->mempool, &now) < 0) + if (pa_rtp_recv(s->rtp_context, &chunk, s->userdata->module->core->mempool, ×tamp, &now) < 0) return 0; - if (s->sdp_info.payload != s->rtp_context.payload || - !PA_SINK_IS_OPENED(s->sink_input->sink->thread_info.state)) { + if (!PA_SINK_IS_OPENED(s->sink_input->sink->thread_info.state)) { pa_memblock_unref(chunk.memblock); return 0; } if (!s->first_packet) { s->first_packet = true; - - s->ssrc = s->rtp_context.ssrc; - s->offset = s->rtp_context.timestamp; - - if (s->ssrc == s->userdata->module->core->cookie) - pa_log_warn("Detected RTP packet loop!"); - } else { - if (s->ssrc != s->rtp_context.ssrc) { - pa_memblock_unref(chunk.memblock); - return 0; - } + s->offset = timestamp; } /* Check whether there was a timestamp overflow */ - k = (int64_t) s->rtp_context.timestamp - (int64_t) s->offset; - j = (int64_t) 0x100000000LL - (int64_t) s->offset + (int64_t) s->rtp_context.timestamp; + k = (int64_t) timestamp - (int64_t) s->offset; + j = (int64_t) 0x100000000LL - (int64_t) s->offset + (int64_t) timestamp; if ((k < 0 ? -k : k) < (j < 0 ? -j : j)) delta = k; else delta = j; - pa_memblockq_seek(s->memblockq, delta * (int64_t) s->rtp_context.frame_size, PA_SEEK_RELATIVE, true); + pa_memblockq_seek(s->memblockq, delta * (int64_t) pa_rtp_context_get_frame_size(s->rtp_context), PA_SEEK_RELATIVE, + true); if (now.tv_sec == 0) { PA_ONCE_BEGIN { @@ -277,7 +267,7 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) { pa_memblock_unref(chunk.memblock); /* The next timestamp we expect */ - s->offset = s->rtp_context.timestamp + (uint32_t) (chunk.length / s->rtp_context.frame_size); + s->offset = timestamp + (uint32_t) (chunk.length / pa_rtp_context_get_frame_size(s->rtp_context)); pa_atomic_store(&s->timestamp, (int) now.tv_sec); @@ -386,21 +376,14 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) { /* Called from I/O thread context */ static void sink_input_attach(pa_sink_input *i) { struct session *s; - struct pollfd *p; pa_sink_input_assert_ref(i); pa_assert_se(s = i->userdata); pa_assert(!s->rtpoll_item); - s->rtpoll_item = pa_rtpoll_item_new(i->sink->thread_info.rtpoll, PA_RTPOLL_LATE, 1); - - p = pa_rtpoll_item_get_pollfd(s->rtpoll_item, NULL); - p->fd = s->rtp_context.fd; - p->events = POLLIN; - p->revents = 0; + s->rtpoll_item = pa_rtp_context_get_rtpoll_item(s->rtp_context, i->sink->thread_info.rtpoll); - pa_rtpoll_item_set_work_callback(s->rtpoll_item, rtpoll_work_cb); - pa_rtpoll_item_set_userdata(s->rtpoll_item, s); + pa_rtpoll_item_set_work_callback(s->rtpoll_item, rtpoll_work_cb, s); } /* Called from I/O thread context */ @@ -585,7 +568,8 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in pa_memblock_unref(silence.memblock); - pa_rtp_context_init_recv(&s->rtp_context, fd, pa_frame_size(&s->sdp_info.sample_spec)); + if (!(s->rtp_context = pa_rtp_context_new_recv(fd, sdp_info->payload, &s->sdp_info.sample_spec))) + goto fail; pa_hashmap_put(s->userdata->by_origin, s->sdp_info.origin, s); u->n_sessions++; @@ -620,7 +604,7 @@ static void session_free(struct session *s) { pa_memblockq_free(s->memblockq); pa_sdp_info_destroy(&s->sdp_info); - pa_rtp_context_destroy(&s->rtp_context); + pa_rtp_context_free(s->rtp_context); pa_xfree(s); } diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index fbaf644..5a4c6fc 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -107,9 +107,8 @@ struct userdata { pa_source_output *source_output; pa_memblockq *memblockq; - pa_rtp_context rtp_context; + pa_rtp_context *rtp_context; pa_sap_context sap_context; - size_t mtu; pa_time_event *sap_event; @@ -144,7 +143,7 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) return; } - pa_rtp_send(&u->rtp_context, u->mtu, u->memblockq); + pa_rtp_send(u->rtp_context, u->memblockq); } static pa_source_output_flags_t get_dont_inhibit_auto_suspend_flag(pa_source *source, @@ -159,7 +158,7 @@ static pa_source_output_flags_t get_dont_inhibit_auto_suspend_flag(pa_source *so return PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; case INHIBIT_AUTO_SUSPEND_ONLY_WITH_NON_MONITOR_SOURCES: - return source->monitor_of ? 0 : PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; + return source->monitor_of ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0; } pa_assert_not_reached(); @@ -466,8 +465,6 @@ int pa__init(pa_module*m) { 0, NULL); - u->mtu = mtu; - k = sizeof(sa_dst); pa_assert_se((r = getsockname(fd, (struct sockaddr*) &sa_dst, &k)) >= 0); @@ -491,10 +488,12 @@ int pa__init(pa_module*m) { pa_xfree(n); - pa_rtp_context_init_send(&u->rtp_context, fd, m->core->cookie, payload, pa_frame_size(&ss)); + if (!(u->rtp_context = pa_rtp_context_new_send(fd, payload, mtu, &ss))) + goto fail; pa_sap_context_init_send(&u->sap_context, sap_fd, p); - pa_log_info("RTP stream initialized with mtu %u on %s:%u from %s ttl=%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dst_addr, port, src_addr, ttl, u->rtp_context.ssrc, payload, u->rtp_context.sequence); + pa_log_info("RTP stream initialized with mtu %u on %s:%u from %s ttl=%u, payload=%u", + mtu, dst_addr, port, src_addr, ttl, payload); pa_log_info("SDP-Data:\n%s\nEOF", p); pa_sap_send(&u->sap_context, 0); @@ -536,7 +535,7 @@ void pa__done(pa_module*m) { pa_source_output_unref(u->source_output); } - pa_rtp_context_destroy(&u->rtp_context); + pa_rtp_context_free(u->rtp_context); pa_sap_send(&u->sap_context, 1); pa_sap_context_destroy(&u->sap_context); diff --git a/src/modules/rtp/rtp-common.c b/src/modules/rtp/rtp-common.c new file mode 100644 index 0000000..65e2c7a --- /dev/null +++ b/src/modules/rtp/rtp-common.c @@ -0,0 +1,97 @@ +/*** + This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "rtp.h" + +#include <pulsecore/core-util.h> + +uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) { + pa_assert(ss); + + if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 2) + return 10; + if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 1) + return 11; + + return 127; +} + +pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec *ss) { + pa_assert(ss); + + switch (payload) { + case 10: + ss->channels = 2; + ss->format = PA_SAMPLE_S16BE; + ss->rate = 44100; + break; + + case 11: + ss->channels = 1; + ss->format = PA_SAMPLE_S16BE; + ss->rate = 44100; + break; + + default: + return NULL; + } + + return ss; +} + +pa_sample_spec *pa_rtp_sample_spec_fixup(pa_sample_spec * ss) { + pa_assert(ss); + + if (!pa_rtp_sample_spec_valid(ss)) + ss->format = PA_SAMPLE_S16BE; + + pa_assert(pa_rtp_sample_spec_valid(ss)); + return ss; +} + +int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) { + pa_assert(ss); + + if (!pa_sample_spec_valid(ss)) + return 0; + + return ss->format == PA_SAMPLE_S16BE; +} + +const char* pa_rtp_format_to_string(pa_sample_format_t f) { + switch (f) { + case PA_SAMPLE_S16BE: + return "L16"; + default: + return NULL; + } +} + +pa_sample_format_t pa_rtp_string_to_format(const char *s) { + pa_assert(s); + + if (pa_streq(s, "L16")) + return PA_SAMPLE_S16BE; + else + return PA_SAMPLE_INVALID; +} diff --git a/src/modules/rtp/rtp-gstreamer.c b/src/modules/rtp/rtp-gstreamer.c new file mode 100644 index 0000000..3ee77cb --- /dev/null +++ b/src/modules/rtp/rtp-gstreamer.c @@ -0,0 +1,524 @@ +/*** + This file is part of PulseAudio. + + Copyright 2016 Arun Raghavan <mail@arunraghavan.net> + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <pulse/timeval.h> +#include <pulsecore/fdsem.h> +#include <pulsecore/core-rtclock.h> + +#include "rtp.h" + +#include <gio/gio.h> + +#include <gst/gst.h> +#include <gst/app/gstappsrc.h> +#include <gst/app/gstappsink.h> +#include <gst/rtp/gstrtpbuffer.h> + +#define MAKE_ELEMENT_NAMED(v, e, n) \ + v = gst_element_factory_make(e, n); \ + if (!v) { \ + pa_log("Could not create %s element", e); \ + goto fail; \ + } + +#define MAKE_ELEMENT(v, e) MAKE_ELEMENT_NAMED((v), (e), NULL) + +struct pa_rtp_context { + pa_fdsem *fdsem; + pa_sample_spec ss; + + GstElement *pipeline; + GstElement *appsrc; + GstElement *appsink; + + uint32_t last_timestamp; +}; + +static GstCaps* caps_from_sample_spec(const pa_sample_spec *ss) { + if (ss->format != PA_SAMPLE_S16BE) + return NULL; + + return gst_caps_new_simple("audio/x-raw", + "format", G_TYPE_STRING, "S16BE", + "rate", G_TYPE_INT, (int) ss->rate, + "channels", G_TYPE_INT, (int) ss->channels, + "layout", G_TYPE_STRING, "interleaved", + NULL); +} +static bool init_send_pipeline(pa_rtp_context *c, int fd, uint8_t payload, size_t mtu, const pa_sample_spec *ss) { + GstElement *appsrc = NULL, *pay = NULL, *capsf = NULL, *rtpbin = NULL, *sink = NULL; + GstCaps *caps; + GSocket *socket; + GInetSocketAddress *addr; + GInetAddress *iaddr; + guint16 port; + gchar *addr_str; + + MAKE_ELEMENT(appsrc, "appsrc"); + MAKE_ELEMENT(pay, "rtpL16pay"); + MAKE_ELEMENT(capsf, "capsfilter"); + MAKE_ELEMENT(rtpbin, "rtpbin"); + MAKE_ELEMENT(sink, "udpsink"); + + c->pipeline = gst_pipeline_new(NULL); + + gst_bin_add_many(GST_BIN(c->pipeline), appsrc, pay, capsf, rtpbin, sink, NULL); + + caps = caps_from_sample_spec(ss); + if (!caps) { + pa_log("Unsupported format to payload"); + goto fail; + } + + socket = g_socket_new_from_fd(fd, NULL); + if (!socket) { + pa_log("Failed to create socket"); + goto fail; + } + + addr = G_INET_SOCKET_ADDRESS(g_socket_get_remote_address(socket, NULL)); + iaddr = g_inet_socket_address_get_address(addr); + addr_str = g_inet_address_to_string(iaddr); + port = g_inet_socket_address_get_port(addr); + + g_object_set(appsrc, "caps", caps, "is-live", TRUE, "blocksize", mtu, "format", 3 /* time */, NULL); + g_object_set(pay, "mtu", mtu, NULL); + g_object_set(sink, "socket", socket, "host", addr_str, "port", port, + "enable-last-sample", FALSE, "sync", FALSE, "loop", + g_socket_get_multicast_loopback(socket), "ttl", + g_socket_get_ttl(socket), "ttl-mc", + g_socket_get_multicast_ttl(socket), "auto-multicast", FALSE, + NULL); + + g_free(addr_str); + g_object_unref(addr); + g_object_unref(socket); + + gst_caps_unref(caps); + + /* Force the payload type that we want */ + caps = gst_caps_new_simple("application/x-rtp", "payload", G_TYPE_INT, (int) payload, NULL); + g_object_set(capsf, "caps", caps, NULL); + gst_caps_unref(caps); + + if (!gst_element_link(appsrc, pay) || + !gst_element_link(pay, capsf) || + !gst_element_link_pads(capsf, "src", rtpbin, "send_rtp_sink_0") || + !gst_element_link_pads(rtpbin, "send_rtp_src_0", sink, "sink")) { + + pa_log("Could not set up send pipeline"); + goto fail; + } + + if (gst_element_set_state(c->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + pa_log("Could not start pipeline"); + goto fail; + } + + c->appsrc = gst_object_ref(appsrc); + + return true; + +fail: + if (c->pipeline) { + gst_object_unref(c->pipeline); + } else { + /* These weren't yet added to pipeline, so we still have a ref */ + if (appsrc) + gst_object_unref(appsrc); + if (pay) + gst_object_unref(pay); + if (capsf) + gst_object_unref(capsf); + if (rtpbin) + gst_object_unref(rtpbin); + if (sink) + gst_object_unref(sink); + } + + return false; +} + +pa_rtp_context* pa_rtp_context_new_send(int fd, uint8_t payload, size_t mtu, const pa_sample_spec *ss) { + pa_rtp_context *c = NULL; + GError *error = NULL; + + pa_assert(fd >= 0); + + pa_log_info("Initialising GStreamer RTP backend for send"); + + c = pa_xnew0(pa_rtp_context, 1); + + c->ss = *ss; + + if (!gst_init_check(NULL, NULL, &error)) { + pa_log_error("Could not initialise GStreamer: %s", error->message); + g_error_free(error); + goto fail; + } + + if (!init_send_pipeline(c, fd, payload, mtu, ss)) + goto fail; + + return c; + +fail: + pa_rtp_context_free(c); + return NULL; +} + +/* Called from I/O thread context */ +static bool process_bus_messages(pa_rtp_context *c) { + GstBus *bus; + GstMessage *message; + bool ret = true; + + bus = gst_pipeline_get_bus(GST_PIPELINE(c->pipeline)); + + while (ret && (message = gst_bus_pop(bus))) { + if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_ERROR) { + GError *error = NULL; + + ret = false; + + gst_message_parse_error(message, &error, NULL); + pa_log("Got an error: %s", error->message); + + g_error_free(error); + } + + gst_message_unref(message); + } + + gst_object_unref(bus); + + return ret; +} + +static void free_buffer(pa_memblock *memblock) { + pa_memblock_release(memblock); + pa_memblock_unref(memblock); +} + +/* Called from I/O thread context */ +int pa_rtp_send(pa_rtp_context *c, pa_memblockq *q) { + pa_memchunk chunk = { 0, }; + GstBuffer *buf; + void *data; + bool stop = false; + int ret = 0; + + pa_assert(c); + pa_assert(q); + + if (!process_bus_messages(c)) + return -1; + + while (!stop && pa_memblockq_peek(q, &chunk) == 0) { + GstClock *clock; + GstClockTime timestamp, clock_time; + + clock = gst_element_get_clock(c->pipeline); + clock_time = gst_clock_get_time(clock); + gst_object_unref(clock); + + timestamp = gst_element_get_base_time(c->pipeline); + if (timestamp > clock_time) + timestamp -= clock_time; + else + timestamp = 0; + + pa_assert(chunk.memblock); + + data = pa_memblock_acquire(chunk.memblock); + + buf = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY | GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS, + data, chunk.length, chunk.index, chunk.length, chunk.memblock, + (GDestroyNotify) free_buffer); + + GST_BUFFER_PTS(buf) = timestamp; + + if (gst_app_src_push_buffer(GST_APP_SRC(c->appsrc), buf) != GST_FLOW_OK) { + pa_log_error("Could not push buffer"); + stop = true; + ret = -1; + } + + pa_memblockq_drop(q, chunk.length); + } + + return ret; +} + +static GstCaps* rtp_caps_from_sample_spec(const pa_sample_spec *ss) { + if (ss->format != PA_SAMPLE_S16BE) + return NULL; + + return gst_caps_new_simple("application/x-rtp", + "media", G_TYPE_STRING, "audio", + "encoding-name", G_TYPE_STRING, "L16", + "clock-rate", G_TYPE_INT, (int) ss->rate, + "payload", G_TYPE_INT, (int) pa_rtp_payload_from_sample_spec(ss), + "layout", G_TYPE_STRING, "interleaved", + NULL); +} + +static void on_pad_added(GstElement *element, GstPad *pad, gpointer userdata) { + pa_rtp_context *c = (pa_rtp_context *) userdata; + GstElement *depay; + GstPad *sinkpad; + GstPadLinkReturn ret; + + depay = gst_bin_get_by_name(GST_BIN(c->pipeline), "depay"); + pa_assert(depay); + + sinkpad = gst_element_get_static_pad(depay, "sink"); + + ret = gst_pad_link(pad, sinkpad); + if (ret != GST_PAD_LINK_OK) { + GstBus *bus; + GError *error; + + bus = gst_pipeline_get_bus(GST_PIPELINE(c->pipeline)); + error = g_error_new(GST_CORE_ERROR, GST_CORE_ERROR_PAD, "Could not link rtpbin to depayloader"); + gst_bus_post(bus, gst_message_new_error(GST_OBJECT(c->pipeline), error, NULL)); + + /* Actually cause the I/O thread to wake up and process the error */ + pa_fdsem_post(c->fdsem); + + g_error_free(error); + gst_object_unref(bus); + } + + gst_object_unref(sinkpad); + gst_object_unref(depay); +} + +static bool init_receive_pipeline(pa_rtp_context *c, int fd, const pa_sample_spec *ss) { + GstElement *udpsrc = NULL, *rtpbin = NULL, *depay = NULL, *appsink = NULL; + GstCaps *caps; + GSocket *socket; + GError *error = NULL; + + MAKE_ELEMENT(udpsrc, "udpsrc"); + MAKE_ELEMENT(rtpbin, "rtpbin"); + MAKE_ELEMENT_NAMED(depay, "rtpL16depay", "depay"); + MAKE_ELEMENT(appsink, "appsink"); + + c->pipeline = gst_pipeline_new(NULL); + + gst_bin_add_many(GST_BIN(c->pipeline), udpsrc, rtpbin, depay, appsink, NULL); + + socket = g_socket_new_from_fd(fd, &error); + if (error) { + pa_log("Could not create socket: %s", error->message); + g_error_free(error); + goto fail; + } + + caps = rtp_caps_from_sample_spec(ss); + if (!caps) { + pa_log("Unsupported format to payload"); + goto fail; + } + + g_object_set(udpsrc, "socket", socket, "caps", caps, "auto-multicast" /* caller handles this */, FALSE, NULL); + g_object_set(rtpbin, "latency", 0, "buffer-mode", 0 /* none */, NULL); + g_object_set(appsink, "sync", FALSE, "enable-last-sample", FALSE, NULL); + + gst_caps_unref(caps); + g_object_unref(socket); + + if (!gst_element_link_pads(udpsrc, "src", rtpbin, "recv_rtp_sink_0") || + !gst_element_link(depay, appsink)) { + + pa_log("Could not set up receive pipeline"); + goto fail; + } + + g_signal_connect(G_OBJECT(rtpbin), "pad-added", G_CALLBACK(on_pad_added), c); + + if (gst_element_set_state(c->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + pa_log("Could not start pipeline"); + goto fail; + } + + c->appsink = gst_object_ref(appsink); + + return true; + +fail: + if (c->pipeline) { + gst_object_unref(c->pipeline); + } else { + /* These weren't yet added to pipeline, so we still have a ref */ + if (udpsrc) + gst_object_unref(udpsrc); + if (depay) + gst_object_unref(depay); + if (rtpbin) + gst_object_unref(rtpbin); + if (appsink) + gst_object_unref(appsink); + } + + return false; +} + +/* Called from the GStreamer streaming thread */ +static void appsink_eos(GstAppSink *appsink, gpointer userdata) { + pa_rtp_context *c = (pa_rtp_context *) userdata; + + pa_fdsem_post(c->fdsem); +} + +/* Called from the GStreamer streaming thread */ +static GstFlowReturn appsink_new_sample(GstAppSink *appsink, gpointer userdata) { + pa_rtp_context *c = (pa_rtp_context *) userdata; + + pa_fdsem_post(c->fdsem); + + return GST_FLOW_OK; +} + +pa_rtp_context* pa_rtp_context_new_recv(int fd, uint8_t payload, const pa_sample_spec *ss) { + pa_rtp_context *c = NULL; + GstAppSinkCallbacks callbacks = { 0, }; + GError *error = NULL; + + pa_assert(fd >= 0); + + pa_log_info("Initialising GStreamer RTP backend for receive"); + + c = pa_xnew0(pa_rtp_context, 1); + + c->fdsem = pa_fdsem_new(); + c->ss = *ss; + + if (!gst_init_check(NULL, NULL, &error)) { + pa_log_error("Could not initialise GStreamer: %s", error->message); + g_error_free(error); + goto fail; + } + + if (!init_receive_pipeline(c, fd, ss)) + goto fail; + + callbacks.eos = appsink_eos; + callbacks.new_sample = appsink_new_sample; + gst_app_sink_set_callbacks(GST_APP_SINK(c->appsink), &callbacks, c, NULL); + + return c; + +fail: + pa_rtp_context_free(c); + return NULL; +} + +/* Called from I/O thread context */ +int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, uint32_t *rtp_tstamp, struct timeval *tstamp) { + GstSample *sample = NULL; + GstBuffer *buf; + GstMapInfo info; + void *data; + + if (!process_bus_messages(c)) + goto fail; + + sample = gst_app_sink_pull_sample(GST_APP_SINK(c->appsink)); + if (!sample) { + pa_log_warn("Could not get any more data"); + goto fail; + } + + buf = gst_sample_get_buffer(sample); + + if (GST_BUFFER_IS_DISCONT(buf)) + pa_log_info("Discontinuity detected, possibly lost some packets"); + + if (!gst_buffer_map(buf, &info, GST_MAP_READ)) + goto fail; + + pa_assert(pa_mempool_block_size_max(pool) >= info.size); + + chunk->memblock = pa_memblock_new(pool, info.size); + chunk->index = 0; + chunk->length = info.size; + + data = pa_memblock_acquire_chunk(chunk); + /* TODO: we could probably just provide an allocator and avoid a memcpy */ + memcpy(data, info.data, info.size); + pa_memblock_release(chunk->memblock); + + /* When buffer-mode = none, the buffer PTS is the RTP timestamp, converted + * to time units (instead of clock-rate units as is in the header) and + * wraparound-corrected, and the DTS is the pipeline clock timestamp from + * when the buffer was acquired at the source (this is actually the running + * time which is why we need to add base time). */ + *rtp_tstamp = gst_util_uint64_scale_int(GST_BUFFER_PTS(buf), c->ss.rate, GST_SECOND) & 0xFFFFFFFFU; + pa_timeval_rtstore(tstamp, (GST_BUFFER_DTS(buf) + gst_element_get_base_time(c->pipeline)) / GST_USECOND, false); + + gst_buffer_unmap(buf, &info); + gst_sample_unref(sample); + + return 0; + +fail: + if (sample) + gst_sample_unref(sample); + + if (chunk->memblock) + pa_memblock_unref(chunk->memblock); + + return -1; +} + +void pa_rtp_context_free(pa_rtp_context *c) { + pa_assert(c); + + if (c->appsrc) { + gst_app_src_end_of_stream(GST_APP_SRC(c->appsrc)); + gst_object_unref(c->appsrc); + } + + if (c->appsink) + gst_object_unref(c->appsink); + + if (c->pipeline) { + gst_element_set_state(c->pipeline, GST_STATE_NULL); + gst_object_unref(c->pipeline); + } + + if (c->fdsem) + pa_fdsem_free(c->fdsem); + + pa_xfree(c); +} + +pa_rtpoll_item* pa_rtp_context_get_rtpoll_item(pa_rtp_context *c, pa_rtpoll *rtpoll) { + return pa_rtpoll_item_new_fdsem(rtpoll, PA_RTPOLL_LATE, c->fdsem); +} + +size_t pa_rtp_context_get_frame_size(pa_rtp_context *c) { + return pa_frame_size(&c->ss); +} diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp-native.c index 5ab80e7..01e668c 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp-native.c @@ -40,19 +40,40 @@ #include <pulsecore/macro.h> #include <pulsecore/core-util.h> #include <pulsecore/arpa-inet.h> +#include <pulsecore/poll.h> #include "rtp.h" -pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload, size_t frame_size) { - pa_assert(c); +typedef struct pa_rtp_context { + int fd; + uint16_t sequence; + uint32_t timestamp; + uint32_t ssrc; + uint8_t payload; + size_t frame_size; + size_t mtu; + + uint8_t *recv_buf; + size_t recv_buf_size; + pa_memchunk memchunk; +} pa_rtp_context; + +pa_rtp_context* pa_rtp_context_new_send(int fd, uint8_t payload, size_t mtu, const pa_sample_spec *ss) { + pa_rtp_context *c; + pa_assert(fd >= 0); + pa_log_info("Initialising native RTP backend for send"); + + c = pa_xnew0(pa_rtp_context, 1); + c->fd = fd; c->sequence = (uint16_t) (rand()*rand()); c->timestamp = 0; - c->ssrc = ssrc ? ssrc : (uint32_t) (rand()*rand()); + c->ssrc = (uint32_t) (rand()*rand()); c->payload = (uint8_t) (payload & 127U); - c->frame_size = frame_size; + c->frame_size = pa_frame_size(ss); + c->mtu = mtu; c->recv_buf = NULL; c->recv_buf_size = 0; @@ -63,17 +84,16 @@ pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssr #define MAX_IOVECS 16 -int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { +int pa_rtp_send(pa_rtp_context *c, pa_memblockq *q) { struct iovec iov[MAX_IOVECS]; pa_memblock* mb[MAX_IOVECS]; int iov_idx = 1; size_t n = 0; pa_assert(c); - pa_assert(size > 0); pa_assert(q); - if (pa_memblockq_get_length(q) < size) + if (pa_memblockq_get_length(q) < c->mtu) return 0; for (;;) { @@ -84,7 +104,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { if ((r = pa_memblockq_peek(q, &chunk)) >= 0) { - size_t k = n + chunk.length > size ? size - n : chunk.length; + size_t k = n + chunk.length > c->mtu ? c->mtu - n : chunk.length; pa_assert(chunk.memblock); @@ -99,7 +119,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { pa_assert(n % c->frame_size == 0); - if (r < 0 || n >= size || iov_idx >= MAX_IOVECS) { + if (r < 0 || n >= c->mtu || iov_idx >= MAX_IOVECS) { uint32_t header[3]; struct msghdr m; ssize_t k; @@ -140,7 +160,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { return -1; } - if (r < 0 || pa_memblockq_get_length(q) < size) + if (r < 0 || pa_memblockq_get_length(q) < c->mtu) break; n = 0; @@ -151,19 +171,25 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { return 0; } -pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame_size) { - pa_assert(c); +pa_rtp_context* pa_rtp_context_new_recv(int fd, uint8_t payload, const pa_sample_spec *ss) { + pa_rtp_context *c; + + pa_log_info("Initialising native RTP backend for receive"); + + c = pa_xnew0(pa_rtp_context, 1); c->fd = fd; - c->frame_size = frame_size; + c->payload = payload; + c->frame_size = pa_frame_size(ss); c->recv_buf_size = 2000; c->recv_buf = pa_xmalloc(c->recv_buf_size); pa_memchunk_reset(&c->memchunk); + return c; } -int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, struct timeval *tstamp) { +int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, uint32_t *rtp_tstamp, struct timeval *tstamp) { int size; size_t audio_length; size_t metadata_length; @@ -171,6 +197,8 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, struct struct cmsghdr *cm; struct iovec iov; uint32_t header; + uint32_t ssrc; + uint8_t payload; unsigned cc; ssize_t r; uint8_t aux[1024]; @@ -246,12 +274,12 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, struct } memcpy(&header, iov.iov_base, sizeof(uint32_t)); - memcpy(&c->timestamp, (uint8_t*) iov.iov_base + 4, sizeof(uint32_t)); - memcpy(&c->ssrc, (uint8_t*) iov.iov_base + 8, sizeof(uint32_t)); + memcpy(rtp_tstamp, (uint8_t*) iov.iov_base + 4, sizeof(uint32_t)); + memcpy(&ssrc, (uint8_t*) iov.iov_base + 8, sizeof(uint32_t)); header = ntohl(header); - c->timestamp = ntohl(c->timestamp); - c->ssrc = ntohl(c->ssrc); + *rtp_tstamp = ntohl(*rtp_tstamp); + ssrc = ntohl(c->ssrc); if ((header >> 30) != 2) { pa_log_warn("Unsupported RTP version."); @@ -268,12 +296,22 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, struct goto fail; } + if (ssrc != c->ssrc) { + pa_log_debug("Got unexpected SSRC"); + goto fail; + } + cc = (header >> 24) & 0xF; - c->payload = (uint8_t) ((header >> 16) & 127U); + payload = (uint8_t) ((header >> 16) & 127U); c->sequence = (uint16_t) (header & 0xFFFFU); metadata_length = 12 + cc * 4; + if (payload != c->payload) { + pa_log_debug("Got unexpected payload: %u", payload); + goto fail; + } + if (metadata_length > (unsigned) size) { pa_log_warn("RTP packet too short. (CSRC)"); goto fail; @@ -335,80 +373,7 @@ fail: return -1; } -uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) { - pa_assert(ss); - - if (ss->format == PA_SAMPLE_ULAW && ss->rate == 8000 && ss->channels == 1) - return 0; - if (ss->format == PA_SAMPLE_ALAW && ss->rate == 8000 && ss->channels == 1) - return 8; - if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 2) - return 10; - if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 1) - return 11; - - return 127; -} - -pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec *ss) { - pa_assert(ss); - - switch (payload) { - case 0: - ss->channels = 1; - ss->format = PA_SAMPLE_ULAW; - ss->rate = 8000; - break; - - case 8: - ss->channels = 1; - ss->format = PA_SAMPLE_ALAW; - ss->rate = 8000; - break; - - case 10: - ss->channels = 2; - ss->format = PA_SAMPLE_S16BE; - ss->rate = 44100; - break; - - case 11: - ss->channels = 1; - ss->format = PA_SAMPLE_S16BE; - ss->rate = 44100; - break; - - default: - return NULL; - } - - return ss; -} - -pa_sample_spec *pa_rtp_sample_spec_fixup(pa_sample_spec * ss) { - pa_assert(ss); - - if (!pa_rtp_sample_spec_valid(ss)) - ss->format = PA_SAMPLE_S16BE; - - pa_assert(pa_rtp_sample_spec_valid(ss)); - return ss; -} - -int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) { - pa_assert(ss); - - if (!pa_sample_spec_valid(ss)) - return 0; - - return - ss->format == PA_SAMPLE_U8 || - ss->format == PA_SAMPLE_ALAW || - ss->format == PA_SAMPLE_ULAW || - ss->format == PA_SAMPLE_S16BE; -} - -void pa_rtp_context_destroy(pa_rtp_context *c) { +void pa_rtp_context_free(pa_rtp_context *c) { pa_assert(c); pa_assert_se(pa_close(c->fd) == 0); @@ -417,36 +382,23 @@ void pa_rtp_context_destroy(pa_rtp_context *c) { pa_memblock_unref(c->memchunk.memblock); pa_xfree(c->recv_buf); - c->recv_buf = NULL; - c->recv_buf_size = 0; + pa_xfree(c); } -const char* pa_rtp_format_to_string(pa_sample_format_t f) { - switch (f) { - case PA_SAMPLE_S16BE: - return "L16"; - case PA_SAMPLE_U8: - return "L8"; - case PA_SAMPLE_ALAW: - return "PCMA"; - case PA_SAMPLE_ULAW: - return "PCMU"; - default: - return NULL; - } +size_t pa_rtp_context_get_frame_size(pa_rtp_context *c) { + return c->frame_size; } -pa_sample_format_t pa_rtp_string_to_format(const char *s) { - pa_assert(s); - - if (pa_streq(s, "L16")) - return PA_SAMPLE_S16BE; - else if (pa_streq(s, "L8")) - return PA_SAMPLE_U8; - else if (pa_streq(s, "PCMA")) - return PA_SAMPLE_ALAW; - else if (pa_streq(s, "PCMU")) - return PA_SAMPLE_ULAW; - else - return PA_SAMPLE_INVALID; +pa_rtpoll_item* pa_rtp_context_get_rtpoll_item(pa_rtp_context *c, pa_rtpoll *rtpoll) { + pa_rtpoll_item *item; + struct pollfd *p; + + item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_LATE, 1); + + p = pa_rtpoll_item_get_pollfd(item, NULL); + p->fd = c->fd; + p->events = POLLIN; + p->revents = 0; + + return item; } diff --git a/src/modules/rtp/rtp.h b/src/modules/rtp/rtp.h index 0b877d5..372df75 100644 --- a/src/modules/rtp/rtp.h +++ b/src/modules/rtp/rtp.h @@ -25,30 +25,24 @@ #include <sys/types.h> #include <pulsecore/memblockq.h> #include <pulsecore/memchunk.h> +#include <pulsecore/rtpoll.h> -typedef struct pa_rtp_context { - int fd; - uint16_t sequence; - uint32_t timestamp; - uint32_t ssrc; - uint8_t payload; - size_t frame_size; +typedef struct pa_rtp_context pa_rtp_context; - uint8_t *recv_buf; - size_t recv_buf_size; - pa_memchunk memchunk; -} pa_rtp_context; - -pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload, size_t frame_size); +int pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint8_t payload, size_t mtu, size_t frame_size); +pa_rtp_context* pa_rtp_context_new_send(int fd, uint8_t payload, size_t mtu, const pa_sample_spec *ss); /* If the memblockq doesn't have a silence memchunk set, then the caller must * guarantee that the current read index doesn't point to a hole. */ -int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q); +int pa_rtp_send(pa_rtp_context *c, pa_memblockq *q); + +pa_rtp_context* pa_rtp_context_new_recv(int fd, uint8_t payload, const pa_sample_spec *ss); +int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, uint32_t *rtp_tstamp, struct timeval *tstamp); -pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame_size); -int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, struct timeval *tstamp); +void pa_rtp_context_free(pa_rtp_context *c); -void pa_rtp_context_destroy(pa_rtp_context *c); +size_t pa_rtp_context_get_frame_size(pa_rtp_context *c); +pa_rtpoll_item* pa_rtp_context_get_rtpoll_item(pa_rtp_context *c, pa_rtpoll *rtpoll); pa_sample_spec* pa_rtp_sample_spec_fixup(pa_sample_spec *ss); int pa_rtp_sample_spec_valid(const pa_sample_spec *ss); diff --git a/src/modules/rtp/rtsp_client.c b/src/modules/rtp/rtsp_client.c index 34210f9..9fd386a 100644 --- a/src/modules/rtp/rtsp_client.c +++ b/src/modules/rtp/rtsp_client.c @@ -27,6 +27,8 @@ #include <unistd.h> #include <sys/ioctl.h> #include <netinet/in.h> +#include <pulse/rtclock.h> +#include <pulse/timeval.h> #ifdef HAVE_SYS_FILIO_H #include <sys/filio.h> @@ -42,9 +44,12 @@ #include <pulsecore/ioline.h> #include <pulsecore/arpa-inet.h> #include <pulsecore/random.h> +#include <pulsecore/core-rtclock.h> #include "rtsp_client.h" +#define RECONNECT_INTERVAL (5 * PA_USEC_PER_SEC) + struct pa_rtsp_client { pa_mainloop_api *mainloop; char *hostname; @@ -73,9 +78,11 @@ struct pa_rtsp_client { uint32_t cseq; char *session; char *transport; + pa_time_event *reconnect_event; + bool autoreconnect; }; -pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char *hostname, uint16_t port, const char *useragent) { +pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char *hostname, uint16_t port, const char *useragent, bool autoreconnect) { pa_rtsp_client *c; pa_assert(mainloop); @@ -93,12 +100,23 @@ pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char *hostna else c->useragent = "PulseAudio RTSP Client"; + c->autoreconnect = autoreconnect; return c; } +static void free_events(pa_rtsp_client *c) { + pa_assert(c); + + if (c->reconnect_event) { + c->mainloop->time_free(c->reconnect_event); + c->reconnect_event = NULL; + } +} + void pa_rtsp_client_free(pa_rtsp_client *c) { pa_assert(c); + free_events(c); if (c->sc) pa_socket_client_unref(c->sc); @@ -293,6 +311,13 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) { pa_xfree(s2); } +static void reconnect_cb(pa_mainloop_api *a, pa_time_event *e, const struct timeval *t, void *userdata) { + if (userdata) { + pa_rtsp_client *c = userdata; + pa_rtsp_connect(c); + } +} + static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata) { pa_rtsp_client *c = userdata; union { @@ -310,7 +335,18 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata c->sc = NULL; if (!io) { - pa_log("Connection failed: %s", pa_cstrerror(errno)); + if (c->autoreconnect) { + struct timeval tv; + + pa_log_warn("Connection to server %s:%d failed: %s - will try later", c->hostname, c->port, pa_cstrerror(errno)); + + if (!c->reconnect_event) + c->reconnect_event = c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, pa_rtclock_now() + RECONNECT_INTERVAL, true), reconnect_cb, c); + else + c->mainloop->time_restart(c->reconnect_event, pa_timeval_rtstore(&tv, pa_rtclock_now() + RECONNECT_INTERVAL, true)); + } else { + pa_log("Connection to server %s:%d failed: %s", c->hostname, c->port, pa_cstrerror(errno)); + } return; } pa_assert(!c->ioline); diff --git a/src/modules/rtp/rtsp_client.h b/src/modules/rtp/rtsp_client.h index 4e031d8..2593085 100644 --- a/src/modules/rtp/rtsp_client.h +++ b/src/modules/rtp/rtsp_client.h @@ -54,7 +54,7 @@ typedef enum pa_rtsp_status { typedef void (*pa_rtsp_cb_t)(pa_rtsp_client *c, pa_rtsp_state_t state, pa_rtsp_status_t code, pa_headerlist *headers, void *userdata); -pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char *hostname, uint16_t port, const char *useragent); +pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char *hostname, uint16_t port, const char *useragent, bool autoreconnect); void pa_rtsp_client_free(pa_rtsp_client *c); int pa_rtsp_connect(pa_rtsp_client *c); diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c index 14953cf..6a2e0c9 100644 --- a/src/modules/rtp/sdp.c +++ b/src/modules/rtp/sdp.c @@ -89,15 +89,6 @@ static pa_sample_spec *parse_sdp_sample_spec(pa_sample_spec *ss, char *c) { if (pa_startswith(c, "L16/")) { ss->format = PA_SAMPLE_S16BE; c += 4; - } else if (pa_startswith(c, "L8/")) { - ss->format = PA_SAMPLE_U8; - c += 3; - } else if (pa_startswith(c, "PCMA/")) { - ss->format = PA_SAMPLE_ALAW; - c += 5; - } else if (pa_startswith(c, "PCMU/")) { - ss->format = PA_SAMPLE_ULAW; - c += 5; } else return NULL; diff --git a/src/modules/x11/module-x11-bell.c b/src/modules/x11/module-x11-bell.c index 0200359..eab1e6c 100644 --- a/src/modules/x11/module-x11-bell.c +++ b/src/modules/x11/module-x11-bell.c @@ -44,6 +44,7 @@ static const char* const valid_modargs[] = { "sink", "sample", "display", + "xauthority", NULL }; @@ -125,6 +126,13 @@ int pa__init(pa_module*m) { u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); u->x11_client = NULL; + if (pa_modargs_get_value(ma, "xauthority", NULL)) { + if (setenv("XAUTHORITY", pa_modargs_get_value(ma, "xauthority", NULL), 1)) { + pa_log("setenv() for $XAUTHORITY failed"); + goto fail; + } + } + if (!(u->x11_wrapper = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL)))) goto fail; diff --git a/src/modules/x11/module-x11-cork-request.c b/src/modules/x11/module-x11-cork-request.c index ab391c6..6b1a86b 100644 --- a/src/modules/x11/module-x11-cork-request.c +++ b/src/modules/x11/module-x11-cork-request.c @@ -46,6 +46,7 @@ PA_MODULE_USAGE("display=<X11 display>"); static const char* const valid_modargs[] = { "display", + "xauthority", NULL }; @@ -128,6 +129,13 @@ int pa__init(pa_module *m) { m->userdata = u = pa_xnew0(struct userdata, 1); u->module = m; + if (pa_modargs_get_value(ma, "xauthority", NULL)) { + if (setenv("XAUTHORITY", pa_modargs_get_value(ma, "xauthority", NULL), 1)) { + pa_log("setenv() for $XAUTHORITY failed"); + goto fail; + } + } + if (!(u->x11_wrapper = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL)))) goto fail; diff --git a/src/modules/x11/module-x11-publish.c b/src/modules/x11/module-x11-publish.c index e6735ec..68adf15 100644 --- a/src/modules/x11/module-x11-publish.c +++ b/src/modules/x11/module-x11-publish.c @@ -56,6 +56,7 @@ static const char* const valid_modargs[] = { "sink", "source", "cookie", + "xauthority", NULL }; @@ -156,6 +157,13 @@ int pa__init(pa_module*m) { if (!(u->auth_cookie = pa_auth_cookie_get(m->core, pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), true, PA_NATIVE_COOKIE_LENGTH))) goto fail; + if (pa_modargs_get_value(ma, "xauthority", NULL)) { + if (setenv("XAUTHORITY", pa_modargs_get_value(ma, "xauthority", NULL), 1)) { + pa_log("setenv() for $XAUTHORITY failed"); + goto fail; + } + } + if (!(u->x11_wrapper = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL)))) goto fail; diff --git a/src/modules/x11/module-x11-xsmp.c b/src/modules/x11/module-x11-xsmp.c index 6f80123..459da13 100644 --- a/src/modules/x11/module-x11-xsmp.c +++ b/src/modules/x11/module-x11-xsmp.c @@ -46,6 +46,7 @@ static bool ice_in_use = false; static const char* const valid_modargs[] = { "session_manager", "display", + "xauthority", NULL }; @@ -139,6 +140,13 @@ int pa__init(pa_module*m) { goto fail; } + if (pa_modargs_get_value(ma, "xauthority", NULL)) { + if (setenv("XAUTHORITY", pa_modargs_get_value(ma, "xauthority", NULL), 1)) { + pa_log("setenv() for $XAUTHORITY failed"); + goto fail; + } + } + if (!(u->x11 = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL)))) goto fail; diff --git a/src/pulse/context.c b/src/pulse/context.c index 180e687..1d1bb9e 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -274,6 +274,7 @@ static void context_free(pa_context *c) { pa_proplist_free(c->proplist); pa_xfree(c->server); + pa_xfree(c->error); pa_xfree(c); } diff --git a/src/pulse/gccmacro.h b/src/pulse/gccmacro.h index e5ba5bd..81729db 100644 --- a/src/pulse/gccmacro.h +++ b/src/pulse/gccmacro.h @@ -129,4 +129,42 @@ #endif #endif +#ifndef PA_LIKELY +#ifdef __GNUC__ +#define PA_LIKELY(x) (__builtin_expect(!!(x),1)) +#define PA_UNLIKELY(x) (__builtin_expect(!!(x),0)) +#else +#define PA_LIKELY(x) (x) +#define PA_UNLIKELY(x) (x) +#endif +#endif + +#ifdef __GNUC__ +#define PA_CLAMP(x, low, high) \ + __extension__ ({ \ + typeof(x) _x = (x); \ + typeof(low) _low = (low); \ + typeof(high) _high = (high); \ + ((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \ + }) +#else +#define PA_CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) +#endif + +#ifdef __GNUC__ +#define PA_CLAMP_UNLIKELY(x, low, high) \ + __extension__ ({ \ + typeof(x) _x = (x); \ + typeof(low) _low = (low); \ + typeof(high) _high = (high); \ + (PA_UNLIKELY(_x > _high) ? _high : (PA_UNLIKELY(_x < _low) ? _low : _x)); \ + }) +#else +#define PA_CLAMP_UNLIKELY(x, low, high) (PA_UNLIKELY((x) > (high)) ? (high) : (PA_UNLIKELY((x) < (low)) ? (low) : (x))) +#endif + +/* We don't define a PA_CLAMP_LIKELY here, because it doesn't really + * make sense: we cannot know if it is more likely that the value is + * lower or greater than the boundaries. */ + #endif diff --git a/src/pulse/meson.build b/src/pulse/meson.build index 00c6867..aaebff5 100644 --- a/src/pulse/meson.build +++ b/src/pulse/meson.build @@ -81,14 +81,14 @@ libpulse = shared_library('pulse', link_args : [nodelete_link_args, versioning_link_args], install : true, install_rpath : privlibdir, - dependencies : [libm_dep, thread_dep, libpulsecommon_dep, dbus_dep, dl_dep, iconv_dep], + dependencies : [libm_dep, thread_dep, libpulsecommon_dep, dbus_dep, dl_dep, iconv_dep, libintl_dep], implicit_include_directories : false) libpulse_dep = declare_dependency(link_with: libpulse) -install_data( +install_headers( libpulse_headers, 'simple.h', - install_dir : join_paths(includedir, 'pulse') + subdir : 'pulse' ) libpulse_simple = shared_library('pulse-simple', diff --git a/src/pulse/stream.h b/src/pulse/stream.h index 7913f7f..f9b52d4 100644 --- a/src/pulse/stream.h +++ b/src/pulse/stream.h @@ -414,7 +414,7 @@ int pa_stream_is_corked(const pa_stream *s); * Returns zero on success. */ int pa_stream_connect_playback( pa_stream *s /**< The stream to connect to a sink */, - const char *dev /**< Name of the sink to connect to, or NULL for default */ , + const char *dev /**< Name of the sink to connect to, or NULL to let the server decide */ , const pa_buffer_attr *attr /**< Buffering attributes, or NULL for default */, pa_stream_flags_t flags /**< Additional flags, or 0 for default */, const pa_cvolume *volume /**< Initial volume, or NULL for default */, @@ -423,7 +423,7 @@ int pa_stream_connect_playback( /** Connect the stream to a source. Returns zero on success. */ int pa_stream_connect_record( pa_stream *s /**< The stream to connect to a source */ , - const char *dev /**< Name of the source to connect to, or NULL for default */, + const char *dev /**< Name of the source to connect to, or NULL to let the server decide */, const pa_buffer_attr *attr /**< Buffer attributes, or NULL for default */, pa_stream_flags_t flags /**< Additional flags, or 0 for default */); diff --git a/src/pulse/version.h b/src/pulse/version.h index cac3638..c01760a 100644 --- a/src/pulse/version.h +++ b/src/pulse/version.h @@ -33,7 +33,7 @@ PA_C_DECL_BEGIN /** Return the version of the header files. Keep in mind that this is a macro and not a function, so it is impossible to get the pointer of it. */ -#define pa_get_headers_version() ("13.0.0") +#define pa_get_headers_version() ("13.99.0") /** Return the version of the library the current application is * linked to. */ @@ -53,7 +53,7 @@ const char* pa_get_library_version(void); #define PA_MAJOR 13 /** The minor version of PA. \since 0.9.15 */ -#define PA_MINOR 0 +#define PA_MINOR 99 /** The micro version of PA (will always be 0 from v1.0 onwards). \since 0.9.15 */ #define PA_MICRO 0 diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h index a82ca83..e5c1401 100644 --- a/src/pulsecore/atomic.h +++ b/src/pulsecore/atomic.h @@ -117,7 +117,7 @@ static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) { } static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void* p) { - __atomic_store_n(&a->value, p, __ATOMIC_SEQ_CST); + __atomic_store_n(&a->value, (unsigned long) p, __ATOMIC_SEQ_CST); } #else diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 270acd8..601b1d1 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -784,12 +784,16 @@ void pa_reset_priority(void) { #endif } +/* Check whenever any substring in v matches the provided regex. */ int pa_match(const char *expr, const char *v) { #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) int k; regex_t re; int r; + pa_assert(expr); + pa_assert(v); + if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) { errno = EINVAL; return -1; @@ -814,6 +818,22 @@ int pa_match(const char *expr, const char *v) { #endif } +/* Check whenever the provided regex pattern is valid. */ +bool pa_is_regex_valid(const char *expr) { +#if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) + regex_t re; + + if (expr == NULL || regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) { + return false; + } + + regfree(&re); + return true; +#else + return false; +#endif +} + /* Try to parse a boolean string value.*/ int pa_parse_boolean(const char *v) { pa_assert(v); @@ -859,7 +879,7 @@ int pa_parse_volume(const char *v, pa_volume_t *volume) { len = strlen(v); - if (len >= 64) + if (len <= 0 || len >= 64) return -1; memcpy(str, v, len + 1); @@ -1428,7 +1448,7 @@ static int check_ours(const char *p) { return -errno; #ifdef HAVE_GETUID - if (st.st_uid != getuid()) + if (st.st_uid != getuid() && st.st_uid != 0) return -EACCES; #endif @@ -2873,6 +2893,32 @@ bool pa_str_in_list_spaces(const char *haystack, const char *needle) { return false; } +char* pa_str_strip_suffix(const char *str, const char *suffix) { + size_t str_l, suf_l, prefix; + char *ret; + + pa_assert(str); + pa_assert(suffix); + + str_l = strlen(str); + suf_l = strlen(suffix); + + if (str_l < suf_l) + return NULL; + + prefix = str_l - suf_l; + + if (!pa_streq(&str[prefix], suffix)) + return NULL; + + ret = pa_xmalloc(prefix + 1); + + strncpy(ret, str, prefix); + ret[prefix] = '\0'; + + return ret; +} + char *pa_get_user_name_malloc(void) { ssize_t k; char *u; diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index cfb9eb2..9440af9 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -158,6 +158,7 @@ size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap); char *pa_truncate_utf8(char *c, size_t l); int pa_match(const char *expr, const char *v); +bool pa_is_regex_valid(const char *expr); char *pa_getcwd(void); char *pa_make_path_absolute(const char *p); @@ -231,6 +232,8 @@ static inline bool pa_safe_streq(const char *a, const char *b) { bool pa_str_in_list_spaces(const char *needle, const char *haystack); bool pa_str_in_list(const char *haystack, const char *delimiters, const char *needle); +char* pa_str_strip_suffix(const char *str, const char *suffix); + char *pa_get_host_name_malloc(void); char *pa_get_user_name_malloc(void); diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index e5bb2e4..335f802 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -144,7 +144,8 @@ pa_core* pa_core_new(pa_mainloop_api *m, bool shared, bool enable_memfd, size_t c->realtime_priority = 5; c->disable_remixing = false; c->remixing_use_all_sink_channels = true; - c->disable_lfe_remixing = true; + c->remixing_produce_lfe = false; + c->remixing_consume_lfe = false; c->lfe_crossover_freq = 0; c->deferred_volume = true; c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 1; @@ -349,6 +350,10 @@ void pa_core_update_default_sink(pa_core *core) { pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX); pa_hook_fire(&core->hooks[PA_CORE_HOOK_DEFAULT_SINK_CHANGED], core->default_sink); + + /* try to move the streams from old_default_sink to the new default_sink conditionally */ + if (old_default_sink) + pa_sink_move_streams_to_default_sink(core, old_default_sink, true); } /* a < b -> return -1 @@ -430,6 +435,10 @@ void pa_core_update_default_source(pa_core *core) { old_default_source ? old_default_source->name : "(unset)", best ? best->name : "(unset)"); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX); pa_hook_fire(&core->hooks[PA_CORE_HOOK_DEFAULT_SOURCE_CHANGED], core->default_source); + + /* try to move the streams from old_default_source to the new default_source conditionally */ + if (old_default_source) + pa_source_move_streams_to_default_source(core, old_default_source, true); } void pa_core_set_exit_idle_time(pa_core *core, int time) { @@ -519,6 +528,72 @@ void pa_core_rttime_restart(pa_core *c, pa_time_event *e, pa_usec_t usec) { c->mainloop->time_restart(e, pa_timeval_rtstore(&tv, usec, true)); } +void pa_core_move_streams_to_newly_available_preferred_sink(pa_core *c, pa_sink *s) { + pa_sink_input *si; + uint32_t idx; + + pa_assert(c); + pa_assert(s); + + PA_IDXSET_FOREACH(si, c->sink_inputs, idx) { + if (si->sink == s) + continue; + + if (!si->sink) + continue; + + /* Skip this sink input if it is connecting a filter sink to + * the master */ + if (si->origin_sink) + continue; + + /* It might happen that a stream and a sink are set up at the + same time, in which case we want to make sure we don't + interfere with that */ + if (!PA_SINK_INPUT_IS_LINKED(si->state)) + continue; + + if (pa_safe_streq(si->preferred_sink, s->name)) + pa_sink_input_move_to(si, s, false); + } + +} + +void pa_core_move_streams_to_newly_available_preferred_source(pa_core *c, pa_source *s) { + pa_source_output *so; + uint32_t idx; + + pa_assert(c); + pa_assert(s); + + PA_IDXSET_FOREACH(so, c->source_outputs, idx) { + if (so->source == s) + continue; + + if (so->direct_on_input) + continue; + + if (!so->source) + continue; + + /* Skip this source output if it is connecting a filter source to + * the master */ + if (so->destination_source) + continue; + + /* It might happen that a stream and a source are set up at the + same time, in which case we want to make sure we don't + interfere with that */ + if (!PA_SOURCE_OUTPUT_IS_LINKED(so->state)) + continue; + + if (pa_safe_streq(so->preferred_source, s->name)) + pa_source_output_move_to(so, s, false); + } + +} + + /* Helper macro to reduce repetition in pa_suspend_cause_to_string(). * Parameters: * char *p: the current position in the write buffer diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index d03897c..57924b9 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -213,6 +213,7 @@ struct pa_core { int exit_idle_time, scache_idle_time; bool flat_volumes:1; + bool rescue_streams:1; bool disallow_module_loading:1; bool disallow_exit:1; bool running_as_daemon:1; @@ -220,7 +221,8 @@ struct pa_core { bool avoid_resampling:1; bool disable_remixing:1; bool remixing_use_all_sink_channels:1; - bool disable_lfe_remixing:1; + bool remixing_produce_lfe:1; + bool remixing_consume_lfe:1; bool deferred_volume:1; pa_resample_method_t resample_method; @@ -278,4 +280,8 @@ static const size_t PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE = * provided buffer. The same buffer is the return value of this function. */ const char *pa_suspend_cause_to_string(pa_suspend_cause_t cause, char buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE]); +void pa_core_move_streams_to_newly_available_preferred_sink(pa_core *c, pa_sink *s); + +void pa_core_move_streams_to_newly_available_preferred_source(pa_core *c, pa_source *s); + #endif diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c index fb12772..b104c49 100644 --- a/src/pulsecore/device-port.c +++ b/src/pulsecore/device-port.c @@ -100,6 +100,30 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t status) { else pa_core_update_default_source(p->core); + if (p->direction == PA_DIRECTION_OUTPUT) { + pa_sink *sink; + + sink = pa_device_port_get_sink(p); + if (sink && p == sink->active_port) { + if (sink->active_port->available == PA_AVAILABLE_NO) { + if (p->core->rescue_streams) + pa_sink_move_streams_to_default_sink(p->core, sink, false); + } else + pa_core_move_streams_to_newly_available_preferred_sink(p->core, sink); + } + } else { + pa_source *source; + + source = pa_device_port_get_source(p); + if (source && p == source->active_port) { + if (source->active_port->available == PA_AVAILABLE_NO) { + if (p->core->rescue_streams) + pa_source_move_streams_to_default_source(p->core, source, false); + } else + pa_core_move_streams_to_newly_available_preferred_source(p->core, source); + } + } + pa_subscription_post(p->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, p->card->index); pa_hook_fire(&p->core->hooks[PA_CORE_HOOK_PORT_AVAILABLE_CHANGED], p); } @@ -224,3 +248,29 @@ pa_device_port *pa_device_port_find_best(pa_hashmap *ports) return best; } + +pa_sink *pa_device_port_get_sink(pa_device_port *p) { + pa_sink *rs = NULL; + pa_sink *sink; + uint32_t state; + + PA_IDXSET_FOREACH(sink, p->card->sinks, state) + if (p == pa_hashmap_get(sink->ports, p->name)) { + rs = sink; + break; + } + return rs; +} + +pa_source *pa_device_port_get_source(pa_device_port *p) { + pa_source *rs = NULL; + pa_source *source; + uint32_t state; + + PA_IDXSET_FOREACH(source, p->card->sources, state) + if (p == pa_hashmap_get(source->ports, p->name)) { + rs = source; + break; + } + return rs; +} diff --git a/src/pulsecore/device-port.h b/src/pulsecore/device-port.h index fbdce1a..41198f6 100644 --- a/src/pulsecore/device-port.h +++ b/src/pulsecore/device-port.h @@ -87,4 +87,8 @@ void pa_device_port_set_preferred_profile(pa_device_port *p, const char *new_pp) pa_device_port *pa_device_port_find_best(pa_hashmap *ports); +pa_sink *pa_device_port_get_sink(pa_device_port *p); + +pa_source *pa_device_port_get_source(pa_device_port *p); + #endif diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h index bb15b7f..ec8d31c 100644 --- a/src/pulsecore/macro.h +++ b/src/pulsecore/macro.h @@ -34,16 +34,6 @@ #error "Please include config.h before including this file!" #endif -#ifndef PA_LIKELY -#ifdef __GNUC__ -#define PA_LIKELY(x) (__builtin_expect(!!(x),1)) -#define PA_UNLIKELY(x) (__builtin_expect(!!(x),0)) -#else -#define PA_LIKELY(x) (x) -#define PA_UNLIKELY(x) (x) -#endif -#endif - /* Rounds down */ static inline void* PA_ALIGN_PTR(const void *p) { return (void*) (((size_t) p) & ~(sizeof(void*) - 1)); @@ -100,34 +90,6 @@ static inline size_t PA_ALIGN(size_t l) { #endif #ifdef __GNUC__ -#define PA_CLAMP(x, low, high) \ - __extension__ ({ \ - typeof(x) _x = (x); \ - typeof(low) _low = (low); \ - typeof(high) _high = (high); \ - ((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \ - }) -#else -#define PA_CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) -#endif - -#ifdef __GNUC__ -#define PA_CLAMP_UNLIKELY(x, low, high) \ - __extension__ ({ \ - typeof(x) _x = (x); \ - typeof(low) _low = (low); \ - typeof(high) _high = (high); \ - (PA_UNLIKELY(_x > _high) ? _high : (PA_UNLIKELY(_x < _low) ? _low : _x)); \ - }) -#else -#define PA_CLAMP_UNLIKELY(x, low, high) (PA_UNLIKELY((x) > (high)) ? (high) : (PA_UNLIKELY((x) < (low)) ? (low) : (x))) -#endif - -/* We don't define a PA_CLAMP_LIKELY here, because it doesn't really - * make sense: we cannot know if it is more likely that the values is - * lower or greater than the boundaries.*/ - -#ifdef __GNUC__ #define PA_ROUND_UP(a, b) \ __extension__ ({ \ typeof(a) _a = (a); \ diff --git a/src/pulsecore/meson.build b/src/pulsecore/meson.build index 19f6b9e..0bd596c 100644 --- a/src/pulsecore/meson.build +++ b/src/pulsecore/meson.build @@ -198,7 +198,7 @@ libpulsecore = shared_library('pulsecore-' + pa_version_major_minor, install_rpath : privlibdir, install_dir : privlibdir, link_with : libpulsecore_simd_lib, - dependencies : [libm_dep, libpulsecommon_dep, libpulse_dep, ltdl_dep, shm_dep, sndfile_dep, database_dep, dbus_dep, libatomic_ops_dep, orc_dep, samplerate_dep, soxr_dep, speex_dep, x11_dep], + dependencies : [libm_dep, libpulsecommon_dep, libpulse_dep, ltdl_dep, shm_dep, sndfile_dep, database_dep, dbus_dep, libatomic_ops_dep, orc_dep, samplerate_dep, soxr_dep, speex_dep, x11_dep, libintl_dep], implicit_include_directories : false) libpulsecore_dep = declare_dependency(link_with: libpulsecore) diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index ff9795e..58463f1 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -1099,7 +1099,7 @@ static void setup_remap(const pa_resampler *r, pa_remap_t *m, bool *lfe_remixed) * right input channel. Something is really wrong in this * case anyway. */ - } else if (on_lfe(b) && !(r->flags & PA_RESAMPLER_NO_LFE)) { + } else if (on_lfe(b) && (r->flags & PA_RESAMPLER_PRODUCE_LFE)) { /* We are not connected and an LFE. Let's average all * channels for LFE. */ @@ -1150,7 +1150,7 @@ static void setup_remap(const pa_resampler *r, pa_remap_t *m, bool *lfe_remixed) m->map_table_f[oc][ic] = (1.f/9.f) / (float) ic_unconnected_center; ic_unconnected_center_mixed_in = true; - } else if (on_lfe(a) && !(r->flags & PA_RESAMPLER_NO_LFE)) + } else if (on_lfe(a) && (r->flags & PA_RESAMPLER_CONSUME_LFE)) m->map_table_f[oc][ic] = .375f / (float) ic_unconnected_lfe; } } diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h index 5d3171f..5a264b3 100644 --- a/src/pulsecore/resampler.h +++ b/src/pulsecore/resampler.h @@ -68,8 +68,9 @@ typedef enum pa_resample_flags { PA_RESAMPLER_VARIABLE_RATE = 0x0001U, PA_RESAMPLER_NO_REMAP = 0x0002U, /* implies NO_REMIX */ PA_RESAMPLER_NO_REMIX = 0x0004U, - PA_RESAMPLER_NO_LFE = 0x0008U, PA_RESAMPLER_NO_FILL_SINK = 0x0010U, + PA_RESAMPLER_PRODUCE_LFE = 0x0020U, + PA_RESAMPLER_CONSUME_LFE = 0x0040U, } pa_resample_flags_t; struct pa_resampler { diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c index 98cf88f..1085bf9 100644 --- a/src/pulsecore/rtpoll.c +++ b/src/pulsecore/rtpoll.c @@ -77,7 +77,9 @@ struct pa_rtpoll_item { int (*work_cb)(pa_rtpoll_item *i); int (*before_cb)(pa_rtpoll_item *i); void (*after_cb)(pa_rtpoll_item *i); - void *userdata; + void *work_userdata; + void *before_userdata; + void *after_userdata; PA_LLIST_FIELDS(pa_rtpoll_item); }; @@ -411,7 +413,9 @@ pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsi i->pollfd = NULL; i->priority = prio; - i->userdata = NULL; + i->work_userdata = NULL; + i->before_userdata = NULL; + i->work_userdata = NULL; i->before_cb = NULL; i->after_cb = NULL; i->work_cb = NULL; @@ -458,42 +462,39 @@ struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds) { return i->pollfd; } -void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i)) { +void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i), void *userdata) { pa_assert(i); pa_assert(i->priority < PA_RTPOLL_NEVER); i->before_cb = before_cb; + i->before_userdata = userdata; } -void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i)) { +void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i), void *userdata) { pa_assert(i); pa_assert(i->priority < PA_RTPOLL_NEVER); i->after_cb = after_cb; + i->after_userdata = userdata; } -void pa_rtpoll_item_set_work_callback(pa_rtpoll_item *i, int (*work_cb)(pa_rtpoll_item *i)) { +void pa_rtpoll_item_set_work_callback(pa_rtpoll_item *i, int (*work_cb)(pa_rtpoll_item *i), void *userdata) { pa_assert(i); pa_assert(i->priority < PA_RTPOLL_NEVER); i->work_cb = work_cb; + i->work_userdata = userdata; } -void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata) { +void* pa_rtpoll_item_get_work_userdata(pa_rtpoll_item *i) { pa_assert(i); - i->userdata = userdata; -} - -void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i) { - pa_assert(i); - - return i->userdata; + return i->work_userdata; } static int fdsem_before(pa_rtpoll_item *i) { - if (pa_fdsem_before_poll(i->userdata) < 0) + if (pa_fdsem_before_poll(i->before_userdata) < 0) return 1; /* 1 means immediate restart of the loop */ return 0; @@ -503,7 +504,7 @@ static void fdsem_after(pa_rtpoll_item *i) { pa_assert(i); pa_assert((i->pollfd[0].revents & ~POLLIN) == 0); - pa_fdsem_after_poll(i->userdata); + pa_fdsem_after_poll(i->after_userdata); } pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_fdsem *f) { @@ -520,9 +521,8 @@ pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio pollfd->fd = pa_fdsem_get(f); pollfd->events = POLLIN; - i->before_cb = fdsem_before; - i->after_cb = fdsem_after; - i->userdata = f; + pa_rtpoll_item_set_before_callback(i, fdsem_before, f); + pa_rtpoll_item_set_after_callback(i, fdsem_after, f); return i; } @@ -530,7 +530,7 @@ pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio static int asyncmsgq_read_before(pa_rtpoll_item *i) { pa_assert(i); - if (pa_asyncmsgq_read_before_poll(i->userdata) < 0) + if (pa_asyncmsgq_read_before_poll(i->before_userdata) < 0) return 1; /* 1 means immediate restart of the loop */ return 0; @@ -540,7 +540,7 @@ static void asyncmsgq_read_after(pa_rtpoll_item *i) { pa_assert(i); pa_assert((i->pollfd[0].revents & ~POLLIN) == 0); - pa_asyncmsgq_read_after_poll(i->userdata); + pa_asyncmsgq_read_after_poll(i->after_userdata); } static int asyncmsgq_read_work(pa_rtpoll_item *i) { @@ -552,11 +552,11 @@ static int asyncmsgq_read_work(pa_rtpoll_item *i) { pa_assert(i); - if (pa_asyncmsgq_get(i->userdata, &object, &code, &data, &offset, &chunk, 0) == 0) { + if (pa_asyncmsgq_get(i->work_userdata, &object, &code, &data, &offset, &chunk, 0) == 0) { int ret; if (!object && code == PA_MESSAGE_SHUTDOWN) { - pa_asyncmsgq_done(i->userdata, 0); + pa_asyncmsgq_done(i->work_userdata, 0); /* Requests the loop to exit. Will cause the next iteration of * pa_rtpoll_run() to return 0 */ i->rtpoll->quit = true; @@ -564,7 +564,7 @@ static int asyncmsgq_read_work(pa_rtpoll_item *i) { } ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk); - pa_asyncmsgq_done(i->userdata, ret); + pa_asyncmsgq_done(i->work_userdata, ret); return 1; } @@ -584,10 +584,9 @@ pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_read(pa_rtpoll *p, pa_rtpoll_priori pollfd->fd = pa_asyncmsgq_read_fd(q); pollfd->events = POLLIN; - i->before_cb = asyncmsgq_read_before; - i->after_cb = asyncmsgq_read_after; - i->work_cb = asyncmsgq_read_work; - i->userdata = q; + pa_rtpoll_item_set_before_callback(i, asyncmsgq_read_before, q); + pa_rtpoll_item_set_after_callback(i, asyncmsgq_read_after, q); + pa_rtpoll_item_set_work_callback(i, asyncmsgq_read_work, q); return i; } @@ -595,7 +594,7 @@ pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_read(pa_rtpoll *p, pa_rtpoll_priori static int asyncmsgq_write_before(pa_rtpoll_item *i) { pa_assert(i); - pa_asyncmsgq_write_before_poll(i->userdata); + pa_asyncmsgq_write_before_poll(i->before_userdata); return 0; } @@ -603,7 +602,7 @@ static void asyncmsgq_write_after(pa_rtpoll_item *i) { pa_assert(i); pa_assert((i->pollfd[0].revents & ~POLLIN) == 0); - pa_asyncmsgq_write_after_poll(i->userdata); + pa_asyncmsgq_write_after_poll(i->after_userdata); } pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_write(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q) { @@ -619,10 +618,8 @@ pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_write(pa_rtpoll *p, pa_rtpoll_prior pollfd->fd = pa_asyncmsgq_write_fd(q); pollfd->events = POLLIN; - i->before_cb = asyncmsgq_write_before; - i->after_cb = asyncmsgq_write_after; - i->work_cb = NULL; - i->userdata = q; + pa_rtpoll_item_set_before_callback(i, asyncmsgq_write_before, q); + pa_rtpoll_item_set_after_callback(i, asyncmsgq_write_after, q); return i; } diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h index 8f0715a..121b51e 100644 --- a/src/pulsecore/rtpoll.h +++ b/src/pulsecore/rtpoll.h @@ -80,19 +80,18 @@ struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds); /* Set the callback that shall be called when there's time to do some work: If the * callback returns a value > 0, the poll is skipped and the next * iteration of the loop will start immediately. */ -void pa_rtpoll_item_set_work_callback(pa_rtpoll_item *i, int (*work_cb)(pa_rtpoll_item *i)); +void pa_rtpoll_item_set_work_callback(pa_rtpoll_item *i, int (*work_cb)(pa_rtpoll_item *i), void *userdata); /* Set the callback that shall be called immediately before entering * the sleeping poll: If the callback returns a value > 0, the poll is * skipped and the next iteration of the loop will start immediately. */ -void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i)); +void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i), void *userdata); /* Set the callback that shall be called immediately after having * entered the sleeping poll */ -void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i)); +void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i), void *userdata); -void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata); -void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i); +void* pa_rtpoll_item_get_work_userdata(pa_rtpoll_item *i); pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_fdsem *s); pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_read(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q); diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index d3ead2c..12e3c8b 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -190,7 +190,10 @@ bool pa_sink_input_new_data_set_sink(pa_sink_input_new_data *data, pa_sink *s, b if (!data->req_formats) { /* We're not working with the extended API */ data->sink = s; - data->save_sink = save; + if (save) { + pa_xfree(data->preferred_sink); + data->preferred_sink = pa_xstrdup(s->name); + } data->sink_requested_by_application = requested_by_application; } else { /* Extended API: let's see if this sink supports the formats the client can provide */ @@ -199,7 +202,10 @@ bool pa_sink_input_new_data_set_sink(pa_sink_input_new_data *data, pa_sink *s, b if (formats && !pa_idxset_isempty(formats)) { /* Sink supports at least one of the requested formats */ data->sink = s; - data->save_sink = save; + if (save) { + pa_xfree(data->preferred_sink); + data->preferred_sink = pa_xstrdup(s->name); + } data->sink_requested_by_application = requested_by_application; if (data->nego_formats) pa_idxset_free(data->nego_formats, (pa_free_cb_t) pa_format_info_free); @@ -226,7 +232,7 @@ bool pa_sink_input_new_data_set_formats(pa_sink_input_new_data *data, pa_idxset if (data->sink) { /* Trigger format negotiation */ - return pa_sink_input_new_data_set_sink(data, data->sink, data->save_sink, data->sink_requested_by_application); + return pa_sink_input_new_data_set_sink(data, data->sink, (data->preferred_sink != NULL), data->sink_requested_by_application); } return true; @@ -250,6 +256,9 @@ void pa_sink_input_new_data_done(pa_sink_input_new_data *data) { if (data->volume_factor_sink_items) pa_hashmap_free(data->volume_factor_sink_items); + if (data->preferred_sink) + pa_xfree(data->preferred_sink); + pa_proplist_free(data->proplist); } @@ -467,7 +476,8 @@ int pa_sink_input_new( ((data->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | (core->disable_remixing || (data->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) | (core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) | - (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) { + (core->remixing_produce_lfe ? PA_RESAMPLER_PRODUCE_LFE : 0) | + (core->remixing_consume_lfe ? PA_RESAMPLER_CONSUME_LFE : 0)))) { pa_log_warn("Unsupported resampling operation."); return -PA_ERR_NOTSUPPORTED; } @@ -518,7 +528,7 @@ int pa_sink_input_new( pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels); i->volume_writable = data->volume_writable; i->save_volume = data->save_volume; - i->save_sink = data->save_sink; + i->preferred_sink = pa_xstrdup(data->preferred_sink); i->save_muted = data->save_muted; i->muted = data->muted; @@ -776,6 +786,9 @@ static void sink_input_free(pa_object *o) { if (i->volume_factor_sink_items) pa_hashmap_free(i->volume_factor_sink_items); + if (i->preferred_sink) + pa_xfree(i->preferred_sink); + pa_xfree(i->driver); pa_xfree(i); } @@ -1914,7 +1927,16 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, bool save) { i->moving(i, dest); i->sink = dest; - i->save_sink = save; + /* save == true, means user is calling the move_to() and want to + save the preferred_sink */ + if (save) { + pa_xfree(i->preferred_sink); + if (dest == dest->core->default_sink) + i->preferred_sink = NULL; + else + i->preferred_sink = pa_xstrdup(dest->name); + } + pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL); PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state) @@ -1957,6 +1979,12 @@ void pa_sink_input_fail_move(pa_sink_input *i) { if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_STOP) return; + /* Can we move the sink input to the default sink? */ + if (i->core->rescue_streams && pa_sink_input_may_move_to(i, i->core->default_sink)) { + if (pa_sink_input_finish_move(i, i->core->default_sink, false) >= 0) + return; + } + if (i->moving) i->moving(i, NULL); @@ -2292,7 +2320,8 @@ int pa_sink_input_update_resampler(pa_sink_input *i) { ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) | (i->core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) | - (i->core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)); + (i->core->remixing_produce_lfe ? PA_RESAMPLER_PRODUCE_LFE : 0) | + (i->core->remixing_consume_lfe ? PA_RESAMPLER_CONSUME_LFE : 0)); if (!new_resampler) { pa_log_warn("Unsupported resampling operation."); @@ -2404,3 +2433,17 @@ void pa_sink_input_set_reference_ratio(pa_sink_input *i, const pa_cvolume *ratio pa_cvolume_snprint_verbose(old_ratio_str, sizeof(old_ratio_str), &old_ratio, &i->channel_map, true), pa_cvolume_snprint_verbose(new_ratio_str, sizeof(new_ratio_str), ratio, &i->channel_map, true)); } + +/* Called from the main thread. */ +void pa_sink_input_set_preferred_sink(pa_sink_input *i, pa_sink *s) { + pa_assert(i); + + pa_xfree(i->preferred_sink); + if (s) { + i->preferred_sink = pa_xstrdup(s->name); + pa_sink_input_move_to(i, s, false); + } else { + i->preferred_sink = NULL; + pa_sink_input_move_to(i, i->core->default_sink, false); + } +} diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index f7f9237..d3de6e3 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -119,11 +119,16 @@ struct pa_sink_input { bool muted:1; - /* if true then the sink we are connected to and/or the volume - * set is worth remembering, i.e. was explicitly chosen by the - * user and not automatically. module-stream-restore looks for + /* if true then the volume and the mute state of this sink-input + * are worth remembering, module-stream-restore looks for * this.*/ - bool save_sink:1, save_volume:1, save_muted:1; + bool save_volume:1, save_muted:1; + + /* if users move the sink-input to a sink, and the sink is not default_sink, + * the sink->name will be saved in preferred_sink. And later if sink-input + * is moved to other sinks for some reason, it still can be restored to the + * preferred_sink at an appropriate time */ + char *preferred_sink; pa_resample_method_t requested_resample_method, actual_resample_method; @@ -315,7 +320,9 @@ typedef struct pa_sink_input_new_data { bool volume_writable:1; - bool save_sink:1, save_volume:1, save_muted:1; + bool save_volume:1, save_muted:1; + + char *preferred_sink; } pa_sink_input_new_data; pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data); @@ -454,6 +461,8 @@ void pa_sink_input_set_volume_direct(pa_sink_input *i, const pa_cvolume *volume) * i->reference_ratio and logs a message if the value changes. */ void pa_sink_input_set_reference_ratio(pa_sink_input *i, const pa_cvolume *ratio); +void pa_sink_input_set_preferred_sink(pa_sink_input *i, pa_sink *s); + #define pa_sink_input_assert_io_context(s) \ pa_assert(pa_thread_mq_get() || !PA_SINK_INPUT_IS_LINKED((s)->state)) diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 55e9af3..11c3849 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -724,9 +724,14 @@ void pa_sink_put(pa_sink* s) { pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index); pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PUT], s); - /* This function must be called after the PA_CORE_HOOK_SINK_PUT hook, - * because module-switch-on-connect needs to know the old default sink */ + /* It's good to fire the SINK_PUT hook before updating the default sink, + * because module-switch-on-connect will set the new sink as the default + * sink, and if we were to call pa_core_update_default_sink() before that, + * the default sink might change twice, causing unnecessary stream moving. */ + pa_core_update_default_sink(s->core); + + pa_core_move_streams_to_newly_available_preferred_sink(s->core, s); } /* Called from main context */ @@ -757,6 +762,9 @@ void pa_sink_unlink(pa_sink* s) { pa_core_update_default_sink(s->core); + if (linked && s->core->rescue_streams) + pa_sink_move_streams_to_default_sink(s->core, s, false); + if (s->card) pa_idxset_remove_by_data(s->card->sinks, s, NULL); @@ -3931,3 +3939,44 @@ void pa_sink_set_reference_volume_direct(pa_sink *s, const pa_cvolume *volume) { pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_VOLUME_CHANGED], s); } + +void pa_sink_move_streams_to_default_sink(pa_core *core, pa_sink *old_sink, bool default_sink_changed) { + pa_sink_input *i; + uint32_t idx; + + pa_assert(core); + pa_assert(old_sink); + + if (core->state == PA_CORE_SHUTDOWN) + return; + + if (core->default_sink == NULL || core->default_sink->unlink_requested) + return; + + if (old_sink == core->default_sink) + return; + + PA_IDXSET_FOREACH(i, old_sink->inputs, idx) { + if (!PA_SINK_INPUT_IS_LINKED(i->state)) + continue; + + if (!i->sink) + continue; + + /* If default_sink_changed is false, the old sink became unavailable, so all streams must be moved. */ + if (pa_safe_streq(old_sink->name, i->preferred_sink) && default_sink_changed) + continue; + + if (!pa_sink_input_may_move_to(i, core->default_sink)) + continue; + + if (default_sink_changed) + pa_log_info("The sink input %u \"%s\" is moving to %s due to change of the default sink.", + i->index, pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), core->default_sink->name); + else + pa_log_info("The sink input %u \"%s\" is moving to %s, because the old sink became unavailable.", + i->index, pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), core->default_sink->name); + + pa_sink_input_move_to(i, core->default_sink, false); + } +} diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index b9dd64f..1778eb7 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -558,6 +558,12 @@ int64_t pa_sink_get_latency_within_thread(pa_sink *s, bool allow_negative); * s->reference_volume and fires change notifications. */ void pa_sink_set_reference_volume_direct(pa_sink *s, const pa_cvolume *volume); +/* When the default_sink is changed or the active_port of a sink is changed to + * PA_AVAILABLE_NO, this function is called to move the streams of the old + * default_sink or the sink with active_port equals PA_AVAILABLE_NO to the + * current default_sink conditionally*/ +void pa_sink_move_streams_to_default_sink(pa_core *core, pa_sink *old_sink, bool default_sink_changed); + /* Verify that we called in IO context (aka 'thread context), or that * the sink is not yet set up, i.e. the thread not set up yet. See * pa_assert_io_context() in thread-mq.h for more information. */ diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index f5005ab..92f74d4 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -134,7 +134,10 @@ bool pa_source_output_new_data_set_source(pa_source_output_new_data *data, pa_so if (!data->req_formats) { /* We're not working with the extended API */ data->source = s; - data->save_source = save; + if (save) { + pa_xfree(data->preferred_source); + data->preferred_source = pa_xstrdup(s->name); + } data->source_requested_by_application = requested_by_application; } else { /* Extended API: let's see if this source supports the formats the client would like */ @@ -143,7 +146,10 @@ bool pa_source_output_new_data_set_source(pa_source_output_new_data *data, pa_so if (formats && !pa_idxset_isempty(formats)) { /* Source supports at least one of the requested formats */ data->source = s; - data->save_source = save; + if (save) { + pa_xfree(data->preferred_source); + data->preferred_source = pa_xstrdup(s->name); + } data->source_requested_by_application = requested_by_application; if (data->nego_formats) pa_idxset_free(data->nego_formats, (pa_free_cb_t) pa_format_info_free); @@ -170,7 +176,7 @@ bool pa_source_output_new_data_set_formats(pa_source_output_new_data *data, pa_i if (data->source) { /* Trigger format negotiation */ - return pa_source_output_new_data_set_source(data, data->source, data->save_source, + return pa_source_output_new_data_set_source(data, data->source, (data->preferred_source != NULL), data->source_requested_by_application); } @@ -189,6 +195,9 @@ void pa_source_output_new_data_done(pa_source_output_new_data *data) { if (data->format) pa_format_info_free(data->format); + if (data->preferred_source) + pa_xfree(data->preferred_source); + pa_proplist_free(data->proplist); } @@ -414,7 +423,8 @@ int pa_source_output_new( ((data->flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | (core->disable_remixing || (data->flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) | (core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) | - (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) { + (core->remixing_produce_lfe ? PA_RESAMPLER_PRODUCE_LFE : 0) | + (core->remixing_consume_lfe ? PA_RESAMPLER_CONSUME_LFE : 0)))) { pa_log_warn("Unsupported resampling operation."); return -PA_ERR_NOTSUPPORTED; } @@ -459,7 +469,7 @@ int pa_source_output_new( pa_cvolume_reset(&o->real_ratio, o->sample_spec.channels); o->volume_writable = data->volume_writable; o->save_volume = data->save_volume; - o->save_source = data->save_source; + o->preferred_source = pa_xstrdup(data->preferred_source); o->save_muted = data->save_muted; o->muted = data->muted; @@ -651,6 +661,9 @@ static void source_output_free(pa_object* mo) { if (o->proplist) pa_proplist_free(o->proplist); + if (o->preferred_source) + pa_xfree(o->preferred_source); + pa_xfree(o->driver); pa_xfree(o); } @@ -1544,7 +1557,16 @@ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, bool save o->moving(o, dest); o->source = dest; - o->save_source = save; + /* save == true, means user is calling the move_to() and want to + save the preferred_source */ + if (save) { + pa_xfree(o->preferred_source); + if (dest == dest->core->default_source) + o->preferred_source = NULL; + else + o->preferred_source = pa_xstrdup(dest->name); + } + pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL); pa_cvolume_remap(&o->volume_factor_source, &o->channel_map, &o->source->channel_map); @@ -1584,6 +1606,12 @@ void pa_source_output_fail_move(pa_source_output *o) { if (pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FAIL], o) == PA_HOOK_STOP) return; + /* Can we move the source output to the default source? */ + if (o->core->rescue_streams && pa_source_output_may_move_to(o, o->core->default_source)) { + if (pa_source_output_finish_move(o, o->core->default_source, false) >= 0) + return; + } + if (o->moving) o->moving(o, NULL); @@ -1755,7 +1783,8 @@ int pa_source_output_update_resampler(pa_source_output *o) { ((o->flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | (o->core->disable_remixing || (o->flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) | (o->core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) | - (o->core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)); + (o->core->remixing_produce_lfe ? PA_RESAMPLER_PRODUCE_LFE : 0) | + (o->core->remixing_consume_lfe ? PA_RESAMPLER_CONSUME_LFE : 0)); if (!new_resampler) { pa_log_warn("Unsupported resampling operation."); @@ -1867,3 +1896,17 @@ void pa_source_output_set_reference_ratio(pa_source_output *o, const pa_cvolume pa_cvolume_snprint_verbose(old_ratio_str, sizeof(old_ratio_str), &old_ratio, &o->channel_map, true), pa_cvolume_snprint_verbose(new_ratio_str, sizeof(new_ratio_str), ratio, &o->channel_map, true)); } + +/* Called from the main thread. */ +void pa_source_output_set_preferred_source(pa_source_output *o, pa_source *s) { + pa_assert(o); + + pa_xfree(o->preferred_source); + if (s) { + o->preferred_source = pa_xstrdup(s->name); + pa_source_output_move_to(o, s, false); + } else { + o->preferred_source = NULL; + pa_source_output_move_to(o, o->core->default_source, false); + } +} diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index 16853c0..2bf5682 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -106,11 +106,15 @@ struct pa_source_output { bool muted:1; - /* if true then the source we are connected to and/or the volume - * set is worth remembering, i.e. was explicitly chosen by the - * user and not automatically. module-stream-restore looks for - * this.*/ - bool save_source:1, save_volume:1, save_muted:1; + /* if true then the volume and the mute state of this source-output + * are worth remembering, module-stream-restore looks for this. */ + bool save_volume:1, save_muted:1; + + /* if users move the source-output to a source, and the source is not + * default_source, the source->name will be saved in preferred_source. And + * later if source-output is moved to other sources for some reason, it + * still can be restored to the preferred_source at an appropriate time */ + char *preferred_source; pa_resample_method_t requested_resample_method, actual_resample_method; @@ -277,7 +281,8 @@ typedef struct pa_source_output_new_data { bool volume_writable:1; - bool save_source:1, save_volume:1, save_muted:1; + bool save_volume:1, save_muted:1; + char *preferred_source; } pa_source_output_new_data; pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data); @@ -397,6 +402,8 @@ void pa_source_output_set_volume_direct(pa_source_output *o, const pa_cvolume *v * o->reference_ratio and logs a message if the value changes. */ void pa_source_output_set_reference_ratio(pa_source_output *o, const pa_cvolume *ratio); +void pa_source_output_set_preferred_source(pa_source_output *o, pa_source *s); + #define pa_source_output_assert_io_context(s) \ pa_assert(pa_thread_mq_get() || !PA_SOURCE_OUTPUT_IS_LINKED((s)->state)) diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 855d3de..1cb83f9 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -666,9 +666,13 @@ void pa_source_put(pa_source *s) { pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index); pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s); - /* This function must be called after the PA_CORE_HOOK_SOURCE_PUT hook, - * because module-switch-on-connect needs to know the old default source */ + /* It's good to fire the SOURCE_PUT hook before updating the default source, + * because module-switch-on-connect will set the new source as the default + * source, and if we were to call pa_core_update_default_source() before that, + * the default source might change twice, causing unnecessary stream moving. */ pa_core_update_default_source(s->core); + + pa_core_move_streams_to_newly_available_preferred_source(s->core, s); } /* Called from main context */ @@ -698,6 +702,9 @@ void pa_source_unlink(pa_source *s) { pa_core_update_default_source(s->core); + if (linked && s->core->rescue_streams) + pa_source_move_streams_to_default_source(s->core, s, false); + if (s->card) pa_idxset_remove_by_data(s->card->sources, s, NULL); @@ -2988,3 +2995,44 @@ void pa_source_set_reference_volume_direct(pa_source *s, const pa_cvolume *volum pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_VOLUME_CHANGED], s); } + +void pa_source_move_streams_to_default_source(pa_core *core, pa_source *old_source, bool default_source_changed) { + pa_source_output *o; + uint32_t idx; + + pa_assert(core); + pa_assert(old_source); + + if (core->state == PA_CORE_SHUTDOWN) + return; + + if (core->default_source == NULL || core->default_source->unlink_requested) + return; + + if (old_source == core->default_source) + return; + + PA_IDXSET_FOREACH(o, old_source->outputs, idx) { + if (!PA_SOURCE_OUTPUT_IS_LINKED(o->state)) + continue; + + if (!o->source) + continue; + + /* If default_source_changed is false, the old source became unavailable, so all streams must be moved. */ + if (pa_safe_streq(old_source->name, o->preferred_source) && default_source_changed) + continue; + + if (!pa_source_output_may_move_to(o, core->default_source)) + continue; + + if (default_source_changed) + pa_log_info("The source output %u \"%s\" is moving to %s due to change of the default source.", + o->index, pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), core->default_source->name); + else + pa_log_info("The source output %u \"%s\" is moving to %s, because the old source became unavailable.", + o->index, pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), core->default_source->name); + + pa_source_output_move_to(o, core->default_source, false); + } +} diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index e9462c6..12e37d6 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -479,6 +479,12 @@ int64_t pa_source_get_latency_within_thread(pa_source *s, bool allow_negative); * sets s->reference_volume and fires change notifications. */ void pa_source_set_reference_volume_direct(pa_source *s, const pa_cvolume *volume); +/* When the default_source is changed or the active_port of a source is changed to + * PA_AVAILABLE_NO, this function is called to move the streams of the old + * default_source or the source with active_port equals PA_AVAILABLE_NO to the + * current default_source conditionally*/ +void pa_source_move_streams_to_default_source(pa_core *core, pa_source *old_source, bool default_source_changed); + #define pa_source_assert_io_context(s) \ pa_assert(pa_thread_mq_get() || !PA_SOURCE_IS_LINKED((s)->state)) diff --git a/src/tests/alsa-mixer-path-test.c b/src/tests/alsa-mixer-path-test.c index ee40587..75cf086 100644 --- a/src/tests/alsa-mixer-path-test.c +++ b/src/tests/alsa-mixer-path-test.c @@ -13,6 +13,10 @@ #include <pulsecore/strlist.h> #include <modules/alsa/alsa-mixer.h> +/* This test inspects the Makefile, so this is not applicable when using + * Meson. */ +#ifndef MESON_BUILD + /* This function was copied from alsa-mixer.c */ static const char *get_default_paths_dir(void) { if (pa_run_from_build_tree()) @@ -52,6 +56,7 @@ static pa_strlist *load_makefile() { fclose(f); return result; } +#endif /* end of #ifndef MESON_BUILD */ START_TEST (mixer_path_test) { #ifdef MESON_BUILD diff --git a/src/tests/meson.build b/src/tests/meson.build index 621c2c9..643a08d 100644 --- a/src/tests/meson.build +++ b/src/tests/meson.build @@ -53,7 +53,7 @@ default_tests = [ [ 'queue-test', 'queue-test.c', [ check_dep, libpulse_dep, libpulsecommon_dep, libpulsecore_dep ] ], [ 'resampler-test', 'resampler-test.c', - [ libpulse_dep, libpulsecommon_dep, libpulsecore_dep ] ], + [ libpulse_dep, libpulsecommon_dep, libpulsecore_dep, libintl_dep ] ], [ 'rtpoll-test', 'rtpoll-test.c', [ check_dep, libpulse_dep, libpulsecommon_dep, libpulsecore_dep ] ], [ 'smoother-test', 'smoother-test.c', @@ -143,7 +143,7 @@ echo_cancel_test_sources += module_echo_cancel_orc_sources norun_tests += [ [ 'echo-cancel-test', echo_cancel_test_sources, - module_echo_cancel_deps + [ libpulse_dep, libpulsecommon_dep, libpulsecore_dep ], + module_echo_cancel_deps + [ libpulse_dep, libpulsecommon_dep, libpulsecore_dep, libintl_dep ], module_echo_cancel_libs, module_echo_cancel_flags + server_c_args + [ '-DPA_MODULE_NAME=module_echo_cancel', '-DECHO_CANCEL_TEST=1' ] ] ] diff --git a/src/tests/remix-test.c b/src/tests/remix-test.c index 0dcc2f1..8e1292d 100644 --- a/src/tests/remix-test.c +++ b/src/tests/remix-test.c @@ -33,7 +33,7 @@ struct resample_flags { }; /* Call like this to get an initializer for struct resample_flags: - * RESAMPLE_FLAGS(PA_RESAMPLER_NO_LFE) + * RESAMPLE_FLAGS(PA_RESAMPLER_PRODUCE_LFE) */ #define RESAMPLE_FLAGS(flags) { .str = #flags, .value = (flags) } @@ -60,9 +60,13 @@ int main(int argc, char *argv[]) { RESAMPLE_FLAGS(0), RESAMPLE_FLAGS(PA_RESAMPLER_NO_REMAP), RESAMPLE_FLAGS(PA_RESAMPLER_NO_REMIX), - RESAMPLE_FLAGS(PA_RESAMPLER_NO_LFE), + RESAMPLE_FLAGS(PA_RESAMPLER_PRODUCE_LFE), RESAMPLE_FLAGS(PA_RESAMPLER_NO_FILL_SINK), - RESAMPLE_FLAGS(PA_RESAMPLER_NO_LFE | PA_RESAMPLER_NO_FILL_SINK), + RESAMPLE_FLAGS(PA_RESAMPLER_PRODUCE_LFE | PA_RESAMPLER_NO_FILL_SINK), + RESAMPLE_FLAGS(PA_RESAMPLER_CONSUME_LFE), + RESAMPLE_FLAGS(PA_RESAMPLER_CONSUME_LFE | PA_RESAMPLER_NO_FILL_SINK), + RESAMPLE_FLAGS(PA_RESAMPLER_PRODUCE_LFE | PA_RESAMPLER_CONSUME_LFE), + RESAMPLE_FLAGS(PA_RESAMPLER_PRODUCE_LFE | PA_RESAMPLER_CONSUME_LFE | PA_RESAMPLER_NO_FILL_SINK), { .str = NULL, .value = 0 }, }; diff --git a/src/tests/rtpoll-test.c b/src/tests/rtpoll-test.c index 24c6619..aab637b 100644 --- a/src/tests/rtpoll-test.c +++ b/src/tests/rtpoll-test.c @@ -48,15 +48,15 @@ START_TEST (rtpoll_test) { p = pa_rtpoll_new(); i = pa_rtpoll_item_new(p, PA_RTPOLL_EARLY, 1); - pa_rtpoll_item_set_before_callback(i, before); - pa_rtpoll_item_set_after_callback(i, after); + pa_rtpoll_item_set_before_callback(i, before, NULL); + pa_rtpoll_item_set_after_callback(i, after, NULL); pollfd = pa_rtpoll_item_get_pollfd(i, NULL); pollfd->fd = 0; pollfd->events = POLLIN; w = pa_rtpoll_item_new(p, PA_RTPOLL_NORMAL, 0); - pa_rtpoll_item_set_before_callback(w, worker); + pa_rtpoll_item_set_before_callback(w, worker, NULL); pa_rtpoll_set_timer_relative(p, 10000000); /* 10 s */ @@ -65,8 +65,8 @@ START_TEST (rtpoll_test) { pa_rtpoll_item_free(i); i = pa_rtpoll_item_new(p, PA_RTPOLL_EARLY, 1); - pa_rtpoll_item_set_before_callback(i, before); - pa_rtpoll_item_set_after_callback(i, after); + pa_rtpoll_item_set_before_callback(i, before, NULL); + pa_rtpoll_item_set_after_callback(i, after, NULL); pollfd = pa_rtpoll_item_get_pollfd(i, NULL); pollfd->fd = 0; diff --git a/src/utils/meson.build b/src/utils/meson.build index d00e030..dedf4e4 100644 --- a/src/utils/meson.build +++ b/src/utils/meson.build @@ -15,7 +15,7 @@ executable('pacat', install_rpath : privlibdir, include_directories : [configinc, topinc], link_with : [libpulsecommon, libpulse], - dependencies : [sndfile_dep], + dependencies : [sndfile_dep, libintl_dep], c_args : pa_c_args, ) @@ -36,7 +36,7 @@ executable('pactl', install_rpath : privlibdir, include_directories : [configinc, topinc], link_with : [libpulsecommon, libpulse], - dependencies : [sndfile_dep], + dependencies : [sndfile_dep, libintl_dep], c_args : pa_c_args, ) @@ -50,6 +50,7 @@ executable('pasuspender', install_rpath : privlibdir, include_directories : [configinc, topinc], link_with : [libpulsecommon, libpulse], + dependencies: [libintl_dep], c_args : pa_c_args, ) @@ -63,6 +64,7 @@ executable('pacmd', install_rpath : privlibdir, include_directories : [configinc, topinc], link_with : [libpulsecommon, libpulse], + dependencies: [libintl_dep], c_args : pa_c_args, ) @@ -77,7 +79,7 @@ if x11_dep.found() install_rpath : privlibdir, include_directories : [configinc, topinc], link_with : [libpulsecommon, libpulse], - dependencies : [x11_dep], + dependencies : [x11_dep, libintl_dep], c_args : pa_c_args, ) endif diff --git a/src/utils/qpaeq b/src/utils/qpaeq index ac0daec..7e01d87 100755 --- a/src/utils/qpaeq +++ b/src/utils/qpaeq @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # qpaeq is a equalizer interface for pulseaudio's equalizer sinks # Copyright (C) 2009 Jason Newton <nevion@gmail.com # @@ -18,7 +18,6 @@ import os,math,sys try: - import PyQt5,sip from PyQt5 import QtWidgets,QtCore import dbus.mainloop.pyqt5 import dbus |