summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.tarball-version2
-rw-r--r--.version2
-rw-r--r--NEWS140
-rw-r--r--config.h.in3
-rwxr-xr-xconfigure184
-rw-r--r--configure.ac3
-rw-r--r--man/default.pa.56
-rw-r--r--man/pax11publish.12
-rw-r--r--man/pulse-cli-syntax.54
-rw-r--r--man/pulse-client.conf.56
-rw-r--r--man/pulse-daemon.conf.58
-rw-r--r--man/pulseaudio.16
-rw-r--r--meson.build1
-rw-r--r--po/de.gmobin49326 -> 68462 bytes
-rw-r--r--po/fi.gmobin28045 -> 38315 bytes
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.in39
-rw-r--r--src/daemon/main.c1
-rw-r--r--src/modules/alsa/alsa-mixer.c247
-rw-r--r--src/modules/alsa/alsa-mixer.h12
-rw-r--r--src/modules/alsa/alsa-ucm.c4
-rw-r--r--src/modules/alsa/alsa-util.c4
-rw-r--r--src/modules/alsa/alsa-util.h2
-rw-r--r--src/modules/alsa/mixer/paths/analog-output-headphones-2.conf20
-rw-r--r--src/modules/alsa/mixer/paths/analog-output-headphones.conf11
-rw-r--r--src/modules/alsa/mixer/paths/analog-output-lineout.conf4
-rw-r--r--src/modules/alsa/mixer/paths/analog-output-mono.conf4
-rw-r--r--src/modules/alsa/mixer/paths/analog-output-speaker-always.conf4
-rw-r--r--src/modules/alsa/mixer/paths/analog-output-speaker.conf4
-rw-r--r--src/modules/alsa/module-alsa-card.c6
-rw-r--r--src/modules/bluetooth/backend-ofono.c3
-rw-r--r--src/modules/module-card-restore.c12
-rw-r--r--src/modules/module-device-manager.c12
-rw-r--r--src/modules/module-device-restore.c12
-rw-r--r--src/modules/module-equalizer-sink.c24
-rw-r--r--src/modules/module-ladspa-sink.c3
-rw-r--r--src/modules/module-stream-restore.c12
-rw-r--r--src/modules/module-switch-on-port-available.c32
-rw-r--r--src/pulse/version.h4
-rw-r--r--src/pulsecore/cli-command.c46
-rw-r--r--src/pulsecore/database-gdbm.c15
-rw-r--r--src/pulsecore/database-simple.c12
-rw-r--r--src/pulsecore/database-tdb.c12
-rw-r--r--src/pulsecore/database.c107
-rw-r--r--src/pulsecore/database.h25
-rw-r--r--src/pulsecore/meson.build1
46 files changed, 742 insertions, 321 deletions
diff --git a/.tarball-version b/.tarball-version
index ed9d00f..9dc0691 100644
--- a/.tarball-version
+++ b/.tarball-version
@@ -1 +1 @@
-14.0
+14.1
diff --git a/.version b/.version
index ed9d00f..9dc0691 100644
--- a/.version
+++ b/.version
@@ -1 +1 @@
-14.0
+14.1
diff --git a/NEWS b/NEWS
index 782a612..308eedb 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,143 @@
+PulseAudio 14.1
+
+A bug fix release.
+
+ * Support upto 8 mixer channels on ALSA devices
+ * Handle ALSA jacks with the same name but different index values
+ * Switch to plugged-in headset when mic availability is unknown
+ * Fix a potential segfault in the Bluetooth oFono HFP backend
+ * Fix a problem with module-ladspa-sink when avoid-resampling=true
+ * Fix database names containing canonical host for meson builds
+
+Contributors
+
+ Arun Raghavan
+ Hui Wang
+ Igor V. Kovalenko
+ Jaroslav Kysela
+ Kai-Heng Feng
+ Patrick Gaskin
+ Tanu Kaskinen
+ morrishoresh
+
+
+PulseAudio 14.0
+
+Changes at a glance:
+
+ * Notes for end users
+ * Significant routing changes to default sinks/sources
+ * Changing the default sink moves streams from the old default sink to the new
+ * Moving a stream to the default sink removes the "manually routed" status of the stream
+ * If a sink changes status to available, streams that prefer that sink move there automatically
+ * The same changes have been applied to the source stream routing
+ * Workaround for GNOME Sound Settings' stream routing behaviour
+ * module-rescue-streams is deprecated, functionality moved to the core
+ * New rescue-streams option in daemon.conf
+ * Automatic switching to HDMI is now disabled by default
+ * Better support for some USB gaming headsets
+ * Flat volumes are now disabled by default
+ * The RAOP sink can be configured to automatically reconnect on connection failures
+ * Separate sink_channels and source_channels for module-jackdbus-detect
+ * Improved support for ALSA UCM
+ * Support for ALSA mixer controls with non-zero index
+ * It's now possible to set intended roles for devices in the ALSA profile configuration
+ * Ports now have a type associated with them
+ * Mappings have a new "description-key" option in the ALSA profile configuration
+ * New xauthority argument for X11 modules
+ * module-null-sink's compressed format support can now be configured at run-time
+ * The enable-lfe-remixing option in daemon.conf was split into remixing-produce-lfe and remixing-consume-lfe
+ * New channel_map argument for module-raop-sink
+ * Notes for application developers
+ * pa_mainloop_prepare interprets the timeout argument as microseconds again
+ * New availability_group and type fields in the port info structs
+ * New macros: PA_LIKELY(), PA_UNLIKELY(), PA_CLAMP() and PA_CLAMP_UNLIKELY()
+ * Notes for packagers
+ * New GStreamer-based RTP implementation
+ * qpaeq switched from Python 2 to Python 3
+ * Compile-time option to forget pre-14.0 stream routing
+ * The install path of the ALSA configuration files is now configurable
+ * GNU gettext minimum version requirement bumped from 0.19.3 to 0.19.8
+ * Heads-up: dropping autotools build system
+ * Heads-up: dropping EsounD support is considered, tell us if you still need it
+ * Heads-up: dropping GConf support
+
+Detailed change log:
+
+ https://www.freedesktop.org/wiki/Software/PulseAudio/Notes/14.0/
+
+Contributors
+
+ Alexander E. Patrakov
+ Arun Raghavan
+ Balázs Meskó
+ Baurzhan Muftakhidinov
+ Ben Buchwald
+ Daniil Kovalev
+ Dave Chiluk
+ David Heidelberg
+ Dusan Kazik
+ Eero Nurkkala
+ Emanuil Novachev
+ Emilio Herrera
+ Felipe Sateler
+ Felix Yan
+ Geert Warrink
+ Georg Chini
+ Göran Uddeborg
+ Hugo Osvaldo Barrera
+ Hui Wang
+ Igor V. Kovalenko
+ Jan Alexander Steffens
+ Jarno Suni
+ Jaroslav Kysela
+ Jaska Uimonen
+ Jean-Baptiste Holcroft
+ Josh
+ Juliano de Souza Camargo
+ Kai-Heng Feng
+ Karl Ove Hufthammer
+ Khem Raj
+ Krzysztof Stasiowski
+ Laurent Bigonville
+ Libin Yang
+ Marc Ranolfi
+ Michael Pivonka
+ Milo Casagrande
+ Milo Ivir
+ Nick Moriarty
+ Oğuz Ersen
+ Pali Rohár
+ Peter Levine
+ Peter Meerwald
+ Philip Withnall
+ Piotr Drąg
+ RODRIGUEZ Christophe
+ Rafael Fontenelle
+ Ralph Seichter
+ Rasmus Thomsen
+ Rickie Schroeder
+ Rosen Penev
+ Ryszard Knop
+ Sanchayan Maity
+ Sebastian Dröge
+ Sebastien
+ StefanBruens
+ Taahir Ahmed
+ Tanu Kaskinen
+ Timo Gurr
+ Tom Yan
+ Tomasz Kontusz
+ Vasilis Tsiligiannis
+ Wim Taymans
+ Yi-Jyun Pan
+ Yuri Chornoivan
+ itsthem
+ muzena
+ roshal
+ zhaochengyi
+
+
PulseAudio 13.0
Changes at a glance:
diff --git a/config.h.in b/config.h.in
index d889efd..2f8667d 100644
--- a/config.h.in
+++ b/config.h.in
@@ -12,9 +12,6 @@
/* Enable memory barriers */
#undef ATOMIC_ARM_MEMORY_BARRIER_ENABLED
-/* Canonical host string. */
-#undef CANONICAL_HOST
-
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
diff --git a/configure b/configure
index 65ba92a..7b0a811 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for pulseaudio 14.0.
+# Generated by GNU Autoconf 2.69 for pulseaudio 14.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='14.0'
-PACKAGE_STRING='pulseaudio 14.0'
+PACKAGE_VERSION='14.1'
+PACKAGE_STRING='pulseaudio 14.1'
PACKAGE_BUGREPORT='pulseaudio-discuss (at) lists (dot) freedesktop (dot) org'
PACKAGE_URL='http://pulseaudio.org/'
@@ -913,6 +913,14 @@ INTLLIBS
LTLIBICONV
LIBICONV
INTL_MACOSX_LIBS
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
XGETTEXT_EXTRA_OPTIONS
MSGMERGE
XGETTEXT_015
@@ -956,14 +964,6 @@ CFLAGS
CC
LN_S
STOW
-host_os
-host_vendor
-host_cpu
-host
-build_os
-build_vendor
-build_cpu
-build
LIBPULSE_MAINLOOP_GLIB_VERSION_INFO
LIBPULSE_SIMPLE_VERSION_INFO
LIBPULSE_VERSION_INFO
@@ -1742,7 +1742,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 14.0 to adapt to many kinds of systems.
+\`configure' configures pulseaudio 14.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1812,7 +1812,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of pulseaudio 14.0:";;
+ short | recursive ) echo "Configuration of pulseaudio 14.1:";;
esac
cat <<\_ACEOF
@@ -2142,7 +2142,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-pulseaudio configure 14.0
+pulseaudio configure 14.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2915,7 +2915,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 14.0, which was
+It was created by pulseaudio $as_me 14.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3871,7 +3871,7 @@ fi
# Define the identity of the package.
PACKAGE='pulseaudio'
- VERSION='14.0'
+ VERSION='14.1'
cat >>confdefs.h <<_ACEOF
@@ -4141,83 +4141,6 @@ LIBPULSE_SIMPLE_VERSION_INFO=1:1:1
LIBPULSE_MAINLOOP_GLIB_VERSION_INFO=0:6:0
-# Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_build_alias=$build_alias
-test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
-test "x$ac_build_alias" = x &&
- as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
-case $ac_cv_build in
-*-*-*) ;;
-*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
-esac
-build=$ac_cv_build
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_build
-shift
-build_cpu=$1
-build_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-build_os=$*
-IFS=$ac_save_IFS
-case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "x$host_alias" = x; then
- ac_cv_host=$ac_cv_build
-else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
-case $ac_cv_host in
-*-*-*) ;;
-*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
-esac
-host=$ac_cv_host
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_host
-shift
-host_cpu=$1
-host_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-host_os=$*
-IFS=$ac_save_IFS
-case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define CANONICAL_HOST "$host"
-_ACEOF
-
-
# Extract the first word of "stow", so it can be a program name with args.
set dummy stow; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@@ -7473,6 +7396,77 @@ fi
eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
prefix="$acl_save_prefix"
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
# Check whether --with-gnu-ld was given.
@@ -30729,7 +30723,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 14.0, which was
+This file was extended by pulseaudio $as_me 14.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -30796,7 +30790,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 14.0
+pulseaudio config.status 14.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index a519e63..6809897 100644
--- a/configure.ac
+++ b/configure.ac
@@ -56,9 +56,6 @@ AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [1:1:1])
# info x:y:z always will hold x=z
AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:6:0])
-AC_CANONICAL_HOST
-AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.])
-
AC_CHECK_PROG([STOW], [stow], [yes], [no])
AS_IF([test "x$STOW" = "xyes" && test -d /usr/local/stow], [
diff --git a/man/default.pa.5 b/man/default.pa.5
index e7c0a72..46c87e7 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/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/etc/pulse/default.pa\fB
+\fI/home/arun/code/pulseaudio/pulseaudio/build-old/install/etc/pulse/default.pa\fB
-\fI/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/etc/pulse/system.pa\fB
+\fI/home/arun/code/pulseaudio/pulseaudio/build-old/install/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/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/etc/pulse/default.pa\f1 is used. When PulseAudio runs as a system service, \fI/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/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/code/pulseaudio/pulseaudio/build-old/install/etc/pulse/default.pa\f1 is used. When PulseAudio runs as a system service, \fI/home/arun/code/pulseaudio/pulseaudio/build-old/install/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 82818ef..dc23e80 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/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/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/code/pulseaudio/pulseaudio/build-old/install/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 05ab7b0..89144cc 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/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/etc/pulse/default.pa\fB
+\fI/home/arun/code/pulseaudio/pulseaudio/build-old/install/etc/pulse/default.pa\fB
-\fI/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/etc/pulse/system.pa\fB
+\fI/home/arun/code/pulseaudio/pulseaudio/build-old/install/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 feae66b..ac47b60 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/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/etc/pulse/client.conf\fB
+\fI/home/arun/code/pulseaudio/pulseaudio/build-old/install/etc/pulse/client.conf\fB
-\fI/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/etc/pulse/client.conf.d/*.conf\fB
+\fI/home/arun/code/pulseaudio/pulseaudio/build-old/install/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/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/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/code/pulseaudio/pulseaudio/build-old/install-old/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/code/pulseaudio/pulseaudio/build-old/install/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/code/pulseaudio/pulseaudio/build-old/install/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 9d20fc4..fb15b78 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/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/etc/pulse/daemon.conf\fB
+\fI/home/arun/code/pulseaudio/pulseaudio/build-old/install/etc/pulse/daemon.conf\fB
-\fI/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/etc/pulse/daemon.conf.d/*.conf\fB
+\fI/home/arun/code/pulseaudio/pulseaudio/build-old/install/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/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/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/code/pulseaudio/pulseaudio/build-old/install-old/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/code/pulseaudio/pulseaudio/build-old/install/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/code/pulseaudio/pulseaudio/build-old/install/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.
@@ -85,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/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/etc/pulse/default.pa\f1. If run in system-wide mode the file \fI/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/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/code/pulseaudio/pulseaudio/build-old/install/etc/pulse/default.pa\f1. If run in system-wide mode the file \fI/home/arun/code/pulseaudio/pulseaudio/build-old/install/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/pulseaudio.1 b/man/pulseaudio.1
index e5fdcfd..c18d25b 100644
--- a/man/pulseaudio.1
+++ b/man/pulseaudio.1
@@ -136,11 +136,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/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/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/code/pulseaudio/pulseaudio/build-old/install/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/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/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/code/pulseaudio/pulseaudio/build-old/install/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/home/arun/code/pulseaudio/pulseaudio/build-old/install-old/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/code/pulseaudio/pulseaudio/build-old/install/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).
diff --git a/meson.build b/meson.build
index 658eeee..a526321 100644
--- a/meson.build
+++ b/meson.build
@@ -125,7 +125,6 @@ cdata = configuration_data()
cdata.set_quoted('PACKAGE', 'pulseaudio')
cdata.set_quoted('PACKAGE_NAME', 'pulseaudio')
cdata.set_quoted('PACKAGE_VERSION', pa_version_str)
-cdata.set_quoted('CANONICAL_HOST', host_machine.cpu())
cdata.set('PA_MAJOR', pa_version_major)
cdata.set('PA_MINOR', pa_version_minor)
cdata.set('PA_API_VERSION', pa_api_version)
diff --git a/po/de.gmo b/po/de.gmo
index 452916f..1ba3f22 100644
--- a/po/de.gmo
+++ b/po/de.gmo
Binary files differ
diff --git a/po/fi.gmo b/po/fi.gmo
index 27c2e51..5de29b2 100644
--- a/po/fi.gmo
+++ b/po/fi.gmo
Binary files differ
diff --git a/src/Makefile.am b/src/Makefile.am
index bd76403..454b644 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1037,7 +1037,7 @@ libpulsecore_@PA_MAJORMINOR@_la_SOURCES = \
pulsecore/source.c pulsecore/source.h \
pulsecore/start-child.c pulsecore/start-child.h \
pulsecore/thread-mq.c pulsecore/thread-mq.h \
- pulsecore/database.h
+ pulsecore/database.c pulsecore/database.h
libpulsecore_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS) $(LIBSNDFILE_CFLAGS) $(WINSOCK_CFLAGS)
libpulsecore_@PA_MAJORMINOR@_la_LDFLAGS = $(AM_LDFLAGS) $(AM_LIBLDFLAGS) -avoid-version
diff --git a/src/Makefile.in b/src/Makefile.in
index 21b509c..eda27ee 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -994,14 +994,14 @@ am__libpulsecore_@PA_MAJORMINOR@_la_SOURCES_DIST = \
pulsecore/source-output.c pulsecore/source-output.h \
pulsecore/source.c pulsecore/source.h pulsecore/start-child.c \
pulsecore/start-child.h pulsecore/thread-mq.c \
- pulsecore/thread-mq.h pulsecore/database.h \
- pulsecore/svolume_orc.c pulsecore/x11wrap.c \
- pulsecore/x11wrap.h pulsecore/dbus-shared.c \
- pulsecore/dbus-shared.h pulsecore/protocol-dbus.c \
- pulsecore/protocol-dbus.h pulsecore/database-gdbm.c \
- pulsecore/database-tdb.c pulsecore/database-simple.c \
- pulsecore/resampler/speex.c pulsecore/resampler/soxr.c \
- pulsecore/resampler/libsamplerate.c
+ pulsecore/thread-mq.h pulsecore/database.c \
+ pulsecore/database.h pulsecore/svolume_orc.c \
+ pulsecore/x11wrap.c pulsecore/x11wrap.h \
+ pulsecore/dbus-shared.c pulsecore/dbus-shared.h \
+ pulsecore/protocol-dbus.c pulsecore/protocol-dbus.h \
+ pulsecore/database-gdbm.c pulsecore/database-tdb.c \
+ pulsecore/database-simple.c pulsecore/resampler/speex.c \
+ pulsecore/resampler/soxr.c pulsecore/resampler/libsamplerate.c
@HAVE_ORC_TRUE@am__objects_14 = pulsecore/libpulsecore_@PA_MAJORMINOR@_la-svolume_orc.lo
@HAVE_X11_TRUE@am__objects_15 = pulsecore/libpulsecore_@PA_MAJORMINOR@_la-x11wrap.lo
@HAVE_DBUS_TRUE@am__objects_16 = pulsecore/libpulsecore_@PA_MAJORMINOR@_la-dbus-shared.lo \
@@ -1069,6 +1069,7 @@ am_libpulsecore_@PA_MAJORMINOR@_la_OBJECTS = pulsecore/filter/libpulsecore_@PA_M
pulsecore/libpulsecore_@PA_MAJORMINOR@_la-source.lo \
pulsecore/libpulsecore_@PA_MAJORMINOR@_la-start-child.lo \
pulsecore/libpulsecore_@PA_MAJORMINOR@_la-thread-mq.lo \
+ pulsecore/libpulsecore_@PA_MAJORMINOR@_la-database.lo \
$(am__objects_14) $(am__objects_15) $(am__objects_16) \
$(am__objects_17) $(am__objects_18) $(am__objects_19) \
$(am__objects_20) $(am__objects_21) $(am__objects_22)
@@ -3007,6 +3008,7 @@ am__depfiles_remade = daemon/$(DEPDIR)/cpulimit_test-cpulimit.Po \
pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database-gdbm.Plo \
pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database-simple.Plo \
pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database-tdb.Plo \
+ pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database.Plo \
pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-dbus-shared.Plo \
pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-device-port.Plo \
pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-hook-list.Plo \
@@ -4627,10 +4629,11 @@ libpulsecore_@PA_MAJORMINOR@_la_SOURCES = \
pulsecore/source-output.c pulsecore/source-output.h \
pulsecore/source.c pulsecore/source.h pulsecore/start-child.c \
pulsecore/start-child.h pulsecore/thread-mq.c \
- pulsecore/thread-mq.h pulsecore/database.h $(am__append_54) \
- $(am__append_57) $(am__append_60) $(am__append_63) \
- $(am__append_66) $(am__append_69) $(am__append_70) \
- $(am__append_73) $(am__append_76)
+ pulsecore/thread-mq.h pulsecore/database.c \
+ pulsecore/database.h $(am__append_54) $(am__append_57) \
+ $(am__append_60) $(am__append_63) $(am__append_66) \
+ $(am__append_69) $(am__append_70) $(am__append_73) \
+ $(am__append_76)
libpulsecore_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS) \
$(LIBSNDFILE_CFLAGS) $(WINSOCK_CFLAGS) $(am__append_55) \
$(am__append_58) $(am__append_61) $(am__append_64) \
@@ -6230,6 +6233,8 @@ pulsecore/libpulsecore_@PA_MAJORMINOR@_la-start-child.lo: \
pulsecore/$(am__dirstamp) pulsecore/$(DEPDIR)/$(am__dirstamp)
pulsecore/libpulsecore_@PA_MAJORMINOR@_la-thread-mq.lo: \
pulsecore/$(am__dirstamp) pulsecore/$(DEPDIR)/$(am__dirstamp)
+pulsecore/libpulsecore_@PA_MAJORMINOR@_la-database.lo: \
+ pulsecore/$(am__dirstamp) pulsecore/$(DEPDIR)/$(am__dirstamp)
pulsecore/libpulsecore_@PA_MAJORMINOR@_la-svolume_orc.lo: \
pulsecore/$(am__dirstamp) pulsecore/$(DEPDIR)/$(am__dirstamp)
pulsecore/libpulsecore_@PA_MAJORMINOR@_la-x11wrap.lo: \
@@ -7741,6 +7746,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database-gdbm.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database-simple.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database-tdb.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-dbus-shared.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-device-port.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-hook-list.Plo@am__quote@ # am--include-marker
@@ -9149,6 +9155,13 @@ pulsecore/libpulsecore_@PA_MAJORMINOR@_la-thread-mq.lo: pulsecore/thread-mq.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) $(libpulsecore_@PA_MAJORMINOR@_la_CFLAGS) $(CFLAGS) -c -o pulsecore/libpulsecore_@PA_MAJORMINOR@_la-thread-mq.lo `test -f 'pulsecore/thread-mq.c' || echo '$(srcdir)/'`pulsecore/thread-mq.c
+pulsecore/libpulsecore_@PA_MAJORMINOR@_la-database.lo: pulsecore/database.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) $(libpulsecore_@PA_MAJORMINOR@_la_CFLAGS) $(CFLAGS) -MT pulsecore/libpulsecore_@PA_MAJORMINOR@_la-database.lo -MD -MP -MF pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database.Tpo -c -o pulsecore/libpulsecore_@PA_MAJORMINOR@_la-database.lo `test -f 'pulsecore/database.c' || echo '$(srcdir)/'`pulsecore/database.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database.Tpo pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pulsecore/database.c' object='pulsecore/libpulsecore_@PA_MAJORMINOR@_la-database.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) $(libpulsecore_@PA_MAJORMINOR@_la_CFLAGS) $(CFLAGS) -c -o pulsecore/libpulsecore_@PA_MAJORMINOR@_la-database.lo `test -f 'pulsecore/database.c' || echo '$(srcdir)/'`pulsecore/database.c
+
pulsecore/libpulsecore_@PA_MAJORMINOR@_la-svolume_orc.lo: pulsecore/svolume_orc.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) $(libpulsecore_@PA_MAJORMINOR@_la_CFLAGS) $(CFLAGS) -MT pulsecore/libpulsecore_@PA_MAJORMINOR@_la-svolume_orc.lo -MD -MP -MF pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-svolume_orc.Tpo -c -o pulsecore/libpulsecore_@PA_MAJORMINOR@_la-svolume_orc.lo `test -f 'pulsecore/svolume_orc.c' || echo '$(srcdir)/'`pulsecore/svolume_orc.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-svolume_orc.Tpo pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-svolume_orc.Plo
@@ -12389,6 +12402,7 @@ distclean: distclean-am
-rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database-gdbm.Plo
-rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database-simple.Plo
-rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database-tdb.Plo
+ -rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database.Plo
-rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-dbus-shared.Plo
-rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-device-port.Plo
-rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-hook-list.Plo
@@ -12851,6 +12865,7 @@ maintainer-clean: maintainer-clean-am
-rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database-gdbm.Plo
-rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database-simple.Plo
-rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database-tdb.Plo
+ -rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-database.Plo
-rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-dbus-shared.Plo
-rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-device-port.Plo
-rm -f pulsecore/$(DEPDIR)/libpulsecore_@PA_MAJORMINOR@_la-hook-list.Plo
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 59f9312..30ef499 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -916,7 +916,6 @@ int main(int argc, char *argv[]) {
pa_set_env_and_record("PULSE_SYSTEM", conf->system_instance ? "1" : "0");
pa_log_info("This is PulseAudio %s", PACKAGE_VERSION);
- pa_log_debug("Compilation host: %s", CANONICAL_HOST);
pa_log_debug("Compilation CFLAGS: %s", PA_CFLAGS);
#ifdef HAVE_LIBSAMPLERATE
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 0631790..e494a12 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -113,7 +113,7 @@ struct description2_map {
pa_device_port_type_t type;
};
-static char *alsa_id_str(char *dst, size_t dst_len, pa_alsa_mixer_id *id) {
+char *pa_alsa_mixer_id_to_string(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 {
@@ -153,7 +153,7 @@ static int alsa_id_decode(const char *src, char *name, int *index) {
return 0;
}
-pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name) {
+pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name, int index) {
pa_alsa_jack *jack;
pa_assert(name);
@@ -162,7 +162,8 @@ pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name
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->alsa_id.name = pa_sprintf_malloc("%s Jack", name);
+ jack->alsa_id.index = index;
jack->state_unplugged = PA_AVAILABLE_NO;
jack->state_plugged = PA_AVAILABLE_YES;
jack->ucm_devices = pa_dynarray_new(NULL);
@@ -177,7 +178,7 @@ void pa_alsa_jack_free(pa_alsa_jack *jack) {
pa_dynarray_free(jack->ucm_hw_mute_devices);
pa_dynarray_free(jack->ucm_devices);
- pa_xfree(jack->alsa_name);
+ pa_xfree(jack->alsa_id.name);
pa_xfree(jack->name);
pa_xfree(jack->mixer_device_name);
pa_xfree(jack);
@@ -689,6 +690,20 @@ static const snd_mixer_selem_channel_id_t alsa_channel_ids[PA_CHANNEL_POSITION_M
[PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = SND_MIXER_SCHN_UNKNOWN
};
+static snd_mixer_selem_channel_id_t alsa_channel_positions[POSITION_MASK_CHANNELS] = {
+ SND_MIXER_SCHN_FRONT_LEFT,
+ SND_MIXER_SCHN_FRONT_RIGHT,
+ SND_MIXER_SCHN_REAR_LEFT,
+ SND_MIXER_SCHN_REAR_RIGHT,
+ SND_MIXER_SCHN_FRONT_CENTER,
+ SND_MIXER_SCHN_WOOFER,
+ SND_MIXER_SCHN_SIDE_LEFT,
+ SND_MIXER_SCHN_SIDE_RIGHT,
+#if POSITION_MASK_CHANNELS > 8
+#error "Extend alsa_channel_positions[] array (9+)"
+#endif
+};
+
static void setting_free(pa_alsa_setting *s) {
pa_assert(s);
@@ -821,7 +836,7 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return -1;
}
@@ -847,14 +862,14 @@ 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_alsa_mixer_id_to_string(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.", 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_alsa_mixer_id_to_string(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.", buf, c,
e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
@@ -877,14 +892,14 @@ 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_alsa_mixer_id_to_string(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.", 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_alsa_mixer_id_to_string(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.", buf, c,
e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
@@ -992,7 +1007,7 @@ static int element_get_switch(pa_alsa_element *e, snd_mixer_t *m, bool *b) {
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return -1;
}
@@ -1158,7 +1173,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return -1;
}
@@ -1350,7 +1365,7 @@ static int element_set_switch(pa_alsa_element *e, snd_mixer_t *m, bool b) {
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return -1;
}
@@ -1361,7 +1376,7 @@ static int element_set_switch(pa_alsa_element *e, snd_mixer_t *m, bool b) {
r = snd_mixer_selem_set_capture_switch_all(me, b);
if (r < 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Failed to set switch of %s: %s", buf, pa_alsa_strerror(errno));
}
@@ -1405,7 +1420,7 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) {
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return -1;
}
@@ -1450,7 +1465,7 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) {
}
if (r < 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Failed to set volume of %s: %s", buf, pa_alsa_strerror(errno));
}
@@ -1656,19 +1671,19 @@ 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) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(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) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(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_alsa_mixer_id_to_string(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, buf, e->min_volume, e->max_volume);
return false;
@@ -1676,7 +1691,7 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
if (e->db_fix && ((e->min_volume > e->db_fix->min_step) || (e->max_volume < e->db_fix->max_step))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(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);
@@ -1703,19 +1718,19 @@ 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) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(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) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(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_alsa_mixer_id_to_string(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.", buf, min_dB / 100.0, max_dB / 100.0,
@@ -1738,7 +1753,7 @@ 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) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(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.",
buf, e->path->name, e->volume_limit, e->min_volume + 1, e->max_volume);
@@ -1750,7 +1765,7 @@ 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) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(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
@@ -1767,7 +1782,11 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
if (is_mono) {
e->n_channels = 1;
- if (!e->override_map) {
+ if ((e->override_map & (1 << (e->n_channels-1))) && e->masks[SND_MIXER_SCHN_MONO][e->n_channels-1] == 0) {
+ pa_log_warn("Override map for mono element %s is invalid, ignoring override map", e->path->name);
+ e->override_map &= ~(1 << (e->n_channels-1));
+ }
+ if (!(e->override_map & (1 << (e->n_channels-1)))) {
for (p = PA_CHANNEL_POSITION_FRONT_LEFT; p < PA_CHANNEL_POSITION_MAX; p++) {
if (alsa_channel_ids[p] == SND_MIXER_SCHN_UNKNOWN)
continue;
@@ -1791,27 +1810,28 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
}
if (e->n_channels <= 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Volume element %s with no channels?", buf);
return false;
- } else if (e->n_channels > 2) {
+ } else if (e->n_channels > POSITION_MASK_CHANNELS) {
/* FIXME: In some places code like this is used:
*
* e->masks[alsa_channel_ids[p]][e->n_channels-1]
*
* The definition of e->masks is
*
- * pa_channel_position_mask_t masks[SND_MIXER_SCHN_LAST + 1][2];
+ * pa_channel_position_mask_t masks[SND_MIXER_SCHN_LAST + 1][POSITION_MASK_CHANNELS];
*
- * Since the array size is fixed at 2, we obviously
- * don't support elements with more than two
+ * Since the array size is fixed at POSITION_MASK_CHANNELS, we obviously
+ * don't support elements with more than POSITION_MASK_CHANNELS
* channels... */
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(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;
}
- if (!e->override_map) {
+retry:
+ if (!(e->override_map & (1 << (e->n_channels-1)))) {
for (p = PA_CHANNEL_POSITION_FRONT_LEFT; p < PA_CHANNEL_POSITION_MAX; p++) {
bool has_channel;
@@ -1834,6 +1854,17 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
e->merged_mask |= e->masks[alsa_channel_ids[p]][e->n_channels-1];
}
+
+ if (e->merged_mask == 0) {
+ if (!(e->override_map & (1 << (e->n_channels-1)))) {
+ pa_log_warn("Channel map for element %s is invalid", e->path->name);
+ return false;
+ }
+ pa_log_warn("Override map for element %s has empty result, ignoring override map", e->path->name);
+ e->override_map &= ~(1 << (e->n_channels-1));
+ goto retry;
+ }
+
return true;
}
@@ -1943,12 +1974,12 @@ static int jack_probe(pa_alsa_jack *j, pa_alsa_mapping *mapping, snd_mixer_t *m)
}
new_name = pa_sprintf_malloc("%s,pcm=%i Jack", j->name, mapping->hw_device_index);
- pa_xfree(j->alsa_name);
- j->alsa_name = new_name;
+ pa_xfree(j->alsa_id.name);
+ j->alsa_id.name = new_name;
j->append_pcm_to_name = false;
}
- has_control = pa_alsa_mixer_find_card(m, j->alsa_name, 0) != NULL;
+ has_control = pa_alsa_mixer_find_card(m, &j->alsa_id, 0) != NULL;
pa_alsa_jack_set_has_control(j, has_control);
if (j->has_control) {
@@ -2011,19 +2042,26 @@ finish:
static pa_alsa_jack* jack_get(pa_alsa_path *p, const char *section) {
pa_alsa_jack *j;
+ char *name;
+ int index;
if (!pa_startswith(section, "Jack "))
return NULL;
section += 5;
- if (p->last_jack && pa_streq(p->last_jack->name, section))
+ name = alloca(strlen(section) + 1);
+ if (alsa_id_decode(section, name, &index))
+ return NULL;
+
+ if (p->last_jack && pa_streq(p->last_jack->name, name) &&
+ p->last_jack->alsa_id.index == index)
return p->last_jack;
PA_LLIST_FOREACH(j, p->jacks)
- if (pa_streq(j->name, section))
+ if (pa_streq(j->name, name) && j->alsa_id.index == index)
goto finish;
- j = pa_alsa_jack_new(p, NULL, section);
+ j = pa_alsa_jack_new(p, NULL, name, index);
PA_LLIST_INSERT_AFTER(pa_alsa_jack, p->jacks, p->last_jack, j);
finish:
@@ -2427,6 +2465,16 @@ static int element_parse_volume_limit(pa_config_parser_state *state) {
return 0;
}
+static unsigned int parse_channel_position(const char *m)
+{
+ pa_channel_position_t p;
+
+ if ((p = pa_channel_position_from_string(m)) == PA_CHANNEL_POSITION_INVALID)
+ return SND_MIXER_SCHN_UNKNOWN;
+
+ return alsa_channel_ids[p];
+}
+
static pa_channel_position_mask_t parse_mask(const char *m) {
pa_channel_position_mask_t v;
@@ -2464,7 +2512,9 @@ static int element_parse_override_map(pa_config_parser_state *state) {
pa_alsa_path *p;
pa_alsa_element *e;
const char *split_state = NULL;
+ char *s;
unsigned i = 0;
+ int channel_count = 0;
char *n;
pa_assert(state);
@@ -2476,31 +2526,60 @@ static int element_parse_override_map(pa_config_parser_state *state) {
return -1;
}
+ s = strstr(state->lvalue, ".");
+ if (s) {
+ pa_atoi(s + 1, &channel_count);
+ if (channel_count < 1 || channel_count > POSITION_MASK_CHANNELS) {
+ pa_log("[%s:%u] Override map index '%s' invalid in '%s'", state->filename, state->lineno, state->lvalue, state->section);
+ return 0;
+ }
+ } else {
+ pa_log("[%s:%u] Invalid override map syntax '%s' in '%s'", state->filename, state->lineno, state->lvalue, state->section);
+ return -1;
+ }
+
while ((n = pa_split(state->rvalue, ",", &split_state))) {
pa_channel_position_mask_t m;
+ snd_mixer_selem_channel_id_t channel_position;
+
+ if (i >= (unsigned)channel_count) {
+ pa_log("[%s:%u] Invalid override map size (>%d) in '%s'", state->filename, state->lineno, channel_count, state->section);
+ return -1;
+ }
+ channel_position = alsa_channel_positions[i];
if (!*n)
m = 0;
else {
- if ((m = parse_mask(n)) == 0) {
- pa_log("[%s:%u] Override map '%s' invalid in '%s'", state->filename, state->lineno, n, state->section);
+ s = strstr(n, ":");
+ if (s) {
+ *s = '\0';
+ s++;
+ channel_position = parse_channel_position(n);
+ if (channel_position == SND_MIXER_SCHN_UNKNOWN) {
+ pa_log("[%s:%u] Override map position '%s' invalid in '%s'", state->filename, state->lineno, n, state->section);
+ pa_xfree(n);
+ return -1;
+ }
+ }
+ if ((m = parse_mask(s ? s : n)) == 0) {
+ pa_log("[%s:%u] Override map '%s' invalid in '%s'", state->filename, state->lineno, s ? s : n, state->section);
pa_xfree(n);
return -1;
}
}
- if (pa_streq(state->lvalue, "override-map.1"))
- e->masks[i++][0] = m;
- else
- e->masks[i++][1] = m;
-
- /* Later on we might add override-map.3 and so on here ... */
-
+ if (e->masks[channel_position][channel_count-1]) {
+ pa_log("[%s:%u] Override map '%s' duplicate position '%s' in '%s'", state->filename, state->lineno, s ? s : n, snd_mixer_selem_channel_name(channel_position), state->section);
+ pa_xfree(n);
+ return -1;
+ }
+ e->override_map |= (1 << (channel_count - 1));
+ e->masks[channel_position][channel_count-1] = m;
pa_xfree(n);
+ i++;
}
- e->override_map = true;
-
return 0;
}
@@ -2574,7 +2653,7 @@ static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx)
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return -1;
}
@@ -2587,7 +2666,7 @@ static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx)
r = snd_mixer_selem_set_capture_switch_all(me, alsa_idx);
if (r < 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Failed to set switch of %s: %s", buf, pa_alsa_strerror(errno));
}
@@ -2595,7 +2674,7 @@ static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx)
pa_assert(e->enumeration_use == PA_ALSA_ENUMERATION_SELECT);
if ((r = snd_mixer_selem_set_enum_item(me, 0, alsa_idx)) < 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Failed to set enumeration of %s: %s", buf, pa_alsa_strerror(errno));
}
}
@@ -2652,7 +2731,7 @@ 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) {
- alsa_id_str(buf, sizeof(buf), &o->element->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &o->element->alsa_id);
pa_log("Element %s of option %s not set for select.", buf, o->name);
return -1;
}
@@ -2660,7 +2739,7 @@ static int option_verify(pa_alsa_option *o) {
if (o->element->switch_use == PA_ALSA_SWITCH_SELECT &&
!pa_streq(o->alsa_name, "on") &&
!pa_streq(o->alsa_name, "off")) {
- alsa_id_str(buf, sizeof(buf), &o->element->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &o->element->alsa_id);
pa_log("Switch %s options need be named off or on ", buf);
return -1;
}
@@ -2686,13 +2765,13 @@ 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)) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(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) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log("Element %s cannot set select for both switch and enumeration.", buf);
return -1;
}
@@ -2718,6 +2797,7 @@ static int path_verify(pa_alsa_path *p) {
{ "analog-input-video", N_("Video"), PA_DEVICE_PORT_TYPE_VIDEO },
{ "analog-output", N_("Analog Output"), PA_DEVICE_PORT_TYPE_ANALOG },
{ "analog-output-headphones", N_("Headphones"), PA_DEVICE_PORT_TYPE_HEADPHONES },
+ { "analog-output-headphones-2", N_("Headphones 2"), PA_DEVICE_PORT_TYPE_HEADPHONES },
{ "analog-output-headphones-mono", N_("Headphones Mono Output"), PA_DEVICE_PORT_TYPE_HEADPHONES },
{ "analog-output-lineout", N_("Line Out"), PA_DEVICE_PORT_TYPE_LINE },
{ "analog-output-mono", N_("Analog Mono Output"), PA_DEVICE_PORT_TYPE_ANALOG },
@@ -2800,6 +2880,15 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa
{ "enumeration", element_parse_enumeration, NULL, NULL },
{ "override-map.1", element_parse_override_map, NULL, NULL },
{ "override-map.2", element_parse_override_map, NULL, NULL },
+ { "override-map.3", element_parse_override_map, NULL, NULL },
+ { "override-map.4", element_parse_override_map, NULL, NULL },
+ { "override-map.5", element_parse_override_map, NULL, NULL },
+ { "override-map.6", element_parse_override_map, NULL, NULL },
+ { "override-map.7", element_parse_override_map, NULL, NULL },
+ { "override-map.8", element_parse_override_map, NULL, NULL },
+#if POSITION_MASK_CHANNELS > 8
+#error "Add override-map.9+ definitions"
+#endif
/* ... later on we might add override-map.3 and so on here ... */
{ "required", element_parse_required, NULL, NULL },
{ "required-any", element_parse_required, NULL, NULL },
@@ -3017,6 +3106,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;
+ bool min_dB_set, max_dB_set;
char buf[64];
pa_assert(p);
@@ -3032,22 +3122,23 @@ int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m
pa_log_debug("Probing path '%s'", p->name);
PA_LLIST_FOREACH(j, p->jacks) {
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &j->alsa_id);
if (jack_probe(j, mapping, m) < 0) {
p->supported = false;
- pa_log_debug("Probe of jack '%s' failed.", j->alsa_name);
+ pa_log_debug("Probe of jack %s failed.", buf);
return -1;
}
- pa_log_debug("Probe of jack '%s' succeeded (%s)", j->alsa_name, j->has_control ? "found!" : "not found");
+ pa_log_debug("Probe of jack %s succeeded (%s)", buf, j->has_control ? "found!" : "not found");
}
PA_LLIST_FOREACH(e, p->elements) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
if (element_probe(e, m) < 0) {
p->supported = false;
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).", buf, e->volume_use, e->switch_use, e->enumeration_use);
+ pa_log_debug("Probe of element %s succeeded (volume=%d, switch=%d, enumeration=%d, has_dB=%d).", buf, e->volume_use, e->switch_use, e->enumeration_use, e->has_dB);
if (ignore_dB)
e->has_dB = false;
@@ -3111,18 +3202,30 @@ int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m
p->supported = true;
p->min_dB = INFINITY;
+ min_dB_set = false;
p->max_dB = -INFINITY;
+ max_dB_set = false;
for (t = 0; t < PA_CHANNEL_POSITION_MAX; t++) {
if (path_volume_channels & PA_CHANNEL_POSITION_MASK(t)) {
- if (p->min_dB > min_dB[t])
+ if (p->min_dB > min_dB[t]) {
p->min_dB = min_dB[t];
+ min_dB_set = true;
+ }
- if (p->max_dB < max_dB[t])
+ if (p->max_dB < max_dB[t]) {
p->max_dB = max_dB[t];
+ max_dB_set = true;
+ }
}
}
+ /* this is probably a wrong prediction, but it should be safe */
+ if (!min_dB_set)
+ p->min_dB = -INFINITY;
+ if (!max_dB_set)
+ p->max_dB = 0;
+
return 0;
}
@@ -3138,7 +3241,7 @@ void pa_alsa_setting_dump(pa_alsa_setting *s) {
void pa_alsa_jack_dump(pa_alsa_jack *j) {
pa_assert(j);
- pa_log_debug("Jack %s, alsa_name='%s', detection %s", j->name, j->alsa_name, j->has_control ? "possible" : "unavailable");
+ pa_log_debug("Jack %s, alsa_name='%s', index='%d', detection %s", j->name, j->alsa_id.name, j->alsa_id.index, j->has_control ? "possible" : "unavailable");
}
void pa_alsa_option_dump(pa_alsa_option *o) {
@@ -3158,8 +3261,8 @@ void pa_alsa_element_dump(pa_alsa_element *e) {
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",
+ pa_alsa_mixer_id_to_string(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=%02x",
buf,
e->direction,
e->switch_use,
@@ -3171,7 +3274,7 @@ void pa_alsa_element_dump(pa_alsa_element *e) {
e->required_absent,
(long long unsigned) e->merged_mask,
e->n_channels,
- pa_yes_no(e->override_map));
+ e->override_map);
PA_LLIST_FOREACH(o, e->options)
pa_alsa_option_dump(o);
@@ -3218,7 +3321,7 @@ static void element_set_callback(pa_alsa_element *e, snd_mixer_t *m, snd_mixer_e
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return;
}
@@ -3513,7 +3616,7 @@ static bool element_is_subset(pa_alsa_element *a, pa_alsa_element *b, snd_mixer_
SELEM_INIT(sid, &a->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &a->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &a->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return false;
}
@@ -3544,7 +3647,7 @@ 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_alsa_mixer_id_to_string(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",
buf, a->masks[s][a->n_channels-1], b->masks[s][b->n_channels-1], s);
return false;
@@ -3621,7 +3724,8 @@ static void path_set_condense(pa_alsa_path_set *ps, snd_mixer_t *m) {
continue;
PA_LLIST_FOREACH(jb, p2->jacks) {
- if (jb->has_control && pa_streq(jb->alsa_name, ja->alsa_name) &&
+ if (jb->has_control && pa_streq(ja->alsa_id.name, jb->alsa_id.name) &&
+ (ja->alsa_id.index == jb->alsa_id.index) &&
(ja->state_plugged == jb->state_plugged) &&
(ja->state_unplugged == jb->state_unplugged)) {
exists = true;
@@ -4311,7 +4415,8 @@ static void profile_set_set_availability_groups(pa_alsa_profile_set *ps) {
PA_LLIST_FOREACH(j2, p2->jacks) {
if (!j2->has_control || j2->state_plugged == PA_AVAILABLE_NO)
continue;
- if (pa_streq(j->alsa_name, j2->alsa_name)) {
+ if (pa_streq(j->alsa_id.name, j2->alsa_id.name) &&
+ j->alsa_id.index == j2->alsa_id.index) {
j->state_plugged = PA_AVAILABLE_UNKNOWN;
j2->state_plugged = PA_AVAILABLE_UNKNOWN;
found = p2->availability_group;
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index 905e312..db83102 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -50,6 +50,8 @@ typedef struct pa_alsa_port_data pa_alsa_port_data;
#include "alsa-util.h"
#include "alsa-ucm.h"
+#define POSITION_MASK_CHANNELS 8
+
typedef enum pa_alsa_switch_use {
PA_ALSA_SWITCH_IGNORE,
PA_ALSA_SWITCH_MUTE, /* make this switch follow mute status */
@@ -113,6 +115,8 @@ struct pa_alsa_mixer_id {
int index;
};
+char *pa_alsa_mixer_id_to_string(char *dst, size_t dst_len, pa_alsa_mixer_id *id);
+
/* 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. */
@@ -152,7 +156,7 @@ struct pa_alsa_element {
long constant_volume;
- bool override_map:1;
+ unsigned int override_map;
bool direction_try_other:1;
bool has_dB:1;
@@ -160,7 +164,7 @@ struct pa_alsa_element {
long volume_limit; /* -1 for no configured limit */
double min_dB, max_dB;
- pa_channel_position_mask_t masks[SND_MIXER_SCHN_LAST + 1][2];
+ pa_channel_position_mask_t masks[SND_MIXER_SCHN_LAST + 1][POSITION_MASK_CHANNELS];
unsigned n_channels;
pa_channel_position_mask_t merged_mask;
@@ -177,8 +181,8 @@ struct pa_alsa_jack {
snd_mixer_t *mixer_handle;
char *mixer_device_name;
+ struct pa_alsa_mixer_id alsa_id;
char *name; /* E g "Headphone" */
- char *alsa_name; /* E g "Headphone Jack" */
bool has_control; /* is the jack itself present? */
bool plugged_in; /* is this jack currently plugged in? */
snd_mixer_elem_t *melem; /* Jack detection handle */
@@ -194,7 +198,7 @@ struct pa_alsa_jack {
bool append_pcm_to_name;
};
-pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name);
+pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name, int index);
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);
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
index 18925b7..d9cea61 100644
--- a/src/modules/alsa/alsa-ucm.c
+++ b/src/modules/alsa/alsa-ucm.c
@@ -1719,7 +1719,7 @@ static pa_alsa_jack* ucm_get_jack(pa_alsa_ucm_config *ucm, pa_alsa_ucm_device *d
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);
+ j = pa_alsa_jack_new(NULL, mixer_device_name, name, 0);
PA_LLIST_PREPEND(pa_alsa_jack, ucm->jacks, j);
finish:
@@ -1953,7 +1953,7 @@ static void ucm_mapping_jack_probe(pa_alsa_mapping *m, pa_hashmap *mixers) {
continue;
}
- has_control = pa_alsa_mixer_find_card(mixer_handle, dev->jack->alsa_name, 0) != NULL;
+ has_control = pa_alsa_mixer_find_card(mixer_handle, &dev->jack->alsa_id, 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);
}
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index bf35b61..172a7bb 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -1635,8 +1635,8 @@ static snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer,
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_card(snd_mixer_t *mixer, struct pa_alsa_mixer_id *alsa_id, unsigned int device) {
+ return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, alsa_id->name, alsa_id->index, device);
}
snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device) {
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index cb8be22..2eed3ea 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -148,7 +148,7 @@ const char* pa_alsa_strerror(int errnum);
bool pa_alsa_may_tsched(bool want);
-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_card(snd_mixer_t *mixer, struct pa_alsa_mixer_id *alsa_id, 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);
diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf b/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
index 30815d0..1789990 100644
--- a/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
@@ -13,17 +13,24 @@
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
-; Path for mixers that have a 'Headphone2' control
+; Path for the second headphone output on dual-headphone machines.
;
; See analog-output.conf.common for an explanation on the directives
[General]
priority = 98
-description-key = analog-output-headphones
[Properties]
device.icon_name = audio-headphones
+; HP EliteDesk 800 SFF Headphone
+[Jack Front Headphone,1]
+required-any = any
+
+; HP EliteDesk 800 DM Headphone
+[Jack Front Headphone Surround]
+required-any = any
+
[Element Hardware Master]
switch = mute
volume = merge
@@ -47,6 +54,13 @@ volume = off
switch = mute
volume = zero
+[Element Headphone,1]
+required-any = any
+switch = mute
+volume = merge
+override-map.1 = all
+override-map.2 = all-left,all-right
+
[Element Headphone+LO]
switch = mute
volume = zero
@@ -56,7 +70,7 @@ switch = off
volume = off
[Element Headphone2]
-required = any
+required-any = any
switch = mute
volume = merge
override-map.1 = all
diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones.conf b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
index d4ad777..88907f0 100644
--- a/src/modules/alsa/mixer/paths/analog-output-headphones.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
@@ -35,6 +35,10 @@ state.unplugged = unknown
[Jack Front Headphone]
required-any = any
+; HP EliteDesk 800 DM Headset
+[Jack Front Headphone Front]
+required-any = any
+
[Jack Front Headphone Phantom]
required-any = any
state.plugged = unknown
@@ -89,6 +93,13 @@ volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
+; This path is intended to control the first headphones, not
+; the second headphones. But it should not hurt if we leave the second
+; headphone jack enabled nonetheless.
+[Element Headphone,1]
+switch = mute
+volume = zero
+
[Element Headset]
required-any = any
switch = mute
diff --git a/src/modules/alsa/mixer/paths/analog-output-lineout.conf b/src/modules/alsa/mixer/paths/analog-output-lineout.conf
index 9a6af3a..2dde159 100644
--- a/src/modules/alsa/mixer/paths/analog-output-lineout.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-lineout.conf
@@ -127,6 +127,10 @@ required-any = any
switch = off
volume = off
+[Element Headphone,1]
+switch = off
+volume = off
+
[Element Headphone2]
switch = off
volume = off
diff --git a/src/modules/alsa/mixer/paths/analog-output-mono.conf b/src/modules/alsa/mixer/paths/analog-output-mono.conf
index 9896543..5e49405 100644
--- a/src/modules/alsa/mixer/paths/analog-output-mono.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-mono.conf
@@ -44,6 +44,10 @@ override-map.2 = all-left,all-right
switch = mute
volume = zero
+[Element Headphone,1]
+switch = mute
+volume = zero
+
[Element Headphone+LO]
switch = mute
volume = zero
diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf b/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf
index 71f356d..4ee72f5 100644
--- a/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf
@@ -76,6 +76,10 @@ volume = off
switch = mute
volume = zero
+[Element Headphone,1]
+switch = mute
+volume = zero
+
[Element Headphone2]
switch = mute
volume = zero
diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker.conf b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
index 27a3983..fcf2f5c 100644
--- a/src/modules/alsa/mixer/paths/analog-output-speaker.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
@@ -94,6 +94,10 @@ volume = off
switch = off
volume = off
+[Element Headphone,1]
+switch = off
+volume = off
+
[Element Headphone2]
switch = off
volume = off
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index de2fe9c..08e655e 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -621,6 +621,7 @@ static void init_jacks(struct userdata *u) {
void *state;
pa_alsa_path* path;
pa_alsa_jack* jack;
+ char buf[64];
u->jacks = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
@@ -663,9 +664,10 @@ static void init_jacks(struct userdata *u) {
}
}
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);
+ jack->melem = pa_alsa_mixer_find_card(jack->mixer_handle, &jack->alsa_id, 0);
if (!jack->melem) {
- pa_log_warn("Jack '%s' seems to have disappeared.", jack->alsa_name);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &jack->alsa_id);
+ pa_log_warn("Jack %s seems to have disappeared.", buf);
pa_alsa_jack_set_has_control(jack, false);
continue;
}
diff --git a/src/modules/bluetooth/backend-ofono.c b/src/modules/bluetooth/backend-ofono.c
index 0e5bbe8..d7a13ef 100644
--- a/src/modules/bluetooth/backend-ofono.c
+++ b/src/modules/bluetooth/backend-ofono.c
@@ -627,8 +627,6 @@ static DBusMessage *hf_audio_agent_new_connection(DBusConnection *c, DBusMessage
card = pa_hashmap_get(backend->cards, path);
- card->connecting = false;
-
if (!card || codec != HFP_AUDIO_CODEC_CVSD || card->fd >= 0) {
pa_log_warn("New audio connection invalid arguments (path=%s fd=%d, codec=%d)", path, fd, codec);
pa_assert_se(r = dbus_message_new_error(m, "org.ofono.Error.InvalidArguments", "Invalid arguments in method call"));
@@ -639,6 +637,7 @@ static DBusMessage *hf_audio_agent_new_connection(DBusConnection *c, DBusMessage
pa_log_debug("New audio connection on card %s (fd=%d, codec=%d)", path, fd, codec);
+ card->connecting = false;
card->fd = fd;
card->transport->codec = codec;
diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c
index 80506cd..b35cf3e 100644
--- a/src/modules/module-card-restore.c
+++ b/src/modules/module-card-restore.c
@@ -618,7 +618,7 @@ static pa_hook_result_t card_preferred_port_changed_callback(pa_core *core, pa_c
int pa__init(pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
- char *fname;
+ char *state_path;
bool restore_bluetooth_profile;
pa_assert(m);
@@ -648,17 +648,15 @@ int pa__init(pa_module*m) {
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_PROFILE_ADDED], PA_HOOK_NORMAL, (pa_hook_cb_t) card_profile_added_callback, u);
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) port_offset_change_callback, u);
- if (!(fname = pa_state_path("card-database", true)))
+ if (!(state_path = pa_state_path(NULL, true)))
goto fail;
- if (!(u->database = pa_database_open(fname, true))) {
- pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
- pa_xfree(fname);
+ if (!(u->database = pa_database_open(state_path, "card-database", true, true))) {
+ pa_xfree(state_path);
goto fail;
}
- pa_log_info("Successfully opened database file '%s'.", fname);
- pa_xfree(fname);
+ pa_xfree(state_path);
pa_modargs_free(ma);
return 0;
diff --git a/src/modules/module-device-manager.c b/src/modules/module-device-manager.c
index 308ef0b..b51b6c8 100644
--- a/src/modules/module-device-manager.c
+++ b/src/modules/module-device-manager.c
@@ -1544,7 +1544,7 @@ struct prioritised_indexes {
int pa__init(pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
- char *fname;
+ char *state_path;
pa_sink *sink;
pa_source *source;
uint32_t idx;
@@ -1601,17 +1601,15 @@ int pa__init(pa_module*m) {
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);
}
- if (!(fname = pa_state_path("device-manager", true)))
+ if (!(state_path = pa_state_path(NULL, true)))
goto fail;
- if (!(u->database = pa_database_open(fname, true))) {
- pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
- pa_xfree(fname);
+ if (!(u->database = pa_database_open(state_path, "device-manager", true, true))) {
+ pa_xfree(state_path);
goto fail;
}
- pa_log_info("Successfully opened database file '%s'.", fname);
- pa_xfree(fname);
+ pa_xfree(state_path);
/* Attempt to inject the devices into the list in priority order */
total_devices = PA_MAX(pa_idxset_size(m->core->sinks), pa_idxset_size(m->core->sources));
diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
index d15d9ff..a861f6f 100644
--- a/src/modules/module-device-restore.c
+++ b/src/modules/module-device-restore.c
@@ -1195,7 +1195,7 @@ static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_nati
int pa__init(pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
- char *fname;
+ char *state_path;
pa_sink *sink;
pa_source *source;
uint32_t idx;
@@ -1252,17 +1252,15 @@ int pa__init(pa_module*m) {
if (restore_formats)
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_EARLY, (pa_hook_cb_t) sink_put_hook_callback, u);
- if (!(fname = pa_state_path("device-volumes", true)))
+ if (!(state_path = pa_state_path(NULL, true)))
goto fail;
- if (!(u->database = pa_database_open(fname, true))) {
- pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
- pa_xfree(fname);
+ if (!(u->database = pa_database_open(state_path, "device-volumes", true, true))) {
+ pa_xfree(state_path);
goto fail;
}
- pa_log_info("Successfully opened database file '%s'.", fname);
- pa_xfree(fname);
+ pa_xfree(state_path);
PA_IDXSET_FOREACH(sink, m->core->sinks, idx)
subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW, sink->index, u);
diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c
index 4cfe3ed..f8a9e95 100644
--- a/src/modules/module-equalizer-sink.c
+++ b/src/modules/module-equalizer-sink.c
@@ -946,7 +946,7 @@ static void save_state(struct userdata *u) {
float *H;
pa_datum key, data;
pa_database *database;
- char *dbname;
+ char *state_path;
char *packed;
size_t packed_length;
@@ -969,9 +969,9 @@ static void save_state(struct userdata *u) {
data.data = state;
data.size = filter_state_size + packed_length;
//thread safety for 0.9.17?
- pa_assert_se(dbname = pa_state_path(EQ_STATE_DB, false));
- pa_assert_se(database = pa_database_open(dbname, true));
- pa_xfree(dbname);
+ pa_assert_se(state_path = pa_state_path(NULL, false));
+ pa_assert_se(database = pa_database_open(state_path, EQ_STATE_DB, false, true));
+ pa_xfree(state_path);
pa_database_set(database, &key, &data, true);
pa_database_sync(database);
@@ -1020,10 +1020,10 @@ static void load_state(struct userdata *u) {
float *H;
pa_datum key, value;
pa_database *database;
- char *dbname;
- pa_assert_se(dbname = pa_state_path(EQ_STATE_DB, false));
- database = pa_database_open(dbname, false);
- pa_xfree(dbname);
+ char *state_path;
+ pa_assert_se(state_path = pa_state_path(NULL, false));
+ database = pa_database_open(state_path, EQ_STATE_DB, false, false);
+ pa_xfree(state_path);
if (!database) {
pa_log("No resume state");
return;
@@ -1626,12 +1626,12 @@ void dbus_init(struct userdata *u) {
sink_list = pa_shared_get(u->sink->core, SINKLIST);
u->database = pa_shared_get(u->sink->core, EQDB);
if (sink_list == NULL) {
- char *dbname;
+ char *state_path;
sink_list=pa_idxset_new(&pa_idxset_trivial_hash_func, &pa_idxset_trivial_compare_func);
pa_shared_set(u->sink->core, SINKLIST, sink_list);
- pa_assert_se(dbname = pa_state_path("equalizer-presets", false));
- pa_assert_se(u->database = pa_database_open(dbname, true));
- pa_xfree(dbname);
+ pa_assert_se(state_path = pa_state_path(NULL, false));
+ pa_assert_se(u->database = pa_database_open(state_path, "equalizer-presets", false, true));
+ pa_xfree(state_path);
pa_shared_set(u->sink->core, EQDB, u->database);
pa_dbus_protocol_add_interface(u->dbus_protocol, MANAGER_PATH, &manager_info, u->sink->core);
pa_dbus_protocol_register_extension(u->dbus_protocol, EXTNAME);
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index f4fed6d..5726d08 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -714,6 +714,9 @@ static void sink_input_suspend_cb(pa_sink_input *i, pa_sink_state_t old_state, p
pa_sink_input_assert_ref(i);
pa_assert_se(u = i->userdata);
+ if (!PA_SINK_IS_LINKED(u->sink->state))
+ return;
+
if (i->sink->state != PA_SINK_SUSPENDED || i->sink->suspend_cause == PA_SUSPEND_IDLE)
pa_sink_suspend(u->sink, false, PA_SUSPEND_UNAVAILABLE);
else
diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
index 7144a66..c10310d 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -2259,7 +2259,7 @@ static void clean_up_db(struct userdata *u) {
int pa__init(pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
- char *fname;
+ char *state_path;
pa_sink_input *si;
pa_source_output *so;
uint32_t idx;
@@ -2317,17 +2317,15 @@ int pa__init(pa_module*m) {
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);
}
- if (!(fname = pa_state_path("stream-volumes", true)))
+ if (!(state_path = pa_state_path(NULL, true)))
goto fail;
- if (!(u->database = pa_database_open(fname, true))) {
- pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
- pa_xfree(fname);
+ if (!(u->database = pa_database_open(state_path, "stream-volumes", true, true))) {
+ pa_xfree(state_path);
goto fail;
}
- pa_log_info("Successfully opened database file '%s'.", fname);
- pa_xfree(fname);
+ pa_xfree(state_path);
clean_up_db(u);
diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c
index 84b8566..f450004 100644
--- a/src/modules/module-switch-on-port-available.c
+++ b/src/modules/module-switch-on-port-available.c
@@ -228,9 +228,7 @@ static struct port_pointers find_port_pointers(pa_device_port *port) {
}
/* Switches to a port, switching profiles if necessary or preferred */
-static void switch_to_port(pa_device_port *port) {
- struct port_pointers pp = find_port_pointers(port);
-
+static void switch_to_port(pa_device_port *port, struct port_pointers pp) {
if (pp.is_port_active)
return; /* Already selected */
@@ -252,8 +250,7 @@ static void switch_to_port(pa_device_port *port) {
}
/* Switches away from a port, switching profiles if necessary or preferred */
-static void switch_from_port(pa_device_port *port) {
- struct port_pointers pp = find_port_pointers(port);
+static void switch_from_port(pa_device_port *port, struct port_pointers pp) {
pa_device_port *p, *best_port = NULL;
void *state;
@@ -282,12 +279,12 @@ static void switch_from_port(pa_device_port *port) {
* PA_CORE_HOOK_CARD_PROFILE_AVAILABLE_CHANGED callback, as at this point
* the profile availability hasn't been updated yet. */
if (best_port)
- switch_to_port(best_port);
+ switch_to_port(best_port, pp);
}
static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) {
- pa_assert(port);
+ struct port_pointers pp = find_port_pointers(port);
if (!port->card) {
pa_log_warn("Port %s does not have a card", port->name);
@@ -314,6 +311,15 @@ static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port
* functionality for setups that can't trigger this kind of
* interaction.
*
+ * For headset or microphone, if they are part of some availability group
+ * and they become unknown from off, it needs to check if their source is
+ * unlinked or not, if their source is unlinked, let switch_to_port()
+ * process them, then with the running of pa_card_set_profile(), their
+ * source will be created, otherwise the headset or microphone can't be used
+ * to record sound since there is no source for these 2 ports. This issue
+ * is observed on Dell machines which have multi-function audio jack but no
+ * internal mic.
+ *
* We should make this configurable so that users can optionally
* override the default to a headset or mic. */
@@ -323,20 +329,22 @@ static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port
break;
}
- /* For no we only switch the headphone port */
- if (port->direction != PA_DIRECTION_OUTPUT) {
+ /* Switch the headphone port, the input ports without source and the
+ * input ports their source->active_port is part of a group of ports.
+ */
+ if (port->direction == PA_DIRECTION_INPUT && pp.source && !pp.source->active_port->availability_group) {
pa_log_debug("Not switching to input port %s, its availability is unknown.", port->name);
break;
}
- switch_to_port(port);
+ switch_to_port(port, pp);
break;
case PA_AVAILABLE_YES:
- switch_to_port(port);
+ switch_to_port(port, pp);
break;
case PA_AVAILABLE_NO:
- switch_from_port(port);
+ switch_from_port(port, pp);
break;
default:
break;
diff --git a/src/pulse/version.h b/src/pulse/version.h
index 30fbbda..ca9dabc 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() ("14.0.0")
+#define pa_get_headers_version() ("14.1.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 14
/** The minor version of PA. \since 0.9.15 */
-#define PA_MINOR 0
+#define PA_MINOR 1
/** 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/cli-command.c b/src/pulsecore/cli-command.c
index 5205349..58f3d1e 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -2074,34 +2074,34 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b
}
closedir(d);
-
- count = pa_dynarray_size(files);
- sorted_files = pa_xnew(char*, count);
- for (i = 0; i < count; ++i)
- sorted_files[i] = pa_dynarray_get(files, i);
- pa_dynarray_free(files);
-
- for (i = 0; i < count; ++i) {
- for (unsigned j = 0; j < count; ++j) {
- if (strcmp(sorted_files[i], sorted_files[j]) < 0) {
- char *tmp = sorted_files[i];
- sorted_files[i] = sorted_files[j];
- sorted_files[j] = tmp;
+ if ((count = pa_dynarray_size(files))) {
+ sorted_files = pa_xnew(char*, count);
+ for (i = 0; i < count; ++i)
+ sorted_files[i] = pa_dynarray_get(files, i);
+ pa_dynarray_free(files);
+
+ for (i = 0; i < count; ++i) {
+ for (unsigned j = 0; j < count; ++j) {
+ if (strcmp(sorted_files[i], sorted_files[j]) < 0) {
+ char *tmp = sorted_files[i];
+ sorted_files[i] = sorted_files[j];
+ sorted_files[j] = tmp;
+ }
}
}
- }
- for (i = 0; i < count; ++i) {
- if (!failed) {
- if (pa_cli_command_execute_file(c, sorted_files[i], buf, fail) < 0 && *fail)
- failed = true;
- }
+ for (i = 0; i < count; ++i) {
+ if (!failed) {
+ if (pa_cli_command_execute_file(c, sorted_files[i], buf, fail) < 0 && *fail)
+ failed = true;
+ }
- pa_xfree(sorted_files[i]);
+ pa_xfree(sorted_files[i]);
+ }
+ pa_xfree(sorted_files);
+ if (failed)
+ return -1;
}
- pa_xfree(sorted_files);
- if (failed)
- return -1;
}
} else if (pa_cli_command_execute_file(c, filename, buf, fail) < 0 && *fail) {
return -1;
diff --git a/src/pulsecore/database-gdbm.c b/src/pulsecore/database-gdbm.c
index b1da9df..b39f7de 100644
--- a/src/pulsecore/database-gdbm.c
+++ b/src/pulsecore/database-gdbm.c
@@ -59,17 +59,16 @@ void pa_datum_free(pa_datum *d) {
pa_zero(d);
}
-pa_database* pa_database_open(const char *fn, bool for_write) {
+const char* pa_database_get_filename_suffix(void) {
+ return ".gdbm";
+}
+
+pa_database* pa_database_open_internal(const char *path, bool for_write) {
GDBM_FILE f;
int gdbm_cache_size;
- char *path;
- pa_assert(fn);
+ pa_assert(path);
- /* We include the host identifier in the file name because gdbm
- * files are CPU dependent, and we don't want things to go wrong
- * if we are on a multiarch system. */
- path = pa_sprintf_malloc("%s."CANONICAL_HOST".gdbm", fn);
errno = 0;
/* We need to set the block size explicitly here, since otherwise
@@ -80,8 +79,6 @@ pa_database* pa_database_open(const char *fn, bool for_write) {
if (f)
pa_log_debug("Opened GDBM database '%s'", path);
- pa_xfree(path);
-
if (!f) {
if (errno == 0)
errno = EIO;
diff --git a/src/pulsecore/database-simple.c b/src/pulsecore/database-simple.c
index 3876487..96af8e0 100644
--- a/src/pulsecore/database-simple.c
+++ b/src/pulsecore/database-simple.c
@@ -222,14 +222,16 @@ static int fill_data(simple_data *db, FILE *f) {
return pa_hashmap_size(db->map);
}
-pa_database* pa_database_open(const char *fn, bool for_write) {
+const char* pa_database_get_filename_suffix(void) {
+ return ".simple";
+}
+
+pa_database* pa_database_open_internal(const char *path, bool for_write) {
FILE *f;
- char *path;
simple_data *db;
- pa_assert(fn);
+ pa_assert(path);
- path = pa_sprintf_malloc("%s."CANONICAL_HOST".simple", fn);
errno = 0;
f = pa_fopen_cloexec(path, "r");
@@ -251,8 +253,6 @@ pa_database* pa_database_open(const char *fn, bool for_write) {
db = NULL;
}
- pa_xfree(path);
-
return (pa_database*) db;
}
diff --git a/src/pulsecore/database-tdb.c b/src/pulsecore/database-tdb.c
index 282f580..6605ed8 100644
--- a/src/pulsecore/database-tdb.c
+++ b/src/pulsecore/database-tdb.c
@@ -97,18 +97,18 @@ finish:
return c;
}
-pa_database* pa_database_open(const char *fn, bool for_write) {
+const char* pa_database_get_filename_suffix(void) {
+ return ".tdb";
+}
+
+pa_database* pa_database_open_internal(const char *path, bool for_write) {
struct tdb_context *c;
- char *path;
- pa_assert(fn);
+ pa_assert(path);
- path = pa_sprintf_malloc("%s.tdb", fn);
if ((c = tdb_open_cloexec(path, 0, TDB_NOSYNC|TDB_NOLOCK, (for_write ? O_RDWR|O_CREAT : O_RDONLY), 0644)))
pa_log_debug("Opened TDB database '%s'", path);
- pa_xfree(path);
-
if (!c) {
if (errno == 0)
errno = EIO;
diff --git a/src/pulsecore/database.c b/src/pulsecore/database.c
new file mode 100644
index 0000000..8b3b89c
--- /dev/null
+++ b/src/pulsecore/database.c
@@ -0,0 +1,107 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2020 Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <dirent.h>
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/log.h>
+
+#include "database.h"
+#include "core-error.h"
+
+pa_database* pa_database_open(const char *path, const char *fn, bool prependmid, bool for_write) {
+
+ const char *filename_suffix = pa_database_get_filename_suffix();
+
+ char *machine_id = NULL, *filename_prefix, *full_path;
+
+ DIR *database_dir = NULL;
+ struct dirent *de;
+
+ pa_database *f;
+
+ pa_assert(filename_suffix && filename_suffix[0]);
+
+ if (prependmid && !(machine_id = pa_machine_id())) {
+ return NULL;
+ }
+
+ /* Database file name starts with ${machine_id}-${fn} */
+ if (machine_id)
+ filename_prefix = pa_sprintf_malloc("%s-%s", machine_id, fn);
+ else
+ filename_prefix = pa_xstrdup(fn);
+
+ /* Search for existing database directory entry name matching architecture suffix and filename suffix. */
+ database_dir = opendir(path);
+
+ if (database_dir) {
+ for (;;) {
+ errno = 0;
+ de = readdir(database_dir);
+ if (!de) {
+ if (errno) {
+ pa_log_warn("Unable to search for existing database file, readdir() failed: %s", pa_cstrerror(errno));
+ /* can continue as if there is no matching database file candidate */
+ }
+
+ break;
+ }
+
+ if (pa_startswith(de->d_name, filename_prefix)
+ && de->d_name[strlen(filename_prefix)] == '.'
+ && pa_endswith(de->d_name + strlen(filename_prefix) + 1, filename_suffix)) {
+
+ /* candidate filename found, replace filename_prefix with this one */
+
+ pa_log_debug("Found existing database file '%s/%s', using it", path, de->d_name);
+ pa_xfree(filename_prefix);
+ filename_prefix = pa_xstrndup(de->d_name, strlen(de->d_name) - strlen(filename_suffix));
+ break;
+ }
+ }
+
+ closedir(database_dir);
+ } else {
+ pa_log_warn("Unable to search for existing database file, failed to open directory %s: %s", path, pa_cstrerror(errno));
+ }
+
+ full_path = pa_sprintf_malloc("%s" PA_PATH_SEP "%s%s", path, filename_prefix, filename_suffix);
+
+ f = pa_database_open_internal(full_path, for_write);
+
+ if (f)
+ pa_log_info("Successfully opened '%s' database file '%s'.", fn, full_path);
+ else
+ pa_log("Failed to open '%s' database file '%s': %s", fn, full_path, pa_cstrerror(errno));
+
+ pa_xfree(full_path);
+ pa_xfree(filename_prefix);
+
+ /* deallocate machine_id if it was used to construct file name */
+ pa_xfree(machine_id);
+
+ return f;
+}
diff --git a/src/pulsecore/database.h b/src/pulsecore/database.h
index 3a1c7ce..7fa489c 100644
--- a/src/pulsecore/database.h
+++ b/src/pulsecore/database.h
@@ -38,8 +38,29 @@ typedef struct pa_datum {
void pa_datum_free(pa_datum *d);
-/* This will append a suffix to the filename */
-pa_database* pa_database_open(const char *fn, bool for_write);
+/* Database implementation; returns non-empty database filename extension string */
+const char* pa_database_get_filename_suffix(void);
+
+/* Opens a database file. The file is loaded from the directory indicated by
+ * path. The file name is constructed by using fn as the base and then adding
+ * several parts:
+ * 1) If prependmid is true, the machine id is prepended to the file name.
+ * 2) The database implementation specific suffix is added.
+ * 3) Older versions of PulseAudio in some cases added the CPU architecture
+ * to the file name, which was later deemed unnecessary, but for
+ * compatibility reasons we still need to look for those files, so we scan
+ * the directory for files that match the prefix (possible machine id plus
+ * fn) and the suffix, and if any matches are found, we use the first one.
+ *
+ * When no existing file is found, we create a new file for the database
+ * (without the CPU architecture part in the name).
+ *
+ * For a read-only database, set for_write to false. */
+
+pa_database* pa_database_open(const char *path, const char *fn, bool prependmid, bool for_write);
+
+/* Database implementation; opens specified database file using provided path. */
+pa_database* pa_database_open_internal(const char *path, bool for_write);
void pa_database_close(pa_database *db);
pa_datum* pa_database_get(pa_database *db, const pa_datum *key, pa_datum* data);
diff --git a/src/pulsecore/meson.build b/src/pulsecore/meson.build
index 5f78be0..99a702e 100644
--- a/src/pulsecore/meson.build
+++ b/src/pulsecore/meson.build
@@ -14,6 +14,7 @@ libpulsecore_sources = [
'cpu-orc.c',
'cpu-x86.c',
'device-port.c',
+ 'database.c',
'ffmpeg/resample2.c',
'filter/biquad.c',
'filter/crossover.c',