Merge branch 'master' into dbus-work

Conflicts:
	src/daemon/daemon-conf.c
	src/daemon/daemon-conf.h
	src/daemon/main.c
	src/pulsecore/dbus-util.h
This commit is contained in:
Tanu Kaskinen 2009-06-29 18:35:06 +03:00
commit 0bc538b08c
207 changed files with 33341 additions and 18718 deletions

2
.gitignore vendored
View file

@ -1,6 +1,4 @@
.version
shave
shave-libtool
.*.swp
ABOUT-NLS
intltool-extract.in

View file

@ -62,12 +62,6 @@ dist-hook:
fi
echo $(VERSION) > $(distdir)/.tarball-version
update-shave:
for i in shave.in shave.m4 shave-libtool.in; do \
wget -O $$i http://git.lespiau.name/cgit/shave/blob/\?path=shave/$$i ; \
done
mv shave.m4 m4/
.PHONY: homepage distcleancheck doxygen
# see git-version-gen

View file

@ -181,3 +181,10 @@ new messages:
PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED
PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED
### v16, implemented by >= 0.9.15
new messages:
PA_COMMAND_SET_SINK_PORT
PA_COMMAND_SET_SOURCE_PORT

View file

@ -16,7 +16,7 @@
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
VERSION=1.10
VERSION=1.11
run_versioned() {
local P
@ -83,7 +83,7 @@ else
run_versioned automake "$VERSION" --copy --foreign --add-missing
if test "x$NOCONFIGURE" = "x"; then
CFLAGS="-g -O0" ./configure --sysconfdir=/etc --localstatedir=/var --enable-force-preopen --enable-shave "$@"
CFLAGS="-g -O0" ./configure --sysconfdir=/etc --localstatedir=/var --enable-force-preopen "$@"
make clean
fi
fi

View file

@ -22,16 +22,15 @@
AC_PREREQ(2.63)
AC_INIT([pulseaudio], m4_esyscmd([./git-version-gen .tarball-version]),
[mzchyfrnhqvb (at) 0pointer (dot) net])
AC_INIT([pulseaudio],[m4_esyscmd(./git-version-gen .tarball-version)],[mzchyfrnhqvb (at) 0pointer (dot) net])
AC_CONFIG_SRCDIR([src/daemon/main.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([foreign 1.10 -Wall -Wno-portability])
AM_INIT_AUTOMAKE([foreign 1.11 -Wall -Wno-portability silent-rules tar-pax])
m4_define(pa_major, `echo $VERSION | cut -d. -f 1`)
m4_define(pa_minor, `echo $VERSION | cut -d. -f 2`)
m4_define(pa_micro, `echo $VERSION | cut -d. -f 3`)
m4_define(pa_major, `echo $VERSION | cut -d. -f1 | cut -d- -f1`)
m4_define(pa_minor, `echo $VERSION | cut -d. -f2 | cut -d- -f1`)
m4_define(pa_micro, `echo $VERSION | cut -d. -f3 | cut -d- -f1`)
AC_SUBST(PA_MAJOR, pa_major)
AC_SUBST(PA_MINOR, pa_minor)
@ -41,7 +40,7 @@ AC_SUBST(PA_MAJORMINORMICRO, pa_major.pa_minor.pa_micro)
AC_SUBST(PACKAGE_URL, [http://pulseaudio.org/])
AC_SUBST(PA_API_VERSION, 12)
AC_SUBST(PA_PROTOCOL_VERSION, 15)
AC_SUBST(PA_PROTOCOL_VERSION, 16)
# The stable ABI for client applications, for the version info x:y:z
# always will hold y=z
@ -76,6 +75,8 @@ case $host in
;;
esac
AM_SILENT_RULES([yes])
#### Checks for programs. ####
# mkdir -p
@ -539,7 +540,7 @@ AC_CHECK_HEADERS_ONCE([valgrind/memcheck.h])
#### Sound file ####
PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.10 ])
PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.20 ])
AC_SUBST(LIBSNDFILE_CFLAGS)
AC_SUBST(LIBSNDFILE_LIBS)
@ -1057,7 +1058,7 @@ AC_ARG_ENABLE([udev],
],
[udev=auto])
if test "x${udev}" != xno -a \( "x$HAVE_OSS" = "x1" -o "x$HAVE_ALSA" = "x1" \) ; then
PKG_CHECK_MODULES(UDEV, [ libudev >= 137 ],
PKG_CHECK_MODULES(UDEV, [ libudev >= 143 ],
[
HAVE_UDEV=1
AC_DEFINE([HAVE_UDEV], 1, [Have UDEV.])
@ -1152,44 +1153,6 @@ AC_SUBST(DBUS_LIBS)
AC_SUBST(HAVE_DBUS)
AM_CONDITIONAL([HAVE_DBUS], [test "x$HAVE_DBUS" = x1])
#### PolicyKit support (optional) ####
AC_ARG_ENABLE([polkit],
AS_HELP_STRING([--disable-polkit],[Disable optional PolicyKit support]),
[
case "${enableval}" in
yes) polkit=yes ;;
no) polkit=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-polkit) ;;
esac
],
[polkit=auto])
if test "x${polkit}" != xno ; then
PKG_CHECK_MODULES(POLKIT, [ polkit-dbus >= 0.7 ],
[
HAVE_POLKIT=1
AC_DEFINE([HAVE_POLKIT], 1, [Have PolicyKit])
policydir=`pkg-config polkit-dbus --variable prefix`/share/PolicyKit/policy/
AC_SUBST(policydir)
],
[
HAVE_POLKIT=0
if test "x$polkit" = xyes ; then
AC_MSG_ERROR([*** PolicyKit support not found])
fi
])
else
HAVE_POLKIT=0
fi
AC_SUBST(POLKIT_CFLAGS)
AC_SUBST(POLKIT_LIBS)
AC_SUBST(HAVE_POLKIT)
AM_CONDITIONAL([HAVE_POLKIT], [test "x$HAVE_POLKIT" = x1])
### IPv6 connection support (optional) ###
AC_ARG_ENABLE([ipv6],
@ -1276,15 +1239,6 @@ fi
AC_SUBST(PA_SYSTEM_GROUP)
AC_DEFINE_UNQUOTED(PA_SYSTEM_GROUP,"$PA_SYSTEM_GROUP", [Group for the PulseAudio system daemon])
AC_ARG_WITH(realtime_group,AS_HELP_STRING([--with-realtime-group=<group>],[Group for users that are allowed to start the PulseAudio daemon with realtime scheduling (realtime)]))
if test -z "$with_realtime_group" ; then
PA_REALTIME_GROUP=pulse-rt
else
PA_REALTIME_GROUP=$with_realtime_group
fi
AC_SUBST(PA_REALTIME_GROUP)
AC_DEFINE_UNQUOTED(PA_REALTIME_GROUP,"$PA_REALTIME_GROUP", [Realtime group])
AC_ARG_WITH(access_group,AS_HELP_STRING([--with-access-group=<group>],[Group which is allowed access to a system-wide PulseAudio daemon (pulse-access)]))
if test -z "$with_access_group" ; then
PA_ACCESS_GROUP=pulse-access
@ -1350,8 +1304,8 @@ fi
AC_ARG_WITH(
[module-dir],
AS_HELP_STRING([--with-module-dir],[Directory where to install the modules to (defaults to ${libdir}/pulse-${PA_MAJORMINORMICRO}/modules/]),
[modlibexecdir=$withval], [modlibexecdir="${libdir}/pulse-${PA_MAJORMINORMICRO}/modules/"])
AS_HELP_STRING([--with-module-dir],[Directory where to install the modules to (defaults to ${libdir}/pulse-${PA_MAJORMINORMICRO}/modules]),
[modlibexecdir=$withval], [modlibexecdir="${libdir}/pulse-${PA_MAJORMINORMICRO}/modules"])
AC_SUBST(modlibexecdir)
@ -1363,8 +1317,6 @@ AM_CONDITIONAL([FORCE_PREOPEN], [test "x$FORCE_PREOPEN" = "xyes"])
AC_CONFIG_FILES([
Makefile
shave
shave-libtool
src/Makefile
man/Makefile
libpulse.pc
@ -1377,7 +1329,6 @@ src/pulse/version.h
po/Makefile.in
])
SHAVE_INIT
AC_OUTPUT
# ==========================================================================
@ -1461,11 +1412,6 @@ if test "x${HAVE_BLUEZ}" = "x1" ; then
ENABLE_BLUEZ=yes
fi
ENABLE_POLKIT=no
if test "x${HAVE_POLKIT}" = "x1" ; then
ENABLE_POLKIT=yes
fi
ENABLE_GDBM=no
if test "x${HAVE_GDBM}" = "x1" ; then
ENABLE_GDBM=yes
@ -1519,7 +1465,6 @@ echo "
Enable BlueZ: ${ENABLE_BLUEZ}
Enable TCP Wrappers: ${ENABLE_TCPWRAP}
Enable libsamplerate: ${ENABLE_LIBSAMPLERATE}
Enable PolicyKit: ${ENABLE_POLKIT}
Enable IPv6: ${ENABLE_IPV6}
Enable OpenSSL (for Airtunes): ${ENABLE_OPENSSL}
Enable tdb: ${ENABLE_TDB}
@ -1527,7 +1472,6 @@ echo "
System User: ${PA_SYSTEM_USER}
System Group: ${PA_SYSTEM_GROUP}
Realtime Group: ${PA_REALTIME_GROUP}
Access Group: ${PA_ACCESS_GROUP}
Enable per-user EsounD socket: ${ENABLE_PER_USER_ESOUND_SOCKET}
Force preopen: ${FORCE_PREOPEN}

View file

@ -106,22 +106,23 @@ then
# tag or the previous older version that did not?
# Newer: v6.10-77-g0f8faeb
# Older: v6.10-g0f8faeb
case $v in
*-*-*) : git describe is okay three part flavor ;;
*-*)
: git describe is older two part flavor
# Recreate the number of commits and rewrite such that the
# result is the same as if we were using the newer version
# of git describe.
vtag=`echo "$v" | sed 's/-.*//'`
numcommits=`git rev-list "$vtag"..HEAD | wc -l`
v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
;;
esac
# case $v in
# *-*-*) : git describe is okay three part flavor ;;
# *-*)
# : git describe is older two part flavor
# # Recreate the number of commits and rewrite such that the
# # result is the same as if we were using the newer version
# # of git describe.
# vtag=`echo "$v" | sed 's/-.*//'`
# numcommits=`git rev-list "$vtag"..HEAD | wc -l`
# v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
# ;;
# esac
# Change the first '-' to a '.', so version-comparing tools work properly.
# Remove the "g" in git describe's output string, to save a byte.
v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
# v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
:
else
v=UNKNOWN
fi

View file

@ -1,77 +0,0 @@
dnl Make automake/libtool output more friendly to humans
dnl Damien Lespiau <damien.lespiau@gmail.com>
dnl
dnl SHAVE_INIT([shavedir],[default_mode])
dnl
dnl shavedir: the directory where the shave scripts are, it defaults to
dnl $(top_builddir)
dnl default_mode: (enable|disable) default shave mode. This parameter
dnl controls shave's behaviour when no option has been
dnl given to configure. It defaults to disable.
dnl
dnl * SHAVE_INIT should be called late in your configure.(ac|in) file (just
dnl before AC_CONFIG_FILE/AC_OUTPUT is perfect. This macro rewrites CC and
dnl LIBTOOL, you don't want the configure tests to have these variables
dnl re-defined.
dnl * This macro requires GNU make's -s option.
AC_DEFUN([_SHAVE_ARG_ENABLE],
[
AC_ARG_ENABLE([shave],
AS_HELP_STRING(
[--enable-shave],
[use shave to make the build pretty [[default=$1]]]),,
[enable_shave=$1]
)
])
AC_DEFUN([SHAVE_INIT],
[
dnl you can tweak the default value of enable_shave
m4_if([$2], [enable], [_SHAVE_ARG_ENABLE(yes)], [_SHAVE_ARG_ENABLE(no)])
if test x"$enable_shave" = xyes; then
dnl where can we find the shave scripts?
m4_if([$1],,
[shavedir="$ac_pwd"],
[shavedir="$ac_pwd/$1"])
AC_SUBST(shavedir)
dnl make is now quiet
AC_SUBST([MAKEFLAGS], [-s])
AC_SUBST([AM_MAKEFLAGS], ['`test -z $V && echo -s`'])
dnl we need sed
AC_CHECK_PROG(SED,sed,sed,false)
dnl substitute libtool
SHAVE_SAVED_LIBTOOL=$LIBTOOL
LIBTOOL="${SHELL} ${shavedir}/shave-libtool '${SHAVE_SAVED_LIBTOOL}'"
AC_SUBST(LIBTOOL)
dnl substitute cc/cxx
SHAVE_SAVED_CC=$CC
SHAVE_SAVED_CXX=$CXX
SHAVE_SAVED_FC=$FC
SHAVE_SAVED_F77=$F77
SHAVE_SAVED_OBJC=$OBJC
CC="${SHELL} ${shavedir}/shave cc ${SHAVE_SAVED_CC}"
CXX="${SHELL} ${shavedir}/shave cxx ${SHAVE_SAVED_CXX}"
FC="${SHELL} ${shavedir}/shave fc ${SHAVE_SAVED_FC}"
F77="${SHELL} ${shavedir}/shave f77 ${SHAVE_SAVED_F77}"
OBJC="${SHELL} ${shavedir}/shave objc ${SHAVE_SAVED_OBJC}"
AC_SUBST(CC)
AC_SUBST(CXX)
AC_SUBST(FC)
AC_SUBST(F77)
AC_SUBST(OBJC)
V=@
else
V=1
fi
Q='$(V:1=)'
AC_SUBST(V)
AC_SUBST(Q)
])

View file

@ -163,6 +163,14 @@ USA.
memory overcommit.</p>
</option>
<option>
<p><opt>lock-memory=</opt> Locks the entire PulseAudio process
into memory. While this might increase drop-out safety when used
in conjunction with real-time scheduling this takes away a lot
of memory from other processes and might hence considerably slow
down your system. Defaults to <opt>no</opt>.</p>
</option>
<option>
<p><opt>flat-volumes=</opt> Enable 'flat' volumes, i.e. where
possible let the sink volume equal the maximum of the volumes of
@ -227,13 +235,6 @@ USA.
precedence.</p>
</option>
<option>
<p><opt>module-idle-time=</opt> Unload autoloaded modules after
being idle for this time in seconds. Defaults to 20. The
<opt>--module-idle-time</opt> command line option takes
precedence.</p>
</option>
<option>
<p><opt>scache-idle-time=</opt> Unload autoloaded sample cache
entries after being idle for this time in seconds. Defaults to
@ -267,9 +268,9 @@ USA.
</option>
<option>
<p><opt>default-script-file=</opt> Load the default
<p><opt>load-default-script-file=</opt> Load the default
configuration script file as specified
in <opt>default-script-file=</opt>. Defaults to "yes".</p>
in <opt>default-script-file=</opt>. Defaults to <opt>yes</opt>.</p>
</option>
</section>
@ -296,6 +297,23 @@ USA.
might alter this setting.</p>
</option>
<option>
<p><opt>log-meta=</opt> With each logged message log the code
location the message was generated from. Defaults to
<opt>no</opt>.</p>
</option>
<option>
<p><opt>log-time=</opt> With each logged messages log the
relative time since startup. Defaults to <opt>no</opt>.</p>
</option>
<option>
<p><opt>log-backtrace=</opt> When greater than 0, with each
logged message log a code stack trace up the the specified
number of stack frames. Defaults to <opt>0</opt>.</p>
</option>
</section>
<section name="Resource Limits">
@ -371,11 +389,13 @@ USA.
<option>
<p><opt>default-sample-format=</opt> The default sampling
format. Specify one of <opt>u8</opt>, <opt>s16le</opt>,
<opt>s16be</opt>, <opt>s32le</opt>,
<opt>s32be</opt>, <opt>float32le</opt>, <opt>float32be</opt>,
<opt>s16be</opt>, <opt>s24le</opt>, <opt>s24be</opt>,
<opt>s24-32le</opt>, <opt>s24-32be</opt>, <opt>s32le</opt>,
<opt>s32be</opt> <opt>float32le</opt>, <opt>float32be</opt>,
<opt>ulaw</opt>, <opt>alaw</opt>. Depending on the endianess of
the CPU the
formats <opt>s16ne</opt>, <opt>s16re</opt>, <opt>s32ne</opt>, <opt>s32re</opt>,
the CPU the formats <opt>s16ne</opt>, <opt>s16re</opt>,
<opt>s24ne</opt>, <opt>s24re</opt>, <opt>s24-32ne</opt>,
<opt>s24-32re</opt>, <opt>s32ne</opt>, <opt>s32re</opt>,
<opt>float32ne</opt>, <opt>float32re</opt> (for native,
resp. reverse endian) are available as aliases.</p>
</option>
@ -401,7 +421,8 @@ USA.
these buffer metrics for machines with high scheduling
latencies. Not all possible values that may be configured here are
available in all hardware. The driver will to find the nearest
setting supported.</p>
setting supported. Modern drivers that support timer-based
scheduling ignore these options.</p>
<option>
<p><opt>default-fragments=</opt> The default number of

View file

@ -2,13 +2,14 @@ as
bn_IN
ca
cs
de
de_CH
de
el
es
fi
fr
gu
hi
it
kn
mr
@ -17,8 +18,9 @@ or
pa
pl
pt_BR
sr
pt
sr@latin
sr
sv
ta
te

View file

@ -15,7 +15,7 @@ src/modules/alsa/alsa-util.c
src/modules/module-pipe-source.c
src/modules/module-solaris.c
src/modules/module-default-device-restore.c
src/modules/module-x11-xsmp.c
src/modules/x11/module-x11-xsmp.c
src/modules/module-remap-sink.c
src/modules/bluetooth/module-bluetooth-proximity.c
src/modules/module-detect.c
@ -24,23 +24,23 @@ src/modules/module-lirc.c
src/modules/module-hal-detect.c
src/modules/module-sine.c
src/modules/module-zeroconf-publish.c
src/modules/module-jack-source.c
src/modules/jack/module-jack-source.c
src/modules/module-cli.c
src/modules/gconf/module-gconf.c
src/modules/gconf/gconf-helper.c
src/modules/module-esound-sink.c
src/modules/alsa/module-alsa-sink.c
src/modules/module-volume-restore.c
src/modules/module-x11-bell.c
src/modules/x11/module-x11-bell.c
src/modules/module-protocol-stub.c
src/modules/module-stream-restore.c
src/modules/module-jack-sink.c
src/modules/jack/module-jack-sink.c
src/modules/module-esound-compat-spawnfd.c
src/modules/module-esound-compat-spawnpid.c
#src/modules/module-waveout.c
src/modules/module-combine.c
src/modules/bluetooth/proximity-helper.c
src/modules/module-x11-publish.c
src/modules/x11/module-x11-publish.c
src/modules/rtp/module-rtp-recv.c
src/modules/rtp/sdp.c
src/modules/rtp/rtp.c
@ -190,7 +190,6 @@ src/utils/pactl.c
src/utils/padsp.c
src/utils/pax11publish.c
src/utils/pacmd.c
src/utils/paplay.c
src/pulsecore/lock-autospawn.c
src/modules/alsa/alsa-sink.c
src/modules/alsa/alsa-source.c

1181
po/as.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1328
po/ca.po

File diff suppressed because it is too large Load diff

1649
po/cs.po

File diff suppressed because it is too large Load diff

1176
po/de.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1046
po/el.po

File diff suppressed because it is too large Load diff

1194
po/es.po

File diff suppressed because it is too large Load diff

1184
po/fi.po

File diff suppressed because it is too large Load diff

1397
po/fr.po

File diff suppressed because it is too large Load diff

1176
po/gu.po

File diff suppressed because it is too large Load diff

2502
po/hi.po Normal file

File diff suppressed because it is too large Load diff

1038
po/it.po

File diff suppressed because it is too large Load diff

1178
po/kn.po

File diff suppressed because it is too large Load diff

1181
po/mr.po

File diff suppressed because it is too large Load diff

1074
po/nl.po

File diff suppressed because it is too large Load diff

1174
po/or.po

File diff suppressed because it is too large Load diff

1976
po/pa.po

File diff suppressed because it is too large Load diff

1194
po/pl.po

File diff suppressed because it is too large Load diff

2282
po/pt.po Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1180
po/sr.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1066
po/sv.po

File diff suppressed because it is too large Load diff

1262
po/ta.po

File diff suppressed because it is too large Load diff

1181
po/te.po

File diff suppressed because it is too large Load diff

1172
po/uk.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,69 +0,0 @@
#!/bin/sh
# we need sed
SED=@SED@
if test -z "$SED" ; then
SED=sed
fi
lt_unmangle ()
{
last_result=`echo $1 | $SED -e 's#.libs/##' -e 's#[0-9a-zA-Z_\-\.]*_la-##'`
}
# the real libtool to use
LIBTOOL="$1"
shift
# if 1, don't print anything, the underlaying wrapper will do it
pass_though=0
# scan the arguments, keep the right ones for libtool, and discover the mode
preserved_args=
while test "$#" -gt 0; do
opt="$1"
shift
case $opt in
--mode=*)
mode=`echo $opt | $SED -e 's/[-_a-zA-Z0-9]*=//'`
preserved_args="$preserved_args $opt"
;;
-o)
lt_output="$1"
preserved_args="$preserved_args $opt"
;;
*)
preserved_args="$preserved_args $opt"
;;
esac
done
case "$mode" in
compile)
# shave will be called and print the actual CC/CXX/LINK line
preserved_args="$preserved_args --shave-mode=$mode"
pass_though=1
;;
link)
preserved_args="$preserved_args --shave-mode=$mode"
Q=" LINK "
;;
*)
# let's u
# echo "*** libtool: Unimplemented mode: $mode, fill a bug report"
;;
esac
lt_unmangle "$lt_output"
output=$last_result
if test -z $V; then
if test $pass_though -eq 0; then
echo "$Q$output"
fi
$LIBTOOL --silent $preserved_args
else
echo $LIBTOOL $preserved_args
$LIBTOOL $preserved_args
fi

View file

@ -1,79 +0,0 @@
#!/bin/sh
# we need sed
SED=@SED@
if test -z "$SED" ; then
SED=sed
fi
lt_unmangle ()
{
last_result=`echo $1 | $SED -e 's#.libs/##' -e 's#[0-9a-zA-Z_\-\.]*_la-##'`
}
# the tool to wrap (cc, cxx, ar, ranlib, ..)
tool="$1"
shift
# the reel tool (to call)
REEL_TOOL="$1"
shift
pass_through=0
preserved_args=
while test "$#" -gt 0; do
opt="$1"
shift
case $opt in
--shave-mode=*)
mode=`echo $opt | $SED -e 's/[-_a-zA-Z0-9]*=//'`
;;
-o)
lt_output="$1"
preserved_args="$preserved_args $opt"
;;
*)
preserved_args="$preserved_args $opt"
;;
esac
done
# mode=link is handled in the libtool wrapper
case "$mode,$tool" in
link,*)
pass_through=1
;;
*,cxx)
Q=" CXX "
;;
*,cc)
Q=" CC "
;;
*,fc)
Q=" FC "
;;
*,f77)
Q=" F77 "
;;
*,objc)
Q=" OBJC "
;;
*,*)
# should not happen
Q=" CC "
;;
esac
lt_unmangle "$lt_output"
output=$last_result
if test -z $V; then
if test $pass_through -eq 0; then
echo "$Q$output"
fi
$REEL_TOOL $preserved_args
else
echo $REEL_TOOL $preserved_args
$REEL_TOOL $preserved_args
fi

View file

@ -29,6 +29,9 @@ pulsecoreincludedir=$(includedir)/pulsecore
pulseconfdir=$(sysconfdir)/pulse
pulselibexecdir=$(libexecdir)/pulse
xdgautostartdir=$(sysconfdir)/xdg/autostart
alsaprofilesetsdir=$(datadir)/pulseaudio/alsa-mixer/profile-sets
alsapathsdir=$(datadir)/pulseaudio/alsa-mixer/paths
udevrulesdir=/lib/udev/rules.d
###################################
# Defines #
@ -61,6 +64,11 @@ AM_CFLAGS = \
-I$(top_srcdir)/src/modules/alsa \
-I$(top_builddir)/src/modules/alsa \
-I$(top_srcdir)/src/modules/raop \
-I$(top_builddir)/src/modules/raop \
-I$(top_srcdir)/src/modules/x11 \
-I$(top_builddir)/src/modules/x11 \
-I$(top_srcdir)/src/modules/jack \
-I$(top_builddir)/src/modules/jack \
$(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS \
$(LIBSAMPLERATE_CFLAGS) \
$(LIBSNDFILE_CFLAGS) \
@ -73,7 +81,9 @@ AM_CFLAGS = \
-DPA_SYSTEM_STATE_PATH=\"$(PA_SYSTEM_STATE_PATH)\" \
-DAO_REQUIRE_CAS \
-DPULSE_LOCALEDIR=\"$(pulselocaledir)\" \
-DPA_MACHINE_ID=\"$(localstatedir)/lib/dbus/machine-id\"
-DPA_MACHINE_ID=\"$(localstatedir)/lib/dbus/machine-id\" \
-DPA_ALSA_PATHS_DIR=\"$(alsapathsdir)\" \
-DPA_ALSA_PROFILE_SETS_DIR=\"$(alsaprofilesetsdir)\"
AM_LIBADD = $(PTHREAD_LIBS) $(INTLLIBS)
AM_LDADD = $(PTHREAD_LIBS) $(INTLLIBS)
@ -109,7 +119,25 @@ EXTRA_DIST = \
modules/module-defs.h.m4 \
daemon/pulseaudio.desktop.in \
map-file \
daemon/org.pulseaudio.policy.in
modules/alsa/mixer/profile-sets/default.conf \
modules/alsa/mixer/profile-sets/native-instruments-audio4dj.conf \
modules/alsa/mixer/profile-sets/native-instruments-audio8dj.conf \
modules/alsa/mixer/profile-sets/90-pulseaudio.rules \
modules/alsa/mixer/paths/analog-input-aux.conf \
modules/alsa/mixer/paths/analog-input.conf \
modules/alsa/mixer/paths/analog-input.conf.common \
modules/alsa/mixer/paths/analog-input-fm.conf \
modules/alsa/mixer/paths/analog-input-linein.conf \
modules/alsa/mixer/paths/analog-input-mic.conf \
modules/alsa/mixer/paths/analog-input-mic.conf.common \
modules/alsa/mixer/paths/analog-input-mic-line.conf \
modules/alsa/mixer/paths/analog-input-tvtuner.conf \
modules/alsa/mixer/paths/analog-input-video.conf \
modules/alsa/mixer/paths/analog-output.conf \
modules/alsa/mixer/paths/analog-output.conf.common \
modules/alsa/mixer/paths/analog-output-headphones.conf \
modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf \
modules/alsa/mixer/paths/analog-output-mono.conf
pulseconf_DATA = \
default.pa \
@ -161,16 +189,6 @@ else
pulseaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f))
endif
if HAVE_POLKIT
policy_in_files = daemon/org.pulseaudio.policy.in
policy_DATA = $(policy_in_files:.policy.in=.policy)
@INTLTOOL_POLICY_RULE@
pulseaudio_SOURCES += daemon/polkit.c daemon/polkit.h
pulseaudio_CFLAGS += $(POLKIT_CFLAGS)
pulseaudio_LDADD += $(POLKIT_LIBS)
endif
###################################
# Utility programs #
###################################
@ -549,7 +567,9 @@ libpulsecommon_@PA_MAJORMINORMICRO@_la_SOURCES = \
pulsecore/authkey.c pulsecore/authkey.h \
pulsecore/conf-parser.c pulsecore/conf-parser.h \
pulsecore/core-error.c pulsecore/core-error.h \
pulsecore/core-rtclock.c pulsecore/core-rtclock.h \
pulsecore/core-util.c pulsecore/core-util.h \
pulsecore/rtkit.c pulsecore/rtkit.h \
pulsecore/creds.h \
pulsecore/dynarray.c pulsecore/dynarray.h \
pulsecore/endianmacros.h \
@ -587,7 +607,6 @@ libpulsecommon_@PA_MAJORMINORMICRO@_la_SOURCES = \
pulsecore/queue.c pulsecore/queue.h \
pulsecore/random.c pulsecore/random.h \
pulsecore/refcnt.h \
pulsecore/rtclock.c pulsecore/rtclock.h \
pulsecore/shm.c pulsecore/shm.h \
pulsecore/bitset.c pulsecore/bitset.h \
pulsecore/socket-client.c pulsecore/socket-client.h \
@ -665,6 +684,7 @@ pulseinclude_HEADERS = \
pulse/operation.h \
pulse/proplist.h \
pulse/pulseaudio.h \
pulse/rtclock.h \
pulse/sample.h \
pulse/scache.h \
pulse/simple.h \
@ -715,6 +735,7 @@ libpulse_la_SOURCES = \
pulse/operation.c pulse/operation.h \
pulse/proplist.c pulse/proplist.h \
pulse/pulseaudio.h \
pulse/rtclock.c pulse/rtclock.h \
pulse/sample.c pulse/sample.h \
pulse/scache.c pulse/scache.h \
pulse/stream.c pulse/stream.h \
@ -799,7 +820,6 @@ libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES = \
pulsecore/protocol-dbus.h \
pulsecore/resampler.c pulsecore/resampler.h \
pulsecore/rtpoll.c pulsecore/rtpoll.h \
pulsecore/rtsig.c pulsecore/rtsig.h \
pulsecore/sample-util.c pulsecore/sample-util.h \
pulsecore/sconv-s16be.c pulsecore/sconv-s16be.h \
pulsecore/sconv-s16le.c pulsecore/sconv-s16le.h \
@ -955,6 +975,7 @@ modlibexec_LTLIBRARIES += \
module-default-device-restore.la \
module-always-sink.la \
module-rescue-streams.la \
module-intended-roles.la \
module-suspend-on-idle.la \
module-http-protocol-tcp.la \
module-sine.la \
@ -1027,6 +1048,32 @@ modlibexec_LTLIBRARIES += \
module-alsa-sink.la \
module-alsa-source.la \
module-alsa-card.la
alsaprofilesets_DATA = \
modules/alsa/mixer/profile-sets/default.conf \
modules/alsa/mixer/profile-sets/native-instruments-audio4dj.conf \
modules/alsa/mixer/profile-sets/native-instruments-audio8dj.conf
udevrules_DATA = \
modules/alsa/mixer/profile-sets/90-pulseaudio.rules
alsapaths_DATA = \
modules/alsa/mixer/paths/analog-input-aux.conf \
modules/alsa/mixer/paths/analog-input.conf \
modules/alsa/mixer/paths/analog-input.conf.common \
modules/alsa/mixer/paths/analog-input-fm.conf \
modules/alsa/mixer/paths/analog-input-linein.conf \
modules/alsa/mixer/paths/analog-input-mic.conf \
modules/alsa/mixer/paths/analog-input-mic.conf.common \
modules/alsa/mixer/paths/analog-input-mic-line.conf \
modules/alsa/mixer/paths/analog-input-tvtuner.conf \
modules/alsa/mixer/paths/analog-input-video.conf \
modules/alsa/mixer/paths/analog-output.conf \
modules/alsa/mixer/paths/analog-output.conf.common \
modules/alsa/mixer/paths/analog-output-headphones.conf \
modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf \
modules/alsa/mixer/paths/analog-output-mono.conf
endif
if HAVE_SOLARIS
@ -1074,6 +1121,11 @@ modlibexec_LTLIBRARIES += \
module-hal-detect.la
endif
if HAVE_UDEV
modlibexec_LTLIBRARIES += \
module-udev-detect.la
endif
if HAVE_DBUS
modlibexec_LTLIBRARIES += \
module-rygel-media-server.la \
@ -1158,13 +1210,15 @@ SYMDEF_FILES = \
modules/module-default-device-restore-symdef.h \
modules/module-always-sink-symdef.h \
modules/module-rescue-streams-symdef.h \
modules/module-intended-roles-symdef.h \
modules/module-suspend-on-idle-symdef.h \
modules/module-hal-detect-symdef.h \
modules/module-udev-detect-symdef.h \
modules/bluetooth/module-bluetooth-proximity-symdef.h \
modules/bluetooth/module-bluetooth-discover-symdef.h \
modules/bluetooth/module-bluetooth-device-symdef.h \
modules/module-raop-sink-symdef.h \
modules/module-raop-discover-symdef.h \
modules/raop/module-raop-sink-symdef.h \
modules/raop/module-raop-discover-symdef.h \
modules/gconf/module-gconf-symdef.h \
modules/module-position-event-sounds-symdef.h \
modules/module-augment-properties-symdef.h \
@ -1355,7 +1409,7 @@ module_oss_la_LIBADD = $(AM_LIBADD) liboss-util.la libpulsecore-@PA_MAJORMINORMI
# ALSA
libalsa_util_la_SOURCES = modules/alsa/alsa-util.c modules/alsa/alsa-util.h modules/alsa/alsa-sink.c modules/alsa/alsa-sink.h modules/alsa/alsa-source.c modules/alsa/alsa-source.h modules/reserve-wrap.c modules/reserve-wrap.h
libalsa_util_la_SOURCES = modules/alsa/alsa-util.c modules/alsa/alsa-util.h modules/alsa/alsa-mixer.c modules/alsa/alsa-mixer.h modules/alsa/alsa-sink.c modules/alsa/alsa-sink.h modules/alsa/alsa-source.c modules/alsa/alsa-source.h modules/reserve-wrap.c modules/reserve-wrap.h
libalsa_util_la_LDFLAGS = -avoid-version
libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la
libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
@ -1373,7 +1427,7 @@ libalsa_util_la_CFLAGS += $(UDEV_CFLAGS)
endif
if HAVE_DBUS
libalsa_util_la_SOURCES += modules/reserve.h modules/reserve.c
libalsa_util_la_SOURCES += modules/reserve.h modules/reserve.c modules/reserve-monitor.h modules/reserve-monitor.c
libalsa_util_la_LIBADD += $(DBUS_LIBS)
libalsa_util_la_CFLAGS += $(DBUS_CFLAGS)
endif
@ -1499,6 +1553,12 @@ module_rescue_streams_la_LDFLAGS = $(MODULE_LDFLAGS)
module_rescue_streams_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la
module_rescue_streams_la_CFLAGS = $(AM_CFLAGS)
# Automatically move streams to devices that are intended for their roles
module_intended_roles_la_SOURCES = modules/module-intended-roles.c
module_intended_roles_la_LDFLAGS = $(MODULE_LDFLAGS)
module_intended_roles_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la
module_intended_roles_la_CFLAGS = $(AM_CFLAGS)
# Suspend-on-idle module
module_suspend_on_idle_la_SOURCES = modules/module-suspend-on-idle.c
module_suspend_on_idle_la_LDFLAGS = $(MODULE_LDFLAGS)
@ -1533,6 +1593,11 @@ module_hal_detect_la_LDFLAGS = $(MODULE_LDFLAGS)
module_hal_detect_la_LIBADD = $(AM_LIBADD) $(HAL_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la
module_hal_detect_la_CFLAGS = $(AM_CFLAGS) $(HAL_CFLAGS)
module_udev_detect_la_SOURCES = modules/module-udev-detect.c
module_udev_detect_la_LDFLAGS = $(MODULE_LDFLAGS)
module_udev_detect_la_LIBADD = $(AM_LIBADD) $(UDEV_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la
module_udev_detect_la_CFLAGS = $(AM_CFLAGS) $(UDEV_CFLAGS)
module_console_kit_la_SOURCES = modules/module-console-kit.c
module_console_kit_la_LDFLAGS = $(MODULE_LDFLAGS)
module_console_kit_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la
@ -1589,11 +1654,11 @@ module_bluetooth_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_M
module_bluetooth_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
# Apple Airtunes/RAOP
module_raop_sink_la_SOURCES = modules/module-raop-sink.c
module_raop_sink_la_SOURCES = modules/raop/module-raop-sink.c
module_raop_sink_la_LDFLAGS = $(MODULE_LDFLAGS)
module_raop_sink_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la librtp.la libraop.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la
module_raop_discover_la_SOURCES = modules/module-raop-discover.c
module_raop_discover_la_SOURCES = modules/raop/module-raop-discover.c
module_raop_discover_la_LDFLAGS = $(MODULE_LDFLAGS)
module_raop_discover_la_LIBADD = $(AM_LIBADD) $(AVAHI_LIBS) libavahi-wrap.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la
module_raop_discover_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS)
@ -1608,11 +1673,7 @@ module_rygel_media_server_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
# Some minor stuff #
###################################
suid: pulseaudio .libs/lt-pulseaudio
chown root $^
chmod u+s $^
CLEANFILES = esdcompat client.conf default.pa system.pa daemon.conf start-pulseaudio-x11 daemon/pulseaudio.desktop daemon/org.pulseaudio.policy
CLEANFILES = esdcompat client.conf default.pa system.pa daemon.conf start-pulseaudio-x11 daemon/pulseaudio.desktop
esdcompat: daemon/esdcompat.in Makefile
sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \
@ -1650,7 +1711,6 @@ daemon.conf: daemon/daemon.conf.in Makefile
install-exec-hook:
chown root $(DESTDIR)$(bindir)/pulseaudio ; true
chmod u+s $(DESTDIR)$(bindir)/pulseaudio
-chmod u+s $(DESTDIR)$(pulselibexecdir)/proximity-helper
ln -sf pacat $(DESTDIR)$(bindir)/parec
ln -sf pacat $(DESTDIR)$(bindir)/pamon
@ -1685,10 +1745,15 @@ update-sbc:
done
update-reserve:
for i in reserve.c reserve.h ; do \
for i in reserve.c reserve.h reserve-monitor.c reserve-monitor.h ; do \
wget -O modules/$$i http://git.0pointer.de/\?p=reserve.git\;a=blob_plain\;f=$$i\;hb=master ; \
done
update-rtkit:
for i in rtkit.c rtkit.h ; do \
wget -O pulsecore/$$i http://git.0pointer.de/\?p=rtkit.git\;a=blob_plain\;f=$$i\;hb=master ; \
done
# Automatically generate linker version script. We use the same one for all public .sos
update-map-file:
( echo "PULSE_0 {" ; \

View file

@ -39,6 +39,7 @@
#ifdef HAVE_SYS_CAPABILITY_H
#include <sys/capability.h>
#endif
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif
@ -51,12 +52,13 @@ int setresgid(gid_t r, gid_t e, gid_t s);
int setresuid(uid_t r, uid_t e, uid_t s);
#endif
#ifdef HAVE_GETUID
/* Drop root rights when called SUID root */
void pa_drop_root(void) {
uid_t uid = getuid();
#ifdef HAVE_GETUID
uid_t uid;
uid = getuid();
if (uid == 0 || geteuid() != 0)
return;
@ -73,90 +75,19 @@ void pa_drop_root(void) {
pa_assert_se(getuid() == uid);
pa_assert_se(geteuid() == uid);
}
#else
void pa_drop_root(void) {
}
#endif
#if defined(HAVE_SYS_CAPABILITY_H) && defined(HAVE_SYS_PRCTL_H)
/* Limit permitted capabilities set to CAPSYS_NICE */
void pa_limit_caps(void) {
cap_t caps;
cap_value_t nice_cap = CAP_SYS_NICE;
pa_assert_se(caps = cap_init());
pa_assert_se(cap_clear(caps) == 0);
pa_assert_se(cap_set_flag(caps, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET) == 0);
pa_assert_se(cap_set_flag(caps, CAP_PERMITTED, 1, &nice_cap, CAP_SET) == 0);
if (cap_set_proc(caps) < 0)
/* Hmm, so we couldn't limit our caps, which probably means we
* hadn't any in the first place, so let's just make sure of
* that */
pa_drop_caps();
else
pa_log_info(_("Limited capabilities successfully to CAP_SYS_NICE."));
pa_assert_se(cap_free(caps) == 0);
pa_assert_se(prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == 0);
}
/* Drop all capabilities, effectively becoming a normal user */
void pa_drop_caps(void) {
cap_t caps;
#ifndef __OPTIMIZE__
/* Valgrind doesn't not know set_caps, so we bypass it here -- but
* only in development builds.*/
if (pa_in_valgrind() && !pa_have_caps())
return;
#endif
#ifdef HAVE_SYS_PRCTL_H
pa_assert_se(prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) == 0);
pa_assert_se(caps = cap_init());
pa_assert_se(cap_clear(caps) == 0);
pa_assert_se(cap_set_proc(caps) == 0);
pa_assert_se(cap_free(caps) == 0);
pa_assert_se(!pa_have_caps());
}
pa_bool_t pa_have_caps(void) {
cap_t caps;
cap_flag_value_t flag = CAP_CLEAR;
#ifdef __OPTIMIZE__
pa_assert_se(caps = cap_get_proc());
#else
if (!(caps = cap_get_proc()))
return FALSE;
#endif
pa_assert_se(cap_get_flag(caps, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0);
pa_assert_se(cap_free(caps) == 0);
return flag == CAP_SET;
}
#else
/* NOOPs in case capabilities are not available. */
void pa_limit_caps(void) {
}
void pa_drop_caps(void) {
pa_drop_root();
}
pa_bool_t pa_have_caps(void) {
return FALSE;
}
#ifdef HAVE_SYS_CAPABILITY_H
{
cap_t caps;
pa_assert_se(caps = cap_init());
pa_assert_se(cap_clear(caps) == 0);
pa_assert_se(cap_set_proc(caps) == 0);
pa_assert_se(cap_free(caps) == 0);
}
#endif
}

View file

@ -25,8 +25,5 @@
#include <pulsecore/macro.h>
void pa_drop_root(void);
void pa_drop_caps(void);
void pa_limit_caps(void);
pa_bool_t pa_have_caps(void);
#endif

View file

@ -31,6 +31,7 @@
#include <pulse/xmalloc.h>
#include <pulse/i18n.h>
#include <pulse/util.h>
#include <pulsecore/core-util.h>
#include <pulsecore/strbuf.h>
@ -109,15 +110,8 @@ static const struct option long_options[] = {
};
void pa_cmdline_help(const char *argv0) {
const char *e;
pa_assert(argv0);
if ((e = strrchr(argv0, '/')))
e++;
else
e = argv0;
printf(_("%s [options]\n\n"
"COMMANDS:\n"
" -h, --help Show this help\n"
@ -172,7 +166,8 @@ void pa_cmdline_help(const char *argv0) {
" -C Open a command line on the running TTY\n"
" after startup\n\n"
" -n Don't load default script file\n"), e);
" -n Don't load default script file\n"),
pa_path_get_filename(argv0));
}
int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d) {

View file

@ -24,13 +24,14 @@
#endif
#include <pulse/error.h>
#include <pulse/rtclock.h>
#include <pulse/timeval.h>
#include <pulsecore/core-rtclock.h>
#include <pulsecore/core-util.h>
#include <pulsecore/core-error.h>
#include <pulsecore/log.h>
#include <pulsecore/macro.h>
#include <pulsecore/rtclock.h>
#include "cpulimit.h"
@ -125,7 +126,7 @@ static void signal_handler(int sig) {
char t[256];
#endif
now = pa_rtclock_usec();
now = pa_rtclock_now();
elapsed = now - last_time;
#ifdef PRINT_CPU_LOAD
@ -184,7 +185,7 @@ int pa_cpu_limit_init(pa_mainloop_api *m) {
pa_assert(the_pipe[1] == -1);
pa_assert(!installed);
last_time = pa_rtclock_usec();
last_time = pa_rtclock_now();
/* Prepare the main loop pipe */
if (pipe(the_pipe) < 0) {

View file

@ -60,7 +60,7 @@ static const pa_daemon_conf default_conf = {
.fail = TRUE,
.high_priority = TRUE,
.nice_level = -11,
.realtime_scheduling = FALSE,
.realtime_scheduling = TRUE,
.realtime_priority = 5, /* Half of JACK's default rtprio */
.disallow_module_loading = FALSE,
.disallow_exit = FALSE,
@ -88,6 +88,7 @@ static const pa_daemon_conf default_conf = {
#endif
.no_cpu_limit = FALSE,
.disable_shm = FALSE,
.lock_memory = FALSE,
.default_n_fragments = 4,
.default_fragment_size_msec = 25,
.default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 },
@ -484,6 +485,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
{ "no-cpu-limit", pa_config_parse_bool, &c->no_cpu_limit, NULL },
{ "disable-shm", pa_config_parse_bool, &c->disable_shm, NULL },
{ "flat-volumes", pa_config_parse_bool, &c->flat_volumes, NULL },
{ "lock-memory", pa_config_parse_bool, &c->lock_memory, NULL },
{ "exit-idle-time", pa_config_parse_int, &c->exit_idle_time, NULL },
{ "scache-idle-time", pa_config_parse_int, &c->scache_idle_time, NULL },
{ "realtime-priority", parse_rtprio, c, NULL },
@ -633,23 +635,22 @@ FILE *pa_daemon_conf_open_default_script_file(pa_daemon_conf *c) {
return f;
}
static const char* const log_level_to_string[] = {
[PA_LOG_DEBUG] = "debug",
[PA_LOG_INFO] = "info",
[PA_LOG_NOTICE] = "notice",
[PA_LOG_WARN] = "warning",
[PA_LOG_ERROR] = "error"
};
static const char* const server_type_to_string[] = {
[PA_SERVER_TYPE_UNSET] = "!!UNSET!!",
[PA_SERVER_TYPE_USER] = "user",
[PA_SERVER_TYPE_SYSTEM] = "system",
[PA_SERVER_TYPE_NONE] = "none"
};
char *pa_daemon_conf_dump(pa_daemon_conf *c) {
static const char* const log_level_to_string[] = {
[PA_LOG_DEBUG] = "debug",
[PA_LOG_INFO] = "info",
[PA_LOG_NOTICE] = "notice",
[PA_LOG_WARN] = "warning",
[PA_LOG_ERROR] = "error"
};
static const char* const server_type_to_string[] = {
[PA_SERVER_TYPE_UNSET] = "!!UNSET!!",
[PA_SERVER_TYPE_USER] = "user",
[PA_SERVER_TYPE_SYSTEM] = "system",
[PA_SERVER_TYPE_NONE] = "none"
};
pa_strbuf *s;
char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
@ -678,6 +679,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
pa_strbuf_printf(s, "no-cpu-limit = %s\n", pa_yes_no(c->no_cpu_limit));
pa_strbuf_printf(s, "disable-shm = %s\n", pa_yes_no(c->disable_shm));
pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes));
pa_strbuf_printf(s, "lock-memory = %s\n", pa_yes_no(c->lock_memory));
pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time);
pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time);
pa_strbuf_printf(s, "dl-search-path = %s\n", pa_strempty(c->dl_search_path));

View file

@ -74,7 +74,8 @@ typedef struct pa_daemon_conf {
disallow_exit,
log_meta,
log_time,
flat_volumes;
flat_volumes,
lock_memory;
pa_server_type_t local_server_type;
int exit_idle_time,
scache_idle_time,

View file

@ -28,15 +28,16 @@
; local-server-type = user
; disable-shm = no
; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
; lock-memory = no
; no-cpu-limit = no
; high-priority = yes
; nice-level = -11
; realtime-scheduling = no
; realtime-scheduling = yes
; realtime-priority = 5
; exit-idle-time = 20
; module-idle-time = 20
; scache-idle-time = 20
; dl-search-path = (depends on architecture)
@ -56,8 +57,6 @@
; flat-volumes = yes
; no-cpu-limit = no
; rlimit-fsize = -1
; rlimit-data = -1
; rlimit-stack = -1

View file

@ -49,11 +49,11 @@ load-module module-augment-properties
#load-module module-pipe-sink
### Automatically load driver modules depending on the hardware available
.ifexists module-hal-detect@PA_SOEXT@
load-module module-hal-detect
.ifexists module-udev-detect@PA_SOEXT@
load-module module-udev-detect
.else
### Alternatively use the static hardware detection module (for systems that
### lack HAL support)
### lack udev support)
load-module module-detect
.endif
@ -103,6 +103,9 @@ load-module module-rescue-streams
### Make sure we always have a sink around, even if it is a null sink.
load-module module-always-sink
### Honour intended role device property
load-module module-intended-roles
### Automatically suspend sinks/sources that become idle for too long
load-module module-suspend-on-idle

View file

@ -40,6 +40,10 @@
#include <liboil/liboil.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
@ -69,6 +73,7 @@
#include <pulsecore/lock-autospawn.h>
#include <pulsecore/winsock.h>
#include <pulsecore/core-error.h>
#include <pulsecore/core-rtclock.h>
#include <pulsecore/core.h>
#include <pulsecore/memblock.h>
#include <pulsecore/module.h>
@ -80,8 +85,6 @@
#include <pulsecore/pid.h>
#include <pulsecore/namereg.h>
#include <pulsecore/random.h>
#include <pulsecore/rtsig.h>
#include <pulsecore/rtclock.h>
#include <pulsecore/macro.h>
#include <pulsecore/mutex.h>
#include <pulsecore/thread.h>
@ -98,7 +101,6 @@
#include "dumpmodules.h"
#include "caps.h"
#include "ltdl-bind-now.h"
#include "polkit.h"
#include "server-lookup.h"
#ifdef HAVE_LIBWRAP
@ -130,7 +132,7 @@ static void message_cb(pa_mainloop_api*a, pa_time_event*e, const struct timeval
}
pa_timeval_add(pa_gettimeofday(&tvnext), 100000);
a->time_restart(e, &tvnext);
a->rtclock_time_restart(e, &tvnext);
}
#endif
@ -376,9 +378,7 @@ int main(int argc, char *argv[]) {
pa_mainloop *mainloop = NULL;
char *s;
int r = 0, retval = 1, d = 0;
pa_bool_t suid_root, real_root;
pa_bool_t valid_pid_file = FALSE;
gid_t gid = (gid_t) -1;
pa_bool_t ltdl_init = FALSE;
int passed_fd = -1;
const char *e;
@ -424,30 +424,6 @@ int main(int argc, char *argv[]) {
}
#endif
#ifdef HAVE_GETUID
real_root = getuid() == 0;
suid_root = !real_root && geteuid() == 0;
#else
real_root = FALSE;
suid_root = FALSE;
#endif
if (!real_root) {
/* Drop all capabilities except CAP_SYS_NICE */
pa_limit_caps();
/* Drop privileges, but keep CAP_SYS_NICE */
pa_drop_root();
/* After dropping root, the effective set is reset, hence,
* let's raise it again */
pa_limit_caps();
/* When capabilities are not supported we will not be able to
* acquire RT sched anymore. But yes, that's the way it is. It
* is just too risky tun let PA run as root all the time. */
}
if ((e = getenv("PULSE_PASSED_FD"))) {
passed_fd = atoi(e);
@ -455,15 +431,14 @@ int main(int argc, char *argv[]) {
passed_fd = -1;
}
/* We might be autospawned, in which case have no idea in which
* context we have been started. Let's cleanup our execution
* context as good as possible */
pa_drop_root();
pa_close_all(passed_fd, -1);
pa_reset_sigs(-1);
pa_unblock_sigs(-1);
/* At this point, we are a normal user, possibly with CAP_NICE if
* we were started SUID. If we are started as normal root, than we
* still are normal root. */
setlocale(LC_ALL, "");
pa_init_i18n();
@ -506,7 +481,7 @@ int main(int argc, char *argv[]) {
pa_assert_not_reached();
}
start_server = conf->local_server_type == PA_SERVER_TYPE_USER || (real_root && conf->local_server_type == PA_SERVER_TYPE_SYSTEM);
start_server = conf->local_server_type == PA_SERVER_TYPE_USER || (getuid() == 0 && conf->local_server_type == PA_SERVER_TYPE_SYSTEM);
if (!start_server && conf->local_server_type == PA_SERVER_TYPE_SYSTEM) {
pa_log_notice(_("System mode refused for non-root user. Only starting the D-Bus server lookup service."));
@ -514,165 +489,6 @@ int main(int argc, char *argv[]) {
}
#endif
pa_log_debug("Started as real root: %s, suid root: %s", pa_yes_no(real_root), pa_yes_no(suid_root));
#ifdef HAVE_DBUS
/* XXX: Uhh, goto programming... as if this wasn't hard enough to follow
* already. But if we won't start the full server, we want to just skip all
* the capability stuff. */
if (!start_server) {
if (!real_root && pa_have_caps())
pa_drop_caps();
goto after_caps_setup;
}
#endif
if (!real_root && pa_have_caps()) {
#ifdef HAVE_SYS_RESOURCE_H
struct rlimit rl;
#endif
pa_bool_t allow_high_priority = FALSE, allow_realtime = FALSE;
/* Let's better not enable high prio or RT by default */
if (conf->high_priority && !allow_high_priority) {
if (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) > 0) {
pa_log_info(_("We're in the group '%s', allowing high-priority scheduling."), PA_REALTIME_GROUP);
allow_high_priority = TRUE;
}
}
if (conf->realtime_scheduling && !allow_realtime) {
if (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) > 0) {
pa_log_info(_("We're in the group '%s', allowing real-time scheduling."), PA_REALTIME_GROUP);
allow_realtime = TRUE;
}
}
#ifdef HAVE_POLKIT
if (conf->high_priority && !allow_high_priority) {
if (pa_polkit_check("org.pulseaudio.acquire-high-priority") > 0) {
pa_log_info(_("PolicyKit grants us acquire-high-priority privilege."));
allow_high_priority = TRUE;
} else
pa_log_info(_("PolicyKit refuses acquire-high-priority privilege."));
}
if (conf->realtime_scheduling && !allow_realtime) {
if (pa_polkit_check("org.pulseaudio.acquire-real-time") > 0) {
pa_log_info(_("PolicyKit grants us acquire-real-time privilege."));
allow_realtime = TRUE;
} else
pa_log_info(_("PolicyKit refuses acquire-real-time privilege."));
}
#endif
if (!allow_high_priority && !allow_realtime) {
/* OK, there's no further need to keep CAP_NICE. Hence
* let's give it up early */
pa_drop_caps();
}
#ifdef RLIMIT_RTPRIO
if (getrlimit(RLIMIT_RTPRIO, &rl) >= 0)
if (rl.rlim_cur > 0) {
pa_log_info("RLIMIT_RTPRIO is set to %u, allowing real-time scheduling.", (unsigned) rl.rlim_cur);
allow_realtime = TRUE;
}
#endif
#ifdef RLIMIT_NICE
if (getrlimit(RLIMIT_NICE, &rl) >= 0)
if (rl.rlim_cur > 20 ) {
pa_log_info("RLIMIT_NICE is set to %u, allowing high-priority scheduling.", (unsigned) rl.rlim_cur);
allow_high_priority = TRUE;
}
#endif
if ((conf->high_priority && !allow_high_priority) ||
(conf->realtime_scheduling && !allow_realtime))
pa_log_info(_("Called SUID root and real-time and/or high-priority scheduling was requested in the configuration. However, we lack the necessary privileges:\n"
"We are not in group '%s', PolicyKit refuse to grant us the requested privileges and we have no increase RLIMIT_NICE/RLIMIT_RTPRIO resource limits.\n"
"For enabling real-time/high-priority scheduling please acquire the appropriate PolicyKit privileges, or become a member of '%s', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user."),
PA_REALTIME_GROUP, PA_REALTIME_GROUP);
if (!allow_realtime)
conf->realtime_scheduling = FALSE;
if (!allow_high_priority)
conf->high_priority = FALSE;
}
#ifdef HAVE_SYS_RESOURCE_H
/* Reset resource limits. If we are run as root (for system mode)
* this might end up increasing the limits, which is intended
* behaviour. For all other cases, i.e. started as normal user, or
* SUID root at this point we should have no CAP_SYS_RESOURCE and
* increasing the limits thus should fail. Which is, too, intended
* behaviour */
set_all_rlimits(conf);
#endif
if (conf->high_priority && !pa_can_high_priority()) {
pa_log_info(_("High-priority scheduling enabled in configuration but not allowed by policy."));
conf->high_priority = FALSE;
}
if (conf->high_priority && (conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START))
pa_raise_priority(conf->nice_level);
pa_log_debug("Can realtime: %s, can high-priority: %s", pa_yes_no(pa_can_realtime()), pa_yes_no(pa_can_high_priority()));
if (!real_root && pa_have_caps()) {
pa_bool_t drop;
drop = (conf->cmd != PA_CMD_DAEMON && conf->cmd != PA_CMD_START) || !conf->realtime_scheduling;
#ifdef RLIMIT_RTPRIO
if (!drop) {
struct rlimit rl;
/* At this point we still have CAP_NICE if we were loaded
* SUID root. If possible let's acquire RLIMIT_RTPRIO
* instead and give CAP_NICE up. */
if (getrlimit(RLIMIT_RTPRIO, &rl) >= 0) {
if (rl.rlim_cur >= 9)
drop = TRUE;
else {
rl.rlim_max = rl.rlim_cur = 9;
if (setrlimit(RLIMIT_RTPRIO, &rl) >= 0) {
pa_log_info(_("Successfully increased RLIMIT_RTPRIO"));
drop = TRUE;
} else
pa_log_warn(_("RLIMIT_RTPRIO failed: %s"), pa_cstrerror(errno));
}
}
}
#endif
if (drop) {
pa_log_info(_("Giving up CAP_NICE"));
pa_drop_caps();
suid_root = FALSE;
}
}
if (conf->realtime_scheduling && !pa_can_realtime()) {
pa_log_info(_("Real-time scheduling enabled in configuration but not allowed by policy."));
conf->realtime_scheduling = FALSE;
}
#ifdef HAVE_DBUS
after_caps_setup:
#endif
pa_log_debug("Can realtime: %s, can high-priority: %s", pa_yes_no(pa_can_realtime()), pa_yes_no(pa_can_high_priority()));
LTDL_SET_PRELOADED_SYMBOLS();
pa_ltdl_init();
ltdl_init = TRUE;
@ -757,10 +573,10 @@ after_caps_setup:
pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START);
}
if (real_root && !conf->system_instance)
if (getuid() == 0 && !conf->system_instance)
pa_log_warn(_("This program is not intended to be run as root (unless --system is specified)."));
#ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */
else if (!real_root && conf->system_instance) {
else if (getuid() != 0 && conf->system_instance) {
pa_log(_("Root privileges required."));
goto finish;
}
@ -907,6 +723,13 @@ after_caps_setup:
pa_assert_se(chdir("/") == 0);
umask(0022);
#ifdef HAVE_SYS_RESOURCE_H
set_all_rlimits(conf);
#endif
pa_rtclock_hrtimer_enable();
pa_raise_priority(conf->nice_level);
if (conf->system_instance)
if (change_user() < 0)
goto finish;
@ -955,8 +778,8 @@ after_caps_setup:
pa_xfree(s);
if ((s = pa_session_id())) {
pa_log_info(_("Session ID is %s."), s);
pa_xfree(s);
pa_log_info(_("Session ID is %s."), s);
pa_xfree(s);
}
if (!(s = pa_get_runtime_dir()))
@ -971,6 +794,11 @@ after_caps_setup:
pa_log_info(_("Running in system mode: %s"), pa_yes_no(pa_in_system_mode()));
if (pa_in_system_mode())
pa_log_warn(_("OK, so you are running PA in system mode. Please note that you most likely shouldn't be doing that.\n"
"If you do it nonetheless then it's your own fault if things don't work as expected.\n"
"Please read http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode for an explanation why system mode is usually a bad idea."));
if (conf->use_pid_file) {
int z;
@ -998,12 +826,16 @@ after_caps_setup:
else
pa_log_info(_("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!"));
pa_rtclock_hrtimer_enable();
#ifdef SIGRTMIN
/* Valgrind uses SIGRTMAX. To easy debugging we don't use it here */
pa_rtsig_configure(SIGRTMIN, SIGRTMAX-1);
if (conf->lock_memory) {
#ifdef HAVE_SYS_MMAN_H
if (mlockall(MCL_FUTURE) < 0)
pa_log_warn("mlockall() failed: %s", pa_cstrerror(errno));
else
pa_log_info("Sucessfully locked process into memory.");
#else
pa_log_warn("Memory locking requested but not supported on platform.");
#endif
}
pa_memtrap_install();
@ -1028,7 +860,9 @@ after_caps_setup:
c->running_as_daemon = !!conf->daemonize;
c->disallow_exit = conf->disallow_exit;
c->flat_volumes = conf->flat_volumes;
#ifdef HAVE_DBUS
c->server_type = conf->local_server_type;
#endif
pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0);
pa_signal_new(SIGINT, signal_callback, c);
@ -1044,7 +878,7 @@ after_caps_setup:
#endif
#ifdef OS_IS_WIN32
win32_timer = pa_mainloop_get_api(mainloop)->time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&win32_tv), message_cb, NULL);
win32_timer = pa_mainloop_get_api(mainloop)->rtclock_time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&win32_tv), message_cb, NULL);
#endif
oil_init();

View file

@ -28,6 +28,7 @@ pa_channel_map_superset;
pa_channel_map_to_name;
pa_channel_map_to_pretty_name;
pa_channel_map_valid;
pa_channel_position_from_string;
pa_channel_position_to_pretty_string;
pa_channel_position_to_string;
pa_context_add_autoload;
@ -85,6 +86,8 @@ pa_context_ref;
pa_context_remove_autoload_by_index;
pa_context_remove_autoload_by_name;
pa_context_remove_sample;
pa_context_rttime_new;
pa_context_rttime_restart;
pa_context_set_card_profile_by_index;
pa_context_set_card_profile_by_name;
pa_context_set_default_sink;
@ -95,10 +98,14 @@ pa_context_set_sink_input_mute;
pa_context_set_sink_input_volume;
pa_context_set_sink_mute_by_index;
pa_context_set_sink_mute_by_name;
pa_context_set_sink_port_by_index;
pa_context_set_sink_port_by_name;
pa_context_set_sink_volume_by_index;
pa_context_set_sink_volume_by_name;
pa_context_set_source_mute_by_index;
pa_context_set_source_mute_by_name;
pa_context_set_source_port_by_index;
pa_context_set_source_port_by_name;
pa_context_set_source_volume_by_index;
pa_context_set_source_volume_by_name;
pa_context_set_state_callback;
@ -190,6 +197,7 @@ pa_proplist_to_string_sep;
pa_proplist_unset;
pa_proplist_unset_many;
pa_proplist_update;
pa_rtclock_now;
pa_sample_format_is_be;
pa_sample_format_is_le;
pa_sample_format_to_string;
@ -264,7 +272,9 @@ pa_stream_writable_size;
pa_stream_write;
pa_strerror;
pa_sw_cvolume_divide;
pa_sw_cvolume_divide_scalar;
pa_sw_cvolume_multiply;
pa_sw_cvolume_multiply_scalar;
pa_sw_cvolume_snprint_dB;
pa_sw_volume_divide;
pa_sw_volume_from_dB;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,292 @@
#ifndef fooalsamixerhfoo
#define fooalsamixerhfoo
/***
This file is part of PulseAudio.
Copyright 2004-2006 Lennart Poettering
Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
***/
#include <asoundlib.h>
#include <pulse/sample.h>
#include <pulse/volume.h>
#include <pulse/mainloop-api.h>
#include <pulse/channelmap.h>
#include <pulse/proplist.h>
#include <pulse/volume.h>
#include <pulsecore/llist.h>
#include <pulsecore/rtpoll.h>
#include <pulsecore/core.h>
#include <pulsecore/log.h>
typedef struct pa_alsa_fdlist pa_alsa_fdlist;
typedef struct pa_alsa_setting pa_alsa_setting;
typedef struct pa_alsa_option pa_alsa_option;
typedef struct pa_alsa_element pa_alsa_element;
typedef struct pa_alsa_path pa_alsa_path;
typedef struct pa_alsa_path_set pa_alsa_path_set;
typedef struct pa_alsa_mapping pa_alsa_mapping;
typedef struct pa_alsa_profile pa_alsa_profile;
typedef struct pa_alsa_profile_set pa_alsa_profile_set;
typedef struct pa_alsa_port_data pa_alsa_port_data;
#include "alsa-util.h"
typedef enum pa_alsa_switch_use {
PA_ALSA_SWITCH_IGNORE,
PA_ALSA_SWITCH_MUTE, /* make this switch follow mute status */
PA_ALSA_SWITCH_OFF, /* set this switch to 'off' unconditionally */
PA_ALSA_SWITCH_ON, /* set this switch to 'on' unconditionally */
PA_ALSA_SWITCH_SELECT /* allow the user to select switch status through a setting */
} pa_alsa_switch_use_t;
typedef enum pa_alsa_volume_use {
PA_ALSA_VOLUME_IGNORE,
PA_ALSA_VOLUME_MERGE, /* merge this volume slider into the global volume slider */
PA_ALSA_VOLUME_OFF, /* set this volume to minimal unconditionally */
PA_ALSA_VOLUME_ZERO /* set this volume to 0dB unconditionally */
} pa_alsa_volume_use_t;
typedef enum pa_alsa_enumeration_use {
PA_ALSA_ENUMERATION_IGNORE,
PA_ALSA_ENUMERATION_SELECT
} pa_alsa_enumeration_use_t;
typedef enum pa_alsa_required {
PA_ALSA_REQUIRED_IGNORE,
PA_ALSA_REQUIRED_SWITCH,
PA_ALSA_REQUIRED_VOLUME,
PA_ALSA_REQUIRED_ENUMERATION,
PA_ALSA_REQUIRED_ANY
} pa_alsa_required_t;
typedef enum pa_alsa_direction {
PA_ALSA_DIRECTION_ANY,
PA_ALSA_DIRECTION_OUTPUT,
PA_ALSA_DIRECTION_INPUT
} pa_alsa_direction_t;
/* A setting combines a couple of options into a single entity that
* may be selected. Only one setting can be active at the same
* time. */
struct pa_alsa_setting {
pa_alsa_path *path;
PA_LLIST_FIELDS(pa_alsa_setting);
pa_idxset *options;
char *name;
char *description;
unsigned priority;
};
/* 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. */
struct pa_alsa_option {
pa_alsa_element *element;
PA_LLIST_FIELDS(pa_alsa_option);
char *alsa_name;
int alsa_idx;
char *name;
char *description;
unsigned priority;
};
/* And element wraps one specific ALSA element. A series of elements *
make up a path (see below). If the element is an enumeration or switch
* element it may includes a list of options. */
struct pa_alsa_element {
pa_alsa_path *path;
PA_LLIST_FIELDS(pa_alsa_element);
char *alsa_name;
pa_alsa_direction_t direction;
pa_alsa_switch_use_t switch_use;
pa_alsa_volume_use_t volume_use;
pa_alsa_enumeration_use_t enumeration_use;
pa_alsa_required_t required;
pa_alsa_required_t required_absent;
pa_bool_t override_map:1;
pa_bool_t direction_try_other:1;
pa_bool_t has_dB:1;
long min_volume, max_volume;
double min_dB, max_dB;
pa_channel_position_mask_t masks[SND_MIXER_SCHN_LAST][2];
unsigned n_channels;
pa_channel_position_mask_t merged_mask;
PA_LLIST_HEAD(pa_alsa_option, options);
};
/* A path wraps a series of elements into a single entity which can be
* used to control it as if it had a single volume slider, a single
* mute switch and a single list of selectable options. */
struct pa_alsa_path {
pa_alsa_path_set *path_set;
PA_LLIST_FIELDS(pa_alsa_path);
pa_alsa_direction_t direction;
char *name;
char *description;
unsigned priority;
pa_bool_t probed:1;
pa_bool_t supported:1;
pa_bool_t has_mute:1;
pa_bool_t has_volume:1;
pa_bool_t has_dB:1;
long min_volume, max_volume;
double min_dB, max_dB;
/* This is used during parsing only, as a shortcut so that we
* don't have to iterate the list all the time */
pa_alsa_element *last_element;
pa_alsa_option *last_option;
pa_alsa_setting *last_setting;
PA_LLIST_HEAD(pa_alsa_element, elements);
PA_LLIST_HEAD(pa_alsa_setting, settings);
};
/* A path set is simply a set of paths that are applicable to a
* device */
struct pa_alsa_path_set {
PA_LLIST_HEAD(pa_alsa_path, paths);
pa_alsa_direction_t direction;
pa_bool_t probed:1;
/* This is used during parsing only, as a shortcut so that we
* don't have to iterate the list all the time */
pa_alsa_path *last_path;
};
int pa_alsa_setting_select(pa_alsa_setting *s, snd_mixer_t *m);
void pa_alsa_setting_dump(pa_alsa_setting *s);
void pa_alsa_option_dump(pa_alsa_option *o);
void pa_alsa_element_dump(pa_alsa_element *e);
pa_alsa_path *pa_alsa_path_new(const char *fname, pa_alsa_direction_t direction);
pa_alsa_path *pa_alsa_path_synthesize(const char *element, pa_alsa_direction_t direction);
int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, pa_bool_t ignore_dB);
void pa_alsa_path_dump(pa_alsa_path *p);
int pa_alsa_path_get_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v);
int pa_alsa_path_get_mute(pa_alsa_path *path, snd_mixer_t *m, pa_bool_t *muted);
int pa_alsa_path_set_volume(pa_alsa_path *path, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v);
int pa_alsa_path_set_mute(pa_alsa_path *path, snd_mixer_t *m, pa_bool_t muted);
int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m);
void pa_alsa_path_set_callback(pa_alsa_path *p, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata);
void pa_alsa_path_free(pa_alsa_path *p);
pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t direction);
void pa_alsa_path_set_probe(pa_alsa_path_set *s, snd_mixer_t *m, pa_bool_t ignore_dB);
void pa_alsa_path_set_dump(pa_alsa_path_set *s);
void pa_alsa_path_set_set_callback(pa_alsa_path_set *ps, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata);
void pa_alsa_path_set_free(pa_alsa_path_set *s);
struct pa_alsa_mapping {
pa_alsa_profile_set *profile_set;
char *name;
char *description;
unsigned priority;
pa_alsa_direction_t direction;
pa_channel_map channel_map;
char **device_strings;
char **input_path_names;
char **output_path_names;
char **input_element; /* list of fallbacks */
char **output_element;
unsigned supported;
/* Temporarily used during probing */
snd_pcm_t *input_pcm;
snd_pcm_t *output_pcm;
pa_sink *sink;
pa_source *source;
};
struct pa_alsa_profile {
pa_alsa_profile_set *profile_set;
char *name;
char *description;
unsigned priority;
pa_bool_t supported:1;
char **input_mapping_names;
char **output_mapping_names;
pa_idxset *input_mappings;
pa_idxset *output_mappings;
};
struct pa_alsa_profile_set {
pa_hashmap *mappings;
pa_hashmap *profiles;
pa_bool_t auto_profiles;
pa_bool_t probed:1;
};
void pa_alsa_mapping_dump(pa_alsa_mapping *m);
void pa_alsa_profile_dump(pa_alsa_profile *p);
pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus);
void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss);
void pa_alsa_profile_set_free(pa_alsa_profile_set *s);
void pa_alsa_profile_set_dump(pa_alsa_profile_set *s);
snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device);
pa_alsa_fdlist *pa_alsa_fdlist_new(void);
void pa_alsa_fdlist_free(pa_alsa_fdlist *fdl);
int pa_alsa_fdlist_set_mixer(pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m);
/* Data structure for inclusion in pa_device_port for alsa
* sinks/sources. This contains nothing that needs to be freed
* individually */
struct pa_alsa_port_data {
pa_alsa_path *path;
pa_alsa_setting *setting;
};
void pa_alsa_add_ports(pa_hashmap **p, pa_alsa_path_set *ps);
#endif

View file

@ -32,16 +32,18 @@
#include <valgrind/memcheck.h>
#endif
#include <pulse/xmalloc.h>
#include <pulse/util.h>
#include <pulse/timeval.h>
#include <pulse/i18n.h>
#include <pulse/rtclock.h>
#include <pulse/timeval.h>
#include <pulse/util.h>
#include <pulse/xmalloc.h>
#include <pulsecore/core.h>
#include <pulsecore/module.h>
#include <pulsecore/memchunk.h>
#include <pulsecore/sink.h>
#include <pulsecore/modargs.h>
#include <pulsecore/core-rtclock.h>
#include <pulsecore/core-util.h>
#include <pulsecore/sample-util.h>
#include <pulsecore/log.h>
@ -50,7 +52,6 @@
#include <pulsecore/core-error.h>
#include <pulsecore/thread-mq.h>
#include <pulsecore/rtpoll.h>
#include <pulsecore/rtclock.h>
#include <pulsecore/time-smoother.h>
#include <modules/reserve-wrap.h>
@ -80,11 +81,9 @@ struct userdata {
pa_alsa_fdlist *mixer_fdl;
snd_mixer_t *mixer_handle;
snd_mixer_elem_t *mixer_elem;
long hw_volume_max, hw_volume_min;
long hw_dB_max, hw_dB_min;
pa_bool_t hw_dB_supported:1;
pa_bool_t mixer_seperate_channels:1;
pa_alsa_path_set *mixer_path_set;
pa_alsa_path *mixer_path;
pa_cvolume hardware_volume;
size_t
@ -100,7 +99,8 @@ struct userdata {
unsigned nfragments;
pa_memchunk memchunk;
char *device_name;
char *device_name; /* name of the PCM device */
char *control_device; /* name of the control device */
pa_bool_t use_mmap:1, use_tsched:1;
@ -116,6 +116,8 @@ struct userdata {
pa_reserve_wrapper *reserve;
pa_hook_slot *reserve_slot;
pa_reserve_monitor_wrapper *monitor;
pa_hook_slot *monitor_slot;
};
static void userdata_free(struct userdata *u);
@ -124,7 +126,7 @@ static pa_hook_result_t reserve_cb(pa_reserve_wrapper *r, void *forced, struct u
pa_assert(r);
pa_assert(u);
if (pa_sink_suspend(u->sink, TRUE) < 0)
if (pa_sink_suspend(u->sink, TRUE, PA_SUSPEND_APPLICATION) < 0)
return PA_HOOK_CANCEL;
return PA_HOOK_OK;
@ -185,6 +187,57 @@ static int reserve_init(struct userdata *u, const char *dname) {
return 0;
}
static pa_hook_result_t monitor_cb(pa_reserve_monitor_wrapper *w, void* busy, struct userdata *u) {
pa_bool_t b;
pa_assert(w);
pa_assert(u);
b = PA_PTR_TO_UINT(busy) && !u->reserve;
pa_sink_suspend(u->sink, b, PA_SUSPEND_APPLICATION);
return PA_HOOK_OK;
}
static void monitor_done(struct userdata *u) {
pa_assert(u);
if (u->monitor_slot) {
pa_hook_slot_free(u->monitor_slot);
u->monitor_slot = NULL;
}
if (u->monitor) {
pa_reserve_monitor_wrapper_unref(u->monitor);
u->monitor = NULL;
}
}
static int reserve_monitor_init(struct userdata *u, const char *dname) {
char *rname;
pa_assert(u);
pa_assert(dname);
if (pa_in_system_mode())
return 0;
/* We are resuming, try to lock the device */
if (!(rname = pa_alsa_get_reserve_name(dname)))
return 0;
u->monitor = pa_reserve_monitor_wrapper_get(u->core, rname);
pa_xfree(rname);
if (!(u->monitor))
return -1;
pa_assert(!u->monitor_slot);
u->monitor_slot = pa_hook_connect(pa_reserve_monitor_wrapper_hook(u->monitor), PA_HOOK_NORMAL, (pa_hook_cb_t) monitor_cb, u);
return 0;
}
static void fix_min_sleep_wakeup(struct userdata *u) {
size_t max_use, max_use_2;
@ -655,7 +708,7 @@ static void update_smoother(struct userdata *u) {
/* Hmm, if the timestamp is 0, then it wasn't set and we take the current time */
if (now1 <= 0)
now1 = pa_rtclock_usec();
now1 = pa_rtclock_now();
now2 = pa_bytes_to_usec((uint64_t) position, &u->sink->sample_spec);
@ -669,7 +722,7 @@ static pa_usec_t sink_get_latency(struct userdata *u) {
pa_assert(u);
now1 = pa_rtclock_usec();
now1 = pa_rtclock_now();
now2 = pa_smoother_get(u->smoother, now1);
delay = (int64_t) pa_bytes_to_usec(u->write_count, &u->sink->sample_spec) - (int64_t) now2;
@ -700,7 +753,7 @@ static int suspend(struct userdata *u) {
pa_assert(u);
pa_assert(u->pcm_handle);
pa_smoother_pause(u->smoother, pa_rtclock_usec());
pa_smoother_pause(u->smoother, pa_rtclock_now());
/* Let's suspend -- we don't call snd_pcm_drain() here since that might
* take awfully long with our long buffer sizes today. */
@ -786,7 +839,6 @@ static int unsuspend(struct userdata *u) {
pa_log_info("Trying resume...");
snd_config_update_free_global();
if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK,
/*SND_PCM_NONBLOCK|*/
SND_PCM_NO_AUTO_RESAMPLE|
@ -938,191 +990,58 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
return 0;
}
static pa_volume_t from_alsa_volume(struct userdata *u, long alsa_vol) {
return (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) /
(double) (u->hw_volume_max - u->hw_volume_min));
}
static long to_alsa_volume(struct userdata *u, pa_volume_t vol) {
long alsa_vol;
alsa_vol = (long) round(((double) vol * (double) (u->hw_volume_max - u->hw_volume_min))
/ PA_VOLUME_NORM) + u->hw_volume_min;
return PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
}
static void sink_get_volume_cb(pa_sink *s) {
struct userdata *u = s->userdata;
int err;
unsigned i;
pa_cvolume r;
char t[PA_CVOLUME_SNPRINT_MAX];
pa_assert(u);
pa_assert(u->mixer_elem);
pa_assert(u->mixer_path);
pa_assert(u->mixer_handle);
if (u->mixer_seperate_channels) {
if (pa_alsa_path_get_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &r) < 0)
return;
r.channels = s->sample_spec.channels;
for (i = 0; i < s->sample_spec.channels; i++) {
long alsa_vol;
if (u->hw_dB_supported) {
if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
goto fail;
#ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
#endif
r.values[i] = pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0);
} else {
if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
goto fail;
r.values[i] = from_alsa_volume(u, alsa_vol);
}
}
} else {
long alsa_vol;
if (u->hw_dB_supported) {
if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
goto fail;
#ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
#endif
pa_cvolume_set(&r, s->sample_spec.channels, pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0));
} else {
if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
goto fail;
pa_cvolume_set(&r, s->sample_spec.channels, from_alsa_volume(u, alsa_vol));
}
}
/* Shift down by the base volume, so that 0dB becomes maximum volume */
pa_sw_cvolume_multiply_scalar(&r, &r, s->base_volume);
pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &r));
if (!pa_cvolume_equal(&u->hardware_volume, &r)) {
if (pa_cvolume_equal(&u->hardware_volume, &r))
return;
s->virtual_volume = u->hardware_volume = r;
s->virtual_volume = u->hardware_volume = r;
if (u->hw_dB_supported) {
pa_cvolume reset;
if (u->mixer_path->has_dB) {
pa_cvolume reset;
/* Hmm, so the hardware volume changed, let's reset our software volume */
pa_cvolume_reset(&reset, s->sample_spec.channels);
pa_sink_set_soft_volume(s, &reset);
}
/* Hmm, so the hardware volume changed, let's reset our software volume */
pa_cvolume_reset(&reset, s->sample_spec.channels);
pa_sink_set_soft_volume(s, &reset);
}
return;
fail:
pa_log_error("Unable to read volume: %s", pa_alsa_strerror(err));
}
static void sink_set_volume_cb(pa_sink *s) {
struct userdata *u = s->userdata;
int err;
unsigned i;
pa_cvolume r;
char t[PA_CVOLUME_SNPRINT_MAX];
pa_assert(u);
pa_assert(u->mixer_elem);
pa_assert(u->mixer_path);
pa_assert(u->mixer_handle);
if (u->mixer_seperate_channels) {
/* Shift up by the base volume */
pa_sw_cvolume_divide_scalar(&r, &s->virtual_volume, s->base_volume);
r.channels = s->sample_spec.channels;
if (pa_alsa_path_set_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &r) < 0)
return;
for (i = 0; i < s->sample_spec.channels; i++) {
long alsa_vol;
pa_volume_t vol;
vol = s->virtual_volume.values[i];
if (u->hw_dB_supported) {
alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
alsa_vol += u->hw_dB_max;
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
if ((err = snd_mixer_selem_set_playback_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, 1)) < 0)
goto fail;
if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
goto fail;
#ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
#endif
r.values[i] = pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0);
} else {
alsa_vol = to_alsa_volume(u, vol);
if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
goto fail;
if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
goto fail;
r.values[i] = from_alsa_volume(u, alsa_vol);
}
}
} else {
pa_volume_t vol;
long alsa_vol;
vol = pa_cvolume_max(&s->virtual_volume);
if (u->hw_dB_supported) {
alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
alsa_vol += u->hw_dB_max;
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
if ((err = snd_mixer_selem_set_playback_dB_all(u->mixer_elem, alsa_vol, 1)) < 0)
goto fail;
if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
goto fail;
#ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
#endif
pa_cvolume_set(&r, s->sample_spec.channels, pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0));
} else {
alsa_vol = to_alsa_volume(u, vol);
if ((err = snd_mixer_selem_set_playback_volume_all(u->mixer_elem, alsa_vol)) < 0)
goto fail;
if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
goto fail;
pa_cvolume_set(&r, s->sample_spec.channels, from_alsa_volume(u, alsa_vol));
}
}
/* Shift down by the base volume, so that 0dB becomes maximum volume */
pa_sw_cvolume_multiply_scalar(&r, &r, s->base_volume);
u->hardware_volume = r;
if (u->hw_dB_supported) {
char t[PA_CVOLUME_SNPRINT_MAX];
if (u->mixer_path->has_dB) {
/* Match exactly what the user requested by software */
pa_sw_cvolume_divide(&s->soft_volume, &s->virtual_volume, &u->hardware_volume);
@ -1131,45 +1050,75 @@ static void sink_set_volume_cb(pa_sink *s) {
pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &u->hardware_volume));
pa_log_debug("Calculated software volume: %s", pa_cvolume_snprint(t, sizeof(t), &s->soft_volume));
} else
} else {
pa_log_debug("Wrote hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &r));
/* We can't match exactly what the user requested, hence let's
* at least tell the user about it */
s->virtual_volume = r;
return;
fail:
pa_log_error("Unable to set volume: %s", pa_alsa_strerror(err));
}
}
static void sink_get_mute_cb(pa_sink *s) {
struct userdata *u = s->userdata;
int err, sw;
pa_bool_t b;
pa_assert(u);
pa_assert(u->mixer_elem);
pa_assert(u->mixer_path);
pa_assert(u->mixer_handle);
if ((err = snd_mixer_selem_get_playback_switch(u->mixer_elem, 0, &sw)) < 0) {
pa_log_error("Unable to get switch: %s", pa_alsa_strerror(err));
if (pa_alsa_path_get_mute(u->mixer_path, u->mixer_handle, &b) < 0)
return;
}
s->muted = !sw;
s->muted = b;
}
static void sink_set_mute_cb(pa_sink *s) {
struct userdata *u = s->userdata;
int err;
pa_assert(u);
pa_assert(u->mixer_elem);
pa_assert(u->mixer_path);
pa_assert(u->mixer_handle);
if ((err = snd_mixer_selem_set_playback_switch_all(u->mixer_elem, !s->muted)) < 0) {
pa_log_error("Unable to set switch: %s", pa_alsa_strerror(err));
return;
pa_alsa_path_set_mute(u->mixer_path, u->mixer_handle, s->muted);
}
static int sink_set_port_cb(pa_sink *s, pa_device_port *p) {
struct userdata *u = s->userdata;
pa_alsa_port_data *data;
pa_assert(u);
pa_assert(p);
pa_assert(u->mixer_handle);
data = PA_DEVICE_PORT_DATA(p);
pa_assert_se(u->mixer_path = data->path);
pa_alsa_path_select(u->mixer_path, u->mixer_handle);
if (u->mixer_path->has_volume && u->mixer_path->has_dB) {
s->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
s->n_volume_steps = PA_VOLUME_NORM+1;
if (u->mixer_path->max_dB > 0.0)
pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(s->base_volume));
else
pa_log_info("No particular base volume set, fixing to 0 dB");
} else {
s->base_volume = PA_VOLUME_NORM;
s->n_volume_steps = u->mixer_path->max_volume - u->mixer_path->min_volume + 1;
}
if (data->setting)
pa_alsa_setting_select(data->setting, u->mixer_handle);
if (s->set_mute)
s->set_mute(s);
if (s->set_volume)
s->set_volume(s);
return 0;
}
static void sink_update_requested_latency_cb(pa_sink *s) {
@ -1264,7 +1213,6 @@ static void thread_func(void *userdata) {
pa_make_realtime(u->core->realtime_priority);
pa_thread_mq_install(&u->thread_mq);
pa_rtpoll_install(u->rtpoll);
for (;;) {
int ret;
@ -1298,7 +1246,7 @@ static void thread_func(void *userdata) {
pa_log_info("Starting playback.");
snd_pcm_start(u->pcm_handle);
pa_smoother_resume(u->smoother, pa_rtclock_usec(), TRUE);
pa_smoother_resume(u->smoother, pa_rtclock_now(), TRUE);
}
update_smoother(u);
@ -1327,7 +1275,7 @@ static void thread_func(void *userdata) {
/* Convert from the sound card time domain to the
* system time domain */
cusec = pa_smoother_translate(u->smoother, pa_rtclock_usec(), sleep_usec);
cusec = pa_smoother_translate(u->smoother, pa_rtclock_now(), sleep_usec);
/* pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
@ -1386,7 +1334,7 @@ finish:
pa_log_debug("Thread shutting down");
}
static void set_sink_name(pa_sink_new_data *data, pa_modargs *ma, const char *device_id, const char *device_name) {
static void set_sink_name(pa_sink_new_data *data, pa_modargs *ma, const char *device_id, const char *device_name, pa_alsa_mapping *mapping) {
const char *n;
char *t;
@ -1407,82 +1355,136 @@ static void set_sink_name(pa_sink_new_data *data, pa_modargs *ma, const char *de
data->namereg_fail = FALSE;
}
t = pa_sprintf_malloc("alsa_output.%s", n);
if (mapping)
t = pa_sprintf_malloc("alsa_output.%s.%s", n, mapping->name);
else
t = pa_sprintf_malloc("alsa_output.%s", n);
pa_sink_new_data_set_name(data, t);
pa_xfree(t);
}
static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char *element, pa_bool_t ignore_dB) {
if (!mapping && !element)
return;
if (!(u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device))) {
pa_log_info("Failed to find a working mixer device.");
return;
}
if (element) {
if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_OUTPUT)))
goto fail;
if (pa_alsa_path_probe(u->mixer_path, u->mixer_handle, ignore_dB) < 0)
goto fail;
pa_log_debug("Probed mixer path %s:", u->mixer_path->name);
pa_alsa_path_dump(u->mixer_path);
} else {
if (!(u->mixer_path_set = pa_alsa_path_set_new(mapping, PA_ALSA_DIRECTION_OUTPUT)))
goto fail;
pa_alsa_path_set_probe(u->mixer_path_set, u->mixer_handle, ignore_dB);
pa_log_debug("Probed mixer paths:");
pa_alsa_path_set_dump(u->mixer_path_set);
}
return;
fail:
if (u->mixer_path_set) {
pa_alsa_path_set_free(u->mixer_path_set);
u->mixer_path_set = NULL;
} else if (u->mixer_path) {
pa_alsa_path_free(u->mixer_path);
u->mixer_path = NULL;
}
if (u->mixer_handle) {
snd_mixer_close(u->mixer_handle);
u->mixer_handle = NULL;
}
}
static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
pa_assert(u);
if (!u->mixer_handle)
return 0;
pa_assert(u->mixer_elem);
if (u->sink->active_port) {
pa_alsa_port_data *data;
if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) {
pa_bool_t suitable = FALSE;
/* We have a list of supported paths, so let's activate the
* one that has been chosen as active */
if (snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) < 0)
pa_log_info("Failed to get volume range. Falling back to software volume control.");
else if (u->hw_volume_min >= u->hw_volume_max)
pa_log_warn("Your kernel driver is broken: it reports a volume range from %li to %li which makes no sense.", u->hw_volume_min, u->hw_volume_max);
else {
pa_log_info("Volume ranges from %li to %li.", u->hw_volume_min, u->hw_volume_max);
suitable = TRUE;
}
data = PA_DEVICE_PORT_DATA(u->sink->active_port);
u->mixer_path = data->path;
if (suitable) {
if (ignore_dB || snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) < 0)
pa_log_info("Mixer doesn't support dB information or data is ignored.");
else {
#ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_min, sizeof(u->hw_dB_min));
VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_max, sizeof(u->hw_dB_max));
#endif
pa_alsa_path_select(data->path, u->mixer_handle);
if (u->hw_dB_min >= u->hw_dB_max)
pa_log_warn("Your kernel driver is broken: it reports a volume range from %0.2f dB to %0.2f dB which makes no sense.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
else {
pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
u->hw_dB_supported = TRUE;
if (data->setting)
pa_alsa_setting_select(data->setting, u->mixer_handle);
if (u->hw_dB_max > 0) {
u->sink->base_volume = pa_sw_volume_from_dB(- (double) u->hw_dB_max/100.0);
pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u->sink->base_volume));
} else
pa_log_info("No particular base volume set, fixing to 0 dB");
}
}
} else {
if (!u->hw_dB_supported &&
u->hw_volume_max - u->hw_volume_min < 3) {
if (!u->mixer_path && u->mixer_path_set)
u->mixer_path = u->mixer_path_set->paths;
pa_log_info("Device doesn't do dB volume and has less than 4 volume levels. Falling back to software volume control.");
suitable = FALSE;
}
}
if (u->mixer_path) {
/* Hmm, we have only a single path, then let's activate it */
if (suitable) {
u->mixer_seperate_channels = pa_alsa_calc_mixer_map(u->mixer_elem, &u->sink->channel_map, u->mixer_map, TRUE) >= 0;
pa_alsa_path_select(u->mixer_path, u->mixer_handle);
u->sink->get_volume = sink_get_volume_cb;
u->sink->set_volume = sink_set_volume_cb;
u->sink->flags |= PA_SINK_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SINK_DECIBEL_VOLUME : 0);
pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported");
if (!u->hw_dB_supported)
u->sink->n_volume_steps = u->hw_volume_max - u->hw_volume_min + 1;
if (u->mixer_path->settings)
pa_alsa_setting_select(u->mixer_path->settings, u->mixer_handle);
} else
pa_log_info("Using software volume control.");
return 0;
}
if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) {
if (!u->mixer_path->has_volume)
pa_log_info("Driver does not support hardware volume control, falling back to software volume control.");
else {
if (u->mixer_path->has_dB) {
pa_log_info("Hardware volume ranges from %0.2f dB to %0.2f dB.", u->mixer_path->min_dB, u->mixer_path->max_dB);
u->sink->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
u->sink->n_volume_steps = PA_VOLUME_NORM+1;
if (u->mixer_path->max_dB > 0.0)
pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u->sink->base_volume));
else
pa_log_info("No particular base volume set, fixing to 0 dB");
} else {
pa_log_info("Hardware volume ranges from %li to %li.", u->mixer_path->min_volume, u->mixer_path->max_volume);
u->sink->base_volume = PA_VOLUME_NORM;
u->sink->n_volume_steps = u->mixer_path->max_volume - u->mixer_path->min_volume + 1;
}
u->sink->get_volume = sink_get_volume_cb;
u->sink->set_volume = sink_set_volume_cb;
u->sink->flags |= PA_SINK_HW_VOLUME_CTRL | (u->mixer_path->has_dB ? PA_SINK_DECIBEL_VOLUME : 0);
pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->mixer_path->has_dB ? "supported" : "not supported");
}
if (!u->mixer_path->has_mute) {
pa_log_info("Driver does not support hardware mute control, falling back to software mute control.");
} else {
u->sink->get_mute = sink_get_mute_cb;
u->sink->set_mute = sink_set_mute_cb;
u->sink->flags |= PA_SINK_HW_MUTE_CTRL;
} else
pa_log_info("Using software mute control.");
pa_log_info("Using hardware mute control.");
}
u->mixer_fdl = pa_alsa_fdlist_new();
@ -1491,13 +1493,15 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
return -1;
}
snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback);
snd_mixer_elem_set_callback_private(u->mixer_elem, u);
if (u->mixer_path_set)
pa_alsa_path_set_set_callback(u->mixer_path_set, u->mixer_handle, mixer_callback, u);
else
pa_alsa_path_set_callback(u->mixer_path, u->mixer_handle, mixer_callback, u);
return 0;
}
pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, const pa_alsa_profile_info *profile) {
pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, pa_alsa_mapping *mapping) {
struct userdata *u = NULL;
const char *dev_id = NULL;
@ -1508,7 +1512,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
size_t frame_size;
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE;
pa_sink_new_data data;
char *control_device = NULL;
pa_alsa_profile_set *profile_set = NULL;
pa_assert(m);
pa_assert(ma);
@ -1577,43 +1581,51 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
TRUE,
TRUE,
5,
pa_rtclock_usec(),
pa_rtclock_now(),
TRUE);
if (reserve_init(u, pa_modargs_get_value(
ma, "device_id",
pa_modargs_get_value(ma, "device", DEFAULT_DEVICE))) < 0)
dev_id = pa_modargs_get_value(
ma, "device_id",
pa_modargs_get_value(ma, "device", DEFAULT_DEVICE));
if (reserve_init(u, dev_id) < 0)
goto fail;
if (reserve_monitor_init(u, dev_id) < 0)
goto fail;
b = use_mmap;
d = use_tsched;
if (profile) {
if (mapping) {
if (!(dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
pa_log("device_id= not set");
goto fail;
}
if (!(u->pcm_handle = pa_alsa_open_by_device_id_profile(
if (!(u->pcm_handle = pa_alsa_open_by_device_id_mapping(
dev_id,
&u->device_name,
&ss, &map,
SND_PCM_STREAM_PLAYBACK,
&nfrags, &period_frames, tsched_frames,
&b, &d, profile)))
&b, &d, mapping)))
goto fail;
} else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
if (!(profile_set = pa_alsa_profile_set_new(NULL, &map)))
goto fail;
if (!(u->pcm_handle = pa_alsa_open_by_device_id_auto(
dev_id,
&u->device_name,
&ss, &map,
SND_PCM_STREAM_PLAYBACK,
&nfrags, &period_frames, tsched_frames,
&b, &d, &profile)))
&b, &d, profile_set, &mapping)))
goto fail;
@ -1627,7 +1639,6 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
&nfrags, &period_frames, tsched_frames,
&b, &d, FALSE)))
goto fail;
}
pa_assert(u->device_name);
@ -1638,8 +1649,8 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
goto fail;
}
if (profile)
pa_log_info("Selected configuration '%s' (%s).", profile->description, profile->name);
if (mapping)
pa_log_info("Selected mapping '%s' (%s).", mapping->description, mapping->name);
if (use_mmap && !b) {
pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
@ -1665,33 +1676,31 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
/* ALSA might tweak the sample spec, so recalculate the frame size */
frame_size = pa_frame_size(&ss);
pa_alsa_find_mixer_and_elem(u->pcm_handle, &control_device, &u->mixer_handle, &u->mixer_elem, pa_modargs_get_value(ma, "control", NULL), profile);
find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB);
pa_sink_new_data_init(&data);
data.driver = driver;
data.module = m;
data.card = card;
set_sink_name(&data, ma, dev_id, u->device_name);
set_sink_name(&data, ma, dev_id, u->device_name, mapping);
pa_sink_new_data_set_sample_spec(&data, &ss);
pa_sink_new_data_set_channel_map(&data, &map);
pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle, u->mixer_elem);
pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
if (profile) {
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_NAME, profile->name);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile->description);
if (mapping) {
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_NAME, mapping->name);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, mapping->description);
}
pa_alsa_init_description(data.proplist);
if (control_device) {
pa_alsa_init_proplist_ctl(data.proplist, control_device);
pa_xfree(control_device);
}
if (u->control_device)
pa_alsa_init_proplist_ctl(data.proplist, u->control_device);
if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
pa_log("Invalid properties");
@ -1699,6 +1708,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
goto fail;
}
if (u->mixer_path_set)
pa_alsa_add_ports(&data.ports, u->mixer_path_set);
u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY|(u->use_tsched ? PA_SINK_DYNAMIC_LATENCY : 0));
pa_sink_new_data_done(&data);
@ -1710,6 +1722,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
u->sink->parent.process_msg = sink_process_msg;
u->sink->update_requested_latency = sink_update_requested_latency_cb;
u->sink->set_state = sink_set_state_cb;
u->sink->set_port = sink_set_port_cb;
u->sink->userdata = u;
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
@ -1778,6 +1791,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
pa_sink_put(u->sink);
if (profile_set)
pa_alsa_profile_set_free(profile_set);
return u->sink;
fail:
@ -1785,6 +1801,9 @@ fail:
if (u)
userdata_free(u);
if (profile_set)
pa_alsa_profile_set_free(profile_set);
return NULL;
}
@ -1813,23 +1832,30 @@ static void userdata_free(struct userdata *u) {
if (u->rtpoll)
pa_rtpoll_free(u->rtpoll);
if (u->mixer_fdl)
pa_alsa_fdlist_free(u->mixer_fdl);
if (u->mixer_handle)
snd_mixer_close(u->mixer_handle);
if (u->pcm_handle) {
snd_pcm_drop(u->pcm_handle);
snd_pcm_close(u->pcm_handle);
}
if (u->mixer_fdl)
pa_alsa_fdlist_free(u->mixer_fdl);
if (u->mixer_path_set)
pa_alsa_path_set_free(u->mixer_path_set);
else if (u->mixer_path)
pa_alsa_path_free(u->mixer_path);
if (u->mixer_handle)
snd_mixer_close(u->mixer_handle);
if (u->smoother)
pa_smoother_free(u->smoother);
reserve_done(u);
monitor_done(u);
pa_xfree(u->device_name);
pa_xfree(u->control_device);
pa_xfree(u);
}

View file

@ -28,8 +28,9 @@
#include <pulsecore/sink.h>
#include "alsa-util.h"
#include "alsa-mixer.h"
pa_sink* pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, const pa_alsa_profile_info *profile);
pa_sink* pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, pa_alsa_mapping *mapping);
void pa_alsa_sink_free(pa_sink *s);

View file

@ -28,14 +28,11 @@
#include <asoundlib.h>
#ifdef HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif
#include <pulse/xmalloc.h>
#include <pulse/util.h>
#include <pulse/timeval.h>
#include <pulse/i18n.h>
#include <pulse/rtclock.h>
#include <pulse/timeval.h>
#include <pulse/util.h>
#include <pulse/xmalloc.h>
#include <pulsecore/core-error.h>
#include <pulsecore/core.h>
@ -43,6 +40,7 @@
#include <pulsecore/memchunk.h>
#include <pulsecore/sink.h>
#include <pulsecore/modargs.h>
#include <pulsecore/core-rtclock.h>
#include <pulsecore/core-util.h>
#include <pulsecore/sample-util.h>
#include <pulsecore/log.h>
@ -52,7 +50,6 @@
#include <pulsecore/thread-mq.h>
#include <pulsecore/rtpoll.h>
#include <pulsecore/time-smoother.h>
#include <pulsecore/rtclock.h>
#include <modules/reserve-wrap.h>
@ -81,11 +78,8 @@ struct userdata {
pa_alsa_fdlist *mixer_fdl;
snd_mixer_t *mixer_handle;
snd_mixer_elem_t *mixer_elem;
long hw_volume_max, hw_volume_min;
long hw_dB_max, hw_dB_min;
pa_bool_t hw_dB_supported:1;
pa_bool_t mixer_seperate_channels:1;
pa_alsa_path_set *mixer_path_set;
pa_alsa_path *mixer_path;
pa_cvolume hardware_volume;
@ -102,6 +96,7 @@ struct userdata {
unsigned nfragments;
char *device_name;
char *control_device;
pa_bool_t use_mmap:1, use_tsched:1;
@ -114,6 +109,8 @@ struct userdata {
pa_reserve_wrapper *reserve;
pa_hook_slot *reserve_slot;
pa_reserve_monitor_wrapper *monitor;
pa_hook_slot *monitor_slot;
};
static void userdata_free(struct userdata *u);
@ -122,7 +119,7 @@ static pa_hook_result_t reserve_cb(pa_reserve_wrapper *r, void *forced, struct u
pa_assert(r);
pa_assert(u);
if (pa_source_suspend(u->source, TRUE) < 0)
if (pa_source_suspend(u->source, TRUE, PA_SUSPEND_APPLICATION) < 0)
return PA_HOOK_CANCEL;
return PA_HOOK_OK;
@ -183,6 +180,57 @@ static int reserve_init(struct userdata *u, const char *dname) {
return 0;
}
static pa_hook_result_t monitor_cb(pa_reserve_monitor_wrapper *w, void* busy, struct userdata *u) {
pa_bool_t b;
pa_assert(w);
pa_assert(u);
b = PA_PTR_TO_UINT(busy) && !u->reserve;
pa_source_suspend(u->source, b, PA_SUSPEND_APPLICATION);
return PA_HOOK_OK;
}
static void monitor_done(struct userdata *u) {
pa_assert(u);
if (u->monitor_slot) {
pa_hook_slot_free(u->monitor_slot);
u->monitor_slot = NULL;
}
if (u->monitor) {
pa_reserve_monitor_wrapper_unref(u->monitor);
u->monitor = NULL;
}
}
static int reserve_monitor_init(struct userdata *u, const char *dname) {
char *rname;
pa_assert(u);
pa_assert(dname);
if (pa_in_system_mode())
return 0;
/* We are resuming, try to lock the device */
if (!(rname = pa_alsa_get_reserve_name(dname)))
return 0;
u->monitor = pa_reserve_monitor_wrapper_get(u->core, rname);
pa_xfree(rname);
if (!(u->monitor))
return -1;
pa_assert(!u->monitor_slot);
u->monitor_slot = pa_hook_connect(pa_reserve_monitor_wrapper_hook(u->monitor), PA_HOOK_NORMAL, (pa_hook_cb_t) monitor_cb, u);
return 0;
}
static void fix_min_sleep_wakeup(struct userdata *u) {
size_t max_use, max_use_2;
pa_assert(u);
@ -622,7 +670,7 @@ static void update_smoother(struct userdata *u) {
/* Hmm, if the timestamp is 0, then it wasn't set and we take the current time */
if (now1 <= 0)
now1 = pa_rtclock_usec();
now1 = pa_rtclock_now();
now2 = pa_bytes_to_usec(position, &u->source->sample_spec);
@ -635,7 +683,7 @@ static pa_usec_t source_get_latency(struct userdata *u) {
pa_assert(u);
now1 = pa_rtclock_usec();
now1 = pa_rtclock_now();
now2 = pa_smoother_get(u->smoother, now1);
delay = (int64_t) now2 - (int64_t) pa_bytes_to_usec(u->read_count, &u->source->sample_spec);
@ -660,7 +708,7 @@ static int suspend(struct userdata *u) {
pa_assert(u);
pa_assert(u->pcm_handle);
pa_smoother_pause(u->smoother, pa_rtclock_usec());
pa_smoother_pause(u->smoother, pa_rtclock_now());
/* Let's suspend */
snd_pcm_close(u->pcm_handle);
@ -740,8 +788,6 @@ static int unsuspend(struct userdata *u) {
pa_log_info("Trying resume...");
snd_config_update_free_global();
if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE,
/*SND_PCM_NONBLOCK|*/
SND_PCM_NO_AUTO_RESAMPLE|
@ -788,7 +834,7 @@ static int unsuspend(struct userdata *u) {
/* FIXME: We need to reload the volume somehow */
snd_pcm_start(u->pcm_handle);
pa_smoother_resume(u->smoother, pa_rtclock_usec(), TRUE);
pa_smoother_resume(u->smoother, pa_rtclock_now(), TRUE);
pa_log_info("Resumed successfully...");
@ -896,239 +942,135 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
return 0;
}
static pa_volume_t from_alsa_volume(struct userdata *u, long alsa_vol) {
return (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) /
(double) (u->hw_volume_max - u->hw_volume_min));
}
static long to_alsa_volume(struct userdata *u, pa_volume_t vol) {
long alsa_vol;
alsa_vol = (long) round(((double) vol * (double) (u->hw_volume_max - u->hw_volume_min))
/ PA_VOLUME_NORM) + u->hw_volume_min;
return PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
}
static void source_get_volume_cb(pa_source *s) {
struct userdata *u = s->userdata;
int err;
unsigned i;
pa_cvolume r;
char t[PA_CVOLUME_SNPRINT_MAX];
pa_assert(u);
pa_assert(u->mixer_elem);
pa_assert(u->mixer_path);
pa_assert(u->mixer_handle);
if (u->mixer_seperate_channels) {
if (pa_alsa_path_get_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &r) < 0)
return;
r.channels = s->sample_spec.channels;
for (i = 0; i < s->sample_spec.channels; i++) {
long alsa_vol;
if (u->hw_dB_supported) {
if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
goto fail;
#ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
#endif
r.values[i] = pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0);
} else {
if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
goto fail;
r.values[i] = from_alsa_volume(u, alsa_vol);
}
}
} else {
long alsa_vol;
if (u->hw_dB_supported) {
if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
goto fail;
#ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
#endif
pa_cvolume_set(&r, s->sample_spec.channels, pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0));
} else {
if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
goto fail;
pa_cvolume_set(&r, s->sample_spec.channels, from_alsa_volume(u, alsa_vol));
}
}
/* Shift down by the base volume, so that 0dB becomes maximum volume */
pa_sw_cvolume_multiply_scalar(&r, &r, s->base_volume);
pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &r));
if (!pa_cvolume_equal(&u->hardware_volume, &r)) {
if (pa_cvolume_equal(&u->hardware_volume, &r))
return;
s->virtual_volume = u->hardware_volume = r;
s->virtual_volume = u->hardware_volume = r;
if (u->hw_dB_supported) {
pa_cvolume reset;
if (u->mixer_path->has_dB) {
pa_cvolume reset;
/* Hmm, so the hardware volume changed, let's reset our software volume */
pa_cvolume_reset(&reset, s->sample_spec.channels);
pa_source_set_soft_volume(s, &reset);
}
/* Hmm, so the hardware volume changed, let's reset our software volume */
pa_cvolume_reset(&reset, s->sample_spec.channels);
pa_source_set_soft_volume(s, &reset);
}
return;
fail:
pa_log_error("Unable to read volume: %s", pa_alsa_strerror(err));
}
static void source_set_volume_cb(pa_source *s) {
struct userdata *u = s->userdata;
int err;
unsigned i;
pa_cvolume r;
char t[PA_CVOLUME_SNPRINT_MAX];
pa_assert(u);
pa_assert(u->mixer_elem);
pa_assert(u->mixer_path);
pa_assert(u->mixer_handle);
if (u->mixer_seperate_channels) {
/* Shift up by the base volume */
pa_sw_cvolume_divide_scalar(&r, &s->virtual_volume, s->base_volume);
r.channels = s->sample_spec.channels;
if (pa_alsa_path_set_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &r) < 0)
return;
for (i = 0; i < s->sample_spec.channels; i++) {
long alsa_vol;
pa_volume_t vol;
vol = s->virtual_volume.values[i];
if (u->hw_dB_supported) {
alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
alsa_vol += u->hw_dB_max;
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
if ((err = snd_mixer_selem_set_capture_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, 1)) < 0)
goto fail;
if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
goto fail;
#ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
#endif
r.values[i] = pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0);
} else {
alsa_vol = to_alsa_volume(u, vol);
if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
goto fail;
if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
goto fail;
r.values[i] = from_alsa_volume(u, alsa_vol);
}
}
} else {
pa_volume_t vol;
long alsa_vol;
vol = pa_cvolume_max(&s->virtual_volume);
if (u->hw_dB_supported) {
alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
alsa_vol += u->hw_dB_max;
alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
if ((err = snd_mixer_selem_set_capture_dB_all(u->mixer_elem, alsa_vol, 1)) < 0)
goto fail;
if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
goto fail;
#ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
#endif
pa_cvolume_set(&r, s->sample_spec.channels, pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0));
} else {
alsa_vol = to_alsa_volume(u, vol);
if ((err = snd_mixer_selem_set_capture_volume_all(u->mixer_elem, alsa_vol)) < 0)
goto fail;
if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
goto fail;
pa_cvolume_set(&r, s->sample_spec.channels, from_alsa_volume(u, alsa_vol));
}
}
/* Shift down by the base volume, so that 0dB becomes maximum volume */
pa_sw_cvolume_multiply_scalar(&r, &r, s->base_volume);
u->hardware_volume = r;
if (u->hw_dB_supported) {
char t[PA_CVOLUME_SNPRINT_MAX];
if (u->mixer_path->has_dB) {
/* Match exactly what the user requested by software */
pa_sw_cvolume_divide(&s->soft_volume, &s->virtual_volume, &u->hardware_volume);
pa_log_debug("Requested volume: %s", pa_cvolume_snprint(t, sizeof(t), &s->virtual_volume));
pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &u->hardware_volume));
pa_log_debug("Calculated software volume: %s", pa_cvolume_snprint(t, sizeof(t), &s->soft_volume));
} else
} else {
pa_log_debug("Wrote hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &r));
/* We can't match exactly what the user requested, hence let's
* at least tell the user about it */
s->virtual_volume = r;
return;
fail:
pa_log_error("Unable to set volume: %s", pa_alsa_strerror(err));
}
}
static void source_get_mute_cb(pa_source *s) {
struct userdata *u = s->userdata;
int err, sw;
pa_bool_t b;
pa_assert(u);
pa_assert(u->mixer_elem);
pa_assert(u->mixer_path);
pa_assert(u->mixer_handle);
if ((err = snd_mixer_selem_get_capture_switch(u->mixer_elem, 0, &sw)) < 0) {
pa_log_error("Unable to get switch: %s", pa_alsa_strerror(err));
if (pa_alsa_path_get_mute(u->mixer_path, u->mixer_handle, &b) < 0)
return;
}
s->muted = !sw;
s->muted = b;
}
static void source_set_mute_cb(pa_source *s) {
struct userdata *u = s->userdata;
int err;
pa_assert(u);
pa_assert(u->mixer_elem);
pa_assert(u->mixer_path);
pa_assert(u->mixer_handle);
if ((err = snd_mixer_selem_set_capture_switch_all(u->mixer_elem, !s->muted)) < 0) {
pa_log_error("Unable to set switch: %s", pa_alsa_strerror(err));
return;
pa_alsa_path_set_mute(u->mixer_path, u->mixer_handle, s->muted);
}
static int source_set_port_cb(pa_source *s, pa_device_port *p) {
struct userdata *u = s->userdata;
pa_alsa_port_data *data;
pa_assert(u);
pa_assert(p);
pa_assert(u->mixer_handle);
data = PA_DEVICE_PORT_DATA(p);
pa_assert_se(u->mixer_path = data->path);
pa_alsa_path_select(u->mixer_path, u->mixer_handle);
if (u->mixer_path->has_volume && u->mixer_path->has_dB) {
s->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
s->n_volume_steps = PA_VOLUME_NORM+1;
if (u->mixer_path->max_dB > 0.0)
pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(s->base_volume));
else
pa_log_info("No particular base volume set, fixing to 0 dB");
} else {
s->base_volume = PA_VOLUME_NORM;
s->n_volume_steps = u->mixer_path->max_volume - u->mixer_path->min_volume + 1;
}
if (data->setting)
pa_alsa_setting_select(data->setting, u->mixer_handle);
if (s->set_mute)
s->set_mute(s);
if (s->set_volume)
s->set_volume(s);
return 0;
}
static void source_update_requested_latency_cb(pa_source *s) {
@ -1153,7 +1095,6 @@ static void thread_func(void *userdata) {
pa_make_realtime(u->core->realtime_priority);
pa_thread_mq_install(&u->thread_mq);
pa_rtpoll_install(u->rtpoll);
for (;;) {
int ret;
@ -1190,7 +1131,7 @@ static void thread_func(void *userdata) {
/* Convert from the sound card time domain to the
* system time domain */
cusec = pa_smoother_translate(u->smoother, pa_rtclock_usec(), sleep_usec);
cusec = pa_smoother_translate(u->smoother, pa_rtclock_now(), sleep_usec);
/* pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
@ -1244,7 +1185,7 @@ finish:
pa_log_debug("Thread shutting down");
}
static void set_source_name(pa_source_new_data *data, pa_modargs *ma, const char *device_id, const char *device_name) {
static void set_source_name(pa_source_new_data *data, pa_modargs *ma, const char *device_id, const char *device_name, pa_alsa_mapping *mapping) {
const char *n;
char *t;
@ -1265,82 +1206,136 @@ static void set_source_name(pa_source_new_data *data, pa_modargs *ma, const char
data->namereg_fail = FALSE;
}
t = pa_sprintf_malloc("alsa_input.%s", n);
if (mapping)
t = pa_sprintf_malloc("alsa_input.%s.%s", n, mapping->name);
else
t = pa_sprintf_malloc("alsa_input.%s", n);
pa_source_new_data_set_name(data, t);
pa_xfree(t);
}
static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char *element, pa_bool_t ignore_dB) {
if (!mapping && !element)
return;
if (!(u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device))) {
pa_log_info("Failed to find a working mixer device.");
return;
}
if (element) {
if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_INPUT)))
goto fail;
if (pa_alsa_path_probe(u->mixer_path, u->mixer_handle, ignore_dB) < 0)
goto fail;
pa_log_debug("Probed mixer path %s:", u->mixer_path->name);
pa_alsa_path_dump(u->mixer_path);
} else {
if (!(u->mixer_path_set = pa_alsa_path_set_new(mapping, PA_ALSA_DIRECTION_INPUT)))
goto fail;
pa_alsa_path_set_probe(u->mixer_path_set, u->mixer_handle, ignore_dB);
pa_log_debug("Probed mixer paths:");
pa_alsa_path_set_dump(u->mixer_path_set);
}
return;
fail:
if (u->mixer_path_set) {
pa_alsa_path_set_free(u->mixer_path_set);
u->mixer_path_set = NULL;
} else if (u->mixer_path) {
pa_alsa_path_free(u->mixer_path);
u->mixer_path = NULL;
}
if (u->mixer_handle) {
snd_mixer_close(u->mixer_handle);
u->mixer_handle = NULL;
}
}
static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
pa_assert(u);
if (!u->mixer_handle)
return 0;
pa_assert(u->mixer_elem);
if (u->source->active_port) {
pa_alsa_port_data *data;
if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) {
pa_bool_t suitable = FALSE;
/* We have a list of supported paths, so let's activate the
* one that has been chosen as active */
if (snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) < 0)
pa_log_info("Failed to get volume range. Falling back to software volume control.");
else if (u->hw_volume_min >= u->hw_volume_max)
pa_log_warn("Your kernel driver is broken: it reports a volume range from %li to %li which makes no sense.", u->hw_volume_min, u->hw_volume_max);
else {
pa_log_info("Volume ranges from %li to %li.", u->hw_volume_min, u->hw_volume_max);
suitable = TRUE;
}
data = PA_DEVICE_PORT_DATA(u->source->active_port);
u->mixer_path = data->path;
if (suitable) {
if (ignore_dB || snd_mixer_selem_get_capture_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) < 0)
pa_log_info("Mixer doesn't support dB information or data is ignored.");
else {
#ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_min, sizeof(u->hw_dB_min));
VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_max, sizeof(u->hw_dB_max));
#endif
pa_alsa_path_select(data->path, u->mixer_handle);
if (u->hw_dB_min >= u->hw_dB_max)
pa_log_warn("Your kernel driver is broken: it reports a volume range from %0.2f dB to %0.2f dB which makes no sense.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
else {
pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
u->hw_dB_supported = TRUE;
if (data->setting)
pa_alsa_setting_select(data->setting, u->mixer_handle);
if (u->hw_dB_max > 0) {
u->source->base_volume = pa_sw_volume_from_dB(- (double) u->hw_dB_max/100.0);
pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u->source->base_volume));
} else
pa_log_info("No particular base volume set, fixing to 0 dB");
}
}
} else {
if (!u->hw_dB_supported &&
u->hw_volume_max - u->hw_volume_min < 3) {
if (!u->mixer_path && u->mixer_path_set)
u->mixer_path = u->mixer_path_set->paths;
pa_log_info("Device has less than 4 volume levels. Falling back to software volume control.");
suitable = FALSE;
}
}
if (u->mixer_path) {
/* Hmm, we have only a single path, then let's activate it */
if (suitable) {
u->mixer_seperate_channels = pa_alsa_calc_mixer_map(u->mixer_elem, &u->source->channel_map, u->mixer_map, FALSE) >= 0;
pa_alsa_path_select(u->mixer_path, u->mixer_handle);
u->source->get_volume = source_get_volume_cb;
u->source->set_volume = source_set_volume_cb;
u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SOURCE_DECIBEL_VOLUME : 0);
pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported");
if (!u->hw_dB_supported)
u->source->n_volume_steps = u->hw_volume_max - u->hw_volume_min + 1;
if (u->mixer_path->settings)
pa_alsa_setting_select(u->mixer_path->settings, u->mixer_handle);
} else
pa_log_info("Using software volume control.");
return 0;
}
if (snd_mixer_selem_has_capture_switch(u->mixer_elem)) {
if (!u->mixer_path->has_volume)
pa_log_info("Driver does not support hardware volume control, falling back to software volume control.");
else {
if (u->mixer_path->has_dB) {
pa_log_info("Hardware volume ranges from %0.2f dB to %0.2f dB.", u->mixer_path->min_dB, u->mixer_path->max_dB);
u->source->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
u->source->n_volume_steps = PA_VOLUME_NORM+1;
if (u->mixer_path->max_dB > 0.0)
pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u->source->base_volume));
else
pa_log_info("No particular base volume set, fixing to 0 dB");
} else {
pa_log_info("Hardware volume ranges from %li to %li.", u->mixer_path->min_volume, u->mixer_path->max_volume);
u->source->base_volume = PA_VOLUME_NORM;
u->source->n_volume_steps = u->mixer_path->max_volume - u->mixer_path->min_volume + 1;
}
u->source->get_volume = source_get_volume_cb;
u->source->set_volume = source_set_volume_cb;
u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL | (u->mixer_path->has_dB ? PA_SOURCE_DECIBEL_VOLUME : 0);
pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->mixer_path->has_dB ? "supported" : "not supported");
}
if (!u->mixer_path->has_mute) {
pa_log_info("Driver does not support hardware mute control, falling back to software mute control.");
} else {
u->source->get_mute = source_get_mute_cb;
u->source->set_mute = source_set_mute_cb;
u->source->flags |= PA_SOURCE_HW_MUTE_CTRL;
} else
pa_log_info("Using software mute control.");
pa_log_info("Using hardware mute control.");
}
u->mixer_fdl = pa_alsa_fdlist_new();
@ -1349,13 +1344,15 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
return -1;
}
snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback);
snd_mixer_elem_set_callback_private(u->mixer_elem, u);
if (u->mixer_path_set)
pa_alsa_path_set_set_callback(u->mixer_path_set, u->mixer_handle, mixer_callback, u);
else
pa_alsa_path_set_callback(u->mixer_path, u->mixer_handle, mixer_callback, u);
return 0;
}
pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, const pa_alsa_profile_info *profile) {
pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, pa_alsa_mapping *mapping) {
struct userdata *u = NULL;
const char *dev_id = NULL;
@ -1366,7 +1363,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
size_t frame_size;
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE;
pa_source_new_data data;
char *control_device = NULL;
pa_alsa_profile_set *profile_set = NULL;
pa_assert(m);
pa_assert(ma);
@ -1427,7 +1424,6 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
u->use_tsched = use_tsched;
u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
u->alsa_rtpoll_item = NULL;
u->smoother = pa_smoother_new(
DEFAULT_TSCHED_WATERMARK_USEC*2,
@ -1435,42 +1431,50 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
TRUE,
TRUE,
5,
pa_rtclock_usec(),
pa_rtclock_now(),
FALSE);
if (reserve_init(u, pa_modargs_get_value(
ma, "device_id",
pa_modargs_get_value(ma, "device", DEFAULT_DEVICE))) < 0)
dev_id = pa_modargs_get_value(
ma, "device_id",
pa_modargs_get_value(ma, "device", DEFAULT_DEVICE));
if (reserve_init(u, dev_id) < 0)
goto fail;
if (reserve_monitor_init(u, dev_id) < 0)
goto fail;
b = use_mmap;
d = use_tsched;
if (profile) {
if (mapping) {
if (!(dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
pa_log("device_id= not set");
goto fail;
}
if (!(u->pcm_handle = pa_alsa_open_by_device_id_profile(
if (!(u->pcm_handle = pa_alsa_open_by_device_id_mapping(
dev_id,
&u->device_name,
&ss, &map,
SND_PCM_STREAM_CAPTURE,
&nfrags, &period_frames, tsched_frames,
&b, &d, profile)))
&b, &d, mapping)))
goto fail;
} else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
if (!(profile_set = pa_alsa_profile_set_new(NULL, &map)))
goto fail;
if (!(u->pcm_handle = pa_alsa_open_by_device_id_auto(
dev_id,
&u->device_name,
&ss, &map,
SND_PCM_STREAM_CAPTURE,
&nfrags, &period_frames, tsched_frames,
&b, &d, &profile)))
&b, &d, profile_set, &mapping)))
goto fail;
} else {
@ -1493,8 +1497,8 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
goto fail;
}
if (profile)
pa_log_info("Selected configuration '%s' (%s).", profile->description, profile->name);
if (mapping)
pa_log_info("Selected mapping '%s' (%s).", mapping->description, mapping->name);
if (use_mmap && !b) {
pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
@ -1520,33 +1524,31 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
/* ALSA might tweak the sample spec, so recalculate the frame size */
frame_size = pa_frame_size(&ss);
pa_alsa_find_mixer_and_elem(u->pcm_handle, &control_device, &u->mixer_handle, &u->mixer_elem, pa_modargs_get_value(ma, "control", NULL), profile);
find_mixer(u, mapping, pa_modargs_get_value(ma, "control", NULL), ignore_dB);
pa_source_new_data_init(&data);
data.driver = driver;
data.module = m;
data.card = card;
set_source_name(&data, ma, dev_id, u->device_name);
set_source_name(&data, ma, dev_id, u->device_name, mapping);
pa_source_new_data_set_sample_spec(&data, &ss);
pa_source_new_data_set_channel_map(&data, &map);
pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle, u->mixer_elem);
pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
if (profile) {
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_NAME, profile->name);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile->description);
if (mapping) {
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_NAME, mapping->name);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, mapping->description);
}
pa_alsa_init_description(data.proplist);
if (control_device) {
pa_alsa_init_proplist_ctl(data.proplist, control_device);
pa_xfree(control_device);
}
if (u->control_device)
pa_alsa_init_proplist_ctl(data.proplist, u->control_device);
if (pa_modargs_get_proplist(ma, "source_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
pa_log("Invalid properties");
@ -1554,6 +1556,9 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
goto fail;
}
if (u->mixer_path_set)
pa_alsa_add_ports(&data.ports, u->mixer_path_set);
u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|(u->use_tsched ? PA_SOURCE_DYNAMIC_LATENCY : 0));
pa_source_new_data_done(&data);
@ -1565,6 +1570,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
u->source->parent.process_msg = source_process_msg;
u->source->update_requested_latency = source_update_requested_latency_cb;
u->source->set_state = source_set_state_cb;
u->source->set_port = source_set_port_cb;
u->source->userdata = u;
pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
@ -1629,6 +1635,9 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
pa_source_put(u->source);
if (profile_set)
pa_alsa_profile_set_free(profile_set);
return u->source;
fail:
@ -1636,6 +1645,9 @@ fail:
if (u)
userdata_free(u);
if (profile_set)
pa_alsa_profile_set_free(profile_set);
return NULL;
}
@ -1661,23 +1673,30 @@ static void userdata_free(struct userdata *u) {
if (u->rtpoll)
pa_rtpoll_free(u->rtpoll);
if (u->mixer_fdl)
pa_alsa_fdlist_free(u->mixer_fdl);
if (u->mixer_handle)
snd_mixer_close(u->mixer_handle);
if (u->pcm_handle) {
snd_pcm_drop(u->pcm_handle);
snd_pcm_close(u->pcm_handle);
}
if (u->mixer_fdl)
pa_alsa_fdlist_free(u->mixer_fdl);
if (u->mixer_path_set)
pa_alsa_path_set_free(u->mixer_path_set);
else if (u->mixer_path)
pa_alsa_path_free(u->mixer_path);
if (u->mixer_handle)
snd_mixer_close(u->mixer_handle);
if (u->smoother)
pa_smoother_free(u->smoother);
reserve_done(u);
monitor_done(u);
pa_xfree(u->device_name);
pa_xfree(u->control_device);
pa_xfree(u);
}

View file

@ -29,7 +29,7 @@
#include "alsa-util.h"
pa_source* pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, const pa_alsa_profile_info *profile);
pa_source* pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, pa_alsa_mapping *mapping);
void pa_alsa_source_free(pa_source *s);

File diff suppressed because it is too large Load diff

View file

@ -30,105 +30,97 @@
#include <pulse/mainloop-api.h>
#include <pulse/channelmap.h>
#include <pulse/proplist.h>
#include <pulse/volume.h>
#include <pulsecore/llist.h>
#include <pulsecore/rtpoll.h>
#include <pulsecore/core.h>
#include <pulsecore/log.h>
typedef struct pa_alsa_fdlist pa_alsa_fdlist;
struct pa_alsa_fdlist *pa_alsa_fdlist_new(void);
void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl);
int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m);
#include "alsa-mixer.h"
int pa_alsa_set_hw_params(
snd_pcm_t *pcm_handle,
pa_sample_spec *ss,
uint32_t *periods,
snd_pcm_uframes_t *period_size,
pa_sample_spec *ss, /* modified at return */
uint32_t *periods, /* modified at return */
snd_pcm_uframes_t *period_size, /* modified at return */
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap,
pa_bool_t *use_tsched,
pa_bool_t *use_mmap, /* modified at return */
pa_bool_t *use_tsched, /* modified at return */
pa_bool_t require_exact_channel_number);
int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min);
int pa_alsa_set_sw_params(
snd_pcm_t *pcm,
snd_pcm_uframes_t avail_min);
typedef struct pa_alsa_profile_info {
pa_channel_map map;
const char *alsa_name;
const char *alsa_name_fallback;
const char *description; /* internationalized */
const char *name;
unsigned priority;
const char *playback_control_name, *playback_control_fallback;
const char *record_control_name, *record_control_fallback;
} pa_alsa_profile_info;
int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev);
snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback, pa_bool_t playback);
int pa_alsa_find_mixer_and_elem(snd_pcm_t *pcm, char **ctl_device, snd_mixer_t **_m, snd_mixer_elem_t **_e, const char *control_name, const pa_alsa_profile_info*profile);
void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name);
/* Picks a working profile based on the specified ss/map */
/* Picks a working mapping from the profile set based on the specified ss/map */
snd_pcm_t *pa_alsa_open_by_device_id_auto(
const char *dev_id,
char **dev,
pa_sample_spec *ss,
pa_channel_map* map,
char **dev, /* modified at return */
pa_sample_spec *ss, /* modified at return */
pa_channel_map* map, /* modified at return */
int mode,
uint32_t *nfrags,
snd_pcm_uframes_t *period_size,
uint32_t *nfrags, /* modified at return */
snd_pcm_uframes_t *period_size, /* modified at return */
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap,
pa_bool_t *use_tsched,
const pa_alsa_profile_info **profile);
pa_bool_t *use_mmap, /* modified at return */
pa_bool_t *use_tsched, /* modified at return */
pa_alsa_profile_set *ps,
pa_alsa_mapping **mapping); /* modified at return */
/* Uses the specified profile */
snd_pcm_t *pa_alsa_open_by_device_id_profile(
/* Uses the specified mapping */
snd_pcm_t *pa_alsa_open_by_device_id_mapping(
const char *dev_id,
char **dev,
pa_sample_spec *ss,
pa_channel_map* map,
char **dev, /* modified at return */
pa_sample_spec *ss, /* modified at return */
pa_channel_map* map, /* modified at return */
int mode,
uint32_t *nfrags,
snd_pcm_uframes_t *period_size,
uint32_t *nfrags, /* modified at return */
snd_pcm_uframes_t *period_size, /* modified at return */
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap,
pa_bool_t *use_tsched,
const pa_alsa_profile_info *profile);
pa_bool_t *use_mmap, /* modified at return */
pa_bool_t *use_tsched, /* modified at return */
pa_alsa_mapping *mapping);
/* Opens the explicit ALSA device */
snd_pcm_t *pa_alsa_open_by_device_string(
const char *device,
char **dev,
pa_sample_spec *ss,
pa_channel_map* map,
const char *dir,
char **dev, /* modified at return */
pa_sample_spec *ss, /* modified at return */
pa_channel_map* map, /* modified at return */
int mode,
uint32_t *nfrags,
snd_pcm_uframes_t *period_size,
uint32_t *nfrags, /* modified at return */
snd_pcm_uframes_t *period_size, /* modified at return */
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap,
pa_bool_t *use_tsched,
pa_bool_t *use_mmap, /* modified at return */
pa_bool_t *use_tsched, /* modified at return */
pa_bool_t require_exact_channel_number);
int pa_alsa_probe_profiles(
/* Opens the explicit ALSA device with a fallback list */
snd_pcm_t *pa_alsa_open_by_template(
char **template,
const char *dev_id,
const pa_sample_spec *ss,
void (*cb)(const pa_alsa_profile_info *sink, const pa_alsa_profile_info *source, void *userdata),
void *userdata);
int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel_map, snd_mixer_selem_channel_id_t mixer_map[], pa_bool_t playback);
char **dev, /* modified at return */
pa_sample_spec *ss, /* modified at return */
pa_channel_map* map, /* modified at return */
int mode,
uint32_t *nfrags, /* modified at return */
snd_pcm_uframes_t *period_size, /* modified at return */
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap, /* modified at return */
pa_bool_t *use_tsched, /* modified at return */
pa_bool_t require_exact_channel_number);
void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm);
void pa_alsa_dump_status(snd_pcm_t *pcm);
void pa_alsa_redirect_errors_inc(void);
void pa_alsa_redirect_errors_dec(void);
void pa_alsa_refcnt_inc(void);
void pa_alsa_refcnt_dec(void);
void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info);
void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card);
void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm, snd_mixer_elem_t *elem);
void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm);
void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name);
pa_bool_t pa_alsa_init_description(pa_proplist *p);
int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents);
@ -140,13 +132,11 @@ int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_si
int pa_alsa_safe_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames, size_t hwbuf_size, const pa_sample_spec *ss);
char *pa_alsa_get_driver_name(int card);
char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm);
char *pa_alsa_get_reserve_name(const char *device);
pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm);
pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm);
const char* pa_alsa_strerror(int errnum);

View file

@ -0,0 +1,62 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; For devices where an 'Aux' element exists
;
; See analog-output.conf.common for an explanation on the directives
[General]
priority = 90
name = analog-input
[Element Capture]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Mic]
switch = off
volume = off
[Element Line]
switch = off
volume = off
[Element Aux]
required = any
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Video]
switch = off
volume = off
[Element Mic/Line]
switch = off
volume = off
[Element TV Tuner]
switch = off
volume = off
[Element FM]
switch = off
volume = off
.include analog-input.conf.common

View file

@ -0,0 +1,62 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; For devices where an 'FM' element exists
;
; See analog-output.conf.common for an explanation on the directives
[General]
priority = 70
name = analog-input-radio
[Element Capture]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Mic]
switch = off
volume = off
[Element Line]
switch = off
volume = off
[Element Aux]
switch = off
volume = off
[Element Video]
switch = off
volume = off
[Element Mic/Line]
switch = off
volume = off
[Element TV Tuner]
switch = off
volume = off
[Element FM]
required = any
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
.include analog-input.conf.common

View file

@ -0,0 +1,61 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; For devices where a 'Line' element exists
;
; See analog-output.conf.common for an explanation on the directives
[General]
priority = 90
[Element Capture]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Mic]
switch = off
volume = off
[Element Line]
required = any
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Aux]
switch = off
volume = off
[Element Video]
switch = off
volume = off
[Element Mic/Line]
switch = off
volume = off
[Element TV Tuner]
switch = off
volume = off
[Element FM]
switch = off
volume = off
.include analog-input.conf.common

View file

@ -0,0 +1,63 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; For devices where a 'Mic/Line' element exists
;
; See analog-output.conf.common for an explanation on the directives
[General]
priority = 90
name = analog-input
[Element Capture]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Mic]
switch = off
volume = off
[Element Line]
switch = off
volume = off
[Element Aux]
switch = off
volume = off
[Element Video]
switch = off
volume = off
[Element Mic/Line]
required = any
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element TV Tuner]
switch = off
volume = off
[Element FM]
switch = off
volume = off
.include analog-input.conf.common
.include analog-input-mic.conf.common

View file

@ -0,0 +1,63 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; For devices where a 'Mic' element exists
;
; See analog-output.conf.common for an explanation on the directives
[General]
priority = 100
name = analog-input-microphone
[Element Capture]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Mic]
required = any
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Line]
switch = off
volume = off
[Element Aux]
switch = off
volume = off
[Element Video]
switch = off
volume = off
[Element Mic/Line]
switch = off
volume = off
[Element TV Tuner]
switch = off
volume = off
[Element FM]
switch = off
volume = off
.include analog-input.conf.common
.include analog-input-mic.conf.common

View file

@ -0,0 +1,63 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; Common element for all microphone inputs
;
; See analog-output.conf.common for an explanation on the directives
;;; 'Mic Select'
[Element Mic Select]
enumeration = select
[Option Mic Select:Mic1]
name = input-microphone
priority = 20
[Option Mic Select:Mic2]
name = input-microphone
priority = 19
;;; Various Boosts
[Element Mic Boost (+20dB)]
switch = select
volume = merge
[Option Mic Boost (+20dB):on]
name = input-boost-on
[Option Mic Boost (+20dB):off]
name = input-boost-off
[Element Mic Boost]
switch = select
volume = merge
[Option Mic Boost:on]
name = input-boost-on
[Option Mic Boost:off]
name = input-boost-off
[Element Front Mic Boost]
switch = select
[Option Front Mic Boost:on]
name = input-boost-on
[Option Front Mic Boost:off]
name = input-boost-off

View file

@ -0,0 +1,62 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; For devices where a 'TV Tuner' element exists
;
; See analog-output.conf.common for an explanation on the directives
[General]
priority = 70
name = analog-input-video
[Element Capture]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Mic]
switch = off
volume = off
[Element Line]
switch = off
volume = off
[Element Aux]
switch = off
volume = off
[Element Video]
switch = off
volume = off
[Element Mic/Line]
switch = off
volume = off
[Element TV Tuner]
required = any
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element FM]
switch = off
volume = off
.include analog-input.conf.common

View file

@ -0,0 +1,61 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; For devices where a 'Video' element exists
;
; See analog-output.conf.common for an explanation on the directives
[General]
priority = 70
[Element Capture]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Mic]
switch = off
volume = off
[Element Line]
switch = off
volume = off
[Element Aux]
switch = off
volume = off
[Element Video]
required = any
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Mic/Line]
switch = off
volume = off
[Element TV Tuner]
switch = off
volume = off
[Element FM]
switch = off
volume = off
.include analog-input.conf.common

View file

@ -0,0 +1,54 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; A fallback for devices that lack seperate Mic/Line/Aux/Video/TV
; Tuner/FM elements
;
; See analog-output.conf.common for an explanation on the directives
[General]
priority = 100
[Element Capture]
required = volume
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Mic]
required-absent = any
[Element Line]
required-absent = any
[Element Aux]
required-absent = any
[Element Video]
required-absent = any
[Element Mic/Line]
required-absent = any
[Element TV Tuner]
required-absent = any
[Element FM]
required-absent = any
.include analog-input.conf.common
.include analog-input-mic.conf.common

View file

@ -0,0 +1,257 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; Mixer path for PulseAudio's ALSA backend, common elements for all
; input paths. If multiple options by the same id are discovered they
; will be suffixed with a number to distuingish them, in the same
; order they appear here.
;
; Source selection should use the following names:
;
; input -- If we don't know the exact kind of input
; input-microphone
; input-microphone-internal
; input-microphone-external
; input-linein
; input-video
; input-radio
; input-docking-microphone
; input-docking-linein
; input-docking
;
; We explicitly don't want to wrap the following sources:
;
; CD
; Synth/MIDI
; Phone
; Mix
; Digital/SPDIF
; Master
; PC Speaker
;
; See analog-output.conf.common for an explanation on the directives
;;; 'Input Source Select'
[Element Input Source Select]
enumeration = select
[Option Input Source Select:Input1]
name = input
priority = 10
[Option Input Source Select:Input2]
name = input
priority = 5
;;; 'Input Source'
[Element Input Source]
enumeration = select
[Option Input Source:Mic]
name = input-microphone
priority = 20
[Option Input Source:Microphone]
name = input-microphone
priority = 20
[Option Input Source:Front Mic]
name = input-microphone
priority = 19
[Option Input Source:Front Microphone]
name = input-microphone
priority = 19
[Option Input Source:Line]
name = input-linein
priority = 18
[Option Input Source:Line-In]
name = input-linein
priority = 18
[Option Input Source:Line In]
name = input-linein
priority = 18
;;; ' Capture Source'
[Element Capture Source]
enumeration = select
[Option Capture Source:TV Tuner]
name = input-video
[Option Capture Source:FM]
name = input-radio
[Option Capture Source:Mic/Line]
name = input
[Option Capture Source:Line/Mic]
name = input
[Option Capture Source:Mic]
name = input-microphone
[Option Capture Source:Microphone]
name = input-microphone
[Option Capture Source:Int Mic]
name = input-microphone-internal
[Option Capture Source:Int DMic]
name = input-microphone-internal
[Option Capture Source:Internal Mic]
name = input-microphone-internal
[Option Capture Source:iMic]
name = input-microphone-internal
[Option Capture Source:i-Mic]
name = input-microphone-internal
[Option Capture Source:Internal Microphone]
name = input-microphone-internal
[Option Capture Source:Front Mic]
name = input-microphone
[Option Capture Source:Front Microphone]
name = input-microphone
[Option Capture Source:Rear Mic]
name = input-microphone
[Option Capture Source:Mic1]
name = input-microphone
[Option Capture Source:Mic2]
name = input-microphone
[Option Capture Source:D-Mic]
name = input-microphone
[Option Capture Source:IntMic]
name = input-microphone-internal
[Option Capture Source:ExtMic]
name = input-microphone-external
[Option Capture Source:Ext Mic]
name = input-microphone-external
[Option Capture Source:E-Mic]
name = input-microphone-external
[Option Capture Source:e-Mic]
name = input-microphone-external
[Option Capture Source:LineIn]
name = input-linein
[Option Capture Source:Analog]
name = input
[Option Capture Source:Line]
name = input-linein
[Option Capture Source:Line-In]
name = input-linein
[Option Capture Source:Line In]
name = input-linein
[Option Capture Source:Video]
name = input-video
[Option Capture Source:Aux]
name = input
[Option Capture Source:Aux0]
name = input
[Option Capture Source:Aux1]
name = input
[Option Capture Source:Aux2]
name = input
[Option Capture Source:Aux3]
name = input
[Option Capture Source:AUX IN]
name = input
[Option Capture Source:Aux In]
name = input
[Option Capture Source:AOUT]
name = input
[Option Capture Source:AUX]
name = input
[Option Capture Source:Cam Mic]
name = input-microphone
[Option Capture Source:Digital Mic]
name = input-microphone
[Option Capture Source:Digital Mic 1]
name = input-microphone
[Option Capture Source:Digital Mic 2]
name = input-microphone
[Option Capture Source:Analog Inputs]
name = input
[Option Capture Source:Unknown1]
name = input
[Option Capture Source:Unknown2]
name = input
[Option Capture Source:Docking-Station]
name = input-docking
[Option Capture Source:Dock Mic]
name = input-docking-microphone
;;; Various Boosts
[Element Capture Boost]
switch = select
[Option Capture Boost:on]
name = input-boost-on
[Option Capture Boost:off]
name = input-boost-off
[Element Auto Gain Control]
switch = select
[Option Auto Gain Control:on]
name = input-agc-on
[Option Auto Gain Control:off]
name = input-agc-off

View file

@ -0,0 +1,71 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; Path for mixers that have a 'Headphone' control
;
; See analog-output.conf.common for an explanation on the directives
[General]
priority = 90
[Element Hardware Master]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Master]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Master Mono]
switch = off
volume = off
[Element Headphone]
required = any
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Front]
switch = off
volume = off
[Element Rear]
switch = off
volume = off
[Element Sourround]
switch = off
volume = off
[Element Side]
switch = off
volume = off
[Element Center]
switch = off
volume = off
[Element LFE]
switch = off
volume = off
.include analog-output.conf.common

View file

@ -0,0 +1,72 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; Intended for usage in laptops that have a seperate LFE speaker
; connected to the Master mono connector
;
; See analog-output.conf.common for an explanation on the directives
[General]
priority = 40
[Element Hardware Master]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Master]
switch = mute
volume = merge
override-map.1 = all-no-lfe
override-map.2 = all-left,all-right
[Element Master Mono]
required = any
switch = mute
volume = merge
override-map.1 = lfe
override-map.2 = lfe,lfe
[Element Headphone]
switch = off
volume = off
[Element Front]
switch = off
volume = off
[Element Rear]
switch = off
volume = off
[Element Sourround]
switch = off
volume = off
[Element Side]
switch = off
volume = off
[Element Center]
switch = off
volume = off
[Element LFE]
switch = off
volume = off
.include analog-output.conf.common

View file

@ -0,0 +1,69 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; Intended for usage on boards that have a seperate Mono output plug.
;
; See analog-output.conf.common for an explanation on the directives
[General]
priority = 50
[Element Hardware Master]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Master]
switch = off
volume = off
[Element Master Mono]
required = any
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Headphone]
switch = off
volume = off
[Element Front]
switch = off
volume = off
[Element Rear]
switch = off
volume = off
[Element Sourround]
switch = off
volume = off
[Element Side]
switch = off
volume = off
[Element Center]
switch = off
volume = off
[Element LFE]
switch = off
volume = off
.include analog-output.conf.common

View file

@ -0,0 +1,80 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; Intended for the 'default' output
;
; See analog-output.conf.common for an explanation on the directives
[General]
priority = 100
[Element Hardware Master]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Master]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element Master Mono]
switch = off
volume = off
[Element Headphone]
switch = off
volume = off
[Element Front]
switch = mute
volume = merge
override-map.1 = all-front
override-map.2 = front-left,front-right
[Element Rear]
switch = mute
volume = merge
override-map.1 = all-rear
override-map.2 = rear-left,rear-right
[Element Surround]
switch = mute
volume = merge
override-map.1 = all-rear
override-map.2 = rear-left,rear-right
[Element Side]
switch = mute
volume = merge
override-map.1 = all-side
override-map.2 = side-left,side-right
[Element Center]
switch = mute
volume = merge
override-map.1 = all-center
override-map.2 = all-center,all-center
[Element LFE]
switch = mute
volume = merge
override-map.1 = lfe
override-map.2 = lfe,lfe
.include analog-output.conf.common

View file

@ -0,0 +1,111 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; Common part of all paths
; So here's generally how mixer paths are used by PA: PA goes through
; a mixer path file from top to bottom and checks if a mixer element
; described therein exists. If so it is added to the list of mixer
; elements PA will control, keeping the order it read them in. If a
; mixer element described here has set the required= or
; required-absent= directives a path might not be accepted as valid
; and is ignored in its entirety (see below). However usually if a
; element listed here is missing this one element is ignored but not
; the entire path.
;
; When a device shall be muted/unmuted *all* elements listed in a path
; file with "switch = mute" will be toggled.
;
; When a device shall change its volume, PA will got through the list
; of all elements with "volume = merge" and set the volume on the
; first element. If that element does not support dB volumes, this is
; where the story ends. If it does support dB volumes, PA divides the
; requested volume by the volume that was set on this element, and
; then go on to the next element with "volume = merge" and then set
; that there, and so on. That way the first volume element in the
; path will be the one that does the 'biggest' part of the overall
; volume adjustment, with the remaining elements usually being set to
; some value next to 0dB. This logic makes sure we get the full range
; over all volume sliders and a very high granularity of volumes
; already in hardware.
;
; All switches and enumerations set to "select" are exposed via the
; "port" functionality of sinks/sources. Basically every possible
; switch setting and every possible enumeration setting will be
; combined and made into a "port". So make sure you don't list too
; many switches/enums for exposing, because the number of ports might
; rise exponentially.
;
; Only one path can be selected at a time. All paths that are valid
; for an audio device will be exposed as "port" for the sink/source.
; [General]
; priority = ... # Priority for this path
; description = ...
;
; [Option ...:...] # For each option of an enumeration or switch element
; # that shall be exposed as a sink/source port. Needs to
; # be named after the Element, followed by a colon, followed
; # by the option name, resp. on/off if the element is a switch.
; name = ... # Logical name to use in the path identifier
; priority = ... # Priority if this is made into a device port
;
; [Element ...] # For each element that we shall control
; required = ignore | switch | volume | enumeration | any # If set, require this element to be of this kind and available,
; # otherwise don't consider this path valid for the card
; required-absent = ignore | switch | volume # If set, require this element to not be of this kind and not
; # available, otherwise don't consider this path valid for the card
;
; switch = ignore | mute | off | on | select # What to do with this switch: ignore it, make it follow mute status,
; # always set it to off, always to on, or make it selectable as port.
; # If set to 'select' you need to define an Option section for on
; # and off
; volume = ignore | merge | off | zero # What to do with this volume: ignore it, merge it into the device
; # volume slider, always set it to the lowest value possible, or always
; # set it to 0 dB (for whatever that means)
; enumeration = ignore | select # What to do with this enumeration, ignore it or make it selectable
; # via device ports. If set to 'select' you need to define an Option section
; # for each of the items you want to expose
; direction = playback | capture # Is this relevant only for playback or capture? If not set this will implicitly be
; # set the direction of the PCM device is opened as. Generally this doesn't need to be set
; # unless you have a broken driver that has playback controls marked for capture or vice
; # versa
; direction-try-other = no | yes # If the element does not supported what is requested, try the other direction, too?
;
; override-map.1 = ... # Override the channel mask of the mixer control if the control only exposes a single channel
; override-map.2 = ... # Override the channel masks of the mixer control if the control only exposes two channels
; # Override maps should list for each element channel which high-level channels it controls via a
; # channel mask. A channel mask may either be the name of a single channel, or the words "all-left",
; # "all-right", "all-center", "all-front", "all-rear", and "all" to encode a specific subset of
; # channels in a mask
[Element PCM]
switch = mute
volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
[Element External Amplifier]
switch = select
[Option External Amplifier:on]
name = output-amplifier-on
priority = 0
[Option External Amplifier:off]
name = output-amplifier-off
priority = 10

View file

@ -0,0 +1,26 @@
# do not edit this file, it will be overwritten on update
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
SUBSYSTEM!="sound", GOTO="pulseaudio_end"
ACTION!="change", GOTO="pulseaudio_end"
KERNEL!="card*", GOTO="pulseaudio_end"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="1978", ENV{PULSE_PROFILE_SET}="native-instruments-audio8dj.conf"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="0839", ENV{PULSE_PROFILE_SET}="native-instruments-audio4dj.conf"
LABEL="pulseaudio_end"

View file

@ -0,0 +1,144 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; Default profile definitions for the ALSA backend of PulseAudio. This
; is used as fallback for all cards that have no special mapping
; assigned. (and should be good enough for the vast majority of
; cards). Use the udev property PULSE_PROFILE_SET to assign a
; different profile set than this one to a device. So what is this
; about? Simply, what we do here is map ALSA devices to how they are
; exposed in PA. We say which ALSA device string to use to open a
; device, which channel mapping to use then, and which mixer path to
; use. This is encoded in a 'mapping'. Multiple of these mappings can
; be bound together in a 'profile' which is then directly exposed in
; the UI as a card profile. Each mapping assigned to a profile will
; result in one sink/source to be created if the profile is selected
; for the card.
; [General]
; auto-profiles = no | yes # Instead of defining all profiles manually, autogenerate
; # them by combining every input mapping with every output mapping.
;
; [Mapping id]
; device-strings = ... # ALSA device string. %f will be replaced by the card identifier.
; channel-map = ... # Channel mapping to use for this device
; description = ...
; paths-input = ... # A list of mixer paths to use. Every path in this list will be probed.
; # If multiple are found to be working they will be available as device ports
; paths-output = ...
; element-input = ... # Instead of configuring a full mixer path simply configure a single
; # mixer element for volume/mute handling
; element-output = ...
; priority = ...
; direction = any | input | output # Only useful for?
;
; [Profile id]
; input-mappings = ... # Lists mappings for sources on this profile, those mapping must be
; # defined in this file too
; output-mappings = ... # Lists mappings for sinks on this profile, those mappings must be
; # defined in this file too
; description = ...
; priority = ... # Numeric value to deduce priority for this profile
; skip-probe = no | yes # Skip probing for availability? If this is yes then this profile
; # will be assumed as working without probing. Makes initialization
; # a bit faster but only works if the card is really known well.
[General]
auto-profiles = yes
[Mapping analog-mono]
device-strings = hw:%f
channel-map = mono
paths-output = analog-output analog-output-headphones analog-output-mono analog-output-lfe-on-mono
paths-input = analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line
priority = 1
[Mapping analog-stereo]
device-strings = front:%f hw:%f
channel-map = left,right
paths-output = analog-output analog-output-headphones analog-output-mono analog-output-lfe-on-mono
paths-input = analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line
priority = 10
[Mapping analog-surround-40]
device-strings = surround40:%f
channel-map = front-left,front-right,rear-left,rear-right
paths-output = analog-output analog-output-lfe-on-mono
priority = 7
direction = output
[Mapping analog-surround-41]
device-strings = surround41:%f
channel-map = front-left,front-right,rear-left,rear-right,lfe
paths-output = analog-output analog-output-lfe-on-mono
priority = 8
direction = output
[Mapping analog-surround-50]
device-strings = surround50:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center
paths-output = analog-output analog-output-lfe-on-mono
priority = 7
direction = output
[Mapping analog-surround-51]
device-strings = surround51:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe
paths-output = analog-output analog-output-lfe-on-mono
priority = 8
direction = output
[Mapping analog-surround-71]
device-strings = surround71:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right
description = Analog Surround 7.1
paths-output = analog-output analog-output-lfe-on-mono
priority = 7
direction = output
[Mapping iec958-stereo]
device-strings = iec958:%f
channel-map = left,right
priority = 5
[Mapping iec958-surround-40]
device-strings = iec958:%f
channel-map = front-left,front-right,rear-left,rear-right
priority = 1
[Mapping iec958-ac3-surround-40]
device-strings = a52:%f
channel-map = front-left,front-right,rear-left,rear-right
priority = 2
direction = output
[Mapping iec958-ac3-surround-51]
device-strings = a52:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe
priority = 3
direction = output
[Mapping hdmi-stereo]
device-strings = hdmi:%f
channel-map = left,right
priority = 4
direction = output
; An example for defining multiple-sink profiles
#[Profile output:analog-stereo+output:iec958-stereo+input:analog-stereo]
#description = Foobar
#output-mappings = analog-stereo iec958-stereo
#input-mappings = analog-stereo

View file

@ -0,0 +1,91 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; Native Instruments Audio 4 DJ
;
; This card has two stereo pairs of input and two stereo pairs of
; output, named channels A and B. Channel B has an additional
; Headphone connector.
;
; We knowingly only define a subset of the theoretically possible
; mapping combinations as profiles here.
;
; See default.conf for an explanation on the directives used here.
[General]
auto-profiles = no
[Mapping analog-stereo-a]
description = Analog Stereo Channel A
device-strings = hw:%f,0,0
channel-map = left,right
[Mapping analog-stereo-b-output]
description = Analog Stereo Channel B (Headphones)
device-strings = hw:%f,0,1
channel-map = left,right
direction = output
[Mapping analog-stereo-b-input]
description = Analog Stereo Channel B
device-strings = hw:%f,0,1
channel-map = left,right
direction = input
[Profile output:analog-stereo-all+input:analog-stereo-all]
description = Analog Stereo Duplex Channels A, B (Headphones)
output-mappings = analog-stereo-a analog-stereo-b-output
input-mappings = analog-stereo-a analog-stereo-b-input
priority = 100
skip-probe = yes
[Profile output:analog-stereo-a+input:analog-stereo-a]
description = Analog Stereo Duplex Channel A
output-mappings = analog-stereo-a
input-mappings = analog-stereo-a
priority = 40
skip-probe = yes
[Profile output:analog-stereo-b+input:analog-stereo-b]
description = Analog Stereo Duplex Channel B (Headphones)
output-mappings = analog-stereo-b-output
input-mappings = analog-stereo-b-input
priority = 50
skip-probe = yes
[Profile output:analog-stereo-a]
description = Analog Stereo Output Channel A
output-mappings = analog-stereo-a
priority = 5
skip-probe = yes
[Profile output:analog-stereo-b]
description = Analog Stereo Output Channel B (Headphones)
output-mappings = analog-stereo-b-output
priority = 6
skip-probe = yes
[Profile input:analog-stereo-a]
description = Analog Stereo Input Channel A
input-mappings = analog-stereo-a
priority = 2
skip-probe = yes
[Profile input:analog-stereo-b]
description = Analog Stereo Input Channel B
input-mappings = analog-stereo-b-input
priority = 1
skip-probe = yes

View file

@ -0,0 +1,162 @@
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
; Native Instruments Audio 8 DJ
;
; This card has four stereo pairs of input and four stereo pairs of
; output, named channels A to D. Channel C has an additional Mic/Line
; connector, channel D an additional Headphone connector.
;
; We knowingly only define a subset of the theoretically possible
; mapping combinations as profiles here.
;
; See default.conf for an explanation on the directives used here.
[General]
auto-profiles = no
[Mapping analog-stereo-a]
description = Analog Stereo Channel A
device-strings = hw:%f,0,0
channel-map = left,right
[Mapping analog-stereo-b]
description = Analog Stereo Channel B
device-strings = hw:%f,0,1
channel-map = left,right
# Since we want to set a different description for channel C's/D's input
# and output we define two seperate mappings for them
[Mapping analog-stereo-c-output]
description = Analog Stereo Channel C
device-strings = hw:%f,0,2
channel-map = left,right
direction = output
[Mapping analog-stereo-c-input]
description = Analog Stereo Channel C (Line/Mic)
device-strings = hw:%f,0,2
channel-map = left,right
direction = input
[Mapping analog-stereo-d-output]
description = Analog Stereo Channel D (Headphones)
device-strings = hw:%f,0,3
channel-map = left,right
direction = output
[Mapping analog-stereo-d-input]
description = Analog Stereo Channel D
device-strings = hw:%f,0,3
channel-map = left,right
direction = input
[Profile output:analog-stereo-all+input:analog-stereo-all]
description = Analog Stereo Duplex Channels A, B, C (Line/Mic), D (Headphones)
output-mappings = analog-stereo-a analog-stereo-b analog-stereo-c-output analog-stereo-d-output
input-mappings = analog-stereo-a analog-stereo-b analog-stereo-c-input analog-stereo-d-input
priority = 100
skip-probe = yes
[Profile output:analog-stereo-d+input:analog-stereo-c]
description = Analog Stereo Channel D (Headphones) Output, Channel C (Line/Mic) Input
output-mappings = analog-stereo-d-output
input-mappings = analog-stereo-c-input
priority = 90
skip-probe = yes
[Profile output:analog-stereo-c-d+input:analog-stereo-c-d]
description = Analog Stereo Duplex Channels C (Line/Mic), D (Line/Mic)
output-mappings = analog-stereo-c-output analog-stereo-d-output
input-mappings = analog-stereo-c-input analog-stereo-d-input
priority = 80
skip-probe = yes
[Profile output:analog-stereo-a+input:analog-stereo-a]
description = Analog Stereo Duplex Channel A
output-mappings = analog-stereo-a
input-mappings = analog-stereo-a
priority = 50
skip-probe = yes
[Profile output:analog-stereo-b+input:analog-stereo-b]
description = Analog Stereo Duplex Channel B
output-mappings = analog-stereo-b
input-mappings = analog-stereo-b
priority = 40
skip-probe = yes
[Profile output:analog-stereo-c+input:analog-stereo-c]
description = Analog Stereo Duplex Channel C (Line/Mic)
output-mappings = analog-stereo-c-output
input-mappings = analog-stereo-c-input
priority = 60
skip-probe = yes
[Profile output:analog-stereo-d+input:analog-stereo-d]
description = Analog Stereo Duplex Channel D (Headphones)
output-mappings = analog-stereo-d-output
input-mappings = analog-stereo-d-input
priority = 70
skip-probe = yes
[Profile output:analog-stereo-a]
description = Analog Stereo Output Channel A
output-mappings = analog-stereo-a
priority = 6
skip-probe = yes
[Profile output:analog-stereo-b]
description = Analog Stereo Output Channel B
output-mappings = analog-stereo-b
priority = 5
skip-probe = yes
[Profile output:analog-stereo-c]
description = Analog Stereo Output Channel C
output-mappings = analog-stereo-c-output
priority = 7
skip-probe = yes
[Profile output:analog-stereo-d]
description = Analog Stereo Output Channel D (Headphones)
output-mappings = analog-stereo-d-output
priority = 8
skip-probe = yes
[Profile input:analog-stereo-a]
description = Analog Stereo Input Channel A
input-mappings = analog-stereo-a
priority = 2
skip-probe = yes
[Profile input:analog-stereo-b]
description = Analog Stereo Input Channel B
input-mappings = analog-stereo-b
priority = 1
skip-probe = yes
[Profile input:analog-stereo-c]
description = Analog Stereo Input Channel C (Line/Mic)
input-mappings = analog-stereo-c-input
priority = 4
skip-probe = yes
[Profile input:analog-stereo-d]
description = Analog Stereo Input Channel D
input-mappings = analog-stereo-d-input
priority = 3
skip-probe = yes

View file

@ -0,0 +1,150 @@
Simple mixer control 'Master',0
Capabilities: pvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 29 [94%] [-3.00dB] [on]
Front Right: Playback 29 [94%] [-3.00dB] [on]
Simple mixer control 'Master Mono',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 31
Mono: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control 'PCM',0
Capabilities: pvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 23 [74%] [0.00dB] [on]
Front Right: Playback 23 [74%] [0.00dB] [on]
Simple mixer control 'Surround',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 0 [0%] [-46.50dB] [off]
Front Right: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control 'Surround Jack Mode',0
Capabilities: enum
Items: 'Shared' 'Independent'
Item0: 'Shared'
Simple mixer control 'Center',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 31
Mono: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control 'LFE',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 31
Mono: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control 'Line',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'CD',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'Mic',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Mono
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono: Playback 0 [0%] [-34.50dB] [off]
Front Left: Capture [on]
Front Right: Capture [on]
Simple mixer control 'Mic Boost (+20dB)',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'Mic Select',0
Capabilities: enum
Items: 'Mic1' 'Mic2'
Item0: 'Mic1'
Simple mixer control 'Video',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'Phone',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Mono
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono: Playback 31 [100%] [12.00dB] [off]
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'IEC958',0
Capabilities: pswitch pswitch-joined cswitch cswitch-joined
Playback channels: Mono
Capture channels: Mono
Mono: Playback [off] Capture [off]
Simple mixer control 'IEC958 Playback AC97-SPSA',0
Capabilities: volume volume-joined
Playback channels: Mono
Capture channels: Mono
Limits: 0 - 3
Mono: 0 [0%]
Simple mixer control 'IEC958 Playback Source',0
Capabilities: enum
Items: 'PCM' 'Analog In' 'IEC958 In'
Item0: 'PCM'
Simple mixer control 'PC Speaker',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 15
Mono: Playback 0 [0%] [-45.00dB] [on]
Simple mixer control 'Aux',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [on] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [on] Capture [off]
Simple mixer control 'Mono Output Select',0
Capabilities: enum
Items: 'Mix' 'Mic'
Item0: 'Mix'
Simple mixer control 'Capture',0
Capabilities: cvolume cswitch cswitch-joined
Capture channels: Front Left - Front Right
Limits: Capture 0 - 15
Front Left: Capture 12 [80%] [18.00dB] [on]
Front Right: Capture 12 [80%] [18.00dB] [on]
Simple mixer control 'Mix',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'Mix Mono',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'Channel Mode',0
Capabilities: enum
Items: '2ch' '4ch' '6ch'
Item0: '2ch'
Simple mixer control 'Duplicate Front',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'External Amplifier',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [on]

View file

@ -0,0 +1,24 @@
Simple mixer control 'FM',0
Capabilities: cswitch cswitch-joined cswitch-exclusive
Capture exclusive group: 0
Capture channels: Mono
Mono: Capture [off]
Simple mixer control 'Mic/Line',0
Capabilities: cswitch cswitch-joined cswitch-exclusive
Capture exclusive group: 0
Capture channels: Mono
Mono: Capture [off]
Simple mixer control 'Capture',0
Capabilities: cvolume cvolume-joined
Capture channels: Mono
Limits: Capture 0 - 15
Mono: Capture 13 [87%]
Simple mixer control 'Capture Boost',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [on]
Simple mixer control 'TV Tuner',0
Capabilities: cswitch cswitch-joined cswitch-exclusive
Capture exclusive group: 0
Capture channels: Mono
Mono: Capture [on]

View file

@ -0,0 +1,135 @@
Simple mixer control 'Master',0
Capabilities: pvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right
Limits: Playback 0 - 63
Mono:
Front Left: Playback 63 [100%] [0.00dB] [on]
Front Right: Playback 63 [100%] [0.00dB] [on]
Simple mixer control 'Master Mono',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 31
Mono: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control 'Headphone',0
Capabilities: pvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 0 [0%] [-46.50dB] [off]
Front Right: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control '3D Control - Center',0
Capabilities: volume volume-joined
Playback channels: Mono
Capture channels: Mono
Limits: 0 - 15
Mono: 0 [0%]
Simple mixer control '3D Control - Depth',0
Capabilities: volume volume-joined
Playback channels: Mono
Capture channels: Mono
Limits: 0 - 15
Mono: 0 [0%]
Simple mixer control '3D Control - Switch',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'PCM',0
Capabilities: pvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 23 [74%] [0.00dB] [on]
Front Right: Playback 23 [74%] [0.00dB] [on]
Simple mixer control 'Line',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [on]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [on]
Simple mixer control 'CD',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'Mic',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Mono
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono: Playback 23 [74%] [0.00dB] [on]
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'Mic Boost (+20dB)',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'Mic Select',0
Capabilities: enum
Items: 'Mic1' 'Mic2'
Item0: 'Mic1'
Simple mixer control 'Video',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'Phone',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Mono
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono: Playback 0 [0%] [-34.50dB] [off]
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'IEC958',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'PC Speaker',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 15
Mono: Playback 0 [0%] [-45.00dB] [off]
Simple mixer control 'Aux',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'Mono Output Select',0
Capabilities: enum
Items: 'Mix' 'Mic'
Item0: 'Mic'
Simple mixer control 'Capture',0
Capabilities: cvolume cswitch cswitch-joined
Capture channels: Front Left - Front Right
Limits: Capture 0 - 15
Front Left: Capture 15 [100%] [22.50dB] [on]
Front Right: Capture 15 [100%] [22.50dB] [on]
Simple mixer control 'Mix',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'Mix Mono',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'External Amplifier',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]

View file

@ -0,0 +1,4 @@
Simple mixer control 'IEC958',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [on]

View file

@ -0,0 +1,62 @@
Simple mixer control 'Master',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 63
Mono:
Front Left: Playback 63 [100%] [3.00dB] [on]
Front Right: Playback 63 [100%] [3.00dB] [on]
Simple mixer control 'PCM',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 23 [74%] [0.00dB] [on]
Front Right: Playback 23 [74%] [0.00dB] [on]
Simple mixer control 'CD',0
Capabilities: pvolume pswitch cswitch cswitch-joined cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Mono
Limits: Playback 0 - 31
Mono: Capture [off]
Front Left: Playback 0 [0%] [-34.50dB] [off]
Front Right: Playback 0 [0%] [-34.50dB] [off]
Simple mixer control 'Mic',0
Capabilities: pvolume pswitch cswitch cswitch-joined cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Mono
Limits: Playback 0 - 31
Mono: Capture [on]
Front Left: Playback 0 [0%] [-34.50dB] [off]
Front Right: Playback 0 [0%] [-34.50dB] [off]
Simple mixer control 'Mic Boost',0
Capabilities: volume
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: 0 - 3
Front Left: 0 [0%]
Front Right: 0 [0%]
Simple mixer control 'IEC958',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'IEC958 Default PCM',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'IEC958 Playback Source',0
Capabilities: enum
Items: 'PCM' 'ADC'
Item0: 'PCM'
Simple mixer control 'Capture',0
Capabilities: cvolume cswitch
Capture channels: Front Left - Front Right
Limits: Capture 0 - 15
Front Left: Capture 0 [0%] [0.00dB] [on]
Front Right: Capture 0 [0%] [0.00dB] [on]
Simple mixer control 'Mix',0
Capabilities: cswitch cswitch-joined cswitch-exclusive
Capture exclusive group: 0
Capture channels: Mono
Mono: Capture [off]

View file

@ -0,0 +1,113 @@
Simple mixer control 'Master',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 64
Mono: Playback 64 [100%] [0.00dB] [on]
Simple mixer control 'Headphone',0
Capabilities: pswitch
Playback channels: Front Left - Front Right
Mono:
Front Left: Playback [on]
Front Right: Playback [on]
Simple mixer control 'PCM',0
Capabilities: pvolume
Playback channels: Front Left - Front Right
Limits: Playback 0 - 255
Mono:
Front Left: Playback 255 [100%] [0.00dB]
Front Right: Playback 255 [100%] [0.00dB]
Simple mixer control 'Front',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 64
Mono:
Front Left: Playback 44 [69%] [-20.00dB] [on]
Front Right: Playback 44 [69%] [-20.00dB] [on]
Simple mixer control 'Front Mic',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 0 [0%] [-34.50dB] [off]
Front Right: Playback 0 [0%] [-34.50dB] [off]
Simple mixer control 'Front Mic Boost',0
Capabilities: volume
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: 0 - 3
Front Left: 0 [0%]
Front Right: 0 [0%]
Simple mixer control 'Surround',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 64
Mono:
Front Left: Playback 0 [0%] [-64.00dB] [on]
Front Right: Playback 0 [0%] [-64.00dB] [on]
Simple mixer control 'Center',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 64
Mono: Playback 0 [0%] [-64.00dB] [on]
Simple mixer control 'LFE',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 64
Mono: Playback 0 [0%] [-64.00dB] [on]
Simple mixer control 'Side',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 64
Mono:
Front Left: Playback 0 [0%] [-64.00dB] [on]
Front Right: Playback 0 [0%] [-64.00dB] [on]
Simple mixer control 'Line',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 0 [0%] [-34.50dB] [off]
Front Right: Playback 0 [0%] [-34.50dB] [off]
Simple mixer control 'Mic',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 0 [0%] [-34.50dB] [off]
Front Right: Playback 0 [0%] [-34.50dB] [off]
Simple mixer control 'Mic Boost',0
Capabilities: volume
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: 0 - 3
Front Left: 0 [0%]
Front Right: 0 [0%]
Simple mixer control 'IEC958',0
Capabilities: pswitch pswitch-joined cswitch cswitch-joined
Playback channels: Mono
Capture channels: Mono
Mono: Playback [on] Capture [on]
Simple mixer control 'IEC958 Default PCM',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [on]
Simple mixer control 'Capture',0
Capabilities: cvolume cswitch
Capture channels: Front Left - Front Right
Limits: Capture 0 - 46
Front Left: Capture 23 [50%] [7.00dB] [on]
Front Right: Capture 23 [50%] [7.00dB] [on]
Simple mixer control 'Capture',1
Capabilities: cvolume cswitch
Capture channels: Front Left - Front Right
Limits: Capture 0 - 46
Front Left: Capture 0 [0%] [-16.00dB] [off]
Front Right: Capture 0 [0%] [-16.00dB] [off]
Simple mixer control 'Input Source',0
Capabilities: cenum
Items: 'Mic' 'Front Mic' 'Line'
Item0: 'Mic'
Simple mixer control 'Input Source',1
Capabilities: cenum
Items: 'Mic' 'Front Mic' 'Line'
Item0: 'Mic'

View file

@ -0,0 +1,128 @@
Simple mixer control 'Master',0
Capabilities: pvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right
Limits: Playback 0 - 63
Mono:
Front Left: Playback 44 [70%] [-28.50dB] [on]
Front Right: Playback 60 [95%] [-4.50dB] [on]
Simple mixer control 'Master Mono',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 31
Mono: Playback 17 [55%] [-21.00dB] [on]
Simple mixer control '3D Control - Center',0
Capabilities: volume volume-joined
Playback channels: Mono
Capture channels: Mono
Limits: 0 - 15
Mono: 0 [0%]
Simple mixer control '3D Control - Depth',0
Capabilities: volume volume-joined
Playback channels: Mono
Capture channels: Mono
Limits: 0 - 15
Mono: 0 [0%]
Simple mixer control '3D Control - Switch',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'PCM',0
Capabilities: pvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 9 [29%] [-21.00dB] [on]
Front Right: Playback 9 [29%] [-21.00dB] [on]
Simple mixer control 'PCM Out Path & Mute',0
Capabilities: enum
Items: 'pre 3D' 'post 3D'
Item0: 'pre 3D'
Simple mixer control 'Line',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'CD',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 9 [29%] [-21.00dB] [on] Capture [off]
Front Right: Playback 9 [29%] [-21.00dB] [on] Capture [off]
Simple mixer control 'Mic',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Mono
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono: Playback 0 [0%] [-34.50dB] [off]
Front Left: Capture [on]
Front Right: Capture [on]
Simple mixer control 'Mic Boost (+20dB)',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'Mic Select',0
Capabilities: enum
Items: 'Mic1' 'Mic2'
Item0: 'Mic1'
Simple mixer control 'Video',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'Phone',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Mono
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono: Playback 0 [0%] [-34.50dB] [off]
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'PC Speaker',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 15
Mono: Playback 8 [53%] [-21.00dB] [on]
Simple mixer control 'Aux',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'Mono Output Select',0
Capabilities: enum
Items: 'Mix' 'Mic'
Item0: 'Mix'
Simple mixer control 'Capture',0
Capabilities: cvolume cswitch cswitch-joined
Capture channels: Front Left - Front Right
Limits: Capture 0 - 15
Front Left: Capture 13 [87%] [19.50dB] [on]
Front Right: Capture 13 [87%] [19.50dB] [on]
Simple mixer control 'Mix',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'Mix Mono',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'External Amplifier',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [on]

View file

@ -0,0 +1,27 @@
Simple mixer control 'Bass',0
Capabilities: volume volume-joined
Playback channels: Mono
Capture channels: Mono
Limits: 0 - 48
Mono: 22 [46%]
Simple mixer control 'Bass Boost',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'Treble',0
Capabilities: volume volume-joined
Playback channels: Mono
Capture channels: Mono
Limits: 0 - 48
Mono: 25 [52%]
Simple mixer control 'PCM',0
Capabilities: pvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right
Limits: Playback 0 - 44
Mono:
Front Left: Playback 10 [23%] [-31.00dB] [on]
Front Right: Playback 10 [23%] [-31.00dB] [on]
Simple mixer control 'Auto Gain Control',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]

View file

@ -0,0 +1,37 @@
Simple mixer control 'Master',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 255
Mono: Playback 105 [41%] [-28.97dB] [on]
Simple mixer control 'Line',0
Capabilities: pvolume cvolume pswitch pswitch-joined cswitch cswitch-joined
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 255 Capture 0 - 128
Front Left: Playback 191 [75%] [34.38dB] [off] Capture 0 [0%] [0.18dB] [off]
Front Right: Playback 191 [75%] [34.38dB] [off] Capture 0 [0%] [0.18dB] [off]
Simple mixer control 'Mic',0
Capabilities: pvolume pvolume-joined cvolume cvolume-joined pswitch pswitch-joined cswitch cswitch-joined cswitch-exclusive
Capture exclusive group: 0
Playback channels: Mono
Capture channels: Mono
Limits: Playback 0 - 255 Capture 0 - 128
Mono: Playback 191 [75%] [34.38dB] [off] Capture 0 [0%] [0.18dB] [on]
Simple mixer control 'Mic Capture',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'IEC958 In',0
Capabilities: cswitch cswitch-joined
Capture channels: Mono
Mono: Capture [off]
Simple mixer control 'Input 1',0
Capabilities: cswitch cswitch-joined cswitch-exclusive
Capture exclusive group: 0
Capture channels: Mono
Mono: Capture [off]
Simple mixer control 'Input 2',0
Capabilities: cswitch cswitch-joined cswitch-exclusive
Capture exclusive group: 0
Capture channels: Mono
Mono: Capture [off]

View file

@ -0,0 +1,5 @@
Simple mixer control 'Mic',0
Capabilities: cvolume cvolume-joined cswitch cswitch-joined
Capture channels: Mono
Limits: Capture 0 - 3072
Mono: Capture 1536 [50%] [23.00dB] [on]

View file

@ -0,0 +1,211 @@
Simple mixer control 'Master',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 31 [100%] [0.00dB] [on]
Front Right: Playback 31 [100%] [0.00dB] [on]
Simple mixer control 'Master Mono',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 31
Mono: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control 'Master Surround',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 0 [0%] [-46.50dB] [off]
Front Right: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control 'Headphone Jack Sense',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'PCM',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 23 [74%] [0.00dB] [on]
Front Right: Playback 23 [74%] [0.00dB] [on]
Simple mixer control 'Surround',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 0 [0%] [-46.50dB] [off]
Front Right: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control 'Surround Jack Mode',0
Capabilities: enum
Items: 'Shared' 'Independent'
Item0: 'Shared'
Simple mixer control 'Center',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 31
Mono: Playback 31 [100%] [0.00dB] [off]
Simple mixer control 'LFE',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 31
Mono: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control 'Line',0
Capabilities: pvolume pswitch cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'Line Jack Sense',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'CD',0
Capabilities: pvolume pswitch cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'Mic',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Mono
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono: Playback 0 [0%] [-34.50dB] [off]
Front Left: Capture [on]
Front Right: Capture [on]
Simple mixer control 'Mic Boost (+20dB)',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'Mic Select',0
Capabilities: enum
Items: 'Mic1' 'Mic2'
Item0: 'Mic1'
Simple mixer control 'Video',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'Phone',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Mono
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono: Playback 0 [0%] [-34.50dB] [off]
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'IEC958',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'IEC958 Output',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'IEC958 Playback AC97-SPSA',0
Capabilities: volume volume-joined
Playback channels: Mono
Capture channels: Mono
Limits: 0 - 3
Mono: 3 [100%]
Simple mixer control 'IEC958 Playback Source',0
Capabilities: enum
Items: 'AC-Link' 'A/D Converter'
Item0: 'AC-Link'
Simple mixer control 'Aux',0
Capabilities: pvolume pswitch cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'Capture',0
Capabilities: cvolume cswitch
Capture channels: Front Left - Front Right
Limits: Capture 0 - 15
Front Left: Capture 0 [0%] [0.00dB] [on]
Front Right: Capture 0 [0%] [0.00dB] [on]
Simple mixer control 'Mix',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'Mix Mono',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'Channel Mode',0
Capabilities: enum
Items: '2ch' '4ch' '6ch'
Item0: '2ch'
Simple mixer control 'Downmix',0
Capabilities: enum
Items: 'Off' '6 -> 4' '6 -> 2'
Item0: 'Off'
Simple mixer control 'Exchange Front/Surround',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'External Amplifier',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [on]
Simple mixer control 'High Pass Filter Enable',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'Input Source Select',0
Capabilities: enum
Items: 'Input1' 'Input2'
Item0: 'Input1'
Simple mixer control 'Input Source Select',1
Capabilities: enum
Items: 'Input1' 'Input2'
Item0: 'Input1'
Simple mixer control 'Spread Front to Surround and Center/LFE',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'VIA DXS',0
Capabilities: pvolume
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 31 [100%] [-48.00dB]
Front Right: Playback 31 [100%] [-48.00dB]
Simple mixer control 'VIA DXS',1
Capabilities: pvolume
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 31 [100%] [-48.00dB]
Front Right: Playback 31 [100%] [-48.00dB]
Simple mixer control 'VIA DXS',2
Capabilities: pvolume
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 31 [100%] [-48.00dB]
Front Right: Playback 31 [100%] [-48.00dB]
Simple mixer control 'VIA DXS',3
Capabilities: pvolume
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 31 [100%] [-48.00dB]
Front Right: Playback 31 [100%] [-48.00dB]
Simple mixer control 'V_REFOUT Enable',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [on]

View file

@ -0,0 +1,160 @@
Simple mixer control 'Master',0
Capabilities: pvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 0 [0%] [-46.50dB] [off]
Front Right: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control 'PCM',0
Capabilities: pvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 31 [100%] [-48.00dB] [off]
Front Right: Playback 31 [100%] [-48.00dB] [off]
Simple mixer control 'Surround',0
Capabilities: pswitch
Playback channels: Front Left - Front Right
Mono:
Front Left: Playback [off]
Front Right: Playback [off]
Simple mixer control 'Surround Jack Mode',0
Capabilities: enum
Items: 'Shared' 'Independent'
Item0: 'Shared'
Simple mixer control 'Center',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 31
Mono: Playback 31 [100%] [0.00dB] [off]
Simple mixer control 'LFE',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 31
Mono: Playback 0 [0%] [-46.50dB] [off]
Simple mixer control 'Line',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'CD',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'Mic',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [on]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [on]
Simple mixer control 'Mic Boost (+20dB)',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'Mic Select',0
Capabilities: enum
Items: 'Mic1' 'Mic2'
Item0: 'Mic1'
Simple mixer control 'Video',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'Phone',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'IEC958',0
Capabilities: pswitch pswitch-joined cswitch cswitch-joined
Playback channels: Mono
Capture channels: Mono
Mono: Playback [off] Capture [off]
Simple mixer control 'IEC958 Capture Monitor',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'IEC958 Capture Valid',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'IEC958 Output',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'IEC958 Playback AC97-SPSA',0
Capabilities: volume volume-joined
Playback channels: Mono
Capture channels: Mono
Limits: 0 - 3
Mono: 3 [100%]
Simple mixer control 'IEC958 Playback Source',0
Capabilities: enum
Items: 'AC-Link' 'ADC' 'SPDIF-In'
Item0: 'AC-Link'
Simple mixer control 'PC Speaker',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 15
Mono: Playback 0 [0%] [-45.00dB] [off]
Simple mixer control 'Aux',0
Capabilities: pvolume pswitch pswitch-joined cswitch cswitch-exclusive
Capture exclusive group: 0
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31
Front Left: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Front Right: Playback 0 [0%] [-34.50dB] [off] Capture [off]
Simple mixer control 'Mono Output Select',0
Capabilities: enum
Items: 'Mix' 'Mic'
Item0: 'Mix'
Simple mixer control 'Capture',0
Capabilities: cvolume cswitch cswitch-joined
Capture channels: Front Left - Front Right
Limits: Capture 0 - 15
Front Left: Capture 0 [0%] [0.00dB] [on]
Front Right: Capture 0 [0%] [0.00dB] [on]
Simple mixer control 'Mix',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'Mix Mono',0
Capabilities: cswitch cswitch-exclusive
Capture exclusive group: 0
Capture channels: Front Left - Front Right
Front Left: Capture [off]
Front Right: Capture [off]
Simple mixer control 'Channel Mode',0
Capabilities: enum
Items: '2ch' '4ch' '6ch'
Item0: '2ch'
Simple mixer control 'DAC Clock Source',0
Capabilities: enum
Items: 'AC-Link' 'SPDIF-In' 'Both'
Item0: 'AC-Link'
Simple mixer control 'External Amplifier',0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [on]
Simple mixer control 'Input Source Select',0
Capabilities: enum
Items: 'Input1' 'Input2'
Item0: 'Input1'
Simple mixer control 'Input Source Select',1
Capabilities: enum
Items: 'Input1' 'Input2'
Item0: 'Input1'

View file

@ -32,6 +32,10 @@
#include <modules/reserve-wrap.h>
#ifdef HAVE_UDEV
#include <modules/udev-util.h>
#endif
#include "alsa-util.h"
#include "alsa-sink.h"
#include "alsa-source.h"
@ -92,81 +96,53 @@ struct userdata {
char *device_id;
pa_card *card;
pa_sink *sink;
pa_source *source;
pa_modargs *modargs;
pa_hashmap *profiles;
pa_alsa_profile_set *profile_set;
};
struct profile_data {
const pa_alsa_profile_info *sink_profile, *source_profile;
pa_alsa_profile *profile;
};
static void enumerate_cb(
const pa_alsa_profile_info *sink,
const pa_alsa_profile_info *source,
void *userdata) {
static void add_profiles(struct userdata *u, pa_hashmap *h) {
pa_alsa_profile *ap;
void *state;
struct userdata *u = userdata;
char *t, *n;
pa_card_profile *p;
struct profile_data *d;
unsigned bonus = 0;
pa_assert(u);
pa_assert(h);
if (sink && source) {
n = pa_sprintf_malloc("output-%s+input-%s", sink->name, source->name);
t = pa_sprintf_malloc(_("Output %s + Input %s"), sink->description, _(source->description));
} else if (sink) {
n = pa_sprintf_malloc("output-%s", sink->name);
t = pa_sprintf_malloc(_("Output %s"), _(sink->description));
} else {
pa_assert(source);
n = pa_sprintf_malloc("input-%s", source->name);
t = pa_sprintf_malloc(_("Input %s"), _(source->description));
PA_HASHMAP_FOREACH(ap, u->profile_set->profiles, state) {
struct profile_data *d;
pa_card_profile *cp;
pa_alsa_mapping *m;
uint32_t idx;
cp = pa_card_profile_new(ap->name, ap->description, sizeof(struct profile_data));
cp->priority = ap->priority;
if (ap->output_mappings) {
cp->n_sinks = pa_idxset_size(ap->output_mappings);
PA_IDXSET_FOREACH(m, ap->output_mappings, idx)
if (m->channel_map.channels > cp->max_sink_channels)
cp->max_sink_channels = m->channel_map.channels;
}
if (ap->input_mappings) {
cp->n_sources = pa_idxset_size(ap->input_mappings);
PA_IDXSET_FOREACH(m, ap->input_mappings, idx)
if (m->channel_map.channels > cp->max_source_channels)
cp->max_source_channels = m->channel_map.channels;
}
d = PA_CARD_PROFILE_DATA(cp);
d->profile = ap;
pa_hashmap_put(h, cp->name, cp);
}
if (sink) {
if (pa_channel_map_equal(&sink->map, &u->core->default_channel_map))
bonus += 50000;
else if (sink->map.channels == u->core->default_channel_map.channels)
bonus += 40000;
}
if (source) {
if (pa_channel_map_equal(&source->map, &u->core->default_channel_map))
bonus += 30000;
else if (source->map.channels == u->core->default_channel_map.channels)
bonus += 20000;
}
pa_log_info("Found profile '%s'", t);
p = pa_card_profile_new(n, t, sizeof(struct profile_data));
pa_xfree(t);
pa_xfree(n);
p->priority =
(sink ? sink->priority : 0) * 100 +
(source ? source->priority : 0) +
bonus;
p->n_sinks = !!sink;
p->n_sources = !!source;
if (sink)
p->max_sink_channels = sink->map.channels;
if (source)
p->max_source_channels = source->map.channels;
d = PA_CARD_PROFILE_DATA(p);
d->sink_profile = sink;
d->source_profile = source;
pa_hashmap_put(u->profiles, p->name, p);
}
static void add_disabled_profile(pa_hashmap *profiles) {
@ -176,7 +152,7 @@ static void add_disabled_profile(pa_hashmap *profiles) {
p = pa_card_profile_new("off", _("Off"), sizeof(struct profile_data));
d = PA_CARD_PROFILE_DATA(p);
d->sink_profile = d->source_profile = NULL;
d->profile = NULL;
pa_hashmap_put(profiles, p->name, p);
}
@ -184,6 +160,9 @@ static void add_disabled_profile(pa_hashmap *profiles) {
static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
struct userdata *u;
struct profile_data *nd, *od;
uint32_t idx;
pa_alsa_mapping *am;
pa_queue *sink_inputs = NULL, *source_outputs = NULL;
pa_assert(c);
pa_assert(new_profile);
@ -192,67 +171,85 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
nd = PA_CARD_PROFILE_DATA(new_profile);
od = PA_CARD_PROFILE_DATA(c->active_profile);
if (od->sink_profile != nd->sink_profile) {
pa_queue *inputs = NULL;
if (od->profile && od->profile->output_mappings)
PA_IDXSET_FOREACH(am, od->profile->output_mappings, idx) {
if (!am->sink)
continue;
if (u->sink) {
if (nd->sink_profile)
inputs = pa_sink_move_all_start(u->sink);
if (nd->profile &&
nd->profile->output_mappings &&
pa_idxset_get_by_data(nd->profile->output_mappings, am, NULL))
continue;
pa_alsa_sink_free(u->sink);
u->sink = NULL;
sink_inputs = pa_sink_move_all_start(am->sink, sink_inputs);
pa_alsa_sink_free(am->sink);
am->sink = NULL;
}
if (nd->sink_profile) {
u->sink = pa_alsa_sink_new(c->module, u->modargs, __FILE__, c, nd->sink_profile);
if (od->profile && od->profile->input_mappings)
PA_IDXSET_FOREACH(am, od->profile->input_mappings, idx) {
if (!am->source)
continue;
if (inputs) {
if (u->sink)
pa_sink_move_all_finish(u->sink, inputs, FALSE);
else
pa_sink_move_all_fail(inputs);
if (nd->profile &&
nd->profile->input_mappings &&
pa_idxset_get_by_data(nd->profile->input_mappings, am, NULL))
continue;
source_outputs = pa_source_move_all_start(am->source, source_outputs);
pa_alsa_source_free(am->source);
am->source = NULL;
}
if (nd->profile && nd->profile->output_mappings)
PA_IDXSET_FOREACH(am, nd->profile->output_mappings, idx) {
if (!am->sink)
am->sink = pa_alsa_sink_new(c->module, u->modargs, __FILE__, c, am);
if (sink_inputs && am->sink) {
pa_sink_move_all_finish(am->sink, sink_inputs, FALSE);
sink_inputs = NULL;
}
}
}
if (od->source_profile != nd->source_profile) {
pa_queue *outputs = NULL;
if (nd->profile && nd->profile->input_mappings)
PA_IDXSET_FOREACH(am, nd->profile->input_mappings, idx) {
if (u->source) {
if (nd->source_profile)
outputs = pa_source_move_all_start(u->source);
if (!am->source)
am->source = pa_alsa_source_new(c->module, u->modargs, __FILE__, c, am);
pa_alsa_source_free(u->source);
u->source = NULL;
}
if (nd->source_profile) {
u->source = pa_alsa_source_new(c->module, u->modargs, __FILE__, c, nd->source_profile);
if (outputs) {
if (u->source)
pa_source_move_all_finish(u->source, outputs, FALSE);
else
pa_source_move_all_fail(outputs);
if (source_outputs && am->source) {
pa_source_move_all_finish(am->source, source_outputs, FALSE);
source_outputs = NULL;
}
}
}
if (sink_inputs)
pa_sink_move_all_fail(sink_inputs);
if (source_outputs)
pa_source_move_all_fail(source_outputs);
return 0;
}
static void init_profile(struct userdata *u) {
uint32_t idx;
pa_alsa_mapping *am;
struct profile_data *d;
pa_assert(u);
d = PA_CARD_PROFILE_DATA(u->card->active_profile);
if (d->sink_profile)
u->sink = pa_alsa_sink_new(u->module, u->modargs, __FILE__, u->card, d->sink_profile);
if (d->profile && d->profile->output_mappings)
PA_IDXSET_FOREACH(am, d->profile->output_mappings, idx)
am->sink = pa_alsa_sink_new(u->module, u->modargs, __FILE__, u->card, am);
if (d->source_profile)
u->source = pa_alsa_source_new(u->module, u->modargs, __FILE__, u->card, d->source_profile);
if (d->profile && d->profile->input_mappings)
PA_IDXSET_FOREACH(am, d->profile->input_mappings, idx)
am->source = pa_alsa_source_new(u->module, u->modargs, __FILE__, u->card, am);
}
static void set_card_name(pa_card_new_data *data, pa_modargs *ma, const char *device_id) {
@ -286,12 +283,11 @@ int pa__init(pa_module *m) {
pa_modargs *ma;
int alsa_card_index;
struct userdata *u;
char rname[32];
pa_reserve_wrapper *reserve = NULL;
const char *description;
char *fn = NULL;
pa_alsa_redirect_errors_inc();
snd_config_update_free_global();
pa_alsa_refcnt_inc();
pa_assert(m);
@ -300,13 +296,10 @@ int pa__init(pa_module *m) {
goto fail;
}
m->userdata = u = pa_xnew(struct userdata, 1);
m->userdata = u = pa_xnew0(struct userdata, 1);
u->core = m->core;
u->module = m;
u->device_id = pa_xstrdup(pa_modargs_get_value(ma, "device_id", DEFAULT_DEVICE_ID));
u->card = NULL;
u->sink = NULL;
u->source = NULL;
u->modargs = ma;
if ((alsa_card_index = snd_card_get_index(u->device_id)) < 0) {
@ -314,16 +307,36 @@ int pa__init(pa_module *m) {
goto fail;
}
pa_snprintf(rname, sizeof(rname), "Audio%i", alsa_card_index);
if (!pa_in_system_mode()) {
char *rname;
if (!pa_in_system_mode())
if (!(reserve = pa_reserve_wrapper_get(m->core, rname)))
goto fail;
if ((rname = pa_alsa_get_reserve_name(u->device_id))) {
reserve = pa_reserve_wrapper_get(m->core, rname);
pa_xfree(rname);
if (!reserve)
goto fail;
}
}
#ifdef HAVE_UDEV
fn = pa_udev_get_property(alsa_card_index, "PULSE_PROFILE_SET");
#endif
u->profile_set = pa_alsa_profile_set_new(fn, &u->core->default_channel_map);
pa_xfree(fn);
if (!u->profile_set)
goto fail;
pa_alsa_profile_set_probe(u->profile_set, u->device_id, &m->core->default_sample_spec);
pa_card_new_data_init(&data);
data.driver = __FILE__;
data.module = m;
pa_alsa_init_proplist_card(m->core, data.proplist, alsa_card_index);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_id);
pa_alsa_init_description(data.proplist);
set_card_name(&data, ma, u->device_id);
@ -332,11 +345,8 @@ int pa__init(pa_module *m) {
if ((description = pa_proplist_gets(data.proplist, PA_PROP_DEVICE_DESCRIPTION)))
pa_reserve_wrapper_set_application_device_name(reserve, description);
u->profiles = data.profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
if (pa_alsa_probe_profiles(u->device_id, &m->core->default_sample_spec, enumerate_cb, u) < 0) {
pa_card_new_data_done(&data);
goto fail;
}
data.profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
add_profiles(u, data.profiles);
if (pa_hashmap_isempty(data.profiles)) {
pa_log("Failed to find a working profile.");
@ -379,13 +389,22 @@ fail:
int pa__get_n_used(pa_module *m) {
struct userdata *u;
int n = 0;
uint32_t idx;
pa_sink *sink;
pa_source *source;
pa_assert(m);
pa_assert_se(u = m->userdata);
pa_assert(u->card);
return
(u->sink ? pa_sink_linked_by(u->sink) : 0) +
(u->source ? pa_source_linked_by(u->source) : 0);
PA_IDXSET_FOREACH(sink, u->card->sinks, idx)
n += pa_sink_linked_by(sink);
PA_IDXSET_FOREACH(source, u->card->sources, idx)
n += pa_source_linked_by(source);
return n;
}
void pa__done(pa_module*m) {
@ -396,11 +415,19 @@ void pa__done(pa_module*m) {
if (!(u = m->userdata))
goto finish;
if (u->sink)
pa_alsa_sink_free(u->sink);
if (u->card && u->card->sinks) {
pa_sink *s;
if (u->source)
pa_alsa_source_free(u->source);
while ((s = pa_idxset_steal_first(u->card->sinks, NULL)))
pa_alsa_sink_free(s);
}
if (u->card && u->card->sources) {
pa_source *s;
while ((s = pa_idxset_steal_first(u->card->sources, NULL)))
pa_alsa_source_free(s);
}
if (u->card)
pa_card_free(u->card);
@ -408,10 +435,12 @@ void pa__done(pa_module*m) {
if (u->modargs)
pa_modargs_free(u->modargs);
if (u->profile_set)
pa_alsa_profile_set_free(u->profile_set);
pa_xfree(u->device_id);
pa_xfree(u);
finish:
snd_config_update_free_global();
pa_alsa_redirect_errors_dec();
pa_alsa_refcnt_dec();
}

View file

@ -82,8 +82,7 @@ int pa__init(pa_module*m) {
pa_assert(m);
pa_alsa_redirect_errors_inc();
snd_config_update_free_global();
pa_alsa_refcnt_inc();
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log("Failed to parse module arguments");
@ -124,6 +123,5 @@ void pa__done(pa_module*m) {
if ((sink = m->userdata))
pa_alsa_sink_free(sink);
snd_config_update_free_global();
pa_alsa_redirect_errors_dec();
pa_alsa_refcnt_dec();
}

View file

@ -37,6 +37,7 @@
#include <pulse/timeval.h>
#include <pulsecore/core-error.h>
#include <pulsecore/core-rtclock.h>
#include <pulsecore/core.h>
#include <pulsecore/module.h>
#include <pulsecore/memchunk.h>
@ -51,7 +52,6 @@
#include <pulsecore/thread-mq.h>
#include <pulsecore/rtpoll.h>
#include <pulsecore/time-smoother.h>
#include <pulsecore/rtclock.h>
#include "alsa-util.h"
#include "alsa-source.h"
@ -106,8 +106,7 @@ int pa__init(pa_module*m) {
pa_assert(m);
pa_alsa_redirect_errors_inc();
snd_config_update_free_global();
pa_alsa_refcnt_inc();
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log("Failed to parse module arguments");
@ -148,6 +147,5 @@ void pa__done(pa_module*m) {
if ((source = m->userdata))
pa_alsa_source_free(source);
snd_config_update_free_global();
pa_alsa_redirect_errors_dec();
pa_alsa_refcnt_dec();
}

View file

@ -30,13 +30,15 @@
#include <linux/sockios.h>
#include <arpa/inet.h>
#include <pulse/xmalloc.h>
#include <pulse/timeval.h>
#include <pulse/sample.h>
#include <pulse/i18n.h>
#include <pulse/rtclock.h>
#include <pulse/sample.h>
#include <pulse/timeval.h>
#include <pulse/xmalloc.h>
#include <pulsecore/module.h>
#include <pulsecore/modargs.h>
#include <pulsecore/core-rtclock.h>
#include <pulsecore/core-util.h>
#include <pulsecore/core-error.h>
#include <pulsecore/socket-util.h>
@ -44,7 +46,6 @@
#include <pulsecore/thread-mq.h>
#include <pulsecore/rtpoll.h>
#include <pulsecore/time-smoother.h>
#include <pulsecore/rtclock.h>
#include <pulsecore/namereg.h>
#include <pulsecore/dbus-shared.h>
@ -773,7 +774,7 @@ static int start_stream_fd(struct userdata *u) {
TRUE,
TRUE,
10,
pa_rtclock_usec(),
pa_rtclock_now(),
TRUE);
return 0;
@ -867,14 +868,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
if (u->read_smoother) {
pa_usec_t wi, ri;
ri = pa_smoother_get(u->read_smoother, pa_rtclock_usec());
ri = pa_smoother_get(u->read_smoother, pa_rtclock_now());
wi = pa_bytes_to_usec(u->write_index + u->block_size, &u->sample_spec);
*((pa_usec_t*) data) = wi > ri ? wi - ri : 0;
} else {
pa_usec_t ri, wi;
ri = pa_rtclock_usec() - u->started_at;
ri = pa_rtclock_now() - u->started_at;
wi = pa_bytes_to_usec(u->write_index, &u->sample_spec);
*((pa_usec_t*) data) = wi > ri ? wi - ri : 0;
@ -912,7 +913,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
stop_stream_fd(u);
if (u->read_smoother)
pa_smoother_pause(u->read_smoother, pa_rtclock_usec());
pa_smoother_pause(u->read_smoother, pa_rtclock_now());
break;
case PA_SOURCE_IDLE:
@ -939,7 +940,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
case PA_SOURCE_MESSAGE_GET_LATENCY: {
pa_usec_t wi, ri;
wi = pa_smoother_get(u->read_smoother, pa_rtclock_usec());
wi = pa_smoother_get(u->read_smoother, pa_rtclock_now());
ri = pa_bytes_to_usec(u->read_index, &u->sample_spec);
*((pa_usec_t*) data) = (wi > ri ? wi - ri : 0) + u->source->fixed_latency;
@ -1086,7 +1087,7 @@ static int hsp_process_push(struct userdata *u) {
if (!found_tstamp) {
pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!");
tstamp = pa_rtclock_usec();
tstamp = pa_rtclock_now();
}
pa_smoother_put(u->read_smoother, tstamp, pa_bytes_to_usec(u->read_index, &u->sample_spec));
@ -1265,7 +1266,6 @@ static void thread_func(void *userdata) {
goto fail;
pa_thread_mq_install(&u->thread_mq);
pa_rtpoll_install(u->rtpoll);
for (;;) {
struct pollfd *pollfd;
@ -1309,7 +1309,7 @@ static void thread_func(void *userdata) {
/* Hmm, there is no input stream we could synchronize
* to. So let's do things by time */
time_passed = pa_rtclock_usec() - u->started_at;
time_passed = pa_rtclock_now() - u->started_at;
audio_sent = pa_bytes_to_usec(u->write_index, &u->sample_spec);
if (audio_sent <= time_passed) {
@ -1341,7 +1341,7 @@ static void thread_func(void *userdata) {
int n_written;
if (u->write_index <= 0)
u->started_at = pa_rtclock_usec();
u->started_at = pa_rtclock_now();
if (u->profile == PROFILE_A2DP) {
if ((n_written = a2dp_process_render(u)) < 0)
@ -1361,7 +1361,7 @@ static void thread_func(void *userdata) {
/* Hmm, there is no input stream we could synchronize
* to. So let's estimate when we need to wake up the latest */
time_passed = pa_rtclock_usec() - u->started_at;
time_passed = pa_rtclock_now() - u->started_at;
next_write_at = pa_bytes_to_usec(u->write_index, &u->sample_spec);
sleep_for = time_passed < next_write_at ? next_write_at - time_passed : 0;
@ -1443,12 +1443,12 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
if (u->sink && dbus_message_is_signal(m, "org.bluez.Headset", "SpeakerGainChanged")) {
pa_cvolume_set(&v, u->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
pa_sink_volume_changed(u->sink, &v);
pa_sink_volume_changed(u->sink, &v, TRUE);
} else if (u->source && dbus_message_is_signal(m, "org.bluez.Headset", "MicrophoneGainChanged")) {
pa_cvolume_set(&v, u->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
pa_source_volume_changed(u->source, &v);
pa_source_volume_changed(u->source, &v, TRUE);
}
}
}
@ -1622,6 +1622,8 @@ static int add_sink(struct userdata *u) {
data.module = u->module;
pa_sink_new_data_set_sample_spec(&data, &u->sample_spec);
pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile == PROFILE_A2DP ? "a2dp" : "sco");
if (u->profile == PROFILE_HSP)
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_INTENDED_ROLES, "phone");
data.card = u->card;
data.name = get_name("sink", u->modargs, u->address, &b);
data.namereg_fail = b;
@ -1680,6 +1682,8 @@ static int add_source(struct userdata *u) {
data.module = u->module;
pa_source_new_data_set_sample_spec(&data, &u->sample_spec);
pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile == PROFILE_A2DP ? "a2dp" : "hsp");
if (u->profile == PROFILE_HSP)
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_INTENDED_ROLES, "phone");
data.card = u->card;
data.name = get_name("source", u->modargs, u->address, &b);
data.namereg_fail = b;
@ -1916,7 +1920,7 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
if (!(device = pa_bluetooth_discovery_get_by_path(u->discovery, u->path))) {
pa_log_error("Failed to get device object.");
return -1;
return -PA_ERR_IO;
}
/* The state signal is sent by bluez, so it is racy to check
@ -1926,15 +1930,15 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
module will be unloaded. */
if (device->headset_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_HSP) {
pa_log_warn("HSP is not connected, refused to switch profile");
return -1;
return -PA_ERR_IO;
}
else if (device->audio_sink_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_A2DP) {
pa_log_warn("A2DP is not connected, refused to switch profile");
return -1;
return -PA_ERR_IO;
}
if (u->sink) {
inputs = pa_sink_move_all_start(u->sink);
inputs = pa_sink_move_all_start(u->sink, NULL);
#ifdef NOKIA
if (!USE_SCO_OVER_PCM(u))
#endif
@ -1942,7 +1946,7 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
}
if (u->source) {
outputs = pa_source_move_all_start(u->source);
outputs = pa_source_move_all_start(u->source, NULL);
#ifdef NOKIA
if (!USE_SCO_OVER_PCM(u))
#endif

View file

@ -109,7 +109,7 @@ static void update_volume(struct userdata *u) {
}
pa_log_info("Found %u BT devices, unmuting.", u->n_found);
pa_sink_set_mute(s, FALSE);
pa_sink_set_mute(s, FALSE, FALSE);
} else if (!u->muted && (u->n_found+u->n_unknown) <= 0) {
pa_sink *s;
@ -122,7 +122,7 @@ static void update_volume(struct userdata *u) {
}
pa_log_info("No BT devices found, muting.");
pa_sink_set_mute(s, TRUE);
pa_sink_set_mute(s, TRUE, FALSE);
} else
pa_log_info("%u devices now active, %u with unknown state.", u->n_found, u->n_unknown);

View file

@ -225,7 +225,6 @@ static void thread_func(void *userdata) {
pa_make_realtime(u->core->realtime_priority);
pa_thread_mq_install(&u->thread_mq);
pa_rtpoll_install(u->rtpoll);
for (;;) {
int ret;

View file

@ -196,7 +196,6 @@ static void thread_func(void *userdata) {
pa_make_realtime(u->core->realtime_priority);
pa_thread_mq_install(&u->thread_mq);
pa_rtpoll_install(u->rtpoll);
for (;;) {
int ret;

View file

@ -58,6 +58,7 @@ struct rule {
char *process_name;
char *application_name;
char *icon_name;
char *role;
pa_proplist *proplist;
};
@ -72,12 +73,21 @@ static void rule_free(struct rule *r) {
pa_xfree(r->process_name);
pa_xfree(r->application_name);
pa_xfree(r->icon_name);
pa_xfree(r->role);
if (r->proplist)
pa_proplist_free(r->proplist);
pa_xfree(r);
}
static int parse_properties(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
static int parse_properties(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
const char *rvalue,
void *data,
void *userdata) {
struct rule *r = userdata;
pa_proplist *n;
@ -93,11 +103,56 @@ static int parse_properties(const char *filename, unsigned line, const char *sec
return 0;
}
static int check_type(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
static int parse_categories(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
const char *rvalue,
void *data,
void *userdata) {
struct rule *r = userdata;
const char *state = NULL;
char *c;
while ((c = pa_split(rvalue, ";", &state))) {
if (pa_streq(c, "Game")) {
pa_xfree(r->role);
r->role = pa_xstrdup("game");
} else if (pa_streq(c, "Telephony")) {
pa_xfree(r->role);
r->role = pa_xstrdup("phone");
}
pa_xfree(c);
}
return 0;
}
static int check_type(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
const char *rvalue,
void *data,
void *userdata) {
return pa_streq(rvalue, "Application") ? 0 : -1;
}
static int catch_all(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
static int catch_all(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
const char *rvalue,
void *data,
void *userdata) {
return 0;
}
@ -109,6 +164,7 @@ static void update_rule(struct rule *r) {
{ "Icon", pa_config_parse_string, NULL, "Desktop Entry" },
{ "Type", check_type, NULL, "Desktop Entry" },
{ "X-PulseAudio-Properties", parse_properties, NULL, "Desktop Entry" },
{ "Categories", parse_categories, NULL, "Desktop Entry" },
{ NULL, catch_all, NULL, NULL },
{ NULL, NULL, NULL, NULL },
};
@ -131,7 +187,8 @@ static void update_rule(struct rule *r) {
r->mtime = st.st_mtime;
pa_xfree(r->application_name);
pa_xfree(r->icon_name);
r->application_name = r->icon_name = NULL;
pa_xfree(r->role);
r->application_name = r->icon_name = r->role = NULL;
if (r->proplist)
pa_proplist_clear(r->proplist);
@ -151,6 +208,9 @@ static void apply_rule(struct rule *r, pa_proplist *p) {
if (!r->good)
return;
if (r->proplist)
pa_proplist_update(p, PA_UPDATE_MERGE, r->proplist);
if (r->icon_name)
if (!pa_proplist_contains(p, PA_PROP_APPLICATION_ICON_NAME))
pa_proplist_sets(p, PA_PROP_APPLICATION_ICON_NAME, r->icon_name);
@ -164,8 +224,9 @@ static void apply_rule(struct rule *r, pa_proplist *p) {
pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, r->application_name);
}
if (r->proplist)
pa_proplist_update(p, PA_UPDATE_MERGE, r->proplist);
if (r->role)
if (!pa_proplist_contains(p, PA_PROP_MEDIA_ROLE))
pa_proplist_sets(p, PA_PROP_MEDIA_ROLE, r->role);
}
static void make_room(pa_hashmap *cache) {

View file

@ -35,6 +35,7 @@
#include <pulse/volume.h>
#include <pulse/timeval.h>
#include <pulse/util.h>
#include <pulse/rtclock.h>
#include <pulsecore/core-error.h>
#include <pulsecore/module.h>
@ -53,7 +54,7 @@ PA_MODULE_DESCRIPTION("Automatically restore profile of cards");
PA_MODULE_VERSION(PACKAGE_VERSION);
PA_MODULE_LOAD_ONCE(TRUE);
#define SAVE_INTERVAL 10
#define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
static const char* const valid_modargs[] = {
NULL
@ -75,12 +76,11 @@ struct entry {
char profile[PA_NAME_MAX];
} PA_GCC_PACKED ;
static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) {
static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
struct userdata *u = userdata;
pa_assert(a);
pa_assert(e);
pa_assert(tv);
pa_assert(u);
pa_assert(e == u->save_time_event);
@ -132,14 +132,10 @@ fail:
}
static void trigger_save(struct userdata *u) {
struct timeval tv;
if (u->save_time_event)
return;
pa_gettimeofday(&tv);
tv.tv_sec += SAVE_INTERVAL;
u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u);
u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u);
}
static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
@ -197,8 +193,9 @@ static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new
if ((e = read_entry(u, new_data->name)) && e->profile[0]) {
if (!new_data->active_profile) {
pa_card_new_data_set_profile(new_data, e->profile);
pa_log_info("Restoring profile for card %s.", new_data->name);
pa_card_new_data_set_profile(new_data, e->profile);
new_data->save_profile = TRUE;
} else
pa_log_debug("Not restoring profile for card %s, because already set.", new_data->name);
@ -222,11 +219,9 @@ int pa__init(pa_module*m) {
goto fail;
}
m->userdata = u = pa_xnew(struct userdata, 1);
m->userdata = u = pa_xnew0(struct userdata, 1);
u->core = m->core;
u->module = m;
u->save_time_event = NULL;
u->database = NULL;
u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_CARD, subscribe_callback, u);

View file

@ -26,6 +26,7 @@
#include <stdio.h>
#include <errno.h>
#include <pulse/rtclock.h>
#include <pulse/timeval.h>
#include <pulse/xmalloc.h>
@ -36,6 +37,7 @@
#include <pulsecore/sink-input.h>
#include <pulsecore/memblockq.h>
#include <pulsecore/log.h>
#include <pulsecore/core-rtclock.h>
#include <pulsecore/core-util.h>
#include <pulsecore/modargs.h>
#include <pulsecore/namereg.h>
@ -43,7 +45,6 @@
#include <pulsecore/thread.h>
#include <pulsecore/thread-mq.h>
#include <pulsecore/rtpoll.h>
#include <pulsecore/rtclock.h>
#include <pulsecore/core-error.h>
#include <pulsecore/time-smoother.h>
@ -224,9 +225,8 @@ static void adjust_rates(struct userdata *u) {
pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_UPDATE_LATENCY, NULL, (int64_t) avg_total_latency, NULL);
}
static void time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) {
static void time_callback(pa_mainloop_api *a, pa_time_event *e, const struct timeval *t, void *userdata) {
struct userdata *u = userdata;
struct timeval n;
pa_assert(u);
pa_assert(a);
@ -234,9 +234,7 @@ static void time_callback(pa_mainloop_api*a, pa_time_event* e, const struct time
adjust_rates(u);
pa_gettimeofday(&n);
n.tv_sec += (time_t) u->adjust_time;
u->sink->core->mainloop->time_restart(e, &n);
pa_core_rttime_restart(u->core, e, pa_rtclock_now() + u->adjust_time * PA_USEC_PER_SEC);
}
static void process_render_null(struct userdata *u, pa_usec_t now) {
@ -280,9 +278,8 @@ static void thread_func(void *userdata) {
pa_make_realtime(u->core->realtime_priority+1);
pa_thread_mq_install(&u->thread_mq);
pa_rtpoll_install(u->rtpoll);
u->thread_info.timestamp = pa_rtclock_usec();
u->thread_info.timestamp = pa_rtclock_now();
u->thread_info.in_null_mode = FALSE;
for (;;) {
@ -296,7 +293,7 @@ static void thread_func(void *userdata) {
if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && !u->thread_info.active_outputs) {
pa_usec_t now;
now = pa_rtclock_usec();
now = pa_rtclock_now();
if (!u->thread_info.in_null_mode || u->thread_info.timestamp <= now)
process_render_null(u, now);
@ -593,7 +590,7 @@ static void unsuspend(struct userdata *u) {
/* Let's resume */
for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) {
pa_sink_suspend(o->sink, FALSE);
pa_sink_suspend(o->sink, FALSE, PA_SUSPEND_IDLE);
if (PA_SINK_IS_OPENED(pa_sink_get_state(o->sink)))
enable_output(o);
@ -664,16 +661,16 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
pa_atomic_store(&u->thread_info.running, PA_PTR_TO_UINT(data) == PA_SINK_RUNNING);
if (PA_PTR_TO_UINT(data) == PA_SINK_SUSPENDED)
pa_smoother_pause(u->thread_info.smoother, pa_rtclock_usec());
pa_smoother_pause(u->thread_info.smoother, pa_rtclock_now());
else
pa_smoother_resume(u->thread_info.smoother, pa_rtclock_usec(), TRUE);
pa_smoother_resume(u->thread_info.smoother, pa_rtclock_now(), TRUE);
break;
case PA_SINK_MESSAGE_GET_LATENCY: {
pa_usec_t x, y, c, *delay = data;
x = pa_rtclock_usec();
x = pa_rtclock_now();
y = pa_smoother_get(u->thread_info.smoother, x);
c = pa_bytes_to_usec(u->thread_info.counter, &u->sink->sample_spec);
@ -730,7 +727,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
case SINK_MESSAGE_UPDATE_LATENCY: {
pa_usec_t x, y, latency = (pa_usec_t) offset;
x = pa_rtclock_usec();
x = pa_rtclock_now();
y = pa_bytes_to_usec(u->thread_info.counter, &u->sink->sample_spec);
if (y > latency)
@ -873,7 +870,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink) {
}
if (PA_SINK_IS_OPENED(state) || state == PA_SINK_INIT) {
pa_sink_suspend(sink, FALSE);
pa_sink_suspend(sink, FALSE, PA_SUSPEND_IDLE);
if (PA_SINK_IS_OPENED(pa_sink_get_state(sink)))
if (output_create_sink_input(o) < 0)
@ -1170,12 +1167,8 @@ int pa__init(pa_module*m) {
if (o->sink_input)
pa_sink_input_put(o->sink_input);
if (u->adjust_time > 0) {
struct timeval tv;
pa_gettimeofday(&tv);
tv.tv_sec += (time_t) u->adjust_time;
u->time_event = m->core->mainloop->time_new(m->core->mainloop, &tv, time_callback, u);
}
if (u->adjust_time > 0)
u->time_event = pa_core_rttime_new(m->core, pa_rtclock_now() + u->adjust_time * PA_USEC_PER_SEC, time_callback, u);
pa_modargs_free(ma);

Some files were not shown because too many files have changed in this diff Show more