mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-12-19 23:50:05 +01:00
merge 'lennart' branch back into trunk.
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1971 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
6687dd0131
commit
a67c21f093
294 changed files with 79057 additions and 11614 deletions
|
|
@ -48,4 +48,10 @@ doxygen:
|
|||
eolspace:
|
||||
find \( -name '*.c' -o -name '*.h' -o -name 'Makefile.am' \) -exec perl -i -pe 's/\s+\n$$/\1\n/;' \{\} \;
|
||||
|
||||
untabify:
|
||||
find \( -name '*.c' -o -name '*.h' \) -exec perl -i -pe 's/\t/ /g;' \{\} \;
|
||||
|
||||
fedora-snapshot: dist
|
||||
cp $(distdir).tar.gz $$HOME/cvs.fedora/pulseaudio/devel/$(distdir).svn`date +%Y%m%d`.tar.gz
|
||||
|
||||
.PHONY: homepage distcleancheck doxygen
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@ run_versioned() {
|
|||
|
||||
V=$(echo "$2" | sed -e 's,\.,,g')
|
||||
|
||||
if [ -e "`which $1$V`" ] ; then
|
||||
if [ -e "`which $1$V 2> /dev/null`" ] ; then
|
||||
P="$1$V"
|
||||
else
|
||||
if [ -e "`which $1-$2`" ] ; then
|
||||
if [ -e "`which $1-$2 2> /dev/null`" ] ; then
|
||||
P="$1-$2"
|
||||
else
|
||||
P="$1"
|
||||
|
|
@ -48,13 +48,14 @@ else
|
|||
rm -rf autom4te.cache
|
||||
rm -f config.cache
|
||||
|
||||
touch config.rpath
|
||||
test "x$LIBTOOLIZE" = "x" && LIBTOOLIZE=libtoolize
|
||||
|
||||
"$LIBTOOLIZE" -c --force --ltdl
|
||||
run_versioned aclocal "$VERSION"
|
||||
run_versioned autoconf 2.59 -Wall
|
||||
run_versioned autoheader 2.59
|
||||
run_versioned automake "$VERSION" -a -c --foreign
|
||||
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 "$@"
|
||||
|
|
|
|||
233
configure.ac
233
configure.ac
|
|
@ -26,7 +26,7 @@ AC_PREREQ(2.57)
|
|||
|
||||
m4_define(PA_MAJOR, [0])
|
||||
m4_define(PA_MINOR, [9])
|
||||
m4_define(PA_MICRO, [6])
|
||||
m4_define(PA_MICRO, [7])
|
||||
|
||||
AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzcbylcnhqvb (at) 0pointer (dot) de])
|
||||
AC_CONFIG_SRCDIR([src/daemon/main.c])
|
||||
|
|
@ -34,13 +34,13 @@ AC_CONFIG_HEADERS([config.h])
|
|||
AM_INIT_AUTOMAKE([foreign -Wall])
|
||||
|
||||
AC_SUBST(PA_MAJORMINOR, "PA_MAJOR.PA_MINOR")
|
||||
AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/pulseaudio/])
|
||||
AC_SUBST(PACKAGE_URL, [http://pulseaudio.org/])
|
||||
|
||||
AC_SUBST(PA_API_VERSION, 10)
|
||||
AC_SUBST(PA_PROTOCOL_VERSION, 10)
|
||||
AC_SUBST(PA_PROTOCOL_VERSION, 11)
|
||||
|
||||
AC_SUBST(LIBPULSE_VERSION_INFO, [2:0:2])
|
||||
AC_SUBST(LIBPULSECORE_VERSION_INFO, [3:0:0])
|
||||
AC_SUBST(LIBPULSE_VERSION_INFO, [3:0:3])
|
||||
AC_SUBST(LIBPULSECORE_VERSION_INFO, [4:0:0])
|
||||
AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:0:0])
|
||||
AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [1:0:1])
|
||||
AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:2:0])
|
||||
|
|
@ -81,8 +81,8 @@ fi
|
|||
# GCC flags
|
||||
|
||||
test_gcc_flag() {
|
||||
AC_LANG_CONFTEST([int main() {}])
|
||||
$CC -c conftest.c $CFLAGS $@ > /dev/null 2> /dev/null
|
||||
AC_LANG_CONFTEST([int main(int argc, char*argv[]) {}])
|
||||
$CC -c conftest.c $CFLAGS -o conftest.o > /dev/null 2> /dev/null
|
||||
ret=$?
|
||||
rm -f conftest.o
|
||||
return $ret
|
||||
|
|
@ -93,28 +93,64 @@ if test "x$GCC" = "xyes" ; then
|
|||
|
||||
# We use gnu99 instead of c99 because many have interpreted the standard
|
||||
# in a way that int64_t isn't defined on non-64 bit platforms.
|
||||
DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter"
|
||||
DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter -ffast-math"
|
||||
|
||||
for flag in $DESIRED_FLAGS ; do
|
||||
AC_MSG_CHECKING([whether $CC accepts $flag])
|
||||
if test_gcc_flag $flag ; then
|
||||
if test_gcc_flag $flag ; then
|
||||
CFLAGS="$CFLAGS $flag"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
done
|
||||
done
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether $CC knows __sync_bool_compare_and_swap()])
|
||||
AC_LANG_CONFTEST([int main() { int a = 4; __sync_bool_compare_and_swap(&a, 4, 5); }])
|
||||
$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null
|
||||
ret=$?
|
||||
rm -f conftest.o conftest
|
||||
if test $ret -eq 0 ; then
|
||||
AC_DEFINE([HAVE_ATOMIC_BUILTINS], 1, [Have __sync_bool_compare_and_swap() and friends.])
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether $CC knows __thread])
|
||||
AC_LANG_CONFTEST([static __thread int a = 6; int main() { a = 5; }])
|
||||
$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null
|
||||
ret=$?
|
||||
rm -f conftest.o conftest
|
||||
if test $ret -eq 0 ; then
|
||||
AC_DEFINE([HAVE_TLS_BUILTIN], 1, [Have __thread().])
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether $CC knows _Bool])
|
||||
AC_LANG_CONFTEST([int main() { _Bool b; }])
|
||||
$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null
|
||||
ret=$?
|
||||
rm -f conftest.o conftest
|
||||
if test $ret -eq 0 ; then
|
||||
AC_DEFINE([HAVE_STD_BOOL], 1, [Have _Bool.])
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#### libtool stuff ####
|
||||
|
||||
AC_LTDL_ENABLE_INSTALL
|
||||
AC_LIBLTDL_INSTALLABLE
|
||||
AC_SUBST(LTDLINCL)
|
||||
AC_SUBST(LIBLTDL)
|
||||
AC_LIBTOOL_DLOPEN
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AC_PROG_LIBTOOL
|
||||
AC_SUBST(LTDLINCL)
|
||||
AC_SUBST(LIBLTDL)
|
||||
AC_CONFIG_SUBDIRS(libltdl)
|
||||
|
||||
if test "x$enable_ltdl_install" = "xno" && test "x$ac_cv_lib_ltdl_lt_dlinit" = "xno" ; then
|
||||
|
|
@ -149,9 +185,9 @@ AC_HEADER_STDC
|
|||
|
||||
# POSIX
|
||||
AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h netdb.h netinet/in.h \
|
||||
netinet/in_systm.h netinet/tcp.h pwd.h sched.h \
|
||||
netinet/in_systm.h netinet/tcp.h poll.h pwd.h sched.h \
|
||||
sys/mman.h sys/resource.h sys/select.h sys/socket.h sys/wait.h \
|
||||
syslog.h])
|
||||
syslog.h sys/dl.h dlfcn.h linux/sockios.h])
|
||||
AC_CHECK_HEADERS([netinet/ip.h], [], [],
|
||||
[#include <sys/types.h>
|
||||
#if HAVE_NETINET_IN_H
|
||||
|
|
@ -167,9 +203,6 @@ AC_CHECK_HEADERS([sys/un.h], [HAVE_AF_UNIX=1], [HAVE_AF_UNIX=0])
|
|||
AM_CONDITIONAL(HAVE_REGEX, test "x$HAVE_REGEX" = "x1")
|
||||
AM_CONDITIONAL(HAVE_AF_UNIX, test "x$HAVE_AF_UNIX" = "x1")
|
||||
|
||||
# XPG4-UNIX
|
||||
AC_CHECK_HEADERS([sys/poll.h])
|
||||
|
||||
# Linux
|
||||
AC_CHECK_HEADERS([linux/input.h], [HAVE_EVDEV=1], [HAVE_EVDEV=0])
|
||||
|
||||
|
|
@ -185,6 +218,8 @@ AC_CHECK_HEADERS([windows.h winsock2.h ws2tcpip.h])
|
|||
|
||||
# Other
|
||||
AC_CHECK_HEADERS([sys/ioctl.h])
|
||||
AC_CHECK_HEADERS([byteswap.h])
|
||||
AC_CHECK_HEADERS([sys/syscall.h])
|
||||
|
||||
#### Typdefs, structures, etc. ####
|
||||
|
||||
|
|
@ -235,13 +270,17 @@ AC_CHECK_FUNCS([getopt_long], [], [AC_CHECK_LIB([iberty], [getopt_long])])
|
|||
|
||||
#### Check for functions ####
|
||||
|
||||
# ISO
|
||||
AC_CHECK_FUNCS([lrintf strtof])
|
||||
|
||||
# POSIX
|
||||
AC_FUNC_FORK
|
||||
AC_FUNC_GETGROUPS
|
||||
AC_FUNC_SELECT_ARGTYPES
|
||||
AC_CHECK_FUNCS([chmod chown getaddrinfo getgrgid_r getpwuid_r gettimeofday \
|
||||
getuid inet_ntop inet_pton nanosleep pipe posix_memalign setpgid setsid \
|
||||
shm_open sigaction sleep sysconf])
|
||||
AC_CHECK_FUNCS([chmod chown clock_gettime getaddrinfo getgrgid_r \
|
||||
getpwuid_r gettimeofday getuid inet_ntop inet_pton mlock nanosleep \
|
||||
pipe posix_fadvise posix_madvise posix_memalign setpgid setsid shm_open \
|
||||
sigaction sleep sysconf])
|
||||
AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0])
|
||||
|
||||
AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1")
|
||||
|
|
@ -260,7 +299,22 @@ AC_CHECK_FUNCS([lstat])
|
|||
|
||||
# Non-standard
|
||||
|
||||
AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid])
|
||||
AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid ppoll strsignal sig2str strtof_l])
|
||||
|
||||
AC_MSG_CHECKING([for PTHREAD_PRIO_INHERIT])
|
||||
AC_LANG_CONFTEST([AC_LANG_SOURCE([[
|
||||
#include <pthread.h>
|
||||
int main() { int i = PTHREAD_PRIO_INHERIT; }]])])
|
||||
$PTHREAD_CC conftest.c $PTHREAD_CFLAGS $CFLAGS $PTHREAD_LIBS -o conftest > /dev/null 2> /dev/null
|
||||
ret=$?
|
||||
rm -f conftest.o conftest
|
||||
|
||||
if test $ret -eq 0 ; then
|
||||
AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.])
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#### Large File-Support (LFS) ####
|
||||
|
||||
|
|
@ -324,12 +378,6 @@ fi
|
|||
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
#### Sample rate conversion ####
|
||||
|
||||
PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ])
|
||||
AC_SUBST(LIBSAMPLERATE_CFLAGS)
|
||||
AC_SUBST(LIBSAMPLERATE_LIBS)
|
||||
|
||||
#### Sound file ####
|
||||
|
||||
PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.10 ])
|
||||
|
|
@ -347,10 +395,45 @@ if test "x$os_is_win32" != "x1" ; then
|
|||
LIBS="$LIBS -latomic_ops"
|
||||
fi
|
||||
|
||||
#### Libsamplerate support (optional) ####
|
||||
|
||||
AC_ARG_ENABLE([samplerate],
|
||||
AC_HELP_STRING([--disable-samplerate], [Disable optional libsamplerate support]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) samplerate=yes ;;
|
||||
no) samplerate=no ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --disable-samplerate) ;;
|
||||
esac
|
||||
],
|
||||
[samplerate=auto])
|
||||
|
||||
if test "x${samplerate}" != xno ; then
|
||||
PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ],
|
||||
HAVE_LIBSAMPLERATE=1,
|
||||
[
|
||||
HAVE_LIBSAMPLERATE=0
|
||||
if test "x$samplerate" = xyes ; then
|
||||
AC_MSG_ERROR([*** Libsamplerate not found])
|
||||
fi
|
||||
])
|
||||
else
|
||||
HAVE_LIBSAMPLERATE=0
|
||||
fi
|
||||
|
||||
if test "x${HAVE_LIBSAMPLERATE}" = x1 ; then
|
||||
AC_DEFINE([HAVE_LIBSAMPLERATE], 1, [Have libsamplerate?])
|
||||
fi
|
||||
|
||||
AC_SUBST(LIBSAMPLERATE_CFLAGS)
|
||||
AC_SUBST(LIBSAMPLERATE_LIBS)
|
||||
AC_SUBST(HAVE_LIBSAMPLERATE)
|
||||
AM_CONDITIONAL([HAVE_LIBSAMPLERATE], [test "x$HAVE_LIBSAMPLERATE" = x1])
|
||||
|
||||
#### OSS support (optional) ####
|
||||
|
||||
AC_ARG_ENABLE([oss],
|
||||
AC_HELP_STRING([--disable-oss], [Disable optional OSS support]),
|
||||
AC_ARG_ENABLE([oss],
|
||||
AC_HELP_STRING([--disable-oss], [Disable optional OSS support]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) oss=yes ;;
|
||||
|
|
@ -382,8 +465,8 @@ AM_CONDITIONAL([HAVE_OSS], [test "x$HAVE_OSS" = x1])
|
|||
|
||||
#### ALSA support (optional) ####
|
||||
|
||||
AC_ARG_ENABLE([alsa],
|
||||
AC_HELP_STRING([--disable-alsa], [Disable optional ALSA support]),
|
||||
AC_ARG_ENABLE([alsa],
|
||||
AC_HELP_STRING([--disable-alsa], [Disable optional ALSA support]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) alsa=yes ;;
|
||||
|
|
@ -410,14 +493,14 @@ else
|
|||
fi
|
||||
|
||||
AC_SUBST(ASOUNDLIB_CFLAGS)
|
||||
AC_SUBST(ASOUNDLIB_LIBS)
|
||||
AC_SUBST(ASOUNDLIB_LIBS)
|
||||
AC_SUBST(HAVE_ALSA)
|
||||
AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1])
|
||||
|
||||
#### Solaris audio support (optional) ####
|
||||
|
||||
AC_ARG_ENABLE([solaris],
|
||||
AC_HELP_STRING([--disable-solaris], [Disable optional Solaris audio support]),
|
||||
AC_ARG_ENABLE([solaris],
|
||||
AC_HELP_STRING([--disable-solaris], [Disable optional Solaris audio support]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) solaris=yes ;;
|
||||
|
|
@ -448,8 +531,8 @@ AM_CONDITIONAL([HAVE_SOLARIS], [test "x$HAVE_SOLARIS" = x1])
|
|||
|
||||
#### GLib 2 support (optional) ####
|
||||
|
||||
AC_ARG_ENABLE([glib2],
|
||||
AC_HELP_STRING([--disable-glib2], [Disable optional GLib 2 support]),
|
||||
AC_ARG_ENABLE([glib2],
|
||||
AC_HELP_STRING([--disable-glib2], [Disable optional GLib 2 support]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) glib2=yes ;;
|
||||
|
|
@ -479,8 +562,8 @@ AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1])
|
|||
|
||||
#### GConf support (optional) ####
|
||||
|
||||
AC_ARG_ENABLE([gconf],
|
||||
AC_HELP_STRING([--disable-gconf], [Disable optional GConf support]),
|
||||
AC_ARG_ENABLE([gconf],
|
||||
AC_HELP_STRING([--disable-gconf], [Disable optional GConf support]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) gconf=yes ;;
|
||||
|
|
@ -510,8 +593,8 @@ AM_CONDITIONAL([HAVE_GCONF], [test "x$HAVE_GCONF" = x1])
|
|||
|
||||
#### Avahi support (optional) ####
|
||||
|
||||
AC_ARG_ENABLE([avahi],
|
||||
AC_HELP_STRING([--disable-avahi], [Disable optional Avahi support]),
|
||||
AC_ARG_ENABLE([avahi],
|
||||
AC_HELP_STRING([--disable-avahi], [Disable optional Avahi support]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) avahi=yes ;;
|
||||
|
|
@ -547,8 +630,8 @@ AC_SUBST(LIBOIL_LIBS)
|
|||
|
||||
### JACK (optional) ####
|
||||
|
||||
AC_ARG_ENABLE([jack],
|
||||
AC_HELP_STRING([--disable-jack], [Disable optional JACK support]),
|
||||
AC_ARG_ENABLE([jack],
|
||||
AC_HELP_STRING([--disable-jack], [Disable optional JACK support]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) jack=yes ;;
|
||||
|
|
@ -578,8 +661,8 @@ AM_CONDITIONAL([HAVE_JACK], [test "x$HAVE_JACK" = x1])
|
|||
|
||||
#### Async DNS support (optional) ####
|
||||
|
||||
AC_ARG_ENABLE([asyncns],
|
||||
AC_HELP_STRING([--disable-asyncns], [Disable optional Async DNS support]),
|
||||
AC_ARG_ENABLE([asyncns],
|
||||
AC_HELP_STRING([--disable-asyncns], [Disable optional Async DNS support]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) asyncns=yes ;;
|
||||
|
|
@ -613,8 +696,8 @@ fi
|
|||
|
||||
#### TCP wrappers (optional) ####
|
||||
|
||||
AC_ARG_ENABLE([tcpwrap],
|
||||
AC_HELP_STRING([--disable-tcpwrap], [Disable optional TCP wrappers support]),
|
||||
AC_ARG_ENABLE([tcpwrap],
|
||||
AC_HELP_STRING([--disable-tcpwrap], [Disable optional TCP wrappers support]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) tcpwrap=yes ;;
|
||||
|
|
@ -637,8 +720,8 @@ AC_SUBST(LIBWRAP_LIBS)
|
|||
|
||||
#### LIRC support (optional) ####
|
||||
|
||||
AC_ARG_ENABLE([lirc],
|
||||
AC_HELP_STRING([--disable-lirc], [Disable optional LIRC support]),
|
||||
AC_ARG_ENABLE([lirc],
|
||||
AC_HELP_STRING([--disable-lirc], [Disable optional LIRC support]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) lirc=yes ;;
|
||||
|
|
@ -663,8 +746,8 @@ AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1])
|
|||
|
||||
#### HAL support (optional) ####
|
||||
|
||||
AC_ARG_ENABLE([hal],
|
||||
AC_HELP_STRING([--disable-hal], [Disable optional HAL support]),
|
||||
AC_ARG_ENABLE([hal],
|
||||
AC_HELP_STRING([--disable-hal], [Disable optional HAL support]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) hal=yes ;;
|
||||
|
|
@ -673,7 +756,6 @@ AC_ARG_ENABLE([hal],
|
|||
esac
|
||||
],
|
||||
[hal=auto])
|
||||
|
||||
if test "x${hal}" != xno -a \( "x$HAVE_OSS" = "x1" -o "x$HAVE_ALSA" = "x1" \) ; then
|
||||
PKG_CHECK_MODULES(HAL, [ hal >= 0.5.7 ],
|
||||
HAVE_HAL=1,
|
||||
|
|
@ -692,6 +774,49 @@ AC_SUBST(HAL_LIBS)
|
|||
AC_SUBST(HAVE_HAL)
|
||||
AM_CONDITIONAL([HAVE_HAL], [test "x$HAVE_HAL" = x1])
|
||||
|
||||
#### D-Bus support (optional) ####
|
||||
|
||||
AC_ARG_ENABLE([dbus],
|
||||
AC_HELP_STRING([--disable-dbus], [Disable optional D-Bus support]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) dbus=yes ;;
|
||||
no) dbus=no ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --disable-dbus) ;;
|
||||
esac
|
||||
],
|
||||
[dbus=auto])
|
||||
|
||||
if test "x$HAVE_HAL" = x1 ; then
|
||||
dbus=yes
|
||||
fi
|
||||
|
||||
if test "x${dbus}" != xno ; then
|
||||
|
||||
PKG_CHECK_MODULES(DBUS, [ dbus-1 >= 1.0.0 ],
|
||||
[
|
||||
HAVE_DBUS=1
|
||||
saved_LIBS="$LIBS"
|
||||
LIBS="$LIBS $DBUS_LIBS"
|
||||
AC_CHECK_FUNCS(dbus_watch_get_unix_fd)
|
||||
LIBS="$saved_LIBS"
|
||||
AC_DEFINE([HAVE_DBUS], 1, [Have D-Bus.])
|
||||
],
|
||||
[
|
||||
HAVE_DBUS=0
|
||||
if test "x$dbus" = xyes ; then
|
||||
AC_MSG_ERROR([*** D-Bus support not found])
|
||||
fi
|
||||
])
|
||||
else
|
||||
HAVE_DBUS=0
|
||||
fi
|
||||
|
||||
AC_SUBST(DBUS_CFLAGS)
|
||||
AC_SUBST(DBUS_LIBS)
|
||||
AC_SUBST(HAVE_DBUS)
|
||||
AM_CONDITIONAL([HAVE_DBUS], [test "x$HAVE_DBUS" = x1])
|
||||
|
||||
#### PulseAudio system group & user #####
|
||||
|
||||
AC_ARG_WITH(system_user, AS_HELP_STRING([--with-system-user=<user>],[User for running the PulseAudio daemon as a system-wide instance (pulse)]))
|
||||
|
|
@ -845,6 +970,11 @@ if test "x${LIBWRAP_LIBS}" != x ; then
|
|||
ENABLE_TCPWRAP=yes
|
||||
fi
|
||||
|
||||
ENABLE_LIBSAMPLERATE=no
|
||||
if test "x${HAVE_LIBSAMPLERATE}" = "x1" ; then
|
||||
ENABLE_LIBSAMPLERATE=yes
|
||||
fi
|
||||
|
||||
echo "
|
||||
---{ $PACKAGE_NAME $VERSION }---
|
||||
|
||||
|
|
@ -866,6 +996,7 @@ echo "
|
|||
Enable LIRC: ${ENABLE_LIRC}
|
||||
Enable HAL: ${ENABLE_HAL}
|
||||
Enable TCP Wrappers: ${ENABLE_TCPWRAP}
|
||||
Enable libsamplerate: ${ENABLE_LIBSAMPLERATE}
|
||||
System User: ${PA_SYSTEM_USER}
|
||||
System Group: ${PA_SYSTEM_GROUP}
|
||||
Realtime Group: ${PA_REALTIME_GROUP}
|
||||
|
|
|
|||
515
libltdl/COPYING.LIB
Normal file
515
libltdl/COPYING.LIB
Normal file
|
|
@ -0,0 +1,515 @@
|
|||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations
|
||||
below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
^L
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it
|
||||
becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
^L
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control
|
||||
compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
^L
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
^L
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
^L
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
^L
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply, and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License
|
||||
may add an explicit geographical distribution limitation excluding those
|
||||
countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
^L
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
^L
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms
|
||||
of the ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library.
|
||||
It is safest to attach them to the start of each source file to most
|
||||
effectively convey the exclusion of warranty; and each file should
|
||||
have at least the "copyright" line and a pointer to where the full
|
||||
notice is found.
|
||||
|
||||
|
||||
<one line to give the library's name and a brief idea of what it
|
||||
does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper
|
||||
mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or
|
||||
your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James
|
||||
Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
32
libltdl/Makefile.am
Normal file
32
libltdl/Makefile.am
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = no-dependencies foreign
|
||||
|
||||
if INSTALL_LTDL
|
||||
include_HEADERS = ltdl.h
|
||||
lib_LTLIBRARIES = libltdl.la
|
||||
else
|
||||
noinst_HEADERS = ltdl.h
|
||||
endif
|
||||
|
||||
if CONVENIENCE_LTDL
|
||||
noinst_LTLIBRARIES = libltdlc.la
|
||||
endif
|
||||
|
||||
## Make sure these will be cleaned even when they're not built by
|
||||
## default.
|
||||
CLEANFILES = libltdl.la libltdlc.la
|
||||
|
||||
libltdl_la_SOURCES = ltdl.c
|
||||
libltdl_la_LDFLAGS = -no-undefined -version-info 4:5:1
|
||||
libltdl_la_LIBADD = $(LIBADD_DL)
|
||||
|
||||
libltdlc_la_SOURCES = ltdl.c
|
||||
libltdlc_la_LIBADD = $(LIBADD_DL)
|
||||
|
||||
## Because we do not have automatic dependency tracking:
|
||||
ltdl.lo: ltdl.h config.h
|
||||
|
||||
$(libltdl_la_OBJECTS) $(libltdlc_la_OBJECTS): libtool
|
||||
libtool: $(LIBTOOL_DEPS)
|
||||
$(SHELL) ./config.status --recheck
|
||||
656
libltdl/Makefile.in
Normal file
656
libltdl/Makefile.in
Normal file
|
|
@ -0,0 +1,656 @@
|
|||
# Makefile.in generated by automake 1.10 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = .
|
||||
DIST_COMMON = README $(am__configure_deps) $(am__include_HEADERS_DIST) \
|
||||
$(am__noinst_HEADERS_DIST) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in $(srcdir)/config-h.in \
|
||||
$(top_srcdir)/configure COPYING.LIB config.guess config.sub \
|
||||
install-sh ltmain.sh missing mkinstalldirs
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
|
||||
configure.lineno config.status.lineno
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
|
||||
libLTLIBRARIES_INSTALL = $(INSTALL)
|
||||
LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
|
||||
am__DEPENDENCIES_1 =
|
||||
libltdl_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
|
||||
am_libltdl_la_OBJECTS = ltdl.lo
|
||||
libltdl_la_OBJECTS = $(am_libltdl_la_OBJECTS)
|
||||
libltdl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(libltdl_la_LDFLAGS) $(LDFLAGS) -o $@
|
||||
@INSTALL_LTDL_TRUE@am_libltdl_la_rpath = -rpath $(libdir)
|
||||
libltdlc_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
|
||||
am_libltdlc_la_OBJECTS = ltdl.lo
|
||||
libltdlc_la_OBJECTS = $(am_libltdlc_la_OBJECTS)
|
||||
@CONVENIENCE_LTDL_TRUE@am_libltdlc_la_rpath =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@
|
||||
depcomp =
|
||||
am__depfiles_maybe =
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
||||
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
||||
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
|
||||
$(LDFLAGS) -o $@
|
||||
SOURCES = $(libltdl_la_SOURCES) $(libltdlc_la_SOURCES)
|
||||
DIST_SOURCES = $(libltdl_la_SOURCES) $(libltdlc_la_SOURCES)
|
||||
am__include_HEADERS_DIST = ltdl.h
|
||||
includeHEADERS_INSTALL = $(INSTALL_HEADER)
|
||||
am__noinst_HEADERS_DIST = ltdl.h
|
||||
HEADERS = $(include_HEADERS) $(noinst_HEADERS)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
distdir = $(PACKAGE)-$(VERSION)
|
||||
top_distdir = $(distdir)
|
||||
am__remove_distdir = \
|
||||
{ test ! -d $(distdir) \
|
||||
|| { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
|
||||
&& rm -fr $(distdir); }; }
|
||||
DIST_ARCHIVES = $(distdir).tar.gz
|
||||
GZIP_ENV = --best
|
||||
distuninstallcheck_listfiles = find . -type f -print
|
||||
distcleancheck_listfiles = find . -type f -print
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AS = @AS@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
ECHO = @ECHO@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
F77 = @F77@
|
||||
FFLAGS = @FFLAGS@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBADD_DL = @LIBADD_DL@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBTOOL_DEPS = @LIBTOOL_DEPS@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_F77 = @ac_ct_F77@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AUTOMAKE_OPTIONS = no-dependencies foreign
|
||||
@INSTALL_LTDL_TRUE@include_HEADERS = ltdl.h
|
||||
@INSTALL_LTDL_TRUE@lib_LTLIBRARIES = libltdl.la
|
||||
@INSTALL_LTDL_FALSE@noinst_HEADERS = ltdl.h
|
||||
@CONVENIENCE_LTDL_TRUE@noinst_LTLIBRARIES = libltdlc.la
|
||||
CLEANFILES = libltdl.la libltdlc.la
|
||||
libltdl_la_SOURCES = ltdl.c
|
||||
libltdl_la_LDFLAGS = -no-undefined -version-info 4:5:1
|
||||
libltdl_la_LIBADD = $(LIBADD_DL)
|
||||
libltdlc_la_SOURCES = ltdl.c
|
||||
libltdlc_la_LIBADD = $(LIBADD_DL)
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .obj
|
||||
am--refresh:
|
||||
@:
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
|
||||
cd $(srcdir) && $(AUTOMAKE) --foreign \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
echo ' $(SHELL) ./config.status'; \
|
||||
$(SHELL) ./config.status;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
$(SHELL) ./config.status --recheck
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(srcdir) && $(AUTOCONF)
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
|
||||
|
||||
config.h: stamp-h1
|
||||
@if test ! -f $@; then \
|
||||
rm -f stamp-h1; \
|
||||
$(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
|
||||
else :; fi
|
||||
|
||||
stamp-h1: $(srcdir)/config-h.in $(top_builddir)/config.status
|
||||
@rm -f stamp-h1
|
||||
cd $(top_builddir) && $(SHELL) ./config.status config.h
|
||||
$(srcdir)/config-h.in: $(am__configure_deps)
|
||||
cd $(top_srcdir) && $(AUTOHEADER)
|
||||
rm -f stamp-h1
|
||||
touch $@
|
||||
|
||||
distclean-hdr:
|
||||
-rm -f config.h stamp-h1
|
||||
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
|
||||
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
|
||||
if test -f $$p; then \
|
||||
f=$(am__strip_dir) \
|
||||
echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
|
||||
$(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
|
||||
else :; fi; \
|
||||
done
|
||||
|
||||
uninstall-libLTLIBRARIES:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
|
||||
p=$(am__strip_dir) \
|
||||
echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
|
||||
$(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
|
||||
done
|
||||
|
||||
clean-libLTLIBRARIES:
|
||||
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
|
||||
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
|
||||
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
|
||||
test "$$dir" != "$$p" || dir=.; \
|
||||
echo "rm -f \"$${dir}/so_locations\""; \
|
||||
rm -f "$${dir}/so_locations"; \
|
||||
done
|
||||
|
||||
clean-noinstLTLIBRARIES:
|
||||
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
|
||||
@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
|
||||
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
|
||||
test "$$dir" != "$$p" || dir=.; \
|
||||
echo "rm -f \"$${dir}/so_locations\""; \
|
||||
rm -f "$${dir}/so_locations"; \
|
||||
done
|
||||
libltdl.la: $(libltdl_la_OBJECTS) $(libltdl_la_DEPENDENCIES)
|
||||
$(libltdl_la_LINK) $(am_libltdl_la_rpath) $(libltdl_la_OBJECTS) $(libltdl_la_LIBADD) $(LIBS)
|
||||
libltdlc.la: $(libltdlc_la_OBJECTS) $(libltdlc_la_DEPENDENCIES)
|
||||
$(LINK) $(am_libltdlc_la_rpath) $(libltdlc_la_OBJECTS) $(libltdlc_la_LIBADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
$(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
-rm -f libtool
|
||||
install-includeHEADERS: $(include_HEADERS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
|
||||
@list='$(include_HEADERS)'; for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
f=$(am__strip_dir) \
|
||||
echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
|
||||
$(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
|
||||
done
|
||||
|
||||
uninstall-includeHEADERS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(include_HEADERS)'; for p in $$list; do \
|
||||
f=$(am__strip_dir) \
|
||||
echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(includedir)/$$f"; \
|
||||
done
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) config-h.in $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) config-h.in $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) config-h.in $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) config-h.in $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
$(am__remove_distdir)
|
||||
test -d $(distdir) || mkdir $(distdir)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
|
||||
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||
|| chmod -R a+r $(distdir)
|
||||
dist-gzip: distdir
|
||||
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-bzip2: distdir
|
||||
tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-tarZ: distdir
|
||||
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-shar: distdir
|
||||
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist-zip: distdir
|
||||
-rm -f $(distdir).zip
|
||||
zip -rq $(distdir).zip $(distdir)
|
||||
$(am__remove_distdir)
|
||||
|
||||
dist dist-all: distdir
|
||||
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
||||
$(am__remove_distdir)
|
||||
|
||||
# This target untars the dist file and tries a VPATH configuration. Then
|
||||
# it guarantees that the distribution is self-contained by making another
|
||||
# tarfile.
|
||||
distcheck: dist
|
||||
case '$(DIST_ARCHIVES)' in \
|
||||
*.tar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
|
||||
*.tar.bz2*) \
|
||||
bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||
*.tar.Z*) \
|
||||
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||
*.shar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
|
||||
*.zip*) \
|
||||
unzip $(distdir).zip ;;\
|
||||
esac
|
||||
chmod -R a-w $(distdir); chmod a+w $(distdir)
|
||||
mkdir $(distdir)/_build
|
||||
mkdir $(distdir)/_inst
|
||||
chmod a-w $(distdir)
|
||||
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
|
||||
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
|
||||
&& cd $(distdir)/_build \
|
||||
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
|
||||
$(DISTCHECK_CONFIGURE_FLAGS) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) check \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
|
||||
distuninstallcheck \
|
||||
&& chmod -R a-w "$$dc_install_base" \
|
||||
&& ({ \
|
||||
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
|
||||
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
|
||||
} || { rm -rf "$$dc_destdir"; exit 1; }) \
|
||||
&& rm -rf "$$dc_destdir" \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dist \
|
||||
&& rm -rf $(DIST_ARCHIVES) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck
|
||||
$(am__remove_distdir)
|
||||
@(echo "$(distdir) archives ready for distribution: "; \
|
||||
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
|
||||
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
|
||||
distuninstallcheck:
|
||||
@cd $(distuninstallcheck_dir) \
|
||||
&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
|
||||
|| { echo "ERROR: files left after uninstall:" ; \
|
||||
if test -n "$(DESTDIR)"; then \
|
||||
echo " (check DESTDIR support)"; \
|
||||
fi ; \
|
||||
$(distuninstallcheck_listfiles) ; \
|
||||
exit 1; } >&2
|
||||
distcleancheck: distclean
|
||||
@if test '$(srcdir)' = . ; then \
|
||||
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|
||||
|| { echo "ERROR: files left in build directory after distclean:" ; \
|
||||
$(distcleancheck_listfiles) ; \
|
||||
exit 1; } >&2
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LTLIBRARIES) $(HEADERS) config.h
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
|
||||
clean-noinstLTLIBRARIES mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-hdr distclean-libtool distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-includeHEADERS
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-exec-am: install-libLTLIBRARIES
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -rf $(top_srcdir)/autom4te.cache
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
|
||||
clean-generic clean-libLTLIBRARIES clean-libtool \
|
||||
clean-noinstLTLIBRARIES ctags dist dist-all dist-bzip2 \
|
||||
dist-gzip dist-shar dist-tarZ dist-zip distcheck distclean \
|
||||
distclean-compile distclean-generic distclean-hdr \
|
||||
distclean-libtool distclean-tags distcleancheck distdir \
|
||||
distuninstallcheck dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-includeHEADERS install-info \
|
||||
install-info-am install-libLTLIBRARIES install-man install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
tags uninstall uninstall-am uninstall-includeHEADERS \
|
||||
uninstall-libLTLIBRARIES
|
||||
|
||||
|
||||
ltdl.lo: ltdl.h config.h
|
||||
|
||||
$(libltdl_la_OBJECTS) $(libltdlc_la_OBJECTS): libtool
|
||||
libtool: $(LIBTOOL_DEPS)
|
||||
$(SHELL) ./config.status --recheck
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
10
libltdl/README
Normal file
10
libltdl/README
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
This is GNU libltdl, a system independent dlopen wrapper for GNU libtool.
|
||||
|
||||
It supports the following dlopen interfaces:
|
||||
* dlopen (Solaris, Linux and various BSD flavors)
|
||||
* shl_load (HP-UX)
|
||||
* LoadLibrary (Win16 and Win32)
|
||||
* load_add_on (BeOS)
|
||||
* GNU DLD (emulates dynamic linking for static libraries)
|
||||
* dyld (darwin/Mac OS X)
|
||||
* libtool's dlpreopen
|
||||
7025
libltdl/acinclude.m4
Normal file
7025
libltdl/acinclude.m4
Normal file
File diff suppressed because it is too large
Load diff
875
libltdl/aclocal.m4
vendored
Normal file
875
libltdl/aclocal.m4
vendored
Normal file
|
|
@ -0,0 +1,875 @@
|
|||
# generated automatically by aclocal 1.10 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005, 2006 Free Software Foundation, Inc.
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
m4_if(m4_PACKAGE_VERSION, [2.61],,
|
||||
[m4_fatal([this file was generated for autoconf 2.61.
|
||||
You have another version of autoconf. If you want to use that,
|
||||
you should regenerate the build system entirely.], [63])])
|
||||
|
||||
# Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_AUTOMAKE_VERSION(VERSION)
|
||||
# ----------------------------
|
||||
# Automake X.Y traces this macro to ensure aclocal.m4 has been
|
||||
# generated from the m4 files accompanying Automake X.Y.
|
||||
# (This private macro should not be called outside this file.)
|
||||
AC_DEFUN([AM_AUTOMAKE_VERSION],
|
||||
[am__api_version='1.10'
|
||||
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
|
||||
dnl require some minimum version. Point them to the right macro.
|
||||
m4_if([$1], [1.10], [],
|
||||
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
|
||||
])
|
||||
|
||||
# _AM_AUTOCONF_VERSION(VERSION)
|
||||
# -----------------------------
|
||||
# aclocal traces this macro to find the Autoconf version.
|
||||
# This is a private macro too. Using m4_define simplifies
|
||||
# the logic in aclocal, which can simply ignore this definition.
|
||||
m4_define([_AM_AUTOCONF_VERSION], [])
|
||||
|
||||
# AM_SET_CURRENT_AUTOMAKE_VERSION
|
||||
# -------------------------------
|
||||
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
|
||||
# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
|
||||
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
|
||||
[AM_AUTOMAKE_VERSION([1.10])dnl
|
||||
_AM_AUTOCONF_VERSION(m4_PACKAGE_VERSION)])
|
||||
|
||||
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
|
||||
# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
|
||||
# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
|
||||
#
|
||||
# Of course, Automake must honor this variable whenever it calls a
|
||||
# tool from the auxiliary directory. The problem is that $srcdir (and
|
||||
# therefore $ac_aux_dir as well) can be either absolute or relative,
|
||||
# depending on how configure is run. This is pretty annoying, since
|
||||
# it makes $ac_aux_dir quite unusable in subdirectories: in the top
|
||||
# source directory, any form will work fine, but in subdirectories a
|
||||
# relative path needs to be adjusted first.
|
||||
#
|
||||
# $ac_aux_dir/missing
|
||||
# fails when called from a subdirectory if $ac_aux_dir is relative
|
||||
# $top_srcdir/$ac_aux_dir/missing
|
||||
# fails if $ac_aux_dir is absolute,
|
||||
# fails when called from a subdirectory in a VPATH build with
|
||||
# a relative $ac_aux_dir
|
||||
#
|
||||
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
|
||||
# are both prefixed by $srcdir. In an in-source build this is usually
|
||||
# harmless because $srcdir is `.', but things will broke when you
|
||||
# start a VPATH build or use an absolute $srcdir.
|
||||
#
|
||||
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
|
||||
# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
|
||||
# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
|
||||
# and then we would define $MISSING as
|
||||
# MISSING="\${SHELL} $am_aux_dir/missing"
|
||||
# This will work as long as MISSING is not called from configure, because
|
||||
# unfortunately $(top_srcdir) has no meaning in configure.
|
||||
# However there are other variables, like CC, which are often used in
|
||||
# configure, and could therefore not use this "fixed" $ac_aux_dir.
|
||||
#
|
||||
# Another solution, used here, is to always expand $ac_aux_dir to an
|
||||
# absolute PATH. The drawback is that using absolute paths prevent a
|
||||
# configured tree to be moved without reconfiguration.
|
||||
|
||||
AC_DEFUN([AM_AUX_DIR_EXPAND],
|
||||
[dnl Rely on autoconf to set up CDPATH properly.
|
||||
AC_PREREQ([2.50])dnl
|
||||
# expand $ac_aux_dir to an absolute path
|
||||
am_aux_dir=`cd $ac_aux_dir && pwd`
|
||||
])
|
||||
|
||||
# AM_CONDITIONAL -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 8
|
||||
|
||||
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
|
||||
# -------------------------------------
|
||||
# Define a conditional.
|
||||
AC_DEFUN([AM_CONDITIONAL],
|
||||
[AC_PREREQ(2.52)dnl
|
||||
ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
|
||||
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
|
||||
AC_SUBST([$1_TRUE])dnl
|
||||
AC_SUBST([$1_FALSE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
|
||||
if $2; then
|
||||
$1_TRUE=
|
||||
$1_FALSE='#'
|
||||
else
|
||||
$1_TRUE='#'
|
||||
$1_FALSE=
|
||||
fi
|
||||
AC_CONFIG_COMMANDS_PRE(
|
||||
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
|
||||
AC_MSG_ERROR([[conditional "$1" was never defined.
|
||||
Usually this means the macro was only invoked conditionally.]])
|
||||
fi])])
|
||||
|
||||
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 9
|
||||
|
||||
# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
|
||||
# written in clear, in which case automake, when reading aclocal.m4,
|
||||
# will think it sees a *use*, and therefore will trigger all it's
|
||||
# C support machinery. Also note that it means that autoscan, seeing
|
||||
# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
|
||||
|
||||
|
||||
# _AM_DEPENDENCIES(NAME)
|
||||
# ----------------------
|
||||
# See how the compiler implements dependency checking.
|
||||
# NAME is "CC", "CXX", "GCJ", or "OBJC".
|
||||
# We try a few techniques and use that to set a single cache variable.
|
||||
#
|
||||
# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
|
||||
# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
|
||||
# dependency, and given that the user is not expected to run this macro,
|
||||
# just rely on AC_PROG_CC.
|
||||
AC_DEFUN([_AM_DEPENDENCIES],
|
||||
[AC_REQUIRE([AM_SET_DEPDIR])dnl
|
||||
AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
|
||||
AC_REQUIRE([AM_MAKE_INCLUDE])dnl
|
||||
AC_REQUIRE([AM_DEP_TRACK])dnl
|
||||
|
||||
ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
|
||||
[$1], CXX, [depcc="$CXX" am_compiler_list=],
|
||||
[$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
|
||||
[$1], UPC, [depcc="$UPC" am_compiler_list=],
|
||||
[$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
|
||||
[depcc="$$1" am_compiler_list=])
|
||||
|
||||
AC_CACHE_CHECK([dependency style of $depcc],
|
||||
[am_cv_$1_dependencies_compiler_type],
|
||||
[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
|
||||
# We make a subdir and do the tests there. Otherwise we can end up
|
||||
# making bogus files that we don't know about and never remove. For
|
||||
# instance it was reported that on HP-UX the gcc test will end up
|
||||
# making a dummy file named `D' -- because `-MD' means `put the output
|
||||
# in D'.
|
||||
mkdir conftest.dir
|
||||
# Copy depcomp to subdir because otherwise we won't find it if we're
|
||||
# using a relative directory.
|
||||
cp "$am_depcomp" conftest.dir
|
||||
cd conftest.dir
|
||||
# We will build objects and dependencies in a subdirectory because
|
||||
# it helps to detect inapplicable dependency modes. For instance
|
||||
# both Tru64's cc and ICC support -MD to output dependencies as a
|
||||
# side effect of compilation, but ICC will put the dependencies in
|
||||
# the current directory while Tru64 will put them in the object
|
||||
# directory.
|
||||
mkdir sub
|
||||
|
||||
am_cv_$1_dependencies_compiler_type=none
|
||||
if test "$am_compiler_list" = ""; then
|
||||
am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
|
||||
fi
|
||||
for depmode in $am_compiler_list; do
|
||||
# Setup a source with many dependencies, because some compilers
|
||||
# like to wrap large dependency lists on column 80 (with \), and
|
||||
# we should not choose a depcomp mode which is confused by this.
|
||||
#
|
||||
# We need to recreate these files for each test, as the compiler may
|
||||
# overwrite some of them when testing with obscure command lines.
|
||||
# This happens at least with the AIX C compiler.
|
||||
: > sub/conftest.c
|
||||
for i in 1 2 3 4 5 6; do
|
||||
echo '#include "conftst'$i'.h"' >> sub/conftest.c
|
||||
# Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
|
||||
# Solaris 8's {/usr,}/bin/sh.
|
||||
touch sub/conftst$i.h
|
||||
done
|
||||
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
|
||||
|
||||
case $depmode in
|
||||
nosideeffect)
|
||||
# after this tag, mechanisms are not by side-effect, so they'll
|
||||
# only be used when explicitly requested
|
||||
if test "x$enable_dependency_tracking" = xyes; then
|
||||
continue
|
||||
else
|
||||
break
|
||||
fi
|
||||
;;
|
||||
none) break ;;
|
||||
esac
|
||||
# We check with `-c' and `-o' for the sake of the "dashmstdout"
|
||||
# mode. It turns out that the SunPro C++ compiler does not properly
|
||||
# handle `-M -o', and we need to detect this.
|
||||
if depmode=$depmode \
|
||||
source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
|
||||
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
|
||||
$SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
|
||||
>/dev/null 2>conftest.err &&
|
||||
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
|
||||
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
|
||||
grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
|
||||
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
|
||||
# icc doesn't choke on unknown options, it will just issue warnings
|
||||
# or remarks (even with -Werror). So we grep stderr for any message
|
||||
# that says an option was ignored or not supported.
|
||||
# When given -MP, icc 7.0 and 7.1 complain thusly:
|
||||
# icc: Command line warning: ignoring option '-M'; no argument required
|
||||
# The diagnosis changed in icc 8.0:
|
||||
# icc: Command line remark: option '-MP' not supported
|
||||
if (grep 'ignoring option' conftest.err ||
|
||||
grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
|
||||
am_cv_$1_dependencies_compiler_type=$depmode
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
cd ..
|
||||
rm -rf conftest.dir
|
||||
else
|
||||
am_cv_$1_dependencies_compiler_type=none
|
||||
fi
|
||||
])
|
||||
AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
|
||||
AM_CONDITIONAL([am__fastdep$1], [
|
||||
test "x$enable_dependency_tracking" != xno \
|
||||
&& test "$am_cv_$1_dependencies_compiler_type" = gcc3])
|
||||
])
|
||||
|
||||
|
||||
# AM_SET_DEPDIR
|
||||
# -------------
|
||||
# Choose a directory name for dependency files.
|
||||
# This macro is AC_REQUIREd in _AM_DEPENDENCIES
|
||||
AC_DEFUN([AM_SET_DEPDIR],
|
||||
[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
|
||||
AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
|
||||
])
|
||||
|
||||
|
||||
# AM_DEP_TRACK
|
||||
# ------------
|
||||
AC_DEFUN([AM_DEP_TRACK],
|
||||
[AC_ARG_ENABLE(dependency-tracking,
|
||||
[ --disable-dependency-tracking speeds up one-time build
|
||||
--enable-dependency-tracking do not reject slow dependency extractors])
|
||||
if test "x$enable_dependency_tracking" != xno; then
|
||||
am_depcomp="$ac_aux_dir/depcomp"
|
||||
AMDEPBACKSLASH='\'
|
||||
fi
|
||||
AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
|
||||
AC_SUBST([AMDEPBACKSLASH])dnl
|
||||
_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
|
||||
])
|
||||
|
||||
# Generate code to set up dependency tracking. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
#serial 3
|
||||
|
||||
# _AM_OUTPUT_DEPENDENCY_COMMANDS
|
||||
# ------------------------------
|
||||
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
|
||||
[for mf in $CONFIG_FILES; do
|
||||
# Strip MF so we end up with the name of the file.
|
||||
mf=`echo "$mf" | sed -e 's/:.*$//'`
|
||||
# Check whether this is an Automake generated Makefile or not.
|
||||
# We used to match only the files named `Makefile.in', but
|
||||
# some people rename them; so instead we look at the file content.
|
||||
# Grep'ing the first line is not enough: some people post-process
|
||||
# each Makefile.in and add a new line on top of each file to say so.
|
||||
# Grep'ing the whole file is not good either: AIX grep has a line
|
||||
# limit of 2048, but all sed's we know have understand at least 4000.
|
||||
if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then
|
||||
dirpart=`AS_DIRNAME("$mf")`
|
||||
else
|
||||
continue
|
||||
fi
|
||||
# Extract the definition of DEPDIR, am__include, and am__quote
|
||||
# from the Makefile without running `make'.
|
||||
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
|
||||
test -z "$DEPDIR" && continue
|
||||
am__include=`sed -n 's/^am__include = //p' < "$mf"`
|
||||
test -z "am__include" && continue
|
||||
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
|
||||
# When using ansi2knr, U may be empty or an underscore; expand it
|
||||
U=`sed -n 's/^U = //p' < "$mf"`
|
||||
# Find all dependency output files, they are included files with
|
||||
# $(DEPDIR) in their names. We invoke sed twice because it is the
|
||||
# simplest approach to changing $(DEPDIR) to its actual value in the
|
||||
# expansion.
|
||||
for file in `sed -n "
|
||||
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
|
||||
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
|
||||
# Make sure the directory exists.
|
||||
test -f "$dirpart/$file" && continue
|
||||
fdir=`AS_DIRNAME(["$file"])`
|
||||
AS_MKDIR_P([$dirpart/$fdir])
|
||||
# echo "creating $dirpart/$file"
|
||||
echo '# dummy' > "$dirpart/$file"
|
||||
done
|
||||
done
|
||||
])# _AM_OUTPUT_DEPENDENCY_COMMANDS
|
||||
|
||||
|
||||
# AM_OUTPUT_DEPENDENCY_COMMANDS
|
||||
# -----------------------------
|
||||
# This macro should only be invoked once -- use via AC_REQUIRE.
|
||||
#
|
||||
# This code is only required when automatic dependency tracking
|
||||
# is enabled. FIXME. This creates each `.P' file that we will
|
||||
# need in order to bootstrap the dependency handling code.
|
||||
AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
|
||||
[AC_CONFIG_COMMANDS([depfiles],
|
||||
[test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
|
||||
[AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
|
||||
])
|
||||
|
||||
# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 8
|
||||
|
||||
# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS.
|
||||
AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
|
||||
|
||||
# Do all the work for Automake. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005, 2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 12
|
||||
|
||||
# This macro actually does too much. Some checks are only needed if
|
||||
# your package does certain things. But this isn't really a big deal.
|
||||
|
||||
# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
|
||||
# AM_INIT_AUTOMAKE([OPTIONS])
|
||||
# -----------------------------------------------
|
||||
# The call with PACKAGE and VERSION arguments is the old style
|
||||
# call (pre autoconf-2.50), which is being phased out. PACKAGE
|
||||
# and VERSION should now be passed to AC_INIT and removed from
|
||||
# the call to AM_INIT_AUTOMAKE.
|
||||
# We support both call styles for the transition. After
|
||||
# the next Automake release, Autoconf can make the AC_INIT
|
||||
# arguments mandatory, and then we can depend on a new Autoconf
|
||||
# release and drop the old call support.
|
||||
AC_DEFUN([AM_INIT_AUTOMAKE],
|
||||
[AC_PREREQ([2.60])dnl
|
||||
dnl Autoconf wants to disallow AM_ names. We explicitly allow
|
||||
dnl the ones we care about.
|
||||
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
|
||||
AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
|
||||
AC_REQUIRE([AC_PROG_INSTALL])dnl
|
||||
if test "`cd $srcdir && pwd`" != "`pwd`"; then
|
||||
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
|
||||
# is not polluted with repeated "-I."
|
||||
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
|
||||
# test to see if srcdir already configured
|
||||
if test -f $srcdir/config.status; then
|
||||
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
|
||||
fi
|
||||
fi
|
||||
|
||||
# test whether we have cygpath
|
||||
if test -z "$CYGPATH_W"; then
|
||||
if (cygpath --version) >/dev/null 2>/dev/null; then
|
||||
CYGPATH_W='cygpath -w'
|
||||
else
|
||||
CYGPATH_W=echo
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([CYGPATH_W])
|
||||
|
||||
# Define the identity of the package.
|
||||
dnl Distinguish between old-style and new-style calls.
|
||||
m4_ifval([$2],
|
||||
[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
|
||||
AC_SUBST([PACKAGE], [$1])dnl
|
||||
AC_SUBST([VERSION], [$2])],
|
||||
[_AM_SET_OPTIONS([$1])dnl
|
||||
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
|
||||
m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
|
||||
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
|
||||
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
|
||||
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
|
||||
|
||||
_AM_IF_OPTION([no-define],,
|
||||
[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
|
||||
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
|
||||
|
||||
# Some tools Automake needs.
|
||||
AC_REQUIRE([AM_SANITY_CHECK])dnl
|
||||
AC_REQUIRE([AC_ARG_PROGRAM])dnl
|
||||
AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
|
||||
AM_MISSING_PROG(AUTOCONF, autoconf)
|
||||
AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
|
||||
AM_MISSING_PROG(AUTOHEADER, autoheader)
|
||||
AM_MISSING_PROG(MAKEINFO, makeinfo)
|
||||
AM_PROG_INSTALL_SH
|
||||
AM_PROG_INSTALL_STRIP
|
||||
AC_REQUIRE([AM_PROG_MKDIR_P])dnl
|
||||
# We need awk for the "check" target. The system "awk" is bad on
|
||||
# some platforms.
|
||||
AC_REQUIRE([AC_PROG_AWK])dnl
|
||||
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
|
||||
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
|
||||
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
|
||||
[_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
|
||||
[_AM_PROG_TAR([v7])])])
|
||||
_AM_IF_OPTION([no-dependencies],,
|
||||
[AC_PROVIDE_IFELSE([AC_PROG_CC],
|
||||
[_AM_DEPENDENCIES(CC)],
|
||||
[define([AC_PROG_CC],
|
||||
defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
|
||||
AC_PROVIDE_IFELSE([AC_PROG_CXX],
|
||||
[_AM_DEPENDENCIES(CXX)],
|
||||
[define([AC_PROG_CXX],
|
||||
defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
|
||||
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
|
||||
[_AM_DEPENDENCIES(OBJC)],
|
||||
[define([AC_PROG_OBJC],
|
||||
defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
|
||||
])
|
||||
])
|
||||
|
||||
|
||||
# When config.status generates a header, we must update the stamp-h file.
|
||||
# This file resides in the same directory as the config header
|
||||
# that is generated. The stamp files are numbered to have different names.
|
||||
|
||||
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
|
||||
# loop where config.status creates the headers, so we can generate
|
||||
# our stamp files there.
|
||||
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
|
||||
[# Compute $1's index in $config_headers.
|
||||
_am_stamp_count=1
|
||||
for _am_header in $config_headers :; do
|
||||
case $_am_header in
|
||||
$1 | $1:* )
|
||||
break ;;
|
||||
* )
|
||||
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
|
||||
esac
|
||||
done
|
||||
echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
|
||||
|
||||
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_PROG_INSTALL_SH
|
||||
# ------------------
|
||||
# Define $install_sh.
|
||||
AC_DEFUN([AM_PROG_INSTALL_SH],
|
||||
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
||||
install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
|
||||
AC_SUBST(install_sh)])
|
||||
|
||||
# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 2
|
||||
|
||||
# Check whether the underlying file-system supports filenames
|
||||
# with a leading dot. For instance MS-DOS doesn't.
|
||||
AC_DEFUN([AM_SET_LEADING_DOT],
|
||||
[rm -rf .tst 2>/dev/null
|
||||
mkdir .tst 2>/dev/null
|
||||
if test -d .tst; then
|
||||
am__leading_dot=.
|
||||
else
|
||||
am__leading_dot=_
|
||||
fi
|
||||
rmdir .tst 2>/dev/null
|
||||
AC_SUBST([am__leading_dot])])
|
||||
|
||||
# Check to see how 'make' treats includes. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 3
|
||||
|
||||
# AM_MAKE_INCLUDE()
|
||||
# -----------------
|
||||
# Check to see how make treats includes.
|
||||
AC_DEFUN([AM_MAKE_INCLUDE],
|
||||
[am_make=${MAKE-make}
|
||||
cat > confinc << 'END'
|
||||
am__doit:
|
||||
@echo done
|
||||
.PHONY: am__doit
|
||||
END
|
||||
# If we don't find an include directive, just comment out the code.
|
||||
AC_MSG_CHECKING([for style of include used by $am_make])
|
||||
am__include="#"
|
||||
am__quote=
|
||||
_am_result=none
|
||||
# First try GNU make style include.
|
||||
echo "include confinc" > confmf
|
||||
# We grep out `Entering directory' and `Leaving directory'
|
||||
# messages which can occur if `w' ends up in MAKEFLAGS.
|
||||
# In particular we don't look at `^make:' because GNU make might
|
||||
# be invoked under some other name (usually "gmake"), in which
|
||||
# case it prints its new name instead of `make'.
|
||||
if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
|
||||
am__include=include
|
||||
am__quote=
|
||||
_am_result=GNU
|
||||
fi
|
||||
# Now try BSD make style include.
|
||||
if test "$am__include" = "#"; then
|
||||
echo '.include "confinc"' > confmf
|
||||
if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
|
||||
am__include=.include
|
||||
am__quote="\""
|
||||
_am_result=BSD
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([am__include])
|
||||
AC_SUBST([am__quote])
|
||||
AC_MSG_RESULT([$_am_result])
|
||||
rm -f confinc confmf
|
||||
])
|
||||
|
||||
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 5
|
||||
|
||||
# AM_MISSING_PROG(NAME, PROGRAM)
|
||||
# ------------------------------
|
||||
AC_DEFUN([AM_MISSING_PROG],
|
||||
[AC_REQUIRE([AM_MISSING_HAS_RUN])
|
||||
$1=${$1-"${am_missing_run}$2"}
|
||||
AC_SUBST($1)])
|
||||
|
||||
|
||||
# AM_MISSING_HAS_RUN
|
||||
# ------------------
|
||||
# Define MISSING if not defined so far and test if it supports --run.
|
||||
# If it does, set am_missing_run to use it, otherwise, to nothing.
|
||||
AC_DEFUN([AM_MISSING_HAS_RUN],
|
||||
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
||||
AC_REQUIRE_AUX_FILE([missing])dnl
|
||||
test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
|
||||
# Use eval to expand $SHELL
|
||||
if eval "$MISSING --run true"; then
|
||||
am_missing_run="$MISSING --run "
|
||||
else
|
||||
am_missing_run=
|
||||
AC_MSG_WARN([`missing' script is too old or missing])
|
||||
fi
|
||||
])
|
||||
|
||||
# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_PROG_MKDIR_P
|
||||
# ---------------
|
||||
# Check for `mkdir -p'.
|
||||
AC_DEFUN([AM_PROG_MKDIR_P],
|
||||
[AC_PREREQ([2.60])dnl
|
||||
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
|
||||
dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
|
||||
dnl while keeping a definition of mkdir_p for backward compatibility.
|
||||
dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
|
||||
dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
|
||||
dnl Makefile.ins that do not define MKDIR_P, so we do our own
|
||||
dnl adjustment using top_builddir (which is defined more often than
|
||||
dnl MKDIR_P).
|
||||
AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
|
||||
case $mkdir_p in
|
||||
[[\\/$]]* | ?:[[\\/]]*) ;;
|
||||
*/*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
|
||||
esac
|
||||
])
|
||||
|
||||
# Helper functions for option handling. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 3
|
||||
|
||||
# _AM_MANGLE_OPTION(NAME)
|
||||
# -----------------------
|
||||
AC_DEFUN([_AM_MANGLE_OPTION],
|
||||
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
|
||||
|
||||
# _AM_SET_OPTION(NAME)
|
||||
# ------------------------------
|
||||
# Set option NAME. Presently that only means defining a flag for this option.
|
||||
AC_DEFUN([_AM_SET_OPTION],
|
||||
[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
|
||||
|
||||
# _AM_SET_OPTIONS(OPTIONS)
|
||||
# ----------------------------------
|
||||
# OPTIONS is a space-separated list of Automake options.
|
||||
AC_DEFUN([_AM_SET_OPTIONS],
|
||||
[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
|
||||
|
||||
# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
|
||||
# -------------------------------------------
|
||||
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
|
||||
AC_DEFUN([_AM_IF_OPTION],
|
||||
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
|
||||
|
||||
# Check to make sure that the build environment is sane. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 4
|
||||
|
||||
# AM_SANITY_CHECK
|
||||
# ---------------
|
||||
AC_DEFUN([AM_SANITY_CHECK],
|
||||
[AC_MSG_CHECKING([whether build environment is sane])
|
||||
# Just in case
|
||||
sleep 1
|
||||
echo timestamp > conftest.file
|
||||
# Do `set' in a subshell so we don't clobber the current shell's
|
||||
# arguments. Must try -L first in case configure is actually a
|
||||
# symlink; some systems play weird games with the mod time of symlinks
|
||||
# (eg FreeBSD returns the mod time of the symlink's containing
|
||||
# directory).
|
||||
if (
|
||||
set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
|
||||
if test "$[*]" = "X"; then
|
||||
# -L didn't work.
|
||||
set X `ls -t $srcdir/configure conftest.file`
|
||||
fi
|
||||
rm -f conftest.file
|
||||
if test "$[*]" != "X $srcdir/configure conftest.file" \
|
||||
&& test "$[*]" != "X conftest.file $srcdir/configure"; then
|
||||
|
||||
# If neither matched, then we have a broken ls. This can happen
|
||||
# if, for instance, CONFIG_SHELL is bash and it inherits a
|
||||
# broken ls alias from the environment. This has actually
|
||||
# happened. Such a system could not be considered "sane".
|
||||
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
|
||||
alias in your environment])
|
||||
fi
|
||||
|
||||
test "$[2]" = conftest.file
|
||||
)
|
||||
then
|
||||
# Ok.
|
||||
:
|
||||
else
|
||||
AC_MSG_ERROR([newly created file is older than distributed files!
|
||||
Check your system clock])
|
||||
fi
|
||||
AC_MSG_RESULT(yes)])
|
||||
|
||||
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_PROG_INSTALL_STRIP
|
||||
# ---------------------
|
||||
# One issue with vendor `install' (even GNU) is that you can't
|
||||
# specify the program used to strip binaries. This is especially
|
||||
# annoying in cross-compiling environments, where the build's strip
|
||||
# is unlikely to handle the host's binaries.
|
||||
# Fortunately install-sh will honor a STRIPPROG variable, so we
|
||||
# always use install-sh in `make install-strip', and initialize
|
||||
# STRIPPROG with the value of the STRIP variable (set by the user).
|
||||
AC_DEFUN([AM_PROG_INSTALL_STRIP],
|
||||
[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
|
||||
# Installed binaries are usually stripped using `strip' when the user
|
||||
# run `make install-strip'. However `strip' might not be the right
|
||||
# tool to use in cross-compilation environments, therefore Automake
|
||||
# will honor the `STRIP' environment variable to overrule this program.
|
||||
dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
|
||||
if test "$cross_compiling" != no; then
|
||||
AC_CHECK_TOOL([STRIP], [strip], :)
|
||||
fi
|
||||
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
|
||||
AC_SUBST([INSTALL_STRIP_PROGRAM])])
|
||||
|
||||
# Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# _AM_SUBST_NOTMAKE(VARIABLE)
|
||||
# ---------------------------
|
||||
# Prevent Automake from outputing VARIABLE = @VARIABLE@ in Makefile.in.
|
||||
# This macro is traced by Automake.
|
||||
AC_DEFUN([_AM_SUBST_NOTMAKE])
|
||||
|
||||
# Check how to create a tarball. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 2
|
||||
|
||||
# _AM_PROG_TAR(FORMAT)
|
||||
# --------------------
|
||||
# Check how to create a tarball in format FORMAT.
|
||||
# FORMAT should be one of `v7', `ustar', or `pax'.
|
||||
#
|
||||
# Substitute a variable $(am__tar) that is a command
|
||||
# writing to stdout a FORMAT-tarball containing the directory
|
||||
# $tardir.
|
||||
# tardir=directory && $(am__tar) > result.tar
|
||||
#
|
||||
# Substitute a variable $(am__untar) that extract such
|
||||
# a tarball read from stdin.
|
||||
# $(am__untar) < result.tar
|
||||
AC_DEFUN([_AM_PROG_TAR],
|
||||
[# Always define AMTAR for backward compatibility.
|
||||
AM_MISSING_PROG([AMTAR], [tar])
|
||||
m4_if([$1], [v7],
|
||||
[am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
|
||||
[m4_case([$1], [ustar],, [pax],,
|
||||
[m4_fatal([Unknown tar format])])
|
||||
AC_MSG_CHECKING([how to create a $1 tar archive])
|
||||
# Loop over all known methods to create a tar archive until one works.
|
||||
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
|
||||
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
|
||||
# Do not fold the above two line into one, because Tru64 sh and
|
||||
# Solaris sh will not grok spaces in the rhs of `-'.
|
||||
for _am_tool in $_am_tools
|
||||
do
|
||||
case $_am_tool in
|
||||
gnutar)
|
||||
for _am_tar in tar gnutar gtar;
|
||||
do
|
||||
AM_RUN_LOG([$_am_tar --version]) && break
|
||||
done
|
||||
am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
|
||||
am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
|
||||
am__untar="$_am_tar -xf -"
|
||||
;;
|
||||
plaintar)
|
||||
# Must skip GNU tar: if it does not support --format= it doesn't create
|
||||
# ustar tarball either.
|
||||
(tar --version) >/dev/null 2>&1 && continue
|
||||
am__tar='tar chf - "$$tardir"'
|
||||
am__tar_='tar chf - "$tardir"'
|
||||
am__untar='tar xf -'
|
||||
;;
|
||||
pax)
|
||||
am__tar='pax -L -x $1 -w "$$tardir"'
|
||||
am__tar_='pax -L -x $1 -w "$tardir"'
|
||||
am__untar='pax -r'
|
||||
;;
|
||||
cpio)
|
||||
am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
|
||||
am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
|
||||
am__untar='cpio -i -H $1 -d'
|
||||
;;
|
||||
none)
|
||||
am__tar=false
|
||||
am__tar_=false
|
||||
am__untar=false
|
||||
;;
|
||||
esac
|
||||
|
||||
# If the value was cached, stop now. We just wanted to have am__tar
|
||||
# and am__untar set.
|
||||
test -n "${am_cv_prog_tar_$1}" && break
|
||||
|
||||
# tar/untar a dummy directory, and stop if the command works
|
||||
rm -rf conftest.dir
|
||||
mkdir conftest.dir
|
||||
echo GrepMe > conftest.dir/file
|
||||
AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
|
||||
rm -rf conftest.dir
|
||||
if test -s conftest.tar; then
|
||||
AM_RUN_LOG([$am__untar <conftest.tar])
|
||||
grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
|
||||
fi
|
||||
done
|
||||
rm -rf conftest.dir
|
||||
|
||||
AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
|
||||
AC_MSG_RESULT([$am_cv_prog_tar_$1])])
|
||||
AC_SUBST([am__tar])
|
||||
AC_SUBST([am__untar])
|
||||
]) # _AM_PROG_TAR
|
||||
|
||||
m4_include([acinclude.m4])
|
||||
195
libltdl/config-h.in
Normal file
195
libltdl/config-h.in
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
/* config-h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the `argz_append' function. */
|
||||
#undef HAVE_ARGZ_APPEND
|
||||
|
||||
/* Define to 1 if you have the `argz_create_sep' function. */
|
||||
#undef HAVE_ARGZ_CREATE_SEP
|
||||
|
||||
/* Define to 1 if you have the <argz.h> header file. */
|
||||
#undef HAVE_ARGZ_H
|
||||
|
||||
/* Define to 1 if you have the `argz_insert' function. */
|
||||
#undef HAVE_ARGZ_INSERT
|
||||
|
||||
/* Define to 1 if you have the `argz_next' function. */
|
||||
#undef HAVE_ARGZ_NEXT
|
||||
|
||||
/* Define to 1 if you have the `argz_stringify' function. */
|
||||
#undef HAVE_ARGZ_STRINGIFY
|
||||
|
||||
/* Define to 1 if you have the <assert.h> header file. */
|
||||
#undef HAVE_ASSERT_H
|
||||
|
||||
/* Define to 1 if you have the `bcopy' function. */
|
||||
#undef HAVE_BCOPY
|
||||
|
||||
/* Define to 1 if you have the `closedir' function. */
|
||||
#undef HAVE_CLOSEDIR
|
||||
|
||||
/* Define to 1 if you have the <ctype.h> header file. */
|
||||
#undef HAVE_CTYPE_H
|
||||
|
||||
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
#undef HAVE_DIRENT_H
|
||||
|
||||
/* Define if you have the GNU dld library. */
|
||||
#undef HAVE_DLD
|
||||
|
||||
/* Define to 1 if you have the <dld.h> header file. */
|
||||
#undef HAVE_DLD_H
|
||||
|
||||
/* Define to 1 if you have the `dlerror' function. */
|
||||
#undef HAVE_DLERROR
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the <dl.h> header file. */
|
||||
#undef HAVE_DL_H
|
||||
|
||||
/* Define if you have the _dyld_func_lookup function. */
|
||||
#undef HAVE_DYLD
|
||||
|
||||
/* Define to 1 if you have the <errno.h> header file. */
|
||||
#undef HAVE_ERRNO_H
|
||||
|
||||
/* Define to 1 if the system has the type `error_t'. */
|
||||
#undef HAVE_ERROR_T
|
||||
|
||||
/* Define to 1 if you have the `index' function. */
|
||||
#undef HAVE_INDEX
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define if you have the libdl library or equivalent. */
|
||||
#undef HAVE_LIBDL
|
||||
|
||||
/* Define to 1 if you have the <mach-o/dyld.h> header file. */
|
||||
#undef HAVE_MACH_O_DYLD_H
|
||||
|
||||
/* Define to 1 if you have the <malloc.h> header file. */
|
||||
#undef HAVE_MALLOC_H
|
||||
|
||||
/* Define to 1 if you have the `memcpy' function. */
|
||||
#undef HAVE_MEMCPY
|
||||
|
||||
/* Define to 1 if you have the `memmove' function. */
|
||||
#undef HAVE_MEMMOVE
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||
#undef HAVE_NDIR_H
|
||||
|
||||
/* Define to 1 if you have the `opendir' function. */
|
||||
#undef HAVE_OPENDIR
|
||||
|
||||
/* Define if libtool can extract symbol lists from object files. */
|
||||
#undef HAVE_PRELOADED_SYMBOLS
|
||||
|
||||
/* Define to 1 if you have the `readdir' function. */
|
||||
#undef HAVE_READDIR
|
||||
|
||||
/* Define to 1 if you have the `rindex' function. */
|
||||
#undef HAVE_RINDEX
|
||||
|
||||
/* Define if you have the shl_load function. */
|
||||
#undef HAVE_SHL_LOAD
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#undef HAVE_STDIO_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the `strchr' function. */
|
||||
#undef HAVE_STRCHR
|
||||
|
||||
/* Define to 1 if you have the `strcmp' function. */
|
||||
#undef HAVE_STRCMP
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strrchr' function. */
|
||||
#undef HAVE_STRRCHR
|
||||
|
||||
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
#undef HAVE_SYS_DIR_H
|
||||
|
||||
/* Define to 1 if you have the <sys/dl.h> header file. */
|
||||
#undef HAVE_SYS_DL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
#undef HAVE_SYS_NDIR_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define if the OS needs help to load dependent libraries for dlopen(). */
|
||||
#undef LTDL_DLOPEN_DEPLIBS
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LTDL_OBJDIR
|
||||
|
||||
/* Define to the name of the environment variable that determines the dynamic
|
||||
library search path. */
|
||||
#undef LTDL_SHLIBPATH_VAR
|
||||
|
||||
/* Define to the extension used for shared libraries, say, ".so". */
|
||||
#undef LTDL_SHLIB_EXT
|
||||
|
||||
/* Define to the system default library search path. */
|
||||
#undef LTDL_SYSSEARCHPATH
|
||||
|
||||
/* Define if dlsym() requires a leading underscore in symbol names. */
|
||||
#undef NEED_USCORE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
/* Define to a type to use for `error_t' if it is not otherwise available. */
|
||||
#undef error_t
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
#undef inline
|
||||
#endif
|
||||
1516
libltdl/config.guess
vendored
Executable file
1516
libltdl/config.guess
vendored
Executable file
File diff suppressed because it is too large
Load diff
196
libltdl/config.h
Normal file
196
libltdl/config.h
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
/* config.h. Generated from config-h.in by configure. */
|
||||
/* config-h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the `argz_append' function. */
|
||||
#define HAVE_ARGZ_APPEND 1
|
||||
|
||||
/* Define to 1 if you have the `argz_create_sep' function. */
|
||||
#define HAVE_ARGZ_CREATE_SEP 1
|
||||
|
||||
/* Define to 1 if you have the <argz.h> header file. */
|
||||
#define HAVE_ARGZ_H 1
|
||||
|
||||
/* Define to 1 if you have the `argz_insert' function. */
|
||||
#define HAVE_ARGZ_INSERT 1
|
||||
|
||||
/* Define to 1 if you have the `argz_next' function. */
|
||||
#define HAVE_ARGZ_NEXT 1
|
||||
|
||||
/* Define to 1 if you have the `argz_stringify' function. */
|
||||
#define HAVE_ARGZ_STRINGIFY 1
|
||||
|
||||
/* Define to 1 if you have the <assert.h> header file. */
|
||||
#define HAVE_ASSERT_H 1
|
||||
|
||||
/* Define to 1 if you have the `bcopy' function. */
|
||||
/* #undef HAVE_BCOPY */
|
||||
|
||||
/* Define to 1 if you have the `closedir' function. */
|
||||
#define HAVE_CLOSEDIR 1
|
||||
|
||||
/* Define to 1 if you have the <ctype.h> header file. */
|
||||
#define HAVE_CTYPE_H 1
|
||||
|
||||
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
#define HAVE_DIRENT_H 1
|
||||
|
||||
/* Define if you have the GNU dld library. */
|
||||
/* #undef HAVE_DLD */
|
||||
|
||||
/* Define to 1 if you have the <dld.h> header file. */
|
||||
/* #undef HAVE_DLD_H */
|
||||
|
||||
/* Define to 1 if you have the `dlerror' function. */
|
||||
#define HAVE_DLERROR 1
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the <dl.h> header file. */
|
||||
/* #undef HAVE_DL_H */
|
||||
|
||||
/* Define if you have the _dyld_func_lookup function. */
|
||||
/* #undef HAVE_DYLD */
|
||||
|
||||
/* Define to 1 if you have the <errno.h> header file. */
|
||||
#define HAVE_ERRNO_H 1
|
||||
|
||||
/* Define to 1 if the system has the type `error_t'. */
|
||||
#define HAVE_ERROR_T 1
|
||||
|
||||
/* Define to 1 if you have the `index' function. */
|
||||
/* #undef HAVE_INDEX */
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define if you have the libdl library or equivalent. */
|
||||
#define HAVE_LIBDL 1
|
||||
|
||||
/* Define to 1 if you have the <mach-o/dyld.h> header file. */
|
||||
/* #undef HAVE_MACH_O_DYLD_H */
|
||||
|
||||
/* Define to 1 if you have the <malloc.h> header file. */
|
||||
#define HAVE_MALLOC_H 1
|
||||
|
||||
/* Define to 1 if you have the `memcpy' function. */
|
||||
#define HAVE_MEMCPY 1
|
||||
|
||||
/* Define to 1 if you have the `memmove' function. */
|
||||
#define HAVE_MEMMOVE 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||
/* #undef HAVE_NDIR_H */
|
||||
|
||||
/* Define to 1 if you have the `opendir' function. */
|
||||
#define HAVE_OPENDIR 1
|
||||
|
||||
/* Define if libtool can extract symbol lists from object files. */
|
||||
#define HAVE_PRELOADED_SYMBOLS 1
|
||||
|
||||
/* Define to 1 if you have the `readdir' function. */
|
||||
#define HAVE_READDIR 1
|
||||
|
||||
/* Define to 1 if you have the `rindex' function. */
|
||||
/* #undef HAVE_RINDEX */
|
||||
|
||||
/* Define if you have the shl_load function. */
|
||||
/* #undef HAVE_SHL_LOAD */
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#define HAVE_STDIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the `strchr' function. */
|
||||
#define HAVE_STRCHR 1
|
||||
|
||||
/* Define to 1 if you have the `strcmp' function. */
|
||||
#define HAVE_STRCMP 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the `strrchr' function. */
|
||||
#define HAVE_STRRCHR 1
|
||||
|
||||
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
/* #undef HAVE_SYS_DIR_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/dl.h> header file. */
|
||||
/* #undef HAVE_SYS_DL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
/* #undef HAVE_SYS_NDIR_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define if the OS needs help to load dependent libraries for dlopen(). */
|
||||
/* #undef LTDL_DLOPEN_DEPLIBS */
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LTDL_OBJDIR ".libs/"
|
||||
|
||||
/* Define to the name of the environment variable that determines the dynamic
|
||||
library search path. */
|
||||
#define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
|
||||
|
||||
/* Define to the extension used for shared libraries, say, ".so". */
|
||||
#define LTDL_SHLIB_EXT ".so"
|
||||
|
||||
/* Define to the system default library search path. */
|
||||
#define LTDL_SYSSEARCHPATH "/lib:/usr/lib:/usr/lib/atlas:/usr/local/lib:/lib/i486-linux-gnu:/usr/lib/i486-linux-gnu:/usr/local/lib"
|
||||
|
||||
/* Define if dlsym() requires a leading underscore in symbol names. */
|
||||
/* #undef NEED_USCORE */
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "bug-libtool@gnu.org"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "libltdl"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "libltdl 1.2"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "libltdl"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "1.2"
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define to a type to use for `error_t' if it is not otherwise available. */
|
||||
/* #undef error_t */
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
||||
1622
libltdl/config.sub
vendored
Executable file
1622
libltdl/config.sub
vendored
Executable file
File diff suppressed because it is too large
Load diff
23853
libltdl/configure
vendored
Executable file
23853
libltdl/configure
vendored
Executable file
File diff suppressed because it is too large
Load diff
79
libltdl/configure.ac
Normal file
79
libltdl/configure.ac
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
## Process this file with autoconf to create configure. -*- autoconf -*-
|
||||
# Copyright 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301 USA
|
||||
|
||||
|
||||
dnl FIXME: Is this really new enough?
|
||||
AC_PREREQ(2.50)
|
||||
|
||||
|
||||
## ------------------------ ##
|
||||
## Autoconf initialisation. ##
|
||||
## ------------------------ ##
|
||||
AC_INIT([libltdl], [1.2], [bug-libtool@gnu.org])
|
||||
AC_CONFIG_SRCDIR([ltdl.c])
|
||||
|
||||
|
||||
## ------------------------------- ##
|
||||
## Libltdl specific configuration. ##
|
||||
## ------------------------------- ##
|
||||
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
|
||||
if test -z "$enable_ltdl_install$enable_ltdl_convenience"; then
|
||||
if test -f ${srcdir}/ltmain.sh; then
|
||||
# if libltdl is libtoolized, it is assumed to be stand-alone and
|
||||
# installed unless the command line overrides it (tested above)
|
||||
enable_ltdl_install=yes
|
||||
else
|
||||
AC_MSG_WARN([*** The top-level configure must select either])
|
||||
AC_MSG_WARN([*** [A""C_LIBLTDL_INSTALLABLE] or [A""C_LIBLTDL_CONVENIENCE].])
|
||||
AC_MSG_ERROR([*** Maybe you want to --enable-ltdl-install?])
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
## ------------------------ ##
|
||||
## Automake Initialisation. ##
|
||||
## ------------------------ ##
|
||||
AM_INIT_AUTOMAKE(AC_PACKAGE_TARNAME, AC_PACKAGE_VERSION, -)
|
||||
AM_CONFIG_HEADER([config.h:config-h.in])
|
||||
|
||||
|
||||
## ------------------ ##
|
||||
## C compiler checks. ##
|
||||
## ------------------ ##
|
||||
AC_PROG_CC
|
||||
AC_C_CONST
|
||||
AC_C_INLINE
|
||||
|
||||
|
||||
## ----------------------- ##
|
||||
## Libtool initialisation. ##
|
||||
## ----------------------- ##
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AC_PROG_LIBTOOL
|
||||
AC_SUBST([LIBTOOL_DEPS])
|
||||
|
||||
AC_LIB_LTDL
|
||||
|
||||
|
||||
## -------- ##
|
||||
## Outputs. ##
|
||||
## -------- ##
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
519
libltdl/install-sh
Executable file
519
libltdl/install-sh
Executable file
|
|
@ -0,0 +1,519 @@
|
|||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2006-12-25.00
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
nl='
|
||||
'
|
||||
IFS=" "" $nl"
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit=${DOITPROG-}
|
||||
if test -z "$doit"; then
|
||||
doit_exec=exec
|
||||
else
|
||||
doit_exec=$doit
|
||||
fi
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_glob='?'
|
||||
initialize_posix_glob='
|
||||
test "$posix_glob" != "?" || {
|
||||
if (set -f) 2>/dev/null; then
|
||||
posix_glob=
|
||||
else
|
||||
posix_glob=:
|
||||
fi
|
||||
}
|
||||
'
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
no_target_directory=
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *' '* | *'
|
||||
'* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t) dst_arg=$2
|
||||
shift;;
|
||||
|
||||
-T) no_target_directory=true;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names starting with `-'.
|
||||
case $src in
|
||||
-*) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dst=$dst_arg
|
||||
# Protect names starting with `-'.
|
||||
case $dst in
|
||||
-*) dst=./$dst;;
|
||||
esac
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
# Prefer dirname, but fall back on a substitute if dirname fails.
|
||||
dstdir=`
|
||||
(dirname "$dst") 2>/dev/null ||
|
||||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$dst" : 'X\(//\)[^/]' \| \
|
||||
X"$dst" : 'X\(//\)$' \| \
|
||||
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
echo X"$dst" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'
|
||||
`
|
||||
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
if (umask $mkdir_umask &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writeable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/d" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
-*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
eval "$initialize_posix_glob"
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
$posix_glob set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
$posix_glob set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test -z "$d" && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
|
||||
eval "$initialize_posix_glob" &&
|
||||
$posix_glob set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
$posix_glob set +f &&
|
||||
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
4530
libltdl/ltdl.c
Normal file
4530
libltdl/ltdl.c
Normal file
File diff suppressed because it is too large
Load diff
367
libltdl/ltdl.h
Normal file
367
libltdl/ltdl.h
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
/* ltdl.h -- generic dlopen functions
|
||||
Copyright (C) 1998-2001, 2003, 2004, 2007 Free Software Foundation, Inc.
|
||||
Originally by Thomas Tanner <tanner@ffii.org>
|
||||
This file is part of GNU Libtool.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
As a special exception to the GNU Lesser General Public License,
|
||||
if you distribute this file as part of a program or library that
|
||||
is built using GNU libtool, you may include it under the same
|
||||
distribution terms that you use for the rest of that program.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
*/
|
||||
|
||||
/* Only include this header file once. */
|
||||
#ifndef LTDL_H
|
||||
#define LTDL_H 1
|
||||
|
||||
#include <sys/types.h> /* for size_t declaration */
|
||||
|
||||
|
||||
/* --- MACROS FOR PORTABILITY --- */
|
||||
|
||||
|
||||
/* Saves on those hard to debug '\0' typos.... */
|
||||
#define LT_EOS_CHAR '\0'
|
||||
|
||||
/* LTDL_BEGIN_C_DECLS should be used at the beginning of your declarations,
|
||||
so that C++ compilers don't mangle their names. Use LTDL_END_C_DECLS at
|
||||
the end of C declarations. */
|
||||
#ifdef __cplusplus
|
||||
# define LT_BEGIN_C_DECLS extern "C" {
|
||||
# define LT_END_C_DECLS }
|
||||
#else
|
||||
# define LT_BEGIN_C_DECLS /* empty */
|
||||
# define LT_END_C_DECLS /* empty */
|
||||
#endif
|
||||
|
||||
LT_BEGIN_C_DECLS
|
||||
|
||||
|
||||
/* LT_PARAMS is a macro used to wrap function prototypes, so that compilers
|
||||
that don't understand ANSI C prototypes still work, and ANSI C
|
||||
compilers can issue warnings about type mismatches. */
|
||||
#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32) || defined(__cplusplus)
|
||||
# define LT_PARAMS(protos) protos
|
||||
# define lt_ptr void*
|
||||
#else
|
||||
# define LT_PARAMS(protos) ()
|
||||
# define lt_ptr char*
|
||||
#endif
|
||||
|
||||
/* LT_STMT_START/END are used to create macros which expand to a
|
||||
a single compound statement in a portable way. */
|
||||
#if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
|
||||
# define LT_STMT_START (void)(
|
||||
# define LT_STMT_END )
|
||||
#else
|
||||
# if (defined (sun) || defined (__sun__))
|
||||
# define LT_STMT_START if (1)
|
||||
# define LT_STMT_END else (void)0
|
||||
# else
|
||||
# define LT_STMT_START do
|
||||
# define LT_STMT_END while (0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* LT_CONC creates a new concatenated symbol for the compiler
|
||||
in a portable way. */
|
||||
#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER) || defined(_AIX)
|
||||
# define LT_CONC(s,t) s##t
|
||||
#else
|
||||
# define LT_CONC(s,t) s/**/t
|
||||
#endif
|
||||
|
||||
/* LT_STRLEN can be used safely on NULL pointers. */
|
||||
#define LT_STRLEN(s) (((s) && (s)[0]) ? strlen (s) : 0)
|
||||
|
||||
|
||||
|
||||
/* --- WINDOWS SUPPORT --- */
|
||||
|
||||
|
||||
/* Canonicalise Windows and Cygwin recognition macros. */
|
||||
#ifdef __CYGWIN32__
|
||||
# ifndef __CYGWIN__
|
||||
# define __CYGWIN__ __CYGWIN32__
|
||||
# endif
|
||||
#endif
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
# ifndef __WINDOWS__
|
||||
# ifdef _WIN32
|
||||
# define __WINDOWS__ _WIN32
|
||||
# else
|
||||
# ifdef WIN32
|
||||
# define __WINDOWS__ WIN32
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
# ifndef __CYGWIN__
|
||||
/* LT_DIRSEP_CHAR is accepted *in addition* to '/' as a directory
|
||||
separator when it is set. */
|
||||
# define LT_DIRSEP_CHAR '\\'
|
||||
# define LT_PATHSEP_CHAR ';'
|
||||
# endif
|
||||
#endif
|
||||
#ifndef LT_PATHSEP_CHAR
|
||||
# define LT_PATHSEP_CHAR ':'
|
||||
#endif
|
||||
|
||||
/* DLL building support on win32 hosts; mostly to workaround their
|
||||
ridiculous implementation of data symbol exporting. */
|
||||
#ifndef LT_SCOPE
|
||||
# if defined(__WINDOWS__) || defined(__CYGWIN__)
|
||||
# ifdef DLL_EXPORT /* defined by libtool (if required) */
|
||||
# define LT_SCOPE __declspec(dllexport)
|
||||
# endif
|
||||
# ifdef LIBLTDL_DLL_IMPORT /* define if linking with this dll */
|
||||
/* note: cygwin/mingw compilers can rely instead on auto-import */
|
||||
# define LT_SCOPE extern __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
# ifndef LT_SCOPE /* static linking or !__WINDOWS__ */
|
||||
# define LT_SCOPE extern
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER) /* Visual Studio */
|
||||
# define R_OK 4
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* --- DYNAMIC MODULE LOADING API --- */
|
||||
|
||||
|
||||
typedef struct lt_dlhandle_struct *lt_dlhandle; /* A loaded module. */
|
||||
|
||||
/* Initialisation and finalisation functions for libltdl. */
|
||||
LT_SCOPE int lt_dlinit LT_PARAMS((void));
|
||||
LT_SCOPE int lt_dlexit LT_PARAMS((void));
|
||||
|
||||
/* Module search path manipulation. */
|
||||
LT_SCOPE int lt_dladdsearchdir LT_PARAMS((const char *search_dir));
|
||||
LT_SCOPE int lt_dlinsertsearchdir LT_PARAMS((const char *before,
|
||||
const char *search_dir));
|
||||
LT_SCOPE int lt_dlsetsearchpath LT_PARAMS((const char *search_path));
|
||||
LT_SCOPE const char *lt_dlgetsearchpath LT_PARAMS((void));
|
||||
LT_SCOPE int lt_dlforeachfile LT_PARAMS((
|
||||
const char *search_path,
|
||||
int (*func) (const char *filename, lt_ptr data),
|
||||
lt_ptr data));
|
||||
|
||||
/* Portable libltdl versions of the system dlopen() API. */
|
||||
LT_SCOPE lt_dlhandle lt_dlopen LT_PARAMS((const char *filename));
|
||||
LT_SCOPE lt_dlhandle lt_dlopenext LT_PARAMS((const char *filename));
|
||||
LT_SCOPE lt_ptr lt_dlsym LT_PARAMS((lt_dlhandle handle,
|
||||
const char *name));
|
||||
LT_SCOPE const char *lt_dlerror LT_PARAMS((void));
|
||||
LT_SCOPE int lt_dlclose LT_PARAMS((lt_dlhandle handle));
|
||||
|
||||
/* Module residency management. */
|
||||
LT_SCOPE int lt_dlmakeresident LT_PARAMS((lt_dlhandle handle));
|
||||
LT_SCOPE int lt_dlisresident LT_PARAMS((lt_dlhandle handle));
|
||||
|
||||
|
||||
|
||||
|
||||
/* --- MUTEX LOCKING --- */
|
||||
|
||||
|
||||
typedef void lt_dlmutex_lock LT_PARAMS((void));
|
||||
typedef void lt_dlmutex_unlock LT_PARAMS((void));
|
||||
typedef void lt_dlmutex_seterror LT_PARAMS((const char *errmsg));
|
||||
typedef const char *lt_dlmutex_geterror LT_PARAMS((void));
|
||||
|
||||
LT_SCOPE int lt_dlmutex_register LT_PARAMS((lt_dlmutex_lock *lock,
|
||||
lt_dlmutex_unlock *unlock,
|
||||
lt_dlmutex_seterror *seterror,
|
||||
lt_dlmutex_geterror *geterror));
|
||||
|
||||
|
||||
|
||||
|
||||
/* --- MEMORY HANDLING --- */
|
||||
|
||||
|
||||
/* By default, the realloc function pointer is set to our internal
|
||||
realloc implementation which iself uses lt_dlmalloc and lt_dlfree.
|
||||
libltdl relies on a featureful realloc, but if you are sure yours
|
||||
has the right semantics then you can assign it directly. Generally,
|
||||
it is safe to assign just a malloc() and a free() function. */
|
||||
LT_SCOPE lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size));
|
||||
LT_SCOPE lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size));
|
||||
LT_SCOPE void (*lt_dlfree) LT_PARAMS((lt_ptr ptr));
|
||||
|
||||
|
||||
|
||||
|
||||
/* --- PRELOADED MODULE SUPPORT --- */
|
||||
|
||||
|
||||
/* A preopened symbol. Arrays of this type comprise the exported
|
||||
symbols for a dlpreopened module. */
|
||||
typedef struct {
|
||||
const char *name;
|
||||
lt_ptr address;
|
||||
} lt_dlsymlist;
|
||||
|
||||
LT_SCOPE int lt_dlpreload LT_PARAMS((const lt_dlsymlist *preloaded));
|
||||
LT_SCOPE int lt_dlpreload_default
|
||||
LT_PARAMS((const lt_dlsymlist *preloaded));
|
||||
|
||||
#define LTDL_SET_PRELOADED_SYMBOLS() LT_STMT_START{ \
|
||||
extern const lt_dlsymlist lt_preloaded_symbols[]; \
|
||||
lt_dlpreload_default(lt_preloaded_symbols); \
|
||||
}LT_STMT_END
|
||||
|
||||
|
||||
|
||||
|
||||
/* --- MODULE INFORMATION --- */
|
||||
|
||||
|
||||
/* Read only information pertaining to a loaded module. */
|
||||
typedef struct {
|
||||
char *filename; /* file name */
|
||||
char *name; /* module name */
|
||||
int ref_count; /* number of times lt_dlopened minus
|
||||
number of times lt_dlclosed. */
|
||||
} lt_dlinfo;
|
||||
|
||||
LT_SCOPE const lt_dlinfo *lt_dlgetinfo LT_PARAMS((lt_dlhandle handle));
|
||||
LT_SCOPE lt_dlhandle lt_dlhandle_next LT_PARAMS((lt_dlhandle place));
|
||||
LT_SCOPE int lt_dlforeach LT_PARAMS((
|
||||
int (*func) (lt_dlhandle handle, lt_ptr data),
|
||||
lt_ptr data));
|
||||
|
||||
/* Associating user data with loaded modules. */
|
||||
typedef unsigned lt_dlcaller_id;
|
||||
|
||||
LT_SCOPE lt_dlcaller_id lt_dlcaller_register LT_PARAMS((void));
|
||||
LT_SCOPE lt_ptr lt_dlcaller_set_data LT_PARAMS((lt_dlcaller_id key,
|
||||
lt_dlhandle handle,
|
||||
lt_ptr data));
|
||||
LT_SCOPE lt_ptr lt_dlcaller_get_data LT_PARAMS((lt_dlcaller_id key,
|
||||
lt_dlhandle handle));
|
||||
|
||||
|
||||
|
||||
/* --- USER MODULE LOADER API --- */
|
||||
|
||||
|
||||
typedef struct lt_dlloader lt_dlloader;
|
||||
typedef lt_ptr lt_user_data;
|
||||
typedef lt_ptr lt_module;
|
||||
|
||||
/* Function pointer types for creating user defined module loaders. */
|
||||
typedef lt_module lt_module_open LT_PARAMS((lt_user_data loader_data,
|
||||
const char *filename));
|
||||
typedef int lt_module_close LT_PARAMS((lt_user_data loader_data,
|
||||
lt_module handle));
|
||||
typedef lt_ptr lt_find_sym LT_PARAMS((lt_user_data loader_data,
|
||||
lt_module handle,
|
||||
const char *symbol));
|
||||
typedef int lt_dlloader_exit LT_PARAMS((lt_user_data loader_data));
|
||||
|
||||
struct lt_user_dlloader {
|
||||
const char *sym_prefix;
|
||||
lt_module_open *module_open;
|
||||
lt_module_close *module_close;
|
||||
lt_find_sym *find_sym;
|
||||
lt_dlloader_exit *dlloader_exit;
|
||||
lt_user_data dlloader_data;
|
||||
};
|
||||
|
||||
LT_SCOPE lt_dlloader *lt_dlloader_next LT_PARAMS((lt_dlloader *place));
|
||||
LT_SCOPE lt_dlloader *lt_dlloader_find LT_PARAMS((
|
||||
const char *loader_name));
|
||||
LT_SCOPE const char *lt_dlloader_name LT_PARAMS((lt_dlloader *place));
|
||||
LT_SCOPE lt_user_data *lt_dlloader_data LT_PARAMS((lt_dlloader *place));
|
||||
LT_SCOPE int lt_dlloader_add LT_PARAMS((lt_dlloader *place,
|
||||
const struct lt_user_dlloader *dlloader,
|
||||
const char *loader_name));
|
||||
LT_SCOPE int lt_dlloader_remove LT_PARAMS((
|
||||
const char *loader_name));
|
||||
|
||||
|
||||
|
||||
/* --- ERROR MESSAGE HANDLING --- */
|
||||
|
||||
|
||||
/* Defining error strings alongside their symbolic names in a macro in
|
||||
this way allows us to expand the macro in different contexts with
|
||||
confidence that the enumeration of symbolic names will map correctly
|
||||
onto the table of error strings. */
|
||||
#define lt_dlerror_table \
|
||||
LT_ERROR(UNKNOWN, "unknown error") \
|
||||
LT_ERROR(DLOPEN_NOT_SUPPORTED, "dlopen support not available") \
|
||||
LT_ERROR(INVALID_LOADER, "invalid loader") \
|
||||
LT_ERROR(INIT_LOADER, "loader initialization failed") \
|
||||
LT_ERROR(REMOVE_LOADER, "loader removal failed") \
|
||||
LT_ERROR(FILE_NOT_FOUND, "file not found") \
|
||||
LT_ERROR(DEPLIB_NOT_FOUND, "dependency library not found") \
|
||||
LT_ERROR(NO_SYMBOLS, "no symbols defined") \
|
||||
LT_ERROR(CANNOT_OPEN, "can't open the module") \
|
||||
LT_ERROR(CANNOT_CLOSE, "can't close the module") \
|
||||
LT_ERROR(SYMBOL_NOT_FOUND, "symbol not found") \
|
||||
LT_ERROR(NO_MEMORY, "not enough memory") \
|
||||
LT_ERROR(INVALID_HANDLE, "invalid module handle") \
|
||||
LT_ERROR(BUFFER_OVERFLOW, "internal buffer overflow") \
|
||||
LT_ERROR(INVALID_ERRORCODE, "invalid errorcode") \
|
||||
LT_ERROR(SHUTDOWN, "library already shutdown") \
|
||||
LT_ERROR(CLOSE_RESIDENT_MODULE, "can't close resident module") \
|
||||
LT_ERROR(INVALID_MUTEX_ARGS, "invalid mutex handler registration") \
|
||||
LT_ERROR(INVALID_POSITION, "invalid search path insert position")
|
||||
|
||||
/* Enumerate the symbolic error names. */
|
||||
enum {
|
||||
#define LT_ERROR(name, diagnostic) LT_CONC(LT_ERROR_, name),
|
||||
lt_dlerror_table
|
||||
#undef LT_ERROR
|
||||
|
||||
LT_ERROR_MAX
|
||||
};
|
||||
|
||||
/* These functions are only useful from inside custom module loaders. */
|
||||
LT_SCOPE int lt_dladderror LT_PARAMS((const char *diagnostic));
|
||||
LT_SCOPE int lt_dlseterror LT_PARAMS((int errorcode));
|
||||
|
||||
|
||||
|
||||
|
||||
/* --- SOURCE COMPATIBILITY WITH OLD LIBLTDL --- */
|
||||
|
||||
|
||||
#ifdef LT_NON_POSIX_NAMESPACE
|
||||
# define lt_ptr_t lt_ptr
|
||||
# define lt_module_t lt_module
|
||||
# define lt_module_open_t lt_module_open
|
||||
# define lt_module_close_t lt_module_close
|
||||
# define lt_find_sym_t lt_find_sym
|
||||
# define lt_dlloader_exit_t lt_dlloader_exit
|
||||
# define lt_dlloader_t lt_dlloader
|
||||
# define lt_dlloader_data_t lt_user_data
|
||||
#endif
|
||||
|
||||
LT_END_C_DECLS
|
||||
|
||||
#endif /* !LTDL_H */
|
||||
6938
libltdl/ltmain.sh
Normal file
6938
libltdl/ltmain.sh
Normal file
File diff suppressed because it is too large
Load diff
360
libltdl/missing
Executable file
360
libltdl/missing
Executable file
|
|
@ -0,0 +1,360 @@
|
|||
#! /bin/sh
|
||||
# Common stub for a few missing GNU programs while installing.
|
||||
|
||||
scriptversion=2005-06-08.21
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005
|
||||
# Free Software Foundation, Inc.
|
||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run=:
|
||||
|
||||
# In the cases where this matters, `missing' is being run in the
|
||||
# srcdir already.
|
||||
if test -f configure.ac; then
|
||||
configure_ac=configure.ac
|
||||
else
|
||||
configure_ac=configure.in
|
||||
fi
|
||||
|
||||
msg="missing on your system"
|
||||
|
||||
case "$1" in
|
||||
--run)
|
||||
# Try to run requested program, and just exit if it succeeds.
|
||||
run=
|
||||
shift
|
||||
"$@" && exit 0
|
||||
# Exit code 63 means version mismatch. This often happens
|
||||
# when the user try to use an ancient version of a tool on
|
||||
# a file that requires a minimum version. In this case we
|
||||
# we should proceed has if the program had been absent, or
|
||||
# if --run hadn't been passed.
|
||||
if test $? = 63; then
|
||||
run=:
|
||||
msg="probably too old"
|
||||
fi
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
|
||||
error status if there is no known handling for PROGRAM.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
--run try to run the given command, and emulate it if it fails
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal touch file \`aclocal.m4'
|
||||
autoconf touch file \`configure'
|
||||
autoheader touch file \`config.h.in'
|
||||
automake touch all \`Makefile.in' files
|
||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
flex create \`lex.yy.c', if possible, from existing .c
|
||||
help2man touch the output file
|
||||
lex create \`lex.yy.c', if possible, from existing .c
|
||||
makeinfo touch the output file
|
||||
tar try tar, gnutar, gtar, then tar without non-portable flags
|
||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: Unknown \`$1' option"
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# Now exit if we have it, but it failed. Also exit now if we
|
||||
# don't have it and --version was passed (most likely to detect
|
||||
# the program).
|
||||
case "$1" in
|
||||
lex|yacc)
|
||||
# Not GNU programs, they don't have --version.
|
||||
;;
|
||||
|
||||
tar)
|
||||
if test -n "$run"; then
|
||||
echo 1>&2 "ERROR: \`tar' requires --run"
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
# Could not run --version or --help. This is probably someone
|
||||
# running `$TOOL --version' or `$TOOL --help' to check whether
|
||||
# $TOOL exists and not knowing $TOOL uses missing.
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# If it does not exist, or fails to run (possibly an outdated version),
|
||||
# try to emulate it.
|
||||
case "$1" in
|
||||
aclocal*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
|
||||
to install the \`Automake' and \`Perl' packages. Grab them from
|
||||
any GNU archive site."
|
||||
touch aclocal.m4
|
||||
;;
|
||||
|
||||
autoconf)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`${configure_ac}'. You might want to install the
|
||||
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
|
||||
archive site."
|
||||
touch configure
|
||||
;;
|
||||
|
||||
autoheader)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acconfig.h' or \`${configure_ac}'. You might want
|
||||
to install the \`Autoconf' and \`GNU m4' packages. Grab them
|
||||
from any GNU archive site."
|
||||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
|
||||
test -z "$files" && files="config.h"
|
||||
touch_files=
|
||||
for f in $files; do
|
||||
case "$f" in
|
||||
*:*) touch_files="$touch_files "`echo "$f" |
|
||||
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
||||
*) touch_files="$touch_files $f.in";;
|
||||
esac
|
||||
done
|
||||
touch $touch_files
|
||||
;;
|
||||
|
||||
automake*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
|
||||
You might want to install the \`Automake' and \`Perl' packages.
|
||||
Grab them from any GNU archive site."
|
||||
find . -type f -name Makefile.am -print |
|
||||
sed 's/\.am$/.in/' |
|
||||
while read f; do touch "$f"; done
|
||||
;;
|
||||
|
||||
autom4te)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, but is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them.
|
||||
You can get \`$1' as part of \`Autoconf' from any GNU
|
||||
archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
|
||||
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo "#! /bin/sh"
|
||||
echo "# Created by GNU Automake missing as a replacement of"
|
||||
echo "# $ $@"
|
||||
echo "exit 0"
|
||||
chmod +x $file
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
bison|yacc)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' $msg. You should only need it if
|
||||
you modified a \`.y' file. You may need the \`Bison' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Bison' from any GNU archive site."
|
||||
rm -f y.tab.c y.tab.h
|
||||
if [ $# -ne 1 ]; then
|
||||
eval LASTARG="\${$#}"
|
||||
case "$LASTARG" in
|
||||
*.y)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" y.tab.c
|
||||
fi
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" y.tab.h
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ ! -f y.tab.h ]; then
|
||||
echo >y.tab.h
|
||||
fi
|
||||
if [ ! -f y.tab.c ]; then
|
||||
echo 'main() { return 0; }' >y.tab.c
|
||||
fi
|
||||
;;
|
||||
|
||||
lex|flex)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.l' file. You may need the \`Flex' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Flex' from any GNU archive site."
|
||||
rm -f lex.yy.c
|
||||
if [ $# -ne 1 ]; then
|
||||
eval LASTARG="\${$#}"
|
||||
case "$LASTARG" in
|
||||
*.l)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" lex.yy.c
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ ! -f lex.yy.c ]; then
|
||||
echo 'main() { return 0; }' >lex.yy.c
|
||||
fi
|
||||
;;
|
||||
|
||||
help2man)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a dependency of a manual page. You may need the
|
||||
\`Help2man' package in order for those modifications to take
|
||||
effect. You can get \`Help2man' from any GNU archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
||||
if test -z "$file"; then
|
||||
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
|
||||
fi
|
||||
if [ -f "$file" ]; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo ".ab help2man is required to generate this page"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
makeinfo)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.texi' or \`.texinfo' file, or any other file
|
||||
indirectly affecting the aspect of the manual. The spurious
|
||||
call might also be the consequence of using a buggy \`make' (AIX,
|
||||
DU, IRIX). You might want to install the \`Texinfo' package or
|
||||
the \`GNU make' package. Grab either from any GNU archive site."
|
||||
# The file to touch is that specified with -o ...
|
||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
||||
if test -z "$file"; then
|
||||
# ... or it is the one specified with @setfilename ...
|
||||
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
||||
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile`
|
||||
# ... or it is derived from the source name (dir/f.texi becomes f.info)
|
||||
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
|
||||
fi
|
||||
# If the file does not exist, the user really needs makeinfo;
|
||||
# let's fail without touching anything.
|
||||
test -f $file || exit 1
|
||||
touch $file
|
||||
;;
|
||||
|
||||
tar)
|
||||
shift
|
||||
|
||||
# We have already tried tar in the generic part.
|
||||
# Look for gnutar/gtar before invocation to avoid ugly error
|
||||
# messages.
|
||||
if (gnutar --version > /dev/null 2>&1); then
|
||||
gnutar "$@" && exit 0
|
||||
fi
|
||||
if (gtar --version > /dev/null 2>&1); then
|
||||
gtar "$@" && exit 0
|
||||
fi
|
||||
firstarg="$1"
|
||||
if shift; then
|
||||
case "$firstarg" in
|
||||
*o*)
|
||||
firstarg=`echo "$firstarg" | sed s/o//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
case "$firstarg" in
|
||||
*h*)
|
||||
firstarg=`echo "$firstarg" | sed s/h//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: I can't seem to be able to run \`tar' with the given arguments.
|
||||
You may want to install GNU tar or Free paxutils, or check the
|
||||
command line arguments."
|
||||
exit 1
|
||||
;;
|
||||
|
||||
*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, and is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them. Check the \`README' file,
|
||||
it often tells you about the needed prerequisites for installing
|
||||
this package. You may also peek at any GNU archive site, in case
|
||||
some other package would contain this missing \`$1' program."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
161
libltdl/mkinstalldirs
Executable file
161
libltdl/mkinstalldirs
Executable file
|
|
@ -0,0 +1,161 @@
|
|||
#! /bin/sh
|
||||
# mkinstalldirs --- make directory hierarchy
|
||||
|
||||
scriptversion=2006-05-11.19
|
||||
|
||||
# Original author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1993-05-16
|
||||
# Public domain.
|
||||
#
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
IFS=" "" $nl"
|
||||
errstatus=0
|
||||
dirmode=
|
||||
|
||||
usage="\
|
||||
Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
|
||||
|
||||
Create each directory DIR (with mode MODE, if specified), including all
|
||||
leading file name components.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>."
|
||||
|
||||
# process command line arguments
|
||||
while test $# -gt 0 ; do
|
||||
case $1 in
|
||||
-h | --help | --h*) # -h for help
|
||||
echo "$usage"
|
||||
exit $?
|
||||
;;
|
||||
-m) # -m PERM arg
|
||||
shift
|
||||
test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
|
||||
dirmode=$1
|
||||
shift
|
||||
;;
|
||||
--version)
|
||||
echo "$0 $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
--) # stop option processing
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*) # unknown option
|
||||
echo "$usage" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
*) # first non-opt arg
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
for file
|
||||
do
|
||||
if test -d "$file"; then
|
||||
shift
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
case $# in
|
||||
0) exit 0 ;;
|
||||
esac
|
||||
|
||||
# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and
|
||||
# mkdir -p a/c at the same time, both will detect that a is missing,
|
||||
# one will create a, then the other will try to create a and die with
|
||||
# a "File exists" error. This is a problem when calling mkinstalldirs
|
||||
# from a parallel make. We use --version in the probe to restrict
|
||||
# ourselves to GNU mkdir, which is thread-safe.
|
||||
case $dirmode in
|
||||
'')
|
||||
if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
|
||||
echo "mkdir -p -- $*"
|
||||
exec mkdir -p -- "$@"
|
||||
else
|
||||
# On NextStep and OpenStep, the `mkdir' command does not
|
||||
# recognize any option. It will interpret all options as
|
||||
# directories to create, and then abort because `.' already
|
||||
# exists.
|
||||
test -d ./-p && rmdir ./-p
|
||||
test -d ./--version && rmdir ./--version
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 &&
|
||||
test ! -d ./--version; then
|
||||
echo "mkdir -m $dirmode -p -- $*"
|
||||
exec mkdir -m "$dirmode" -p -- "$@"
|
||||
else
|
||||
# Clean up after NextStep and OpenStep mkdir.
|
||||
for d in ./-m ./-p ./--version "./$dirmode";
|
||||
do
|
||||
test -d $d && rmdir $d
|
||||
done
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
for file
|
||||
do
|
||||
case $file in
|
||||
/*) pathcomp=/ ;;
|
||||
*) pathcomp= ;;
|
||||
esac
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
set fnord $file
|
||||
shift
|
||||
IFS=$oIFS
|
||||
|
||||
for d
|
||||
do
|
||||
test "x$d" = x && continue
|
||||
|
||||
pathcomp=$pathcomp$d
|
||||
case $pathcomp in
|
||||
-*) pathcomp=./$pathcomp ;;
|
||||
esac
|
||||
|
||||
if test ! -d "$pathcomp"; then
|
||||
echo "mkdir $pathcomp"
|
||||
|
||||
mkdir "$pathcomp" || lasterr=$?
|
||||
|
||||
if test ! -d "$pathcomp"; then
|
||||
errstatus=$lasterr
|
||||
else
|
||||
if test ! -z "$dirmode"; then
|
||||
echo "chmod $dirmode $pathcomp"
|
||||
lasterr=
|
||||
chmod "$dirmode" "$pathcomp" || lasterr=$?
|
||||
|
||||
if test ! -z "$lasterr"; then
|
||||
errstatus=$lasterr
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
pathcomp=$pathcomp/
|
||||
done
|
||||
done
|
||||
|
||||
exit $errstatus
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
1
libltdl/stamp-h1
Normal file
1
libltdl/stamp-h1
Normal file
|
|
@ -0,0 +1 @@
|
|||
timestamp for config.h
|
||||
388
pulseaudio-text.svg
Normal file
388
pulseaudio-text.svg
Normal file
|
|
@ -0,0 +1,388 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48px"
|
||||
height="48px"
|
||||
id="svg2161"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.45"
|
||||
sodipodi:docbase="/home/lennart/projects/pulseaudio"
|
||||
sodipodi:docname="pulseaudio.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
sodipodi:modified="TRUE">
|
||||
<defs
|
||||
id="defs2163">
|
||||
<linearGradient
|
||||
id="linearGradient3093">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3095" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3097" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3093"
|
||||
id="radialGradient2472"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.266476,0,283.9565)"
|
||||
cx="224.5"
|
||||
cy="387.11252"
|
||||
fx="224.5"
|
||||
fy="387.11252"
|
||||
r="174.5" />
|
||||
<linearGradient
|
||||
id="linearGradient2503">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2505" />
|
||||
<stop
|
||||
style="stop-color:#141413;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2507" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2503"
|
||||
id="linearGradient1476"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.124741,0,0,0.124741,-49.78411,-8.952609)"
|
||||
x1="585"
|
||||
y1="390.61252"
|
||||
x2="585"
|
||||
y2="85.376541" />
|
||||
<linearGradient
|
||||
id="linearGradient2495">
|
||||
<stop
|
||||
style="stop-color:#0a0a09;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2497" />
|
||||
<stop
|
||||
style="stop-color:#282927;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2499" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2495"
|
||||
id="linearGradient1474"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.124741,0,0,0.124741,-49.78411,-8.952609)"
|
||||
x1="674"
|
||||
y1="276.11252"
|
||||
x2="505"
|
||||
y2="199.11252" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2535"
|
||||
id="linearGradient2399"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="585"
|
||||
y1="390.61252"
|
||||
x2="585"
|
||||
y2="85.376541" />
|
||||
<linearGradient
|
||||
id="linearGradient2535">
|
||||
<stop
|
||||
id="stop2537"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:0.36078432;" />
|
||||
<stop
|
||||
id="stop2539"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2535"
|
||||
id="linearGradient2397"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-291.933,627.3998)"
|
||||
x1="532"
|
||||
y1="131.40625"
|
||||
x2="667.5"
|
||||
y2="357.40625" />
|
||||
<linearGradient
|
||||
id="linearGradient3072">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3074" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3076" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3072"
|
||||
id="linearGradient2395"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="585"
|
||||
y1="76.360481"
|
||||
x2="585"
|
||||
y2="170.3912" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3093"
|
||||
id="radialGradient2234"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.266476,0,283.9565)"
|
||||
cx="224.5"
|
||||
cy="387.11252"
|
||||
fx="224.5"
|
||||
fy="387.11252"
|
||||
r="174.5" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2495"
|
||||
id="linearGradient2236"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.124741,0,0,0.124741,-49.78411,-8.952609)"
|
||||
x1="674"
|
||||
y1="276.11252"
|
||||
x2="505"
|
||||
y2="199.11252" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2503"
|
||||
id="linearGradient2238"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.124741,0,0,0.124741,-49.78411,-8.952609)"
|
||||
x1="585"
|
||||
y1="390.61252"
|
||||
x2="585"
|
||||
y2="85.376541" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3072"
|
||||
id="linearGradient2240"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="585"
|
||||
y1="76.360481"
|
||||
x2="585"
|
||||
y2="170.3912" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2535"
|
||||
id="linearGradient2242"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-291.933,627.3998)"
|
||||
x1="532"
|
||||
y1="131.40625"
|
||||
x2="667.5"
|
||||
y2="357.40625" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2535"
|
||||
id="linearGradient2244"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="585"
|
||||
y1="390.61252"
|
||||
x2="585"
|
||||
y2="85.376541" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2495"
|
||||
id="linearGradient2255"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.124741,0,0,0.124741,-49.78411,-8.952609)"
|
||||
x1="674"
|
||||
y1="276.11252"
|
||||
x2="505"
|
||||
y2="199.11252" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2503"
|
||||
id="linearGradient2257"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.124741,0,0,0.124741,-49.78411,-8.952609)"
|
||||
x1="585"
|
||||
y1="390.61252"
|
||||
x2="585"
|
||||
y2="85.376541" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3093"
|
||||
id="radialGradient2260"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.266476,-145.39702,-74.948037)"
|
||||
cx="224.5"
|
||||
cy="387.11252"
|
||||
fx="224.5"
|
||||
fy="387.11252"
|
||||
r="174.5" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4.9497475"
|
||||
inkscape:cx="16.230436"
|
||||
inkscape:cy="-2.4336194"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="2043"
|
||||
inkscape:window-height="794"
|
||||
inkscape:window-x="180"
|
||||
inkscape:window-y="140"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true" />
|
||||
<metadata
|
||||
id="metadata2166">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<cc:license
|
||||
rdf:resource="http://www.gnu.org/copyleft/gpl.html" />
|
||||
<dc:title>PulseAudio logotype</dc:title>
|
||||
<dc:date>2006-08-28</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Pierre Ossman <ossman@cendio.se> for Cendio AB</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Rafael Jannone (basic idea)</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<rect
|
||||
ry="6.5049205"
|
||||
y="2.2257283"
|
||||
x="5.4760308"
|
||||
height="37.047943"
|
||||
width="37.047943"
|
||||
id="rect2371"
|
||||
style="fill:url(#linearGradient2255);fill-opacity:1;stroke:url(#linearGradient2257);stroke-width:0.99792439;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
inkscape:export-filename="/home/lennart/test.png"
|
||||
inkscape:export-xdpi="165.5896"
|
||||
inkscape:export-ydpi="165.5896" />
|
||||
<g
|
||||
transform="matrix(0.124741,0,0,0.124741,-61.69688,-99.94425)"
|
||||
id="g2415"
|
||||
inkscape:export-filename="/home/lennart/test.png"
|
||||
inkscape:export-xdpi="165.5896"
|
||||
inkscape:export-ydpi="165.5896">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:1;fill:#729fcf;fill-opacity:1;stroke:none;stroke-width:8;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path2417"
|
||||
sodipodi:cx="-1"
|
||||
sodipodi:cy="863.61249"
|
||||
sodipodi:rx="23"
|
||||
sodipodi:ry="23"
|
||||
d="M 22 863.61249 A 23 23 0 1 1 -24,863.61249 A 23 23 0 1 1 22 863.61249 z"
|
||||
transform="matrix(1.676363,0,0,1.676363,688.6772,-480.168)" />
|
||||
<path
|
||||
style="opacity:1;fill:#729fcf;fill-opacity:1;stroke:none;stroke-width:8;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M 666.92273,892.01313 C 633.50485,900.88553 608.86021,931.34683 608.86023,967.54442 C 608.86023,1003.7419 633.50486,1034.2345 666.92273,1043.1069 C 642.81497,1032.2877 625.48523,1002.5195 625.48523,967.54442 C 625.48522,932.56943 642.81496,902.83233 666.92273,892.01313 z M 707.07898,892.01313 C 731.18675,902.83233 748.51648,932.56933 748.51648,967.54442 C 748.51648,1002.5195 731.18674,1032.2877 707.07898,1043.1069 C 740.49686,1034.2345 765.1415,1003.7419 765.14148,967.54442 C 765.14148,931.34693 740.49687,900.88553 707.07898,892.01313 z "
|
||||
id="path2419" />
|
||||
<path
|
||||
id="path2421"
|
||||
d="M 655.64705,849.58672 C 603.46201,863.44178 564.97718,911.00985 564.97721,967.53562 C 564.97721,1024.0613 603.46203,1071.6783 655.64705,1085.5333 C 618.0006,1068.6381 590.93865,1022.1524 590.93865,967.53562 C 590.93863,912.91905 618.00059,866.48188 655.64705,849.58672 z M 718.35466,849.58672 C 756.00112,866.48188 783.06306,912.91889 783.06306,967.53562 C 783.06306,1022.1524 756.00111,1068.6381 718.35466,1085.5333 C 770.5397,1071.6783 809.02453,1024.0613 809.0245,967.53562 C 809.0245,911.01001 770.53972,863.44178 718.35466,849.58672 z "
|
||||
style="opacity:1;fill:#729fcf;fill-opacity:1;stroke:none;stroke-width:8;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g1494"
|
||||
transform="matrix(0.124741,0,0,0.124741,-13.36814,-87.21636)"
|
||||
inkscape:export-filename="/home/lennart/test.png"
|
||||
inkscape:export-xdpi="165.5896"
|
||||
inkscape:export-ydpi="165.5896">
|
||||
<path
|
||||
inkscape:export-ydpi="44.099998"
|
||||
inkscape:export-xdpi="44.099998"
|
||||
inkscape:export-filename="/home/ossman/Desktop/pa4.png"
|
||||
d="M 495.15625,93.84375 C 468.52243,93.84375 447.21875,115.11921 447.21875,141.75 L 447.21875,334.46875 C 447.21875,361.09954 468.52545,382.40625 495.15625,382.40625 L 687.84375,382.40625 C 714.47454,382.40625 735.78125,361.09955 735.78125,334.46875 L 735.78125,141.75 C 735.78125,115.11921 714.47755,93.84375 687.84375,93.84375 L 495.15625,93.84375 z "
|
||||
id="path2373"
|
||||
style="fill:url(#linearGradient2240);fill-opacity:1;stroke:none;stroke-width:8;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
inkscape:original="M 495.15625 89.625 C 466.26648 89.625 443 112.86023 443 141.75 L 443 334.46875 C 443 363.35852 466.26647 386.625 495.15625 386.625 L 687.84375 386.625 C 716.73352 386.625 740 363.35853 740 334.46875 L 740 141.75 C 740 112.86023 716.7335 89.625 687.84375 89.625 L 495.15625 89.625 z "
|
||||
inkscape:radius="-4.2074337"
|
||||
sodipodi:type="inkscape:offset"
|
||||
transform="translate(-291.933,627.3998)" />
|
||||
<path
|
||||
inkscape:export-ydpi="44.099998"
|
||||
inkscape:export-xdpi="44.099998"
|
||||
inkscape:export-filename="/home/ossman/Desktop/pa4.png"
|
||||
style="fill:url(#linearGradient2242);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 436.05138,821.4365 C 397.62524,862.62866 358.12861,865.874 299.93097,865.874 C 242.63828,865.874 199.11564,893.22114 163.06701,927.96775 L 163.06701,961.86851 C 163.06701,985.0884 181.12504,1001.9935 203.22326,1001.9935 L 395.91076,1006.0248 C 420.50531,1006.0248 436.03576,986.46307 436.03576,961.86851 L 436.05138,821.4365 z "
|
||||
id="path2375"
|
||||
sodipodi:nodetypes="cscccccc" />
|
||||
<path
|
||||
inkscape:export-ydpi="44.099998"
|
||||
inkscape:export-xdpi="44.099998"
|
||||
inkscape:export-filename="/home/ossman/Desktop/pa4.png"
|
||||
sodipodi:type="inkscape:offset"
|
||||
inkscape:radius="-8"
|
||||
inkscape:original="M 495.15625 89.625 C 466.26648 89.625 443 112.86023 443 141.75 L 443 334.46875 C 443 363.35852 466.26647 386.625 495.15625 386.625 L 687.84375 386.625 C 716.73352 386.625 740 363.35853 740 334.46875 L 740 141.75 C 740 112.86023 716.7335 89.625 687.84375 89.625 L 495.15625 89.625 z "
|
||||
style="fill:none;fill-opacity:1;stroke:url(#linearGradient2244);stroke-width:8;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path2377"
|
||||
d="M 495.15625,97.625 C 470.55593,97.625 451,117.15545 451,141.75 L 451,334.46875 C 451,359.0633 470.56169,378.625 495.15625,378.625 L 687.84375,378.625 C 712.4383,378.625 732,359.06331 732,334.46875 L 732,141.75 C 732,117.15545 712.44405,97.625 687.84375,97.625 L 495.15625,97.625 z "
|
||||
transform="translate(-291.933,627.3998)" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:30.33161926px;font-style:normal;font-weight:normal;line-height:125%;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
|
||||
x="49.689053"
|
||||
y="37.570499"
|
||||
id="text2188"
|
||||
sodipodi:linespacing="125%"
|
||||
inkscape:export-filename="/home/lennart/test.png"
|
||||
inkscape:export-xdpi="165.5896"
|
||||
inkscape:export-ydpi="165.5896"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2190"
|
||||
x="49.689053"
|
||||
y="37.570499"
|
||||
style="font-size:30.33161926px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Tuffy"><tspan
|
||||
style="font-size:30.33161926px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Tuffy"
|
||||
id="tspan2196">Pulse</tspan>Audio</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 16 KiB |
249
src/Makefile.am
249
src/Makefile.am
|
|
@ -30,6 +30,7 @@ pulseincludedir=$(includedir)/pulse
|
|||
pulsecoreincludedir=$(includedir)/pulsecore
|
||||
pulseconfdir=$(sysconfdir)/pulse
|
||||
pulselibexecdir=$(libexecdir)/pulse
|
||||
xdgautostartdir=$(sysconfdir)/xdg/autostart
|
||||
|
||||
###################################
|
||||
# Defines #
|
||||
|
|
@ -76,15 +77,14 @@ endif
|
|||
|
||||
if OS_IS_WIN32
|
||||
PA_THREAD_OBJS = \
|
||||
pulsecore/once-win32.c pulsecore/once.h \
|
||||
pulsecore/mutex-win32.c pulsecore/mutex.h \
|
||||
pulsecore/thread-win32.c pulsecore/thread.h
|
||||
pulsecore/thread-win32.c pulsecore/thread.h \
|
||||
pulsecore/semaphore-win32.c pulsecore/semaphore.h
|
||||
else
|
||||
PA_THREAD_OBJS = \
|
||||
pulsecore/atomic.h \
|
||||
pulsecore/once-posix.c pulsecore/once.h \
|
||||
pulsecore/mutex-posix.c pulsecore/mutex.h \
|
||||
pulsecore/thread-posix.c pulsecore/thread.h
|
||||
pulsecore/thread-posix.c pulsecore/thread.h \
|
||||
pulsecore/semaphore-posix.c pulsecore/semaphore.h
|
||||
endif
|
||||
|
||||
###################################
|
||||
|
|
@ -100,13 +100,19 @@ EXTRA_DIST = \
|
|||
depmod.py \
|
||||
daemon/esdcompat.in \
|
||||
utils/padsp \
|
||||
modules/module-defs.h.m4
|
||||
modules/module-defs.h.m4 \
|
||||
daemon/pulseaudio-module-xsmp.desktop
|
||||
|
||||
pulseconf_DATA = \
|
||||
default.pa \
|
||||
daemon.conf \
|
||||
client.conf
|
||||
|
||||
if HAVE_X11
|
||||
xdgautostart_DATA = \
|
||||
daemon/pulseaudio-module-xsmp.desktop
|
||||
endif
|
||||
|
||||
BUILT_SOURCES = \
|
||||
pulse/version.h
|
||||
|
||||
|
|
@ -122,13 +128,13 @@ pulseaudio_SOURCES = \
|
|||
daemon/cpulimit.c daemon/cpulimit.h \
|
||||
daemon/daemon-conf.c daemon/daemon-conf.h \
|
||||
daemon/dumpmodules.c daemon/dumpmodules.h \
|
||||
daemon/ltdl-bind-now.c daemon/ltdl-bind-now.h \
|
||||
daemon/main.c \
|
||||
pulsecore/gccmacro.h
|
||||
|
||||
pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) $(CAP_CFLAGS) $(LIBOIL_CFLAGS) $(DBUS_CFLAGS)
|
||||
pulseaudio_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
pulseaudio_LDADD = $(AM_LDADD) libpulsecore.la $(LIBLTDL) \
|
||||
$(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS)
|
||||
pulseaudio_LDADD = $(AM_LDADD) libpulsecore.la $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS) $(DBUS_LIBS)
|
||||
# This is needed because automake doesn't properly expand the foreach below
|
||||
pulseaudio_DEPENDENCIES = libpulsecore.la $(PREOPEN_LIBS)
|
||||
|
||||
|
|
@ -151,7 +157,8 @@ endif
|
|||
bin_PROGRAMS += \
|
||||
pacat \
|
||||
pactl \
|
||||
paplay
|
||||
paplay \
|
||||
pasuspender
|
||||
|
||||
if HAVE_AF_UNIX
|
||||
bin_PROGRAMS += pacmd
|
||||
|
|
@ -182,6 +189,11 @@ pactl_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS)
|
|||
pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS)
|
||||
pactl_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
pasuspender_SOURCES = utils/pasuspender.c
|
||||
pasuspender_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS)
|
||||
pasuspender_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS)
|
||||
pasuspender_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
pacmd_SOURCES = utils/pacmd.c pulsecore/pid.c pulsecore/pid.h
|
||||
pacmd_CFLAGS = $(AM_CFLAGS)
|
||||
pacmd_LDADD = $(AM_LDADD) libpulse.la
|
||||
|
|
@ -219,7 +231,14 @@ noinst_PROGRAMS = \
|
|||
hook-list-test \
|
||||
memblock-test \
|
||||
thread-test \
|
||||
flist-test
|
||||
flist-test \
|
||||
asyncq-test \
|
||||
asyncmsgq-test \
|
||||
queue-test \
|
||||
rtpoll-test \
|
||||
sig2str-test \
|
||||
resampler-test \
|
||||
smoother-test
|
||||
|
||||
if HAVE_SIGXCPU
|
||||
noinst_PROGRAMS += \
|
||||
|
|
@ -274,13 +293,31 @@ thread_test_CFLAGS = $(AM_CFLAGS)
|
|||
thread_test_LDADD = $(AM_LDADD) libpulsecore.la
|
||||
thread_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
flist_test_SOURCES = tests/flist-test.c \
|
||||
pulsecore/atomic.h \
|
||||
pulsecore/flist.c pulsecore/flist.h
|
||||
flist_test_SOURCES = tests/flist-test.c
|
||||
flist_test_CFLAGS = $(AM_CFLAGS)
|
||||
flist_test_LDADD = $(AM_LDADD) libpulsecore.la
|
||||
flist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
asyncq_test_SOURCES = tests/asyncq-test.c
|
||||
asyncq_test_CFLAGS = $(AM_CFLAGS)
|
||||
asyncq_test_LDADD = $(AM_LDADD) libpulsecore.la
|
||||
asyncq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
asyncmsgq_test_SOURCES = tests/asyncmsgq-test.c
|
||||
asyncmsgq_test_CFLAGS = $(AM_CFLAGS)
|
||||
asyncmsgq_test_LDADD = $(AM_LDADD) libpulsecore.la
|
||||
asyncmsgq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
queue_test_SOURCES = tests/queue-test.c
|
||||
queue_test_CFLAGS = $(AM_CFLAGS)
|
||||
queue_test_LDADD = $(AM_LDADD) libpulsecore.la
|
||||
queue_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
rtpoll_test_SOURCES = tests/rtpoll-test.c
|
||||
rtpoll_test_CFLAGS = $(AM_CFLAGS)
|
||||
rtpoll_test_LDADD = $(AM_LDADD) libpulsecore.la
|
||||
rtpoll_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
mcalign_test_SOURCES = tests/mcalign-test.c
|
||||
mcalign_test_CFLAGS = $(AM_CFLAGS)
|
||||
mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la
|
||||
|
|
@ -341,6 +378,21 @@ interpol_test_LDADD = $(AM_LDADD) libpulse.la
|
|||
interpol_test_CFLAGS = $(AM_CFLAGS)
|
||||
interpol_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
sig2str_test_SOURCES = tests/sig2str-test.c
|
||||
sig2str_test_LDADD = $(AM_LDADD) libpulsecore.la
|
||||
sig2str_test_CFLAGS = $(AM_CFLAGS)
|
||||
sig2str_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
resampler_test_SOURCES = tests/resampler-test.c
|
||||
resampler_test_LDADD = $(AM_LDADD) libpulsecore.la
|
||||
resampler_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
resampler_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
|
||||
|
||||
smoother_test_SOURCES = tests/smoother-test.c
|
||||
smoother_test_LDADD = $(AM_LDADD) libpulsecore.la
|
||||
smoother_test_CFLAGS = $(AM_CFLAGS)
|
||||
smoother_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
###################################
|
||||
# Client library #
|
||||
###################################
|
||||
|
|
@ -455,6 +507,10 @@ libpulse_la_SOURCES += \
|
|||
pulsecore/core-error.c pulsecore/core-error.h \
|
||||
pulsecore/winsock.h pulsecore/creds.h \
|
||||
pulsecore/shm.c pulsecore/shm.h \
|
||||
pulsecore/flist.c pulsecore/flist.h \
|
||||
pulsecore/object.c pulsecore/object.h \
|
||||
pulsecore/msgobject.c pulsecore/msgobject.h \
|
||||
pulsecore/once.c pulsecore/once.h \
|
||||
$(PA_THREAD_OBJS)
|
||||
|
||||
if OS_IS_WIN32
|
||||
|
|
@ -514,11 +570,27 @@ libpulsedsp_la_CFLAGS = $(AM_CFLAGS)
|
|||
libpulsedsp_la_LIBADD = $(AM_LIBADD) libpulse.la
|
||||
libpulsedsp_la_LDFLAGS = -avoid-version
|
||||
|
||||
###################################
|
||||
# Speex Resampler #
|
||||
###################################
|
||||
|
||||
noinst_LTLIBRARIES = libspeex-resampler-fixed.la libspeex-resampler-float.la libffmpeg-resampler.la
|
||||
|
||||
libspeex_resampler_fixed_la_CPPFLAGS = $(AM_CPPFLAGS) -DRANDOM_PREFIX=paspfx -DOUTSIDE_SPEEX -DFIXED_POINT
|
||||
libspeex_resampler_fixed_la_SOURCES = pulsecore/speex/resample.c pulsecore/speex/speex_resampler.h pulsecore/speex/arch.h pulsecore/speex/fixed_generic.h pulsecore/speexwrap.h
|
||||
|
||||
libspeex_resampler_float_la_CPPFLAGS = $(AM_CPPFLAGS) -DRANDOM_PREFIX=paspfl -DOUTSIDE_SPEEX
|
||||
libspeex_resampler_float_la_SOURCES = pulsecore/speex/resample.c pulsecore/speex/speex_resampler.h pulsecore/speex/arch.h
|
||||
|
||||
libffmpeg_resampler_la_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
libffmpeg_resampler_la_SOURCES = pulsecore/ffmpeg/resample2.c pulsecore/ffmpeg/avcodec.h pulsecore/ffmpeg/dsputil.h
|
||||
|
||||
###################################
|
||||
# Daemon core library #
|
||||
###################################
|
||||
|
||||
pulsecoreinclude_HEADERS = \
|
||||
#pulsecoreinclude_HEADERS =
|
||||
noinst_HEADERS = \
|
||||
pulsecore/autoload.h \
|
||||
pulsecore/atomic.h \
|
||||
pulsecore/cli-command.h \
|
||||
|
|
@ -567,6 +639,7 @@ pulsecoreinclude_HEADERS = \
|
|||
pulsecore/refcnt.h \
|
||||
pulsecore/mutex.h \
|
||||
pulsecore/thread.h \
|
||||
pulsecore/semaphore.h \
|
||||
pulsecore/once.h
|
||||
|
||||
lib_LTLIBRARIES += libpulsecore.la
|
||||
|
|
@ -608,6 +681,7 @@ libpulsecore_la_SOURCES += \
|
|||
pulsecore/memchunk.c pulsecore/memchunk.h \
|
||||
pulsecore/modargs.c pulsecore/modargs.h \
|
||||
pulsecore/modinfo.c pulsecore/modinfo.h \
|
||||
pulsecore/ltdl-helper.c pulsecore/ltdl-helper.h \
|
||||
pulsecore/module.c pulsecore/module.h \
|
||||
pulsecore/namereg.c pulsecore/namereg.h \
|
||||
pulsecore/pid.c pulsecore/pid.h \
|
||||
|
|
@ -636,6 +710,19 @@ libpulsecore_la_SOURCES += \
|
|||
pulsecore/core-error.c pulsecore/core-error.h \
|
||||
pulsecore/hook-list.c pulsecore/hook-list.h \
|
||||
pulsecore/shm.c pulsecore/shm.h \
|
||||
pulsecore/flist.c pulsecore/flist.h \
|
||||
pulsecore/asyncmsgq.c pulsecore/asyncmsgq.h \
|
||||
pulsecore/asyncq.c pulsecore/asyncq.h \
|
||||
pulsecore/thread-mq.c pulsecore/thread-mq.h \
|
||||
pulsecore/fdsem.c pulsecore/fdsem.h \
|
||||
pulsecore/object.c pulsecore/object.h \
|
||||
pulsecore/msgobject.c pulsecore/msgobject.h \
|
||||
pulsecore/rtsig.c pulsecore/rtsig.h \
|
||||
pulsecore/rtpoll.c pulsecore/rtpoll.h \
|
||||
pulsecore/rtclock.c pulsecore/rtclock.h \
|
||||
pulsecore/macro.h \
|
||||
pulsecore/once.c pulsecore/once.h \
|
||||
pulsecore/time-smoother.c pulsecore/time-smoother.h \
|
||||
$(PA_THREAD_OBJS)
|
||||
|
||||
if OS_IS_WIN32
|
||||
|
|
@ -645,13 +732,14 @@ endif
|
|||
|
||||
libpulsecore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS)
|
||||
libpulsecore_la_LDFLAGS = -version-info $(LIBPULSECORE_VERSION_INFO)
|
||||
libpulsecore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LIBICONV)
|
||||
libpulsecore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LIBICONV) libspeex-resampler-fixed.la libspeex-resampler-float.la libffmpeg-resampler.la
|
||||
|
||||
###################################
|
||||
# Plug-in support libraries #
|
||||
###################################
|
||||
|
||||
pulsecoreinclude_HEADERS += \
|
||||
#pulsecoreinclude_HEADERS +=
|
||||
noinst_HEADERS += \
|
||||
pulsecore/socket-util.h \
|
||||
pulsecore/iochannel.h \
|
||||
pulsecore/socket-server.h \
|
||||
|
|
@ -700,9 +788,9 @@ modlibexec_LTLIBRARIES = \
|
|||
libauthkey-prop.la \
|
||||
libstrlist.la \
|
||||
libprotocol-simple.la \
|
||||
libprotocol-esound.la \
|
||||
libprotocol-http.la \
|
||||
libprotocol-native.la \
|
||||
libprotocol-http.la
|
||||
libprotocol-esound.la
|
||||
|
||||
# We need to emulate sendmsg/recvmsg to support this on Win32
|
||||
if !OS_IS_WIN32
|
||||
|
|
@ -711,7 +799,8 @@ modlibexec_LTLIBRARIES += \
|
|||
endif
|
||||
|
||||
if HAVE_X11
|
||||
pulsecoreinclude_HEADERS += \
|
||||
#pulsecoreinclude_HEADERS +=
|
||||
noinst_HEADERS += \
|
||||
pulsecore/x11wrap.h \
|
||||
pulsecore/x11prop.h
|
||||
|
||||
|
|
@ -721,7 +810,8 @@ modlibexec_LTLIBRARIES += \
|
|||
endif
|
||||
|
||||
if HAVE_AVAHI
|
||||
pulsecoreinclude_HEADERS += \
|
||||
#pulsecoreinclude_HEADERS +=
|
||||
noinst_HEADERS += \
|
||||
pulsecore/avahi-wrap.h
|
||||
|
||||
modlibexec_LTLIBRARIES += \
|
||||
|
|
@ -851,19 +941,23 @@ modlibexec_LTLIBRARIES += \
|
|||
module-cli.la \
|
||||
module-cli-protocol-tcp.la \
|
||||
module-simple-protocol-tcp.la \
|
||||
module-esound-protocol-tcp.la \
|
||||
module-native-protocol-tcp.la \
|
||||
module-native-protocol-fd.la \
|
||||
module-sine.la \
|
||||
module-combine.la \
|
||||
module-tunnel-sink.la \
|
||||
module-tunnel-source.la \
|
||||
module-null-sink.la \
|
||||
module-esound-sink.la \
|
||||
module-http-protocol-tcp.la \
|
||||
module-detect.la \
|
||||
module-volume-restore.la \
|
||||
module-rescue-streams.la
|
||||
module-default-device-restore.la \
|
||||
module-rescue-streams.la \
|
||||
module-suspend-on-idle.la \
|
||||
module-http-protocol-tcp.la \
|
||||
module-sine.la \
|
||||
module-native-protocol-tcp.la \
|
||||
module-native-protocol-fd.la \
|
||||
module-esound-protocol-tcp.la \
|
||||
module-combine.la \
|
||||
module-remap-sink.la \
|
||||
module-ladspa-sink.la \
|
||||
module-esound-sink.la
|
||||
# module-tunnel-sink.la
|
||||
# module-tunnel-source.la
|
||||
|
||||
# See comment at librtp.la above
|
||||
if !OS_IS_WIN32
|
||||
|
|
@ -876,9 +970,9 @@ if HAVE_AF_UNIX
|
|||
modlibexec_LTLIBRARIES += \
|
||||
module-cli-protocol-unix.la \
|
||||
module-simple-protocol-unix.la \
|
||||
module-esound-protocol-unix.la \
|
||||
module-http-protocol-unix.la \
|
||||
module-native-protocol-unix.la \
|
||||
module-http-protocol-unix.la
|
||||
module-esound-protocol-unix.la
|
||||
endif
|
||||
|
||||
if HAVE_MKFIFO
|
||||
|
|
@ -901,14 +995,14 @@ endif
|
|||
if HAVE_X11
|
||||
modlibexec_LTLIBRARIES += \
|
||||
module-x11-bell.la \
|
||||
module-x11-publish.la
|
||||
module-x11-publish.la \
|
||||
module-x11-xsmp.la
|
||||
endif
|
||||
|
||||
if HAVE_OSS
|
||||
modlibexec_LTLIBRARIES += \
|
||||
liboss-util.la \
|
||||
module-oss.la \
|
||||
module-oss-mmap.la
|
||||
module-oss.la
|
||||
endif
|
||||
|
||||
if HAVE_ALSA
|
||||
|
|
@ -952,10 +1046,10 @@ pulselibexec_PROGRAMS = \
|
|||
gconf-helper
|
||||
endif
|
||||
|
||||
if OS_IS_WIN32
|
||||
modlibexec_LTLIBRARIES += \
|
||||
module-waveout.la
|
||||
endif
|
||||
#if OS_IS_WIN32
|
||||
#modlibexec_LTLIBRARIES += \
|
||||
# module-waveout.la
|
||||
#endif
|
||||
|
||||
if HAVE_HAL
|
||||
modlibexec_LTLIBRARIES += \
|
||||
|
|
@ -980,6 +1074,8 @@ SYMDEF_FILES = \
|
|||
modules/module-native-protocol-fd-symdef.h \
|
||||
modules/module-sine-symdef.h \
|
||||
modules/module-combine-symdef.h \
|
||||
modules/module-remap-sink-symdef.h \
|
||||
modules/module-ladspa-sink-symdef.h \
|
||||
modules/module-esound-compat-spawnfd-symdef.h \
|
||||
modules/module-esound-compat-spawnpid-symdef.h \
|
||||
modules/module-match-symdef.h \
|
||||
|
|
@ -994,8 +1090,8 @@ SYMDEF_FILES = \
|
|||
modules/module-http-protocol-unix-symdef.h \
|
||||
modules/module-x11-bell-symdef.h \
|
||||
modules/module-x11-publish-symdef.h \
|
||||
modules/module-x11-xsmp-symdef.h \
|
||||
modules/module-oss-symdef.h \
|
||||
modules/module-oss-mmap-symdef.h \
|
||||
modules/module-alsa-sink-symdef.h \
|
||||
modules/module-alsa-source-symdef.h \
|
||||
modules/module-solaris-symdef.h \
|
||||
|
|
@ -1006,7 +1102,9 @@ SYMDEF_FILES = \
|
|||
modules/module-jack-sink-symdef.h \
|
||||
modules/module-jack-source-symdef.h \
|
||||
modules/module-volume-restore-symdef.h \
|
||||
modules/module-default-device-restore-symdef.h \
|
||||
modules/module-rescue-streams-symdef.h \
|
||||
modules/module-suspend-on-idle-symdef.h \
|
||||
modules/module-hal-detect-symdef.h \
|
||||
modules/gconf/module-gconf-symdef.h
|
||||
|
||||
|
|
@ -1126,18 +1224,27 @@ module_combine_la_SOURCES = modules/module-combine.c
|
|||
module_combine_la_LDFLAGS = -module -avoid-version
|
||||
module_combine_la_LIBADD = $(AM_LIBADD) libpulsecore.la
|
||||
|
||||
module_remap_sink_la_SOURCES = modules/module-remap-sink.c
|
||||
module_remap_sink_la_LDFLAGS = -module -avoid-version
|
||||
module_remap_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la
|
||||
|
||||
module_ladspa_sink_la_SOURCES = modules/module-ladspa-sink.c modules/ladspa.h
|
||||
module_ladspa_sink_la_CFLAGS = -DLADSPA_PATH=\"$(libdir)/ladspa:/usr/local/lib/ladspa:/usr/lib/ladspa\" $(AM_CFLAGS)
|
||||
module_ladspa_sink_la_LDFLAGS = -module -avoid-version
|
||||
module_ladspa_sink_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) libpulsecore.la
|
||||
|
||||
module_match_la_SOURCES = modules/module-match.c
|
||||
module_match_la_LDFLAGS = -module -avoid-version
|
||||
module_match_la_LIBADD = $(AM_LIBADD) libpulsecore.la
|
||||
|
||||
module_tunnel_sink_la_SOURCES = modules/module-tunnel.c
|
||||
module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS)
|
||||
module_tunnel_sink_la_LDFLAGS = -module -avoid-version
|
||||
module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la
|
||||
#module_tunnel_sink_la_SOURCES = modules/module-tunnel.c
|
||||
#module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS)
|
||||
#module_tunnel_sink_la_LDFLAGS = -module -avoid-version
|
||||
#module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la
|
||||
|
||||
module_tunnel_source_la_SOURCES = modules/module-tunnel.c
|
||||
module_tunnel_source_la_LDFLAGS = -module -avoid-version
|
||||
module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la
|
||||
#module_tunnel_source_la_SOURCES = modules/module-tunnel.c
|
||||
#module_tunnel_source_la_LDFLAGS = -module -avoid-version
|
||||
#module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la
|
||||
|
||||
# X11
|
||||
|
||||
|
|
@ -1151,6 +1258,11 @@ module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS)
|
|||
module_x11_publish_la_LDFLAGS = -module -avoid-version
|
||||
module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libauthkey.la libauthkey-prop.la libx11prop.la libstrlist.la libpulsecore.la
|
||||
|
||||
module_x11_xsmp_la_SOURCES = modules/module-x11-xsmp.c
|
||||
module_x11_xsmp_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS)
|
||||
module_x11_xsmp_la_LDFLAGS = -module -avoid-version
|
||||
module_x11_xsmp_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libpulsecore.la
|
||||
|
||||
# OSS
|
||||
|
||||
liboss_util_la_SOURCES = modules/oss-util.c modules/oss-util.h
|
||||
|
|
@ -1161,10 +1273,6 @@ module_oss_la_SOURCES = modules/module-oss.c
|
|||
module_oss_la_LDFLAGS = -module -avoid-version
|
||||
module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la libpulsecore.la
|
||||
|
||||
module_oss_mmap_la_SOURCES = modules/module-oss-mmap.c
|
||||
module_oss_mmap_la_LDFLAGS = -module -avoid-version
|
||||
module_oss_mmap_la_LIBADD = $(AM_LIBADD) liboss-util.la libpulsecore.la
|
||||
|
||||
# ALSA
|
||||
|
||||
libalsa_util_la_SOURCES = modules/alsa-util.c modules/alsa-util.h
|
||||
|
|
@ -1211,10 +1319,10 @@ module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS)
|
|||
|
||||
# Windows waveout
|
||||
|
||||
module_waveout_la_SOURCES = modules/module-waveout.c
|
||||
module_waveout_la_LDFLAGS = -module -avoid-version
|
||||
module_waveout_la_LIBADD = $(AM_LIBADD) libpulsecore.la -lwinmm
|
||||
module_waveout_la_CFLAGS = $(AM_CFLAGS)
|
||||
#module_waveout_la_SOURCES = modules/module-waveout.c
|
||||
#module_waveout_la_LDFLAGS = -module -avoid-version
|
||||
#module_waveout_la_LIBADD = $(AM_LIBADD) libpulsecore.la -lwinmm
|
||||
#module_waveout_la_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
# Hardware autodetection module
|
||||
module_detect_la_SOURCES = modules/module-detect.c
|
||||
|
|
@ -1228,16 +1336,28 @@ module_volume_restore_la_LDFLAGS = -module -avoid-version
|
|||
module_volume_restore_la_LIBADD = $(AM_LIBADD) libpulsecore.la
|
||||
module_volume_restore_la_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
# Default sink/source restore module
|
||||
module_default_device_restore_la_SOURCES = modules/module-default-device-restore.c
|
||||
module_default_device_restore_la_LDFLAGS = -module -avoid-version
|
||||
module_default_device_restore_la_LIBADD = $(AM_LIBADD) libpulsecore.la
|
||||
module_default_device_restore_la_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
# Rescue streams module
|
||||
module_rescue_streams_la_SOURCES = modules/module-rescue-streams.c
|
||||
module_rescue_streams_la_LDFLAGS = -module -avoid-version
|
||||
module_rescue_streams_la_LIBADD = $(AM_LIBADD) libpulsecore.la
|
||||
module_rescue_streams_la_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
# Suspend-on-idle module
|
||||
module_suspend_on_idle_la_SOURCES = modules/module-suspend-on-idle.c
|
||||
module_suspend_on_idle_la_LDFLAGS = -module -avoid-version
|
||||
module_suspend_on_idle_la_LIBADD = $(AM_LIBADD) libpulsecore.la
|
||||
module_suspend_on_idle_la_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
# RTP modules
|
||||
module_rtp_send_la_SOURCES = modules/rtp/module-rtp-send.c
|
||||
module_rtp_send_la_LDFLAGS = -module -avoid-version
|
||||
module_rtp_send_la_LIBADD = $(AM_LIBADD) libpulsecore.la librtp.la
|
||||
module_rtp_send_la_LIBADD = $(AM_LIBADD) libpulsecore.la librtp.la libsocket-util.la
|
||||
module_rtp_send_la_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
module_rtp_recv_la_SOURCES = modules/rtp/module-rtp-recv.c
|
||||
|
|
@ -1275,7 +1395,7 @@ module_gconf_la_LIBADD = $(AM_LIBADD) libpulsecore.la
|
|||
module_gconf_la_CFLAGS = $(AM_CFLAGS) -DPA_GCONF_HELPER=\"$(pulselibexecdir)/gconf-helper\"
|
||||
|
||||
gconf_helper_SOURCES = modules/gconf/gconf-helper.c
|
||||
gconf_helper_LDADD = $(AM_LDADD) $(GCONF_LIBS)
|
||||
gconf_helper_LDADD = $(AM_LDADD) $(GCONF_LIBS) libpulsecore.la
|
||||
gconf_helper_CFLAGS = $(AM_CFLAGS) $(GCONF_CFLAGS)
|
||||
gconf_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
|
|
@ -1304,8 +1424,8 @@ default.pa: daemon/default.pa.win32
|
|||
else
|
||||
default.pa: daemon/default.pa.in Makefile
|
||||
sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' \
|
||||
-e 's,@HAVE_HAL_TRUE\@,@HAVE_HAL_TRUE@,g' \
|
||||
-e 's,@HAVE_HAL_FALSE\@,@HAVE_HAL_FALSE@,g' < $< > $@
|
||||
-e 's,@PA_DLSEARCHPATH\@,$(modlibexecdir),g' \
|
||||
-e 's,@PA_SOEXT\@,.so,g' < $< > $@
|
||||
endif
|
||||
|
||||
daemon.conf: daemon/daemon.conf.in Makefile
|
||||
|
|
@ -1323,4 +1443,13 @@ install-exec-hook:
|
|||
massif: pulseaudio
|
||||
libtool --mode=execute valgrind --tool=massif --depth=6 --alloc-fn=pa_xmalloc --alloc-fn=pa_xmalloc0 --alloc-fn=pa_xrealloc --alloc-fn=dbus_realloc --alloc-fn=pa_xnew0_internal --alloc-fn=pa_xnew_internal ./pulseaudio
|
||||
|
||||
update-speex:
|
||||
wget -O pulsecore/speex/speex_resampler.h http://svn.xiph.org/trunk/speex/include/speex/speex_resampler.h
|
||||
wget -O pulsecore/speex/resample.c http://svn.xiph.org/trunk/speex/libspeex/resample.c
|
||||
wget -O pulsecore/speex/arch.h http://svn.xiph.org/trunk/speex/libspeex/arch.h
|
||||
wget -O pulsecore/speex/fixed_generic.h http://svn.xiph.org/trunk/speex/libspeex/fixed_generic.h
|
||||
|
||||
update-ffmpeg:
|
||||
wget -O pulsecore/ffmpeg/resample2.c http://svn.mplayerhq.hu/ffmpeg/trunk/libavcodec/resample2.c?view=co
|
||||
|
||||
.PHONY: utils/padsp
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#ifdef HAVE_SYS_CAPABILITY_H
|
||||
#include <sys/capability.h>
|
||||
|
|
@ -60,7 +60,7 @@ void pa_drop_root(void) {
|
|||
if (uid == 0 || geteuid() != 0)
|
||||
return;
|
||||
|
||||
pa_log_info("dropping root rights.");
|
||||
pa_log_info("Dropping root priviliges.");
|
||||
|
||||
#if defined(HAVE_SETRESUID)
|
||||
setresuid(uid, uid, uid);
|
||||
|
|
@ -88,8 +88,9 @@ int pa_limit_caps(void) {
|
|||
cap_value_t nice_cap = CAP_SYS_NICE;
|
||||
|
||||
caps = cap_init();
|
||||
assert(caps);
|
||||
pa_assert(caps);
|
||||
cap_clear(caps);
|
||||
cap_set_flag(caps, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET);
|
||||
cap_set_flag(caps, CAP_PERMITTED, 1, &nice_cap, CAP_SET);
|
||||
|
||||
if (cap_set_proc(caps) < 0)
|
||||
|
|
@ -98,7 +99,7 @@ int pa_limit_caps(void) {
|
|||
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0)
|
||||
goto fail;
|
||||
|
||||
pa_log_info("dropped capabilities successfully.");
|
||||
pa_log_info("Dropped capabilities successfully.");
|
||||
|
||||
r = 1;
|
||||
|
||||
|
|
@ -114,14 +115,14 @@ int pa_drop_caps(void) {
|
|||
int r = -1;
|
||||
|
||||
caps = cap_init();
|
||||
assert(caps);
|
||||
pa_assert(caps);
|
||||
|
||||
cap_clear(caps);
|
||||
|
||||
prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
|
||||
|
||||
if (cap_set_proc(caps) < 0) {
|
||||
pa_log("failed to drop capabilities: %s", pa_cstrerror(errno));
|
||||
pa_log("Failed to drop capabilities: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
|
|
@ -36,6 +35,7 @@
|
|||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/strbuf.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "cmdline.h"
|
||||
|
||||
|
|
@ -63,7 +63,9 @@ enum {
|
|||
ARG_CHECK,
|
||||
ARG_NO_CPU_LIMIT,
|
||||
ARG_DISABLE_SHM,
|
||||
ARG_SYSTEM
|
||||
ARG_DUMP_RESAMPLE_METHODS,
|
||||
ARG_SYSTEM,
|
||||
ARG_CLEANUP_SHM
|
||||
};
|
||||
|
||||
/* Tabel for getopt_long() */
|
||||
|
|
@ -92,12 +94,16 @@ static struct option long_options[] = {
|
|||
{"system", 2, 0, ARG_SYSTEM},
|
||||
{"no-cpu-limit", 2, 0, ARG_NO_CPU_LIMIT},
|
||||
{"disable-shm", 2, 0, ARG_DISABLE_SHM},
|
||||
{"dump-resample-methods", 2, 0, ARG_DUMP_RESAMPLE_METHODS},
|
||||
{"cleanup-shm", 2, 0, ARG_CLEANUP_SHM},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
void pa_cmdline_help(const char *argv0) {
|
||||
const char *e;
|
||||
|
||||
pa_assert(argv0);
|
||||
|
||||
if ((e = strrchr(argv0, '/')))
|
||||
e++;
|
||||
else
|
||||
|
|
@ -109,6 +115,8 @@ void pa_cmdline_help(const char *argv0) {
|
|||
" --version Show version\n"
|
||||
" --dump-conf Dump default configuration\n"
|
||||
" --dump-modules Dump list of available modules\n"
|
||||
" --dump-resample-methods Dump available resample methods\n"
|
||||
" --cleanup-shm Cleanup stale shared memory segments\n"
|
||||
" -k --kill Kill a running daemon\n"
|
||||
" --check Check for a running daemon\n\n"
|
||||
|
||||
|
|
@ -131,9 +139,8 @@ void pa_cmdline_help(const char *argv0) {
|
|||
" -p, --dl-search-path=PATH Set the search path for dynamic shared\n"
|
||||
" objects (plugins)\n"
|
||||
" --resample-method=[METHOD] Use the specified resampling method\n"
|
||||
" (one of src-sinc-medium-quality,\n"
|
||||
" src-sinc-best-quality,src-sinc-fastest\n"
|
||||
" src-zero-order-hold,src-linear,trivial)\n"
|
||||
" (See --dump-resample-methods for\n"
|
||||
" possible values)\n"
|
||||
" --use-pid-file[=BOOL] Create a PID file\n"
|
||||
" --no-cpu-limit[=BOOL] Do not install CPU load limiter on\n"
|
||||
" platforms that support it.\n"
|
||||
|
|
@ -152,7 +159,10 @@ void pa_cmdline_help(const char *argv0) {
|
|||
int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d) {
|
||||
pa_strbuf *buf = NULL;
|
||||
int c;
|
||||
assert(conf && argc && argv);
|
||||
|
||||
pa_assert(conf);
|
||||
pa_assert(argc > 0);
|
||||
pa_assert(argv);
|
||||
|
||||
buf = pa_strbuf_new();
|
||||
|
||||
|
|
@ -178,6 +188,14 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
|
|||
conf->cmd = PA_CMD_DUMP_MODULES;
|
||||
break;
|
||||
|
||||
case ARG_DUMP_RESAMPLE_METHODS:
|
||||
conf->cmd = PA_CMD_DUMP_RESAMPLE_METHODS;
|
||||
break;
|
||||
|
||||
case ARG_CLEANUP_SHM:
|
||||
conf->cmd = PA_CMD_CLEANUP_SHM;
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
case ARG_KILL:
|
||||
conf->cmd = PA_CMD_KILL;
|
||||
|
|
@ -193,9 +211,12 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
|
|||
break;
|
||||
|
||||
case ARG_FILE:
|
||||
case 'F':
|
||||
pa_strbuf_printf(buf, ".include %s\n", optarg);
|
||||
case 'F': {
|
||||
char *p;
|
||||
pa_strbuf_printf(buf, ".include %s\n", p = pa_make_path_absolute(optarg));
|
||||
pa_xfree(p);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'C':
|
||||
pa_strbuf_puts(buf, "load-module module-cli exit_on_eof=1\n");
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "cpulimit.h"
|
||||
|
||||
|
|
@ -38,7 +39,6 @@
|
|||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
|
@ -92,23 +92,18 @@ static enum {
|
|||
|
||||
/* Reset the SIGXCPU timer to the next t seconds */
|
||||
static void reset_cpu_time(int t) {
|
||||
int r;
|
||||
long n;
|
||||
struct rlimit rl;
|
||||
struct rusage ru;
|
||||
|
||||
/* Get the current CPU time of the current process */
|
||||
r = getrusage(RUSAGE_SELF, &ru);
|
||||
assert(r >= 0);
|
||||
pa_assert_se(getrusage(RUSAGE_SELF, &ru) >= 0);
|
||||
|
||||
n = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec + t;
|
||||
|
||||
r = getrlimit(RLIMIT_CPU, &rl);
|
||||
assert(r >= 0);
|
||||
pa_assert_se(getrlimit(RLIMIT_CPU, &rl) >= 0);
|
||||
|
||||
rl.rlim_cur = n;
|
||||
r = setrlimit(RLIMIT_CPU, &rl);
|
||||
assert(r >= 0);
|
||||
pa_assert_se(setrlimit(RLIMIT_CPU, &rl) >= 0);
|
||||
}
|
||||
|
||||
/* A simple, thread-safe puts() work-alike */
|
||||
|
|
@ -118,7 +113,7 @@ static void write_err(const char *p) {
|
|||
|
||||
/* The signal handler, called on every SIGXCPU */
|
||||
static void signal_handler(int sig) {
|
||||
assert(sig == SIGXCPU);
|
||||
pa_assert(sig == SIGXCPU);
|
||||
|
||||
if (phase == PHASE_IDLE) {
|
||||
time_t now;
|
||||
|
|
@ -130,7 +125,7 @@ static void signal_handler(int sig) {
|
|||
time(&now);
|
||||
|
||||
#ifdef PRINT_CPU_LOAD
|
||||
snprintf(t, sizeof(t), "Using %0.1f%% CPU\n", (double)CPUTIME_INTERVAL_SOFT/(now-last_time)*100);
|
||||
pa_snprintf(t, sizeof(t), "Using %0.1f%% CPU\n", (double)CPUTIME_INTERVAL_SOFT/(now-last_time)*100);
|
||||
write_err(t);
|
||||
#endif
|
||||
|
||||
|
|
@ -160,7 +155,12 @@ static void signal_handler(int sig) {
|
|||
/* Callback for IO events on the FIFO */
|
||||
static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata) {
|
||||
char c;
|
||||
assert(m && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == the_pipe[0]);
|
||||
pa_assert(m);
|
||||
pa_assert(e);
|
||||
pa_assert(f == PA_IO_EVENT_INPUT);
|
||||
pa_assert(e == io_event);
|
||||
pa_assert(fd == the_pipe[0]);
|
||||
|
||||
pa_read(the_pipe[0], &c, sizeof(c), NULL);
|
||||
m->quit(m, 1); /* Quit the main loop */
|
||||
}
|
||||
|
|
@ -168,7 +168,13 @@ static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags
|
|||
/* Initializes CPU load limiter */
|
||||
int pa_cpu_limit_init(pa_mainloop_api *m) {
|
||||
struct sigaction sa;
|
||||
assert(m && !api && !io_event && the_pipe[0] == -1 && the_pipe[1] == -1 && !installed);
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(!api);
|
||||
pa_assert(!io_event);
|
||||
pa_assert(the_pipe[0] == -1);
|
||||
pa_assert(the_pipe[1] == -1);
|
||||
pa_assert(!installed);
|
||||
|
||||
time(&last_time);
|
||||
|
||||
|
|
@ -178,10 +184,10 @@ int pa_cpu_limit_init(pa_mainloop_api *m) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
pa_make_nonblock_fd(the_pipe[0]);
|
||||
pa_make_nonblock_fd(the_pipe[1]);
|
||||
pa_fd_set_cloexec(the_pipe[0], 1);
|
||||
pa_fd_set_cloexec(the_pipe[1], 1);
|
||||
pa_make_fd_nonblock(the_pipe[0]);
|
||||
pa_make_fd_nonblock(the_pipe[1]);
|
||||
pa_make_fd_cloexec(the_pipe[0]);
|
||||
pa_make_fd_cloexec(the_pipe[1]);
|
||||
|
||||
api = m;
|
||||
io_event = api->io_new(m, the_pipe[0], PA_IO_EVENT_INPUT, callback, NULL);
|
||||
|
|
@ -208,24 +214,18 @@ int pa_cpu_limit_init(pa_mainloop_api *m) {
|
|||
|
||||
/* Shutdown CPU load limiter */
|
||||
void pa_cpu_limit_done(void) {
|
||||
int r;
|
||||
|
||||
if (io_event) {
|
||||
assert(api);
|
||||
pa_assert(api);
|
||||
api->io_free(io_event);
|
||||
io_event = NULL;
|
||||
api = NULL;
|
||||
}
|
||||
|
||||
if (the_pipe[0] >= 0)
|
||||
close(the_pipe[0]);
|
||||
if (the_pipe[1] >= 0)
|
||||
close(the_pipe[1]);
|
||||
the_pipe[0] = the_pipe[1] = -1;
|
||||
pa_close_pipe(the_pipe);
|
||||
|
||||
if (installed) {
|
||||
r = sigaction(SIGXCPU, &sigaction_prev, NULL);
|
||||
assert(r >= 0);
|
||||
pa_assert_se(sigaction(SIGXCPU, &sigaction_prev, NULL) >= 0);
|
||||
installed = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
|
@ -39,19 +38,14 @@
|
|||
#include <pulsecore/strbuf.h>
|
||||
#include <pulsecore/conf-parser.h>
|
||||
#include <pulsecore/resampler.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "daemon-conf.h"
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
# define PATH_SEP "/"
|
||||
#else
|
||||
# define PATH_SEP "\\"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "default.pa"
|
||||
#define DEFAULT_SCRIPT_FILE_USER PATH_SEP "default.pa"
|
||||
#define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf"
|
||||
#define DEFAULT_CONFIG_FILE_USER PATH_SEP "daemon.conf"
|
||||
#define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "default.pa"
|
||||
#define DEFAULT_SCRIPT_FILE_USER PA_PATH_SEP "default.pa"
|
||||
#define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "daemon.conf"
|
||||
#define DEFAULT_CONFIG_FILE_USER PA_PATH_SEP "daemon.conf"
|
||||
|
||||
#define ENV_SCRIPT_FILE "PULSE_SCRIPT"
|
||||
#define ENV_CONFIG_FILE "PULSE_CONFIG"
|
||||
|
|
@ -72,31 +66,34 @@ static const pa_daemon_conf default_conf = {
|
|||
.default_script_file = NULL,
|
||||
.log_target = PA_LOG_SYSLOG,
|
||||
.log_level = PA_LOG_NOTICE,
|
||||
.resample_method = PA_RESAMPLER_SRC_SINC_FASTEST,
|
||||
.resample_method = PA_RESAMPLER_AUTO,
|
||||
.config_file = NULL,
|
||||
.use_pid_file = 1,
|
||||
.system_instance = 0,
|
||||
.no_cpu_limit = 0,
|
||||
.disable_shm = 0
|
||||
.disable_shm = 0,
|
||||
.default_n_fragments = 4,
|
||||
.default_fragment_size_msec = 25,
|
||||
.default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 }
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
, .rlimit_as = { .value = 0, .is_set = 0 },
|
||||
.rlimit_core = { .value = 0, .is_set = 0 },
|
||||
.rlimit_data = { .value = 0, .is_set = 0 },
|
||||
.rlimit_fsize = { .value = 0, .is_set = 0 },
|
||||
.rlimit_nofile = { .value = 200, .is_set = 1 },
|
||||
.rlimit_nofile = { .value = 256, .is_set = 1 },
|
||||
.rlimit_stack = { .value = 0, .is_set = 0 }
|
||||
#ifdef RLIMIT_NPROC
|
||||
, .rlimit_nproc = { .value = 0, .is_set = 0 }
|
||||
#endif
|
||||
#ifdef RLIMIT_MEMLOCK
|
||||
, .rlimit_memlock = { .value = 0, .is_set = 1 }
|
||||
, .rlimit_memlock = { .value = 16384, .is_set = 1 }
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
pa_daemon_conf* pa_daemon_conf_new(void) {
|
||||
FILE *f;
|
||||
pa_daemon_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf));
|
||||
pa_daemon_conf *c = pa_xnewdup(pa_daemon_conf, &default_conf, 1);
|
||||
|
||||
if ((f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file, "r")))
|
||||
fclose(f);
|
||||
|
|
@ -106,7 +103,7 @@ pa_daemon_conf* pa_daemon_conf_new(void) {
|
|||
}
|
||||
|
||||
void pa_daemon_conf_free(pa_daemon_conf *c) {
|
||||
assert(c);
|
||||
pa_assert(c);
|
||||
pa_xfree(c->script_commands);
|
||||
pa_xfree(c->dl_search_path);
|
||||
pa_xfree(c->default_script_file);
|
||||
|
|
@ -115,7 +112,8 @@ void pa_daemon_conf_free(pa_daemon_conf *c) {
|
|||
}
|
||||
|
||||
int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string) {
|
||||
assert(c && string);
|
||||
pa_assert(c);
|
||||
pa_assert(string);
|
||||
|
||||
if (!strcmp(string, "auto"))
|
||||
c->auto_log_target = 1;
|
||||
|
|
@ -133,7 +131,8 @@ int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string) {
|
|||
|
||||
int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) {
|
||||
uint32_t u;
|
||||
assert(c && string);
|
||||
pa_assert(c);
|
||||
pa_assert(string);
|
||||
|
||||
if (pa_atou(string, &u) >= 0) {
|
||||
if (u >= PA_LOG_LEVEL_MAX)
|
||||
|
|
@ -158,7 +157,8 @@ int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) {
|
|||
|
||||
int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) {
|
||||
int m;
|
||||
assert(c && string);
|
||||
pa_assert(c);
|
||||
pa_assert(string);
|
||||
|
||||
if ((m = pa_parse_resample_method(string)) < 0)
|
||||
return -1;
|
||||
|
|
@ -169,7 +169,11 @@ int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) {
|
|||
|
||||
static int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
assert(filename && lvalue && rvalue && data);
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_daemon_conf_set_log_target(c, rvalue) < 0) {
|
||||
pa_log("[%s:%u] Invalid log target '%s'.", filename, line, rvalue);
|
||||
|
|
@ -181,7 +185,11 @@ static int parse_log_target(const char *filename, unsigned line, const char *lva
|
|||
|
||||
static int parse_log_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
assert(filename && lvalue && rvalue && data);
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_daemon_conf_set_log_level(c, rvalue) < 0) {
|
||||
pa_log("[%s:%u] Invalid log level '%s'.", filename, line, rvalue);
|
||||
|
|
@ -193,10 +201,14 @@ static int parse_log_level(const char *filename, unsigned line, const char *lval
|
|||
|
||||
static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
assert(filename && lvalue && rvalue && data);
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_daemon_conf_set_resample_method(c, rvalue) < 0) {
|
||||
pa_log("[%s:%u] Inavalid resample method '%s'.", filename, line, rvalue);
|
||||
pa_log("[%s:%u] Invalid resample method '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -206,10 +218,11 @@ static int parse_resample_method(const char *filename, unsigned line, const char
|
|||
static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
struct pa_rlimit *r = data;
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(r);
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(r);
|
||||
|
||||
if (rvalue[strspn(rvalue, "\t ")] == 0) {
|
||||
/* Empty string */
|
||||
|
|
@ -218,7 +231,7 @@ static int parse_rlimit(const char *filename, unsigned line, const char *lvalue,
|
|||
} else {
|
||||
int32_t k;
|
||||
if (pa_atoi(rvalue, &k) < 0) {
|
||||
pa_log("[%s:%u] Inavalid rlimit '%s'.", filename, line, rvalue);
|
||||
pa_log("[%s:%u] Invalid rlimit '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
r->is_set = k >= 0;
|
||||
|
|
@ -231,43 +244,138 @@ static int parse_rlimit(const char *filename, unsigned line, const char *lvalue,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int parse_sample_format(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
pa_sample_format_t f;
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if ((f = pa_parse_sample_format(rvalue)) < 0) {
|
||||
pa_log("[%s:%u] Invalid sample format '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->default_sample_spec.format = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_sample_rate(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t r;
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_atoi(rvalue, &r) < 0 || r > PA_RATE_MAX || r <= 0) {
|
||||
pa_log("[%s:%u] Invalid sample rate '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->default_sample_spec.rate = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_sample_channels(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t n;
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_atoi(rvalue, &n) < 0 || n > PA_CHANNELS_MAX || n <= 0) {
|
||||
pa_log("[%s:%u] Invalid sample channels '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->default_sample_spec.channels = (uint8_t) n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_fragments(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t n;
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_atoi(rvalue, &n) < 0 || n < 2) {
|
||||
pa_log("[%s:%u] Invalid number of fragments '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->default_n_fragments = (unsigned) n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_fragment_size_msec(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
|
||||
pa_daemon_conf *c = data;
|
||||
int32_t n;
|
||||
|
||||
pa_assert(filename);
|
||||
pa_assert(lvalue);
|
||||
pa_assert(rvalue);
|
||||
pa_assert(data);
|
||||
|
||||
if (pa_atoi(rvalue, &n) < 0 || n < 1) {
|
||||
pa_log("[%s:%u] Invalid fragment size '%s'.", filename, line, rvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->default_fragment_size_msec = (unsigned) n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
|
||||
int r = -1;
|
||||
FILE *f = NULL;
|
||||
|
||||
pa_config_item table[] = {
|
||||
{ "daemonize", pa_config_parse_bool, NULL },
|
||||
{ "fail", pa_config_parse_bool, NULL },
|
||||
{ "high-priority", pa_config_parse_bool, NULL },
|
||||
{ "disallow-module-loading", pa_config_parse_bool, NULL },
|
||||
{ "exit-idle-time", pa_config_parse_int, NULL },
|
||||
{ "module-idle-time", pa_config_parse_int, NULL },
|
||||
{ "scache-idle-time", pa_config_parse_int, NULL },
|
||||
{ "dl-search-path", pa_config_parse_string, NULL },
|
||||
{ "default-script-file", pa_config_parse_string, NULL },
|
||||
{ "log-target", parse_log_target, NULL },
|
||||
{ "log-level", parse_log_level, NULL },
|
||||
{ "verbose", parse_log_level, NULL },
|
||||
{ "resample-method", parse_resample_method, NULL },
|
||||
{ "use-pid-file", pa_config_parse_bool, NULL },
|
||||
{ "system-instance", pa_config_parse_bool, NULL },
|
||||
{ "no-cpu-limit", pa_config_parse_bool, NULL },
|
||||
{ "disable-shm", pa_config_parse_bool, NULL },
|
||||
{ "daemonize", pa_config_parse_bool, NULL },
|
||||
{ "fail", pa_config_parse_bool, NULL },
|
||||
{ "high-priority", pa_config_parse_bool, NULL },
|
||||
{ "disallow-module-loading", pa_config_parse_bool, NULL },
|
||||
{ "exit-idle-time", pa_config_parse_int, NULL },
|
||||
{ "module-idle-time", pa_config_parse_int, NULL },
|
||||
{ "scache-idle-time", pa_config_parse_int, NULL },
|
||||
{ "dl-search-path", pa_config_parse_string, NULL },
|
||||
{ "default-script-file", pa_config_parse_string, NULL },
|
||||
{ "log-target", parse_log_target, NULL },
|
||||
{ "log-level", parse_log_level, NULL },
|
||||
{ "verbose", parse_log_level, NULL },
|
||||
{ "resample-method", parse_resample_method, NULL },
|
||||
{ "use-pid-file", pa_config_parse_bool, NULL },
|
||||
{ "system-instance", pa_config_parse_bool, NULL },
|
||||
{ "no-cpu-limit", pa_config_parse_bool, NULL },
|
||||
{ "disable-shm", pa_config_parse_bool, NULL },
|
||||
{ "default-sample-format", parse_sample_format, NULL },
|
||||
{ "default-sample-rate", parse_sample_rate, NULL },
|
||||
{ "default-sample-channels", parse_sample_channels, NULL },
|
||||
{ "default-fragments", parse_fragments, NULL },
|
||||
{ "default-fragment-size-msec", parse_fragment_size_msec, NULL },
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
{ "rlimit-as", parse_rlimit, NULL },
|
||||
{ "rlimit-core", parse_rlimit, NULL },
|
||||
{ "rlimit-data", parse_rlimit, NULL },
|
||||
{ "rlimit-fsize", parse_rlimit, NULL },
|
||||
{ "rlimit-nofile", parse_rlimit, NULL },
|
||||
{ "rlimit-stack", parse_rlimit, NULL },
|
||||
{ "rlimit-as", parse_rlimit, NULL },
|
||||
{ "rlimit-core", parse_rlimit, NULL },
|
||||
{ "rlimit-data", parse_rlimit, NULL },
|
||||
{ "rlimit-fsize", parse_rlimit, NULL },
|
||||
{ "rlimit-nofile", parse_rlimit, NULL },
|
||||
{ "rlimit-stack", parse_rlimit, NULL },
|
||||
#ifdef RLIMIT_NPROC
|
||||
{ "rlimit-nproc", parse_rlimit, NULL },
|
||||
{ "rlimit-nproc", parse_rlimit, NULL },
|
||||
#endif
|
||||
#ifdef RLIMIT_MEMLOCK
|
||||
{ "rlimit-memlock", parse_rlimit, NULL },
|
||||
{ "rlimit-memlock", parse_rlimit, NULL },
|
||||
#endif
|
||||
#endif
|
||||
{ NULL, NULL, NULL },
|
||||
{ NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
table[0].data = &c->daemonize;
|
||||
|
|
@ -287,25 +395,29 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
|
|||
table[14].data = &c->system_instance;
|
||||
table[15].data = &c->no_cpu_limit;
|
||||
table[16].data = &c->disable_shm;
|
||||
table[17].data = c;
|
||||
table[18].data = c;
|
||||
table[19].data = c;
|
||||
table[20].data = c;
|
||||
table[21].data = c;
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
table[17].data = &c->rlimit_as;
|
||||
table[18].data = &c->rlimit_core;
|
||||
table[19].data = &c->rlimit_data;
|
||||
table[20].data = &c->rlimit_fsize;
|
||||
table[21].data = &c->rlimit_nofile;
|
||||
table[22].data = &c->rlimit_stack;
|
||||
table[22].data = &c->rlimit_as;
|
||||
table[23].data = &c->rlimit_core;
|
||||
table[24].data = &c->rlimit_data;
|
||||
table[25].data = &c->rlimit_fsize;
|
||||
table[26].data = &c->rlimit_nofile;
|
||||
table[27].data = &c->rlimit_stack;
|
||||
#ifdef RLIMIT_NPROC
|
||||
table[23].data = &c->rlimit_nproc;
|
||||
table[28].data = &c->rlimit_nproc;
|
||||
#endif
|
||||
#ifdef RLIMIT_MEMLOCK
|
||||
#ifndef RLIMIT_NPROC
|
||||
#error "Houston, we have a numbering problem!"
|
||||
#endif
|
||||
table[24].data = &c->rlimit_memlock;
|
||||
table[29].data = &c->rlimit_memlock;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
pa_xfree(c->config_file);
|
||||
c->config_file = NULL;
|
||||
|
||||
|
|
@ -314,7 +426,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
|
|||
pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file, "r");
|
||||
|
||||
if (!f && errno != ENOENT) {
|
||||
pa_log("WARNING: failed to open configuration file '%s': %s", c->config_file, pa_cstrerror(errno));
|
||||
pa_log_warn("Failed to open configuration file '%s': %s", c->config_file, pa_cstrerror(errno));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -351,12 +463,16 @@ static const char* const log_level_to_string[] = {
|
|||
};
|
||||
|
||||
char *pa_daemon_conf_dump(pa_daemon_conf *c) {
|
||||
pa_strbuf *s = pa_strbuf_new();
|
||||
pa_strbuf *s;
|
||||
|
||||
pa_assert(c);
|
||||
|
||||
s = pa_strbuf_new();
|
||||
|
||||
if (c->config_file)
|
||||
pa_strbuf_printf(s, "### Read from configuration file: %s ###\n", c->config_file);
|
||||
|
||||
assert(c->log_level <= PA_LOG_LEVEL_MAX);
|
||||
pa_assert(c->log_level <= PA_LOG_LEVEL_MAX);
|
||||
|
||||
pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize);
|
||||
pa_strbuf_printf(s, "fail = %i\n", !!c->fail);
|
||||
|
|
@ -373,7 +489,12 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
|
|||
pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file);
|
||||
pa_strbuf_printf(s, "system-instance = %i\n", !!c->system_instance);
|
||||
pa_strbuf_printf(s, "no-cpu-limit = %i\n", !!c->no_cpu_limit);
|
||||
pa_strbuf_printf(s, "disable_shm = %i\n", !!c->disable_shm);
|
||||
pa_strbuf_printf(s, "disable-shm = %i\n", !!c->disable_shm);
|
||||
pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format));
|
||||
pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate);
|
||||
pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels);
|
||||
pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments);
|
||||
pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec);
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1);
|
||||
pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
***/
|
||||
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulse/sample.h>
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
#include <sys/resource.h>
|
||||
|
|
@ -39,7 +40,9 @@ typedef enum pa_daemon_conf_cmd {
|
|||
PA_CMD_DUMP_CONF,
|
||||
PA_CMD_DUMP_MODULES,
|
||||
PA_CMD_KILL,
|
||||
PA_CMD_CHECK
|
||||
PA_CMD_CHECK,
|
||||
PA_CMD_DUMP_RESAMPLE_METHODS,
|
||||
PA_CMD_CLEANUP_SHM
|
||||
} pa_daemon_conf_cmd_t;
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
|
|
@ -80,6 +83,8 @@ typedef struct pa_daemon_conf {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
unsigned default_n_fragments, default_fragment_size_msec;
|
||||
pa_sample_spec default_sample_spec;
|
||||
} pa_daemon_conf;
|
||||
|
||||
/* Allocate a new structure and fill it with sane defaults */
|
||||
|
|
|
|||
|
|
@ -92,10 +92,19 @@
|
|||
; rlimit-core = -1
|
||||
; rlimit-data = -1
|
||||
; rlimit-fsize = -1
|
||||
; rlimit-nofile = 200
|
||||
; rlimit-nofile = 256
|
||||
; rlimit-stack = -1
|
||||
; rlimit-nproc = -1
|
||||
; rlimit-memlock = 25
|
||||
; rlimit-memlock = 16384
|
||||
|
||||
## Disable shared memory data transfer
|
||||
; disable-shm = 0
|
||||
|
||||
## Default sample format
|
||||
; default-sample-format = s16le
|
||||
; default-sample-rate = 44100
|
||||
; default-sample-channels = 2
|
||||
|
||||
## Default fragment settings, for device drivers that need this
|
||||
; default-fragments = 4
|
||||
; default-fragment-size-msec = 25
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#!@PA_BINARY@ -nF
|
||||
|
||||
#!@PA_BINARY@ -nF
|
||||
#
|
||||
# This file is part of PulseAudio.
|
||||
#
|
||||
|
|
@ -17,8 +16,19 @@
|
|||
# along with PulseAudio; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
.nofail
|
||||
|
||||
### Load audio drivers statically
|
||||
### Load something into the sample cache
|
||||
#load-sample-lazy x11-bell /usr/share/sounds/gtk-events/activate.wav
|
||||
load-sample-lazy pulse-hotplug /usr/share/sounds/startup3.wav
|
||||
#load-sample-lazy pulse-coldplug /usr/share/sounds/startup3.wav
|
||||
#load-sample-lazy pulse-access /usr/share/sounds/generic.wav
|
||||
|
||||
.fail
|
||||
|
||||
### Load audio drivers statically (it's probably better to not load
|
||||
### these drivers manually, but instead use module-hal-detect --
|
||||
### see below -- for doing this automatically)
|
||||
#load-module module-alsa-sink
|
||||
#load-module module-alsa-source device=hw:1,0
|
||||
#load-module module-oss device="/dev/dsp" sink_name=output source_name=input
|
||||
|
|
@ -27,19 +37,13 @@
|
|||
#load-module module-pipe-sink
|
||||
|
||||
### Automatically load driver modules depending on the hardware available
|
||||
@HAVE_HAL_TRUE@load-module module-hal-detect
|
||||
|
||||
.ifexists @PA_DLSEARCHPATH@/module-hal-detect@PA_SOEXT@
|
||||
load-module module-hal-detect
|
||||
.else
|
||||
### Alternatively use the static hardware detection module (for systems that
|
||||
### lack HAL support
|
||||
@HAVE_HAL_FALSE@load-module module-detect
|
||||
|
||||
### Load audio drivers automatically on access
|
||||
#add-autoload-sink output module-oss device="/dev/dsp" sink_name=output source_name=input
|
||||
#add-autoload-source input module-oss device="/dev/dsp" sink_name=output source_name=input
|
||||
#add-autoload-sink output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input
|
||||
#add-autoload-source input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input
|
||||
#add-autoload-sink output module-alsa-sink sink_name=output
|
||||
#add-autoload-source input module-alsa-source source_name=input
|
||||
### lack HAL support)
|
||||
load-module module-detect
|
||||
.endif
|
||||
|
||||
### Load several protocols
|
||||
load-module module-esound-protocol-unix
|
||||
|
|
@ -61,27 +65,36 @@ load-module module-native-protocol-unix
|
|||
### Automatically restore the volume of playback streams
|
||||
load-module module-volume-restore
|
||||
|
||||
### Automatically restore the default sink/source when changed by the user during runtime
|
||||
load-module module-default-device-restore
|
||||
|
||||
### Automatically move streams to the default sink if the sink they are
|
||||
### connected to dies, similar for sources
|
||||
load-module module-rescue-streams
|
||||
|
||||
### Make some devices default
|
||||
#set-default-sink output
|
||||
#set-default-source input
|
||||
|
||||
.nofail
|
||||
|
||||
### Load something to the sample cache
|
||||
load-sample x11-bell /usr/share/sounds/gtk-events/activate.wav
|
||||
#load-sample-dir-lazy /usr/share/sounds/*.wav
|
||||
### Automatically suspend sinks/sources that become idle for too long
|
||||
load-module module-suspend-on-idle
|
||||
|
||||
### Load X11 bell module
|
||||
load-module module-x11-bell sample=x11-bell
|
||||
#load-module module-x11-bell sample=x11-bell
|
||||
|
||||
### Publish connection data in the X11 root window
|
||||
.ifexists @PA_DLSEARCHPATH@/module-x11-publish@PA_SOEXT@
|
||||
load-module module-x11-publish
|
||||
.endif
|
||||
|
||||
### Register ourselves in the X11 session manager
|
||||
# Deactivated by default, to avoid deadlock when PA is started as esd from gnome-session
|
||||
# Instead we load this via /etc/xdg/autostart/ and "pactl load-module" now
|
||||
# load-module module-x11-xsmp
|
||||
|
||||
### Load additional modules from GConf settings. This can be configured with the paprefs tool.
|
||||
### Please keep in mind that the modules configured by paprefs might conflict with manually
|
||||
### loaded modules.
|
||||
.ifexists @PA_DLSEARCHPATH@/module-gconf@PA_SOEXT@
|
||||
load-module module-gconf
|
||||
.endif
|
||||
|
||||
### Make some devices default
|
||||
#set-default-sink output
|
||||
#set-default-source input
|
||||
|
|
|
|||
|
|
@ -28,26 +28,30 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <ltdl.h>
|
||||
|
||||
#include <pulse/util.h>
|
||||
|
||||
#include <pulsecore/modinfo.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "dumpmodules.h"
|
||||
|
||||
#define PREFIX "module-"
|
||||
|
||||
static void short_info(const char *name, PA_GCC_UNUSED const char *path, pa_modinfo *i) {
|
||||
assert(name && i);
|
||||
pa_assert(name);
|
||||
pa_assert(i);
|
||||
|
||||
printf("%-40s%s\n", name, i->description ? i->description : "n/a");
|
||||
}
|
||||
|
||||
static void long_info(const char *name, const char *path, pa_modinfo *i) {
|
||||
static int nl = 0;
|
||||
assert(name && i);
|
||||
pa_assert(name);
|
||||
pa_assert(i);
|
||||
|
||||
if (nl)
|
||||
printf("\n");
|
||||
|
|
@ -76,6 +80,8 @@ static void long_info(const char *name, const char *path, pa_modinfo *i) {
|
|||
static void show_info(const char *name, const char *path, void (*info)(const char *name, const char *path, pa_modinfo*i)) {
|
||||
pa_modinfo *i;
|
||||
|
||||
pa_assert(name);
|
||||
|
||||
if ((i = pa_modinfo_get_by_name(path ? path : name))) {
|
||||
info(name, path, i);
|
||||
pa_modinfo_free(i);
|
||||
|
|
@ -93,7 +99,7 @@ static int is_preloaded(const char *name) {
|
|||
if (l->address)
|
||||
continue;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s", l->name);
|
||||
pa_snprintf(buf, sizeof(buf), "%s", l->name);
|
||||
if ((e = strrchr(buf, '.')))
|
||||
*e = 0;
|
||||
|
||||
|
|
@ -121,6 +127,8 @@ static int callback(const char *path, lt_ptr data) {
|
|||
}
|
||||
|
||||
void pa_dump_modules(pa_daemon_conf *c, int argc, char * const argv[]) {
|
||||
pa_assert(c);
|
||||
|
||||
if (argc > 0) {
|
||||
int i;
|
||||
for (i = 0; i < argc; i++)
|
||||
|
|
@ -137,7 +145,7 @@ void pa_dump_modules(pa_daemon_conf *c, int argc, char * const argv[]) {
|
|||
if (strlen(l->name) <= sizeof(PREFIX)-1 || strncmp(l->name, PREFIX, sizeof(PREFIX)-1))
|
||||
continue;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s", l->name);
|
||||
pa_snprintf(buf, sizeof(buf), "%s", l->name);
|
||||
if ((e = strrchr(buf, '.')))
|
||||
*e = 0;
|
||||
|
||||
|
|
|
|||
160
src/daemon/ltdl-bind-now.c
Normal file
160
src/daemon/ltdl-bind-now.c
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/* $Id$ */
|
||||
|
||||
/***
|
||||
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 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_DL_H
|
||||
#include <sys/dl.h>
|
||||
#endif
|
||||
|
||||
#include <ltdl.h>
|
||||
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/mutex.h>
|
||||
#include <pulsecore/thread.h>
|
||||
#include <pulsecore/log.h>
|
||||
|
||||
#include "ltdl-bind-now.h"
|
||||
|
||||
#ifdef RTLD_NOW
|
||||
#define PA_BIND_NOW RTLD_NOW
|
||||
#elif defined(DL_NOW)
|
||||
#define PA_BIND_NOW DL_NOW
|
||||
#else
|
||||
#undef PA_BIND_NOW
|
||||
#endif
|
||||
|
||||
static pa_mutex *libtool_mutex = NULL;
|
||||
|
||||
PA_STATIC_TLS_DECLARE_NO_FREE(libtool_tls);
|
||||
|
||||
static void libtool_lock(void) {
|
||||
pa_mutex_lock(libtool_mutex);
|
||||
}
|
||||
|
||||
static void libtool_unlock(void) {
|
||||
pa_mutex_unlock(libtool_mutex);
|
||||
}
|
||||
|
||||
static void libtool_set_error(const char *error) {
|
||||
PA_STATIC_TLS_SET(libtool_tls, (char*) error);
|
||||
}
|
||||
|
||||
static const char *libtool_get_error(void) {
|
||||
return PA_STATIC_TLS_GET(libtool_tls);
|
||||
}
|
||||
|
||||
#ifdef PA_BIND_NOW
|
||||
|
||||
/*
|
||||
To avoid lazy relocations during runtime in our RT threads we add
|
||||
our own shared object loader with uses RTLD_NOW if it is
|
||||
available. The standard ltdl loader prefers RTLD_LAZY.
|
||||
|
||||
Please note that this loader doesn't have any influence on
|
||||
relocations on any libraries that are already loaded into our
|
||||
process, i.e. because the pulseaudio binary links directly to
|
||||
them. To disable lazy relocations for those libraries it is possible
|
||||
to set $LT_BIND_NOW before starting the pulsaudio binary.
|
||||
*/
|
||||
|
||||
static lt_module bind_now_open(lt_user_data d, const char *fname) {
|
||||
lt_module m;
|
||||
|
||||
pa_assert(fname);
|
||||
|
||||
if (!(m = dlopen(fname, PA_BIND_NOW))) {
|
||||
libtool_set_error(dlerror());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
static int bind_now_close(lt_user_data d, lt_module m) {
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (dlclose(m) != 0){
|
||||
libtool_set_error(dlerror());
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static lt_ptr bind_now_find_sym(lt_user_data d, lt_module m, const char *symbol) {
|
||||
lt_ptr ptr;
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(symbol);
|
||||
|
||||
if (!(ptr = dlsym(m, symbol))) {
|
||||
libtool_set_error(dlerror());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void pa_ltdl_init(void) {
|
||||
|
||||
#ifdef PA_BIND_NOW
|
||||
lt_dlloader *place;
|
||||
static const struct lt_user_dlloader loader = {
|
||||
.module_open = bind_now_open,
|
||||
.module_close = bind_now_close,
|
||||
.find_sym = bind_now_find_sym
|
||||
};
|
||||
#endif
|
||||
|
||||
pa_assert_se(lt_dlinit() == 0);
|
||||
pa_assert_se(libtool_mutex = pa_mutex_new(TRUE, FALSE));
|
||||
pa_assert_se(lt_dlmutex_register(libtool_lock, libtool_unlock, libtool_set_error, libtool_get_error) == 0);
|
||||
|
||||
#ifdef PA_BIND_NOW
|
||||
|
||||
if (!(place = lt_dlloader_find("dlopen")))
|
||||
place = lt_dlloader_next(NULL);
|
||||
|
||||
/* Add our BIND_NOW loader as the default module loader. */
|
||||
if (lt_dlloader_add(place, &loader, "bind-now-loader") != 0)
|
||||
pa_log_warn("Failed to add bind-now-loader.");
|
||||
#endif
|
||||
}
|
||||
|
||||
void pa_ltdl_done(void) {
|
||||
pa_assert_se(lt_dlexit() == 0);
|
||||
pa_mutex_free(libtool_mutex);
|
||||
libtool_mutex = NULL;
|
||||
}
|
||||
|
||||
32
src/daemon/ltdl-bind-now.h
Normal file
32
src/daemon/ltdl-bind-now.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef foopulsecoreltdlbindnowhfoo
|
||||
#define foopulsecoreltdlbindnowhfoo
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2004-2006 Lennart Poettering
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2 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.
|
||||
***/
|
||||
|
||||
|
||||
void pa_ltdl_init(void);
|
||||
void pa_ltdl_done(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -33,7 +33,6 @@
|
|||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include <ltdl.h>
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
|
|
@ -59,13 +58,16 @@
|
|||
#include <tcpd.h>
|
||||
#endif
|
||||
|
||||
#include "../pulsecore/winsock.h"
|
||||
#ifdef HAVE_DBUS
|
||||
#include <dbus/dbus.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/mainloop.h>
|
||||
#include <pulse/mainloop-signal.h>
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/winsock.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/memblock.h>
|
||||
|
|
@ -78,12 +80,20 @@
|
|||
#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>
|
||||
#include <pulsecore/once.h>
|
||||
#include <pulsecore/shm.h>
|
||||
|
||||
#include "cmdline.h"
|
||||
#include "cpulimit.h"
|
||||
#include "daemon-conf.h"
|
||||
#include "dumpmodules.h"
|
||||
#include "caps.h"
|
||||
#include "ltdl-bind-now.h"
|
||||
|
||||
#ifdef HAVE_LIBWRAP
|
||||
/* Only one instance of these variables */
|
||||
|
|
@ -120,7 +130,7 @@ static void message_cb(pa_mainloop_api*a, pa_time_event*e, PA_GCC_UNUSED const s
|
|||
#endif
|
||||
|
||||
static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e, int sig, void *userdata) {
|
||||
pa_log_info("Got signal %s.", pa_strsignal(sig));
|
||||
pa_log_info("Got signal %s.", pa_sig2str(sig));
|
||||
|
||||
switch (sig) {
|
||||
#ifdef SIGUSR1
|
||||
|
|
@ -153,14 +163,6 @@ static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e,
|
|||
}
|
||||
}
|
||||
|
||||
static void close_pipe(int p[2]) {
|
||||
if (p[0] != -1)
|
||||
close(p[0]);
|
||||
if (p[1] != -1)
|
||||
close(p[1]);
|
||||
p[0] = p[1] = -1;
|
||||
}
|
||||
|
||||
#define set_env(key, value) putenv(pa_sprintf_malloc("%s=%s", (key), (value)))
|
||||
|
||||
#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
|
||||
|
|
@ -281,7 +283,7 @@ static int create_runtime_dir(void) {
|
|||
|
||||
static void set_one_rlimit(const pa_rlimit *r, int resource, const char *name) {
|
||||
struct rlimit rl;
|
||||
assert(r);
|
||||
pa_assert(r);
|
||||
|
||||
if (!r->is_set)
|
||||
return;
|
||||
|
|
@ -313,13 +315,11 @@ int main(int argc, char *argv[]) {
|
|||
pa_strbuf *buf = NULL;
|
||||
pa_daemon_conf *conf = NULL;
|
||||
pa_mainloop *mainloop = NULL;
|
||||
|
||||
char *s;
|
||||
int r, retval = 1, d = 0;
|
||||
int r = 0, retval = 1, d = 0;
|
||||
int daemon_pipe[2] = { -1, -1 };
|
||||
int suid_root, real_root;
|
||||
int valid_pid_file = 0;
|
||||
|
||||
gid_t gid = (gid_t) -1;
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
|
|
@ -327,6 +327,23 @@ int main(int argc, char *argv[]) {
|
|||
struct timeval tv;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__linux__) && defined(__OPTIMIZE__)
|
||||
/*
|
||||
Disable lazy relocations to make usage of external libraries
|
||||
more deterministic for our RT threads. We abuse __OPTIMIZE__ as
|
||||
a check whether we are a debug build or not.
|
||||
*/
|
||||
|
||||
if (!getenv("LD_BIND_NOW")) {
|
||||
putenv(pa_xstrdup("LD_BIND_NOW=1"));
|
||||
|
||||
/* We have to execute ourselves, because the libc caches the
|
||||
* value of $LD_BIND_NOW on initialization. */
|
||||
pa_assert_se(execv("/proc/self/exe", argv) == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETUID
|
||||
real_root = getuid() == 0;
|
||||
suid_root = !real_root && geteuid() == 0;
|
||||
|
|
@ -336,16 +353,26 @@ int main(int argc, char *argv[]) {
|
|||
#endif
|
||||
|
||||
if (suid_root) {
|
||||
if (pa_limit_caps() > 0)
|
||||
/* We managed to drop capabilities except the needed
|
||||
* ones. Hence we can drop the uid. */
|
||||
pa_drop_root();
|
||||
/* Drop all capabilities except CAP_SYS_NICE */
|
||||
pa_limit_caps();
|
||||
|
||||
/* Drop priviliges, 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
|
||||
* aquire 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. */
|
||||
}
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) {
|
||||
pa_log_warn("WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'.");
|
||||
if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0)) {
|
||||
pa_log_info("Warning: Called SUID root, but not in group '"PA_REALTIME_GROUP"'. "
|
||||
"For enabling real-time scheduling please become a member of '"PA_REALTIME_GROUP"' , or increase the RLIMIT_RTPRIO user limit.");
|
||||
pa_drop_caps();
|
||||
pa_drop_root();
|
||||
suid_root = real_root = 0;
|
||||
|
|
@ -353,8 +380,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
LTDL_SET_PRELOADED_SYMBOLS();
|
||||
|
||||
r = lt_dlinit();
|
||||
assert(r == 0);
|
||||
pa_ltdl_init();
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
{
|
||||
|
|
@ -386,7 +412,7 @@ int main(int argc, char *argv[]) {
|
|||
if (conf->high_priority && conf->cmd == PA_CMD_DAEMON)
|
||||
pa_raise_priority();
|
||||
|
||||
if (suid_root) {
|
||||
if (suid_root && (conf->cmd != PA_CMD_DAEMON || !conf->high_priority)) {
|
||||
pa_drop_caps();
|
||||
pa_drop_root();
|
||||
}
|
||||
|
|
@ -408,6 +434,16 @@ int main(int argc, char *argv[]) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
case PA_CMD_DUMP_RESAMPLE_METHODS: {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PA_RESAMPLER_MAX; i++)
|
||||
if (pa_resample_method_supported(i))
|
||||
printf("%s\n", pa_resample_method_to_string(i));
|
||||
|
||||
goto finish;
|
||||
}
|
||||
|
||||
case PA_CMD_HELP :
|
||||
pa_cmdline_help(argv[0]);
|
||||
retval = 0;
|
||||
|
|
@ -440,8 +476,15 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
goto finish;
|
||||
|
||||
case PA_CMD_CLEANUP_SHM:
|
||||
|
||||
if (pa_shm_cleanup() >= 0)
|
||||
retval = 0;
|
||||
|
||||
goto finish;
|
||||
|
||||
default:
|
||||
assert(conf->cmd == PA_CMD_DAEMON);
|
||||
pa_assert(conf->cmd == PA_CMD_DAEMON);
|
||||
}
|
||||
|
||||
if (real_root && !conf->system_instance) {
|
||||
|
|
@ -474,7 +517,7 @@ int main(int argc, char *argv[]) {
|
|||
if (child != 0) {
|
||||
/* Father */
|
||||
|
||||
close(daemon_pipe[1]);
|
||||
pa_assert_se(pa_close(daemon_pipe[1]) == 0);
|
||||
daemon_pipe[1] = -1;
|
||||
|
||||
if (pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL) != sizeof(retval)) {
|
||||
|
|
@ -490,7 +533,7 @@ int main(int argc, char *argv[]) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
close(daemon_pipe[0]);
|
||||
pa_assert_se(pa_close(daemon_pipe[0]) == 0);
|
||||
daemon_pipe[0] = -1;
|
||||
#endif
|
||||
|
||||
|
|
@ -505,9 +548,9 @@ int main(int argc, char *argv[]) {
|
|||
#endif
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
pa_close(0);
|
||||
pa_close(1);
|
||||
pa_close(2);
|
||||
|
||||
open("/dev/null", O_RDONLY);
|
||||
open("/dev/null", O_WRONLY);
|
||||
|
|
@ -529,12 +572,12 @@ int main(int argc, char *argv[]) {
|
|||
#ifdef TIOCNOTTY
|
||||
if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
|
||||
ioctl(tty_fd, TIOCNOTTY, (char*) 0);
|
||||
close(tty_fd);
|
||||
pa_assert_se(pa_close(tty_fd) == 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
chdir("/");
|
||||
pa_assert_se(chdir("/") == 0);
|
||||
umask(0022);
|
||||
|
||||
if (conf->system_instance) {
|
||||
|
|
@ -564,18 +607,37 @@ int main(int argc, char *argv[]) {
|
|||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
mainloop = pa_mainloop_new();
|
||||
assert(mainloop);
|
||||
pa_log_info("Page size is %lu bytes", (unsigned long) PA_PAGE_SIZE);
|
||||
|
||||
if (pa_rtclock_hrtimer())
|
||||
pa_log_info("Fresh high-resolution timers available! Bon appetit!");
|
||||
else
|
||||
pa_log_info("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!");
|
||||
|
||||
#ifdef SIGRTMIN
|
||||
/* Valgrind uses SIGRTMAX. To easy debugging we don't use it here */
|
||||
pa_rtsig_configure(SIGRTMIN, SIGRTMAX-1);
|
||||
#endif
|
||||
|
||||
pa_assert_se(mainloop = pa_mainloop_new());
|
||||
|
||||
if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm))) {
|
||||
pa_log("pa_core_new() failed.");
|
||||
pa_log("pa_core_new() failed.");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
c->is_system_instance = !!conf->system_instance;
|
||||
c->high_priority = !!conf->high_priority;
|
||||
c->default_sample_spec = conf->default_sample_spec;
|
||||
c->default_n_fragments = conf->default_n_fragments;
|
||||
c->default_fragment_size_msec = conf->default_fragment_size_msec;
|
||||
c->disallow_module_loading = conf->disallow_module_loading;
|
||||
c->exit_idle_time = conf->exit_idle_time;
|
||||
c->module_idle_time = conf->module_idle_time;
|
||||
c->scache_idle_time = conf->scache_idle_time;
|
||||
c->resample_method = conf->resample_method;
|
||||
|
||||
r = pa_signal_init(pa_mainloop_get_api(mainloop));
|
||||
assert(r == 0);
|
||||
pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0);
|
||||
pa_signal_new(SIGINT, signal_callback, c);
|
||||
pa_signal_new(SIGTERM, signal_callback, c);
|
||||
|
||||
|
|
@ -590,9 +652,7 @@ int main(int argc, char *argv[]) {
|
|||
#endif
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
timer = pa_mainloop_get_api(mainloop)->time_new(
|
||||
pa_mainloop_get_api(mainloop), pa_gettimeofday(&tv), message_cb, NULL);
|
||||
assert(timer);
|
||||
pa_assert_se(timer = pa_mainloop_get_api(mainloop)->time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&tv), message_cb, NULL));
|
||||
#endif
|
||||
|
||||
if (conf->daemonize)
|
||||
|
|
@ -600,10 +660,8 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
oil_init();
|
||||
|
||||
if (!conf->no_cpu_limit) {
|
||||
r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop));
|
||||
assert(r == 0);
|
||||
}
|
||||
if (!conf->no_cpu_limit)
|
||||
pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0);
|
||||
|
||||
buf = pa_strbuf_new();
|
||||
if (conf->default_script_file)
|
||||
|
|
@ -634,12 +692,6 @@ int main(int argc, char *argv[]) {
|
|||
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
|
||||
#endif
|
||||
|
||||
c->disallow_module_loading = conf->disallow_module_loading;
|
||||
c->exit_idle_time = conf->exit_idle_time;
|
||||
c->module_idle_time = conf->module_idle_time;
|
||||
c->scache_idle_time = conf->scache_idle_time;
|
||||
c->resample_method = conf->resample_method;
|
||||
|
||||
if (c->default_sink_name &&
|
||||
pa_namereg_get(c, c->default_sink_name, PA_NAMEREG_SINK, 1) == NULL) {
|
||||
pa_log_error("%s : Fatal error. Default sink name (%s) does not exist in name register.", __FILE__, c->default_sink_name);
|
||||
|
|
@ -656,7 +708,7 @@ int main(int argc, char *argv[]) {
|
|||
pa_mainloop_get_api(mainloop)->time_free(timer);
|
||||
#endif
|
||||
|
||||
pa_core_free(c);
|
||||
pa_core_unref(c);
|
||||
|
||||
if (!conf->no_cpu_limit)
|
||||
pa_cpu_limit_done();
|
||||
|
|
@ -676,13 +728,17 @@ finish:
|
|||
if (valid_pid_file)
|
||||
pa_pid_file_remove();
|
||||
|
||||
close_pipe(daemon_pipe);
|
||||
pa_close_pipe(daemon_pipe);
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
|
||||
lt_dlexit();
|
||||
pa_ltdl_done();
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
dbus_shutdown();
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
10
src/daemon/pulseaudio-module-xsmp.desktop
Normal file
10
src/daemon/pulseaudio-module-xsmp.desktop
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Encoding=UTF-8
|
||||
Name=PulseAudio Session Management
|
||||
Comment=Load module-x11-xsmp into PulseAudio
|
||||
Exec=pactl load-module module-x11-xsmp
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=
|
||||
GenericName=
|
||||
|
|
@ -33,6 +33,7 @@
|
|||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "alsa-util.h"
|
||||
|
||||
|
|
@ -42,7 +43,6 @@ struct pa_alsa_fdlist {
|
|||
/* This is a temporary buffer used to avoid lots of mallocs */
|
||||
struct pollfd *work_fds;
|
||||
|
||||
snd_pcm_t *pcm;
|
||||
snd_mixer_t *mixer;
|
||||
|
||||
pa_mainloop_api *m;
|
||||
|
|
@ -56,11 +56,16 @@ struct pa_alsa_fdlist {
|
|||
};
|
||||
|
||||
static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void *userdata) {
|
||||
struct pa_alsa_fdlist *fdl = (struct pa_alsa_fdlist*)userdata;
|
||||
|
||||
struct pa_alsa_fdlist *fdl = userdata;
|
||||
int err, i;
|
||||
unsigned short revents;
|
||||
|
||||
assert(a && fdl && (fdl->pcm || fdl->mixer) && fdl->fds && fdl->work_fds);
|
||||
pa_assert(a);
|
||||
pa_assert(fdl);
|
||||
pa_assert(fdl->mixer);
|
||||
pa_assert(fdl->fds);
|
||||
pa_assert(fdl->work_fds);
|
||||
|
||||
if (fdl->polled)
|
||||
return;
|
||||
|
|
@ -69,7 +74,7 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io
|
|||
|
||||
memcpy(fdl->work_fds, fdl->fds, sizeof(struct pollfd) * fdl->num_fds);
|
||||
|
||||
for (i = 0;i < fdl->num_fds;i++) {
|
||||
for (i = 0;i < fdl->num_fds; i++) {
|
||||
if (e == fdl->ios[i]) {
|
||||
if (events & PA_IO_EVENT_INPUT)
|
||||
fdl->work_fds[i].revents |= POLLIN;
|
||||
|
|
@ -83,63 +88,46 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io
|
|||
}
|
||||
}
|
||||
|
||||
assert(i != fdl->num_fds);
|
||||
pa_assert(i != fdl->num_fds);
|
||||
|
||||
if (fdl->pcm)
|
||||
err = snd_pcm_poll_descriptors_revents(fdl->pcm, fdl->work_fds, fdl->num_fds, &revents);
|
||||
else
|
||||
err = snd_mixer_poll_descriptors_revents(fdl->mixer, fdl->work_fds, fdl->num_fds, &revents);
|
||||
|
||||
if (err < 0) {
|
||||
pa_log_error("Unable to get poll revent: %s",
|
||||
snd_strerror(err));
|
||||
if ((err = snd_mixer_poll_descriptors_revents(fdl->mixer, fdl->work_fds, fdl->num_fds, &revents)) < 0) {
|
||||
pa_log_error("Unable to get poll revent: %s", snd_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
a->defer_enable(fdl->defer, 1);
|
||||
|
||||
if (revents) {
|
||||
if (fdl->pcm)
|
||||
fdl->cb(fdl->userdata);
|
||||
else
|
||||
snd_mixer_handle_events(fdl->mixer);
|
||||
}
|
||||
if (revents)
|
||||
snd_mixer_handle_events(fdl->mixer);
|
||||
}
|
||||
|
||||
static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *userdata) {
|
||||
struct pa_alsa_fdlist *fdl = (struct pa_alsa_fdlist*)userdata;
|
||||
struct pa_alsa_fdlist *fdl = userdata;
|
||||
int num_fds, i, err;
|
||||
struct pollfd *temp;
|
||||
|
||||
assert(a && fdl && (fdl->pcm || fdl->mixer));
|
||||
pa_assert(a);
|
||||
pa_assert(fdl);
|
||||
pa_assert(fdl->mixer);
|
||||
|
||||
a->defer_enable(fdl->defer, 0);
|
||||
|
||||
if (fdl->pcm)
|
||||
num_fds = snd_pcm_poll_descriptors_count(fdl->pcm);
|
||||
else
|
||||
num_fds = snd_mixer_poll_descriptors_count(fdl->mixer);
|
||||
assert(num_fds > 0);
|
||||
num_fds = snd_mixer_poll_descriptors_count(fdl->mixer);
|
||||
pa_assert(num_fds > 0);
|
||||
|
||||
if (num_fds != fdl->num_fds) {
|
||||
if (fdl->fds)
|
||||
pa_xfree(fdl->fds);
|
||||
if (fdl->work_fds)
|
||||
pa_xfree(fdl->work_fds);
|
||||
fdl->fds = pa_xmalloc0(sizeof(struct pollfd) * num_fds);
|
||||
fdl->work_fds = pa_xmalloc(sizeof(struct pollfd) * num_fds);
|
||||
fdl->fds = pa_xnew0(struct pollfd, num_fds);
|
||||
fdl->work_fds = pa_xnew(struct pollfd, num_fds);
|
||||
}
|
||||
|
||||
memset(fdl->work_fds, 0, sizeof(struct pollfd) * num_fds);
|
||||
|
||||
if (fdl->pcm)
|
||||
err = snd_pcm_poll_descriptors(fdl->pcm, fdl->work_fds, num_fds);
|
||||
else
|
||||
err = snd_mixer_poll_descriptors(fdl->mixer, fdl->work_fds, num_fds);
|
||||
|
||||
if (err < 0) {
|
||||
pa_log_error("Unable to get poll descriptors: %s",
|
||||
snd_strerror(err));
|
||||
if ((err = snd_mixer_poll_descriptors(fdl->mixer, fdl->work_fds, num_fds)) < 0) {
|
||||
pa_log_error("Unable to get poll descriptors: %s", snd_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -149,18 +137,18 @@ static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *u
|
|||
return;
|
||||
|
||||
if (fdl->ios) {
|
||||
for (i = 0;i < fdl->num_fds;i++)
|
||||
for (i = 0; i < fdl->num_fds; i++)
|
||||
a->io_free(fdl->ios[i]);
|
||||
|
||||
if (num_fds != fdl->num_fds) {
|
||||
pa_xfree(fdl->ios);
|
||||
fdl->ios = pa_xmalloc(sizeof(pa_io_event*) * num_fds);
|
||||
assert(fdl->ios);
|
||||
fdl->ios = NULL;
|
||||
}
|
||||
} else {
|
||||
fdl->ios = pa_xmalloc(sizeof(pa_io_event*) * num_fds);
|
||||
assert(fdl->ios);
|
||||
}
|
||||
|
||||
if (!fdl->ios)
|
||||
fdl->ios = pa_xnew(pa_io_event*, num_fds);
|
||||
|
||||
/* Swap pointers */
|
||||
temp = fdl->work_fds;
|
||||
fdl->work_fds = fdl->fds;
|
||||
|
|
@ -168,47 +156,41 @@ static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *u
|
|||
|
||||
fdl->num_fds = num_fds;
|
||||
|
||||
for (i = 0;i < num_fds;i++) {
|
||||
for (i = 0;i < num_fds;i++)
|
||||
fdl->ios[i] = a->io_new(a, fdl->fds[i].fd,
|
||||
((fdl->fds[i].events & POLLIN) ? PA_IO_EVENT_INPUT : 0) |
|
||||
((fdl->fds[i].events & POLLOUT) ? PA_IO_EVENT_OUTPUT : 0),
|
||||
io_cb, fdl);
|
||||
assert(fdl->ios[i]);
|
||||
}
|
||||
}
|
||||
|
||||
struct pa_alsa_fdlist *pa_alsa_fdlist_new(void) {
|
||||
struct pa_alsa_fdlist *fdl;
|
||||
|
||||
fdl = pa_xmalloc(sizeof(struct pa_alsa_fdlist));
|
||||
fdl = pa_xnew0(struct pa_alsa_fdlist, 1);
|
||||
|
||||
fdl->num_fds = 0;
|
||||
fdl->fds = NULL;
|
||||
fdl->work_fds = NULL;
|
||||
|
||||
fdl->pcm = NULL;
|
||||
fdl->mixer = NULL;
|
||||
|
||||
fdl->m = NULL;
|
||||
fdl->defer = NULL;
|
||||
fdl->ios = NULL;
|
||||
|
||||
fdl->polled = 0;
|
||||
|
||||
return fdl;
|
||||
}
|
||||
|
||||
void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl) {
|
||||
assert(fdl);
|
||||
pa_assert(fdl);
|
||||
|
||||
if (fdl->defer) {
|
||||
assert(fdl->m);
|
||||
pa_assert(fdl->m);
|
||||
fdl->m->defer_free(fdl->defer);
|
||||
}
|
||||
|
||||
if (fdl->ios) {
|
||||
int i;
|
||||
assert(fdl->m);
|
||||
pa_assert(fdl->m);
|
||||
for (i = 0;i < fdl->num_fds;i++)
|
||||
fdl->m->io_free(fdl->ios[i]);
|
||||
pa_xfree(fdl->ios);
|
||||
|
|
@ -222,29 +204,15 @@ void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl) {
|
|||
pa_xfree(fdl);
|
||||
}
|
||||
|
||||
int pa_alsa_fdlist_init_pcm(struct pa_alsa_fdlist *fdl, snd_pcm_t *pcm_handle, pa_mainloop_api* m, void (*cb)(void *userdata), void *userdata) {
|
||||
assert(fdl && pcm_handle && m && !fdl->m && cb);
|
||||
|
||||
fdl->pcm = pcm_handle;
|
||||
fdl->m = m;
|
||||
|
||||
fdl->defer = m->defer_new(m, defer_cb, fdl);
|
||||
assert(fdl->defer);
|
||||
|
||||
fdl->cb = cb;
|
||||
fdl->userdata = userdata;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pa_alsa_fdlist_init_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m) {
|
||||
assert(fdl && mixer_handle && m && !fdl->m);
|
||||
int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m) {
|
||||
pa_assert(fdl);
|
||||
pa_assert(mixer_handle);
|
||||
pa_assert(m);
|
||||
pa_assert(!fdl->m);
|
||||
|
||||
fdl->mixer = mixer_handle;
|
||||
fdl->m = m;
|
||||
|
||||
fdl->defer = m->defer_new(m, defer_cb, fdl);
|
||||
assert(fdl->defer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -274,8 +242,8 @@ static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_s
|
|||
|
||||
int i, ret;
|
||||
|
||||
assert(pcm_handle);
|
||||
assert(f);
|
||||
pa_assert(pcm_handle);
|
||||
pa_assert(f);
|
||||
|
||||
if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
|
||||
return ret;
|
||||
|
|
@ -308,7 +276,7 @@ try_auto:
|
|||
|
||||
/* Set the hardware parameters of the given ALSA device. Returns the
|
||||
* selected fragment settings in *period and *period_size */
|
||||
int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) {
|
||||
int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size, int *use_mmap) {
|
||||
int ret = -1;
|
||||
snd_pcm_uframes_t buffer_size;
|
||||
unsigned int r = ss->rate;
|
||||
|
|
@ -316,17 +284,32 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
|
|||
pa_sample_format_t f = ss->format;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
|
||||
assert(pcm_handle);
|
||||
assert(ss);
|
||||
assert(periods);
|
||||
assert(period_size);
|
||||
pa_assert(pcm_handle);
|
||||
pa_assert(ss);
|
||||
pa_assert(periods);
|
||||
pa_assert(period_size);
|
||||
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
|
||||
buffer_size = *periods * *period_size;
|
||||
|
||||
if ((ret = snd_pcm_hw_params_malloc(&hwparams)) < 0 ||
|
||||
(ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 ||
|
||||
(ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0 ||
|
||||
(ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
|
||||
if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 ||
|
||||
(ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0)
|
||||
goto finish;
|
||||
|
||||
if (use_mmap && *use_mmap) {
|
||||
if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0) {
|
||||
|
||||
/* mmap() didn't work, fall back to interleaved */
|
||||
|
||||
if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
|
||||
goto finish;
|
||||
|
||||
if (use_mmap)
|
||||
*use_mmap = 0;
|
||||
}
|
||||
|
||||
} else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
|
||||
goto finish;
|
||||
|
||||
if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
|
||||
|
|
@ -346,7 +329,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
|
|||
goto finish;
|
||||
|
||||
if (ss->rate != r) {
|
||||
pa_log_warn("device doesn't support %u Hz, changed to %u Hz.", ss->rate, r);
|
||||
pa_log_warn("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r);
|
||||
|
||||
/* If the sample rate deviates too much, we need to resample */
|
||||
if (r < ss->rate*.95 || r > ss->rate*1.05)
|
||||
|
|
@ -354,12 +337,12 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
|
|||
}
|
||||
|
||||
if (ss->channels != c) {
|
||||
pa_log_warn("device doesn't support %u channels, changed to %u.", ss->channels, c);
|
||||
pa_log_warn("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c);
|
||||
ss->channels = c;
|
||||
}
|
||||
|
||||
if (ss->format != f) {
|
||||
pa_log_warn("device doesn't support sample format %s, changed to %s.", pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f));
|
||||
pa_log_warn("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f));
|
||||
ss->format = f;
|
||||
}
|
||||
|
||||
|
|
@ -370,24 +353,54 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
|
|||
(ret = snd_pcm_hw_params_get_period_size(hwparams, period_size, NULL)) < 0)
|
||||
goto finish;
|
||||
|
||||
assert(buffer_size > 0);
|
||||
assert(*period_size > 0);
|
||||
pa_assert(buffer_size > 0);
|
||||
pa_assert(*period_size > 0);
|
||||
*periods = buffer_size / *period_size;
|
||||
assert(*periods > 0);
|
||||
pa_assert(*periods > 0);
|
||||
|
||||
ret = 0;
|
||||
|
||||
finish:
|
||||
if (hwparams)
|
||||
snd_pcm_hw_params_free(hwparams);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pa_alsa_set_sw_params(snd_pcm_t *pcm) {
|
||||
snd_pcm_sw_params_t *swparams;
|
||||
int err;
|
||||
|
||||
pa_assert(pcm);
|
||||
|
||||
snd_pcm_sw_params_alloca(&swparams);
|
||||
|
||||
if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) {
|
||||
pa_log_warn("Unable to determine current swparams: %s\n", snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
|
||||
pa_log_warn("Unable to set stop threshold: %s\n", snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
|
||||
pa_log_warn("Unable to set start threshold: %s\n", snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
|
||||
pa_log_warn("Unable to set sw params: %s\n", snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) {
|
||||
int err;
|
||||
|
||||
assert(mixer && dev);
|
||||
pa_assert(mixer);
|
||||
pa_assert(dev);
|
||||
|
||||
if ((err = snd_mixer_attach(mixer, dev)) < 0) {
|
||||
pa_log_warn("Unable to attach to mixer %s: %s", dev, snd_strerror(err));
|
||||
|
|
@ -410,10 +423,11 @@ 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) {
|
||||
snd_mixer_elem_t *elem;
|
||||
snd_mixer_selem_id_t *sid = NULL;
|
||||
|
||||
snd_mixer_selem_id_alloca(&sid);
|
||||
|
||||
assert(mixer);
|
||||
assert(name);
|
||||
pa_assert(mixer);
|
||||
pa_assert(name);
|
||||
|
||||
snd_mixer_selem_id_set_name(sid, name);
|
||||
|
||||
|
|
|
|||
|
|
@ -32,15 +32,14 @@
|
|||
|
||||
#include <pulse/channelmap.h>
|
||||
|
||||
struct pa_alsa_fdlist;
|
||||
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);
|
||||
|
||||
int pa_alsa_fdlist_init_pcm(struct pa_alsa_fdlist *fdl, snd_pcm_t *pcm_handle, pa_mainloop_api* m, void (*cb)(void *userdata), void *userdata);
|
||||
int pa_alsa_fdlist_init_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m);
|
||||
|
||||
int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size);
|
||||
int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size, int *use_mmap);
|
||||
int pa_alsa_set_sw_params(snd_pcm_t *pcm);
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -26,25 +26,25 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/props.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/props.h>
|
||||
|
||||
#include "dbus-util.h"
|
||||
|
||||
struct pa_dbus_connection {
|
||||
int refcount;
|
||||
PA_REFCNT_DECLARE;
|
||||
|
||||
pa_core *core;
|
||||
DBusConnection *connection;
|
||||
const char *property_name;
|
||||
pa_defer_event* dispatch_event;
|
||||
};
|
||||
|
||||
static void dispatch_cb(pa_mainloop_api *ea, pa_defer_event *ev, void *userdata)
|
||||
{
|
||||
DBusConnection *conn = (DBusConnection *) userdata;
|
||||
static void dispatch_cb(pa_mainloop_api *ea, pa_defer_event *ev, void *userdata) {
|
||||
DBusConnection *conn = userdata;
|
||||
|
||||
if (dbus_connection_dispatch(conn) == DBUS_DISPATCH_COMPLETE) {
|
||||
/* no more data to process, disable the deferred */
|
||||
ea->defer_enable(ev, 0);
|
||||
|
|
@ -52,14 +52,17 @@ static void dispatch_cb(pa_mainloop_api *ea, pa_defer_event *ev, void *userdata)
|
|||
}
|
||||
|
||||
/* DBusDispatchStatusFunction callback for the pa mainloop */
|
||||
static void dispatch_status(DBusConnection *conn, DBusDispatchStatus status,
|
||||
void *userdata)
|
||||
{
|
||||
pa_dbus_connection *c = (pa_dbus_connection*) userdata;
|
||||
static void dispatch_status(DBusConnection *conn, DBusDispatchStatus status, void *userdata) {
|
||||
pa_dbus_connection *c = userdata;
|
||||
|
||||
pa_assert(c);
|
||||
|
||||
switch(status) {
|
||||
|
||||
case DBUS_DISPATCH_COMPLETE:
|
||||
c->core->mainloop->defer_enable(c->dispatch_event, 0);
|
||||
break;
|
||||
|
||||
case DBUS_DISPATCH_DATA_REMAINS:
|
||||
case DBUS_DISPATCH_NEED_MEMORY:
|
||||
default:
|
||||
|
|
@ -68,11 +71,13 @@ static void dispatch_status(DBusConnection *conn, DBusDispatchStatus status,
|
|||
}
|
||||
}
|
||||
|
||||
static pa_io_event_flags_t
|
||||
get_watch_flags(DBusWatch *watch)
|
||||
{
|
||||
unsigned int flags = dbus_watch_get_flags(watch);
|
||||
pa_io_event_flags_t events = PA_IO_EVENT_HANGUP | PA_IO_EVENT_ERROR;
|
||||
static pa_io_event_flags_t get_watch_flags(DBusWatch *watch) {
|
||||
unsigned int flags;
|
||||
pa_io_event_flags_t events = 0;
|
||||
|
||||
pa_assert(watch);
|
||||
|
||||
flags = dbus_watch_get_flags(watch);
|
||||
|
||||
/* no watch flags for disabled watches */
|
||||
if (!dbus_watch_get_enabled(watch))
|
||||
|
|
@ -83,21 +88,22 @@ get_watch_flags(DBusWatch *watch)
|
|||
if (flags & DBUS_WATCH_WRITABLE)
|
||||
events |= PA_IO_EVENT_OUTPUT;
|
||||
|
||||
return events;
|
||||
return events | PA_IO_EVENT_HANGUP | PA_IO_EVENT_ERROR;
|
||||
}
|
||||
|
||||
/* pa_io_event_cb_t IO event handler */
|
||||
static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e,
|
||||
int fd, pa_io_event_flags_t events, void *userdata)
|
||||
{
|
||||
static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
|
||||
unsigned int flags = 0;
|
||||
DBusWatch *watch = (DBusWatch*) userdata;
|
||||
DBusWatch *watch = userdata;
|
||||
|
||||
assert(fd == dbus_watch_get_fd(watch));
|
||||
#if HAVE_DBUS_WATCH_GET_UNIX_FD
|
||||
pa_assert(fd == dbus_watch_get_unix_fd(watch));
|
||||
#else
|
||||
pa_assert(fd == dbus_watch_get_fd(watch));
|
||||
#endif
|
||||
|
||||
if (!dbus_watch_get_enabled(watch)) {
|
||||
pa_log_warn("Asked to handle disabled watch: %p %i",
|
||||
(void *) watch, fd);
|
||||
pa_log_warn("Asked to handle disabled watch: %p %i", (void*) watch, fd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -114,10 +120,8 @@ static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e,
|
|||
}
|
||||
|
||||
/* pa_time_event_cb_t timer event handler */
|
||||
static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e,
|
||||
const struct timeval *tv, void *userdata)
|
||||
{
|
||||
DBusTimeout *timeout = (DBusTimeout*) userdata;
|
||||
static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, const struct timeval *tv, void *userdata) {
|
||||
DBusTimeout *timeout = userdata;
|
||||
|
||||
if (dbus_timeout_get_enabled(timeout)) {
|
||||
struct timeval next = *tv;
|
||||
|
|
@ -130,103 +134,154 @@ static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e,
|
|||
}
|
||||
|
||||
/* DBusAddWatchFunction callback for pa mainloop */
|
||||
static dbus_bool_t add_watch(DBusWatch *watch, void *data)
|
||||
{
|
||||
static dbus_bool_t add_watch(DBusWatch *watch, void *data) {
|
||||
pa_core *c = PA_CORE(data);
|
||||
pa_io_event *ev;
|
||||
pa_core *c = (pa_core*) data;
|
||||
|
||||
ev = c->mainloop->io_new(c->mainloop, dbus_watch_get_fd(watch),
|
||||
get_watch_flags(watch),
|
||||
handle_io_event, (void*) watch);
|
||||
if (NULL == ev)
|
||||
return FALSE;
|
||||
pa_assert(watch);
|
||||
pa_assert(c);
|
||||
|
||||
/* dbus_watch_set_data(watch, (void*) ev, c->mainloop->io_free); */
|
||||
dbus_watch_set_data(watch, (void*) ev, NULL);
|
||||
ev = c->mainloop->io_new(
|
||||
c->mainloop,
|
||||
#if HAVE_DBUS_WATCH_GET_UNIX_FD
|
||||
dbus_watch_get_unix_fd(watch),
|
||||
#else
|
||||
dbus_watch_get_fd(watch),
|
||||
#endif
|
||||
get_watch_flags(watch), handle_io_event, watch);
|
||||
|
||||
dbus_watch_set_data(watch, ev, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* DBusRemoveWatchFunction callback for pa mainloop */
|
||||
static void remove_watch(DBusWatch *watch, void *data)
|
||||
{
|
||||
pa_core *c = (pa_core*) data;
|
||||
pa_io_event *ev = (pa_io_event*) dbus_watch_get_data(watch);
|
||||
static void remove_watch(DBusWatch *watch, void *data) {
|
||||
pa_core *c = PA_CORE(data);
|
||||
pa_io_event *ev;
|
||||
|
||||
/* free the event */
|
||||
if (NULL != ev)
|
||||
pa_assert(watch);
|
||||
pa_assert(c);
|
||||
|
||||
if ((ev = dbus_watch_get_data(watch)))
|
||||
c->mainloop->io_free(ev);
|
||||
}
|
||||
|
||||
/* DBusWatchToggledFunction callback for pa mainloop */
|
||||
static void toggle_watch(DBusWatch *watch, void *data)
|
||||
{
|
||||
pa_core *c = (pa_core*) data;
|
||||
pa_io_event *ev = (pa_io_event*) dbus_watch_get_data(watch);
|
||||
static void toggle_watch(DBusWatch *watch, void *data) {
|
||||
pa_core *c = PA_CORE(data);
|
||||
pa_io_event *ev;
|
||||
|
||||
pa_assert(watch);
|
||||
pa_core_assert_ref(c);
|
||||
|
||||
pa_assert_se(ev = dbus_watch_get_data(watch));
|
||||
|
||||
/* get_watch_flags() checks if the watch is enabled */
|
||||
c->mainloop->io_enable(ev, get_watch_flags(watch));
|
||||
}
|
||||
|
||||
/* DBusAddTimeoutFunction callback for pa mainloop */
|
||||
static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
|
||||
{
|
||||
struct timeval tv;
|
||||
static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) {
|
||||
pa_core *c = PA_CORE(data);
|
||||
pa_time_event *ev;
|
||||
pa_core *c = (pa_core*) data;
|
||||
struct timeval tv;
|
||||
|
||||
pa_assert(timeout);
|
||||
pa_assert(c);
|
||||
|
||||
if (!dbus_timeout_get_enabled(timeout))
|
||||
return FALSE;
|
||||
|
||||
if (!pa_gettimeofday(&tv))
|
||||
return -1;
|
||||
|
||||
pa_gettimeofday(&tv);
|
||||
pa_timeval_add(&tv, dbus_timeout_get_interval(timeout) * 1000);
|
||||
|
||||
ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event,
|
||||
(void*) timeout);
|
||||
if (NULL == ev)
|
||||
return FALSE;
|
||||
ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event, timeout);
|
||||
|
||||
/* dbus_timeout_set_data(timeout, (void*) ev, c->mainloop->time_free); */
|
||||
dbus_timeout_set_data(timeout, (void*) ev, NULL);
|
||||
dbus_timeout_set_data(timeout, ev, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* DBusRemoveTimeoutFunction callback for pa mainloop */
|
||||
static void remove_timeout(DBusTimeout *timeout, void *data)
|
||||
{
|
||||
pa_core *c = (pa_core*) data;
|
||||
pa_time_event *ev = (pa_time_event*) dbus_timeout_get_data(timeout);
|
||||
static void remove_timeout(DBusTimeout *timeout, void *data) {
|
||||
pa_core *c = PA_CORE(data);
|
||||
pa_time_event *ev;
|
||||
|
||||
/* free the event */
|
||||
if (NULL != ev)
|
||||
pa_assert(timeout);
|
||||
pa_assert(c);
|
||||
|
||||
if ((ev = dbus_timeout_get_data(timeout)))
|
||||
c->mainloop->time_free(ev);
|
||||
}
|
||||
|
||||
/* DBusTimeoutToggledFunction callback for pa mainloop */
|
||||
static void toggle_timeout(DBusTimeout *timeout, void *data)
|
||||
{
|
||||
struct timeval tv;
|
||||
pa_core *c = (pa_core*) data;
|
||||
pa_time_event *ev = (pa_time_event*) dbus_timeout_get_data(timeout);
|
||||
static void toggle_timeout(DBusTimeout *timeout, void *data) {
|
||||
pa_core *c = PA_CORE(data);
|
||||
pa_time_event *ev;
|
||||
|
||||
pa_assert(timeout);
|
||||
pa_assert(c);
|
||||
|
||||
pa_assert_se(ev = dbus_timeout_get_data(timeout));
|
||||
|
||||
if (dbus_timeout_get_enabled(timeout)) {
|
||||
struct timeval tv;
|
||||
|
||||
pa_gettimeofday(&tv);
|
||||
pa_timeval_add(&tv, dbus_timeout_get_interval(timeout) * 1000);
|
||||
|
||||
c->mainloop->time_restart(ev, &tv);
|
||||
} else {
|
||||
/* disable the timeout */
|
||||
} else
|
||||
c->mainloop->time_restart(ev, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pa_dbus_connection_free(pa_dbus_connection *c)
|
||||
{
|
||||
assert(c);
|
||||
assert(!dbus_connection_get_is_connected(c->connection));
|
||||
static void wakeup_main(void *userdata) {
|
||||
pa_dbus_connection *c = userdata;
|
||||
|
||||
pa_assert(c);
|
||||
|
||||
/* this will wakeup the mainloop and dispatch events, although
|
||||
* it may not be the cleanest way of accomplishing it */
|
||||
c->core->mainloop->defer_enable(c->dispatch_event, 1);
|
||||
}
|
||||
|
||||
static pa_dbus_connection* pa_dbus_connection_new(pa_core* c, DBusConnection *conn, const char* name) {
|
||||
pa_dbus_connection *pconn;
|
||||
|
||||
pconn = pa_xnew(pa_dbus_connection, 1);
|
||||
PA_REFCNT_INIT(pconn);
|
||||
pconn->core = c;
|
||||
pconn->property_name = name;
|
||||
pconn->connection = conn;
|
||||
pconn->dispatch_event = c->mainloop->defer_new(c->mainloop, dispatch_cb, conn);
|
||||
|
||||
pa_property_set(c, name, pconn);
|
||||
|
||||
return pconn;
|
||||
}
|
||||
|
||||
DBusConnection* pa_dbus_connection_get(pa_dbus_connection *c){
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) > 0);
|
||||
pa_assert(c->connection);
|
||||
|
||||
return c->connection;
|
||||
}
|
||||
|
||||
void pa_dbus_connection_unref(pa_dbus_connection *c) {
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) > 0);
|
||||
|
||||
if (PA_REFCNT_DEC(c) > 0)
|
||||
return;
|
||||
|
||||
if (dbus_connection_get_is_connected(c->connection)) {
|
||||
dbus_connection_close(c->connection);
|
||||
/* must process remaining messages, bit of a kludge to handle
|
||||
* both unload and shutdown */
|
||||
while (dbus_connection_read_write_dispatch(c->connection, -1));
|
||||
}
|
||||
|
||||
/* already disconnected, just free */
|
||||
pa_property_remove(c->core, c->property_name);
|
||||
|
|
@ -235,113 +290,39 @@ pa_dbus_connection_free(pa_dbus_connection *c)
|
|||
pa_xfree(c);
|
||||
}
|
||||
|
||||
static void
|
||||
wakeup_main(void *userdata)
|
||||
{
|
||||
pa_dbus_connection *c = (pa_dbus_connection*) userdata;
|
||||
/* this will wakeup the mainloop and dispatch events, although
|
||||
* it may not be the cleanest way of accomplishing it */
|
||||
c->core->mainloop->defer_enable(c->dispatch_event, 1);
|
||||
}
|
||||
pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *c) {
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) > 0);
|
||||
|
||||
static pa_dbus_connection* pa_dbus_connection_new(pa_core* c, DBusConnection *conn, const char* name)
|
||||
{
|
||||
pa_dbus_connection *pconn = pa_xnew(pa_dbus_connection, 1);
|
||||
|
||||
pconn->refcount = 1;
|
||||
pconn->core = c;
|
||||
pconn->property_name = name;
|
||||
pconn->connection = conn;
|
||||
pconn->dispatch_event = c->mainloop->defer_new(c->mainloop, dispatch_cb,
|
||||
(void*) conn);
|
||||
|
||||
pa_property_set(c, name, pconn);
|
||||
|
||||
return pconn;
|
||||
}
|
||||
|
||||
DBusConnection* pa_dbus_connection_get(pa_dbus_connection *c)
|
||||
{
|
||||
assert(c && c->connection);
|
||||
return c->connection;
|
||||
}
|
||||
|
||||
void pa_dbus_connection_unref(pa_dbus_connection *c)
|
||||
{
|
||||
assert(c);
|
||||
|
||||
/* non-zero refcount, still outstanding refs */
|
||||
if (--(c->refcount))
|
||||
return;
|
||||
|
||||
/* refcount is zero */
|
||||
if (dbus_connection_get_is_connected(c->connection)) {
|
||||
/* disconnect as we have no more internal references */
|
||||
dbus_connection_close(c->connection);
|
||||
/* must process remaining messages, bit of a kludge to
|
||||
* handle both unload and shutdown */
|
||||
while(dbus_connection_read_write_dispatch(c->connection, -1));
|
||||
}
|
||||
pa_dbus_connection_free(c);
|
||||
}
|
||||
|
||||
pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *c)
|
||||
{
|
||||
assert(c);
|
||||
|
||||
++(c->refcount);
|
||||
PA_REFCNT_INC(c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type,
|
||||
DBusError *error)
|
||||
{
|
||||
const char* name;
|
||||
pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *error) {
|
||||
|
||||
static const char *const prop_name[] = {
|
||||
[DBUS_BUS_SESSION] = "dbus-connection-session",
|
||||
[DBUS_BUS_SYSTEM] = "dbus-connection-system",
|
||||
[DBUS_BUS_STARTER] = "dbus-connection-starter"
|
||||
};
|
||||
DBusConnection *conn;
|
||||
pa_dbus_connection *pconn;
|
||||
|
||||
switch (type) {
|
||||
case DBUS_BUS_SYSTEM:
|
||||
name = "dbus-connection-system";
|
||||
break;
|
||||
case DBUS_BUS_SESSION:
|
||||
name = "dbus-connection-session";
|
||||
break;
|
||||
case DBUS_BUS_STARTER:
|
||||
name = "dbus-connection-starter";
|
||||
break;
|
||||
default:
|
||||
assert(0); /* never reached */
|
||||
break;
|
||||
}
|
||||
pa_assert(type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION || type == DBUS_BUS_STARTER);
|
||||
|
||||
if ((pconn = pa_property_get(c, name)))
|
||||
if ((pconn = pa_property_get(c, prop_name[type])))
|
||||
return pa_dbus_connection_ref(pconn);
|
||||
|
||||
/* else */
|
||||
conn = dbus_bus_get_private(type, error);
|
||||
if (conn == NULL || dbus_error_is_set(error)) {
|
||||
if (!(conn = dbus_bus_get_private(type, error)))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pconn = pa_dbus_connection_new(c, conn, name);
|
||||
pconn = pa_dbus_connection_new(c, conn, prop_name[type]);
|
||||
|
||||
/* don't exit on disconnect */
|
||||
dbus_connection_set_exit_on_disconnect(conn, FALSE);
|
||||
/* set up the DBUS call backs */
|
||||
dbus_connection_set_dispatch_status_function(conn, dispatch_status,
|
||||
(void*) pconn, NULL);
|
||||
dbus_connection_set_watch_functions(conn,
|
||||
add_watch,
|
||||
remove_watch,
|
||||
toggle_watch,
|
||||
(void*) c, NULL);
|
||||
dbus_connection_set_timeout_functions(conn,
|
||||
add_timeout,
|
||||
remove_timeout,
|
||||
toggle_timeout,
|
||||
(void*) c, NULL);
|
||||
dbus_connection_set_dispatch_status_function(conn, dispatch_status, pconn, NULL);
|
||||
dbus_connection_set_watch_functions(conn, add_watch, remove_watch, toggle_watch, c, NULL);
|
||||
dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, toggle_timeout, c, NULL);
|
||||
dbus_connection_set_wakeup_main_function(conn, wakeup_main, pconn, NULL);
|
||||
|
||||
return pconn;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include <gconf/gconf-client.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
|
||||
#define PA_GCONF_ROOT "/system/pulseaudio"
|
||||
#define PA_GCONF_PATH_MODULES PA_GCONF_ROOT"/modules"
|
||||
|
||||
|
|
@ -40,13 +42,13 @@ static void handle_module(GConfClient *client, const char *name) {
|
|||
gboolean enabled, locked;
|
||||
int i;
|
||||
|
||||
snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/locked", name);
|
||||
pa_snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/locked", name);
|
||||
locked = gconf_client_get_bool(client, p, FALSE);
|
||||
|
||||
if (locked)
|
||||
return;
|
||||
|
||||
snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/enabled", name);
|
||||
pa_snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/enabled", name);
|
||||
enabled = gconf_client_get_bool(client, p, FALSE);
|
||||
|
||||
printf("%c%s%c", enabled ? '+' : '-', name, 0);
|
||||
|
|
@ -56,11 +58,11 @@ static void handle_module(GConfClient *client, const char *name) {
|
|||
for (i = 0; i < 10; i++) {
|
||||
gchar *n, *a;
|
||||
|
||||
snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/name%i", name, i);
|
||||
pa_snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/name%i", name, i);
|
||||
if (!(n = gconf_client_get_string(client, p, NULL)) || !*n)
|
||||
break;
|
||||
|
||||
snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/args%i", name, i);
|
||||
pa_snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/args%i", name, i);
|
||||
a = gconf_client_get_string(client, p, NULL);
|
||||
|
||||
printf("%s%c%s%c", n, 0, a ? a : "", 0);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -34,6 +33,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#ifdef HAVE_SYS_PRCTL_H
|
||||
#include <sys/prctl.h>
|
||||
|
|
@ -95,7 +95,7 @@ struct userdata {
|
|||
|
||||
static int fill_buf(struct userdata *u) {
|
||||
ssize_t r;
|
||||
assert(u);
|
||||
pa_assert(u);
|
||||
|
||||
if (u->buf_fill >= BUF_MAX) {
|
||||
pa_log("read buffer overflow");
|
||||
|
|
@ -111,21 +111,21 @@ static int fill_buf(struct userdata *u) {
|
|||
|
||||
static int read_byte(struct userdata *u) {
|
||||
int ret;
|
||||
assert(u);
|
||||
pa_assert(u);
|
||||
|
||||
if (u->buf_fill < 1)
|
||||
if (fill_buf(u) < 0)
|
||||
return -1;
|
||||
|
||||
ret = u->buf[0];
|
||||
assert(u->buf_fill > 0);
|
||||
pa_assert(u->buf_fill > 0);
|
||||
u->buf_fill--;
|
||||
memmove(u->buf, u->buf+1, u->buf_fill);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *read_string(struct userdata *u) {
|
||||
assert(u);
|
||||
pa_assert(u);
|
||||
|
||||
for (;;) {
|
||||
char *e;
|
||||
|
|
@ -143,9 +143,9 @@ static char *read_string(struct userdata *u) {
|
|||
}
|
||||
|
||||
static void unload_one_module(struct userdata *u, struct module_info*m, unsigned i) {
|
||||
assert(u);
|
||||
assert(m);
|
||||
assert(i < m->n_items);
|
||||
pa_assert(u);
|
||||
pa_assert(m);
|
||||
pa_assert(i < m->n_items);
|
||||
|
||||
if (m->items[i].index == PA_INVALID_INDEX)
|
||||
return;
|
||||
|
|
@ -161,8 +161,8 @@ static void unload_one_module(struct userdata *u, struct module_info*m, unsigned
|
|||
static void unload_all_modules(struct userdata *u, struct module_info*m) {
|
||||
unsigned i;
|
||||
|
||||
assert(u);
|
||||
assert(m);
|
||||
pa_assert(u);
|
||||
pa_assert(m);
|
||||
|
||||
for (i = 0; i < m->n_items; i++)
|
||||
unload_one_module(u, m, i);
|
||||
|
|
@ -180,10 +180,10 @@ static void load_module(
|
|||
|
||||
pa_module *mod;
|
||||
|
||||
assert(u);
|
||||
assert(m);
|
||||
assert(name);
|
||||
assert(args);
|
||||
pa_assert(u);
|
||||
pa_assert(m);
|
||||
pa_assert(name);
|
||||
pa_assert(args);
|
||||
|
||||
if (!is_new) {
|
||||
if (m->items[i].index != PA_INVALID_INDEX &&
|
||||
|
|
@ -212,8 +212,8 @@ static void module_info_free(void *p, void *userdata) {
|
|||
struct module_info *m = p;
|
||||
struct userdata *u = userdata;
|
||||
|
||||
assert(m);
|
||||
assert(u);
|
||||
pa_assert(m);
|
||||
pa_assert(u);
|
||||
|
||||
unload_all_modules(u, m);
|
||||
pa_xfree(m->name);
|
||||
|
|
@ -356,8 +356,10 @@ static int start_client(const char *n, pid_t *pid) {
|
|||
|
||||
return pipe_fds[0];
|
||||
} else {
|
||||
#ifdef __linux__
|
||||
DIR* d;
|
||||
#endif
|
||||
int max_fd, i;
|
||||
|
||||
/* child */
|
||||
|
||||
close(pipe_fds[0]);
|
||||
|
|
@ -372,18 +374,48 @@ static int start_client(const char *n, pid_t *pid) {
|
|||
close(2);
|
||||
open("/dev/null", O_WRONLY);
|
||||
|
||||
max_fd = 1024;
|
||||
#ifdef __linux__
|
||||
|
||||
if ((d = opendir("/proc/self/fd/"))) {
|
||||
|
||||
struct dirent *de;
|
||||
|
||||
while ((de = readdir(d))) {
|
||||
char *e = NULL;
|
||||
int fd;
|
||||
|
||||
if (de->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
errno = 0;
|
||||
fd = strtol(de->d_name, &e, 10);
|
||||
pa_assert(errno == 0 && e && *e == 0);
|
||||
|
||||
if (fd >= 3 && dirfd(d) != fd)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
} else {
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
{
|
||||
struct rlimit r;
|
||||
if (getrlimit(RLIMIT_NOFILE, &r) == 0)
|
||||
max_fd = r.rlim_max;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 3; i < max_fd; i++)
|
||||
close(i);
|
||||
max_fd = 1024;
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
{
|
||||
struct rlimit r;
|
||||
if (getrlimit(RLIMIT_NOFILE, &r) == 0)
|
||||
max_fd = r.rlim_max;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 3; i < max_fd; i++)
|
||||
close(i);
|
||||
#
|
||||
#ifdef __linux__
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PR_SET_PDEATHSIG
|
||||
/* On Linux we can use PR_SET_PDEATHSIG to have the helper
|
||||
|
|
@ -413,12 +445,12 @@ fail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
struct userdata *u;
|
||||
int r;
|
||||
|
||||
u = pa_xnew(struct userdata, 1);
|
||||
u->core = c;
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
m->userdata = u;
|
||||
u->module_infos = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
|
||||
|
|
@ -431,8 +463,8 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
if ((u->fd = start_client(PA_GCONF_HELPER, &u->pid)) < 0)
|
||||
goto fail;
|
||||
|
||||
u->io_event = c->mainloop->io_new(
|
||||
c->mainloop,
|
||||
u->io_event = m->core->mainloop->io_new(
|
||||
m->core->mainloop,
|
||||
u->fd,
|
||||
PA_IO_EVENT_INPUT,
|
||||
io_event_cb,
|
||||
|
|
@ -449,21 +481,20 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
pa__done(c, m);
|
||||
pa__done(m);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
if (u->io_event)
|
||||
c->mainloop->io_free(u->io_event);
|
||||
m->core->mainloop->io_free(u->io_event);
|
||||
|
||||
if (u->fd >= 0)
|
||||
close(u->fd);
|
||||
|
|
|
|||
603
src/modules/ladspa.h
Normal file
603
src/modules/ladspa.h
Normal file
|
|
@ -0,0 +1,603 @@
|
|||
/* ladspa.h
|
||||
|
||||
Linux Audio Developer's Simple Plugin API Version 1.1[LGPL].
|
||||
Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis,
|
||||
Stefan Westerfeld.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public License
|
||||
as published by the Free Software Foundation; either version 2.1 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA. */
|
||||
|
||||
#ifndef LADSPA_INCLUDED
|
||||
#define LADSPA_INCLUDED
|
||||
|
||||
#define LADSPA_VERSION "1.1"
|
||||
#define LADSPA_VERSION_MAJOR 1
|
||||
#define LADSPA_VERSION_MINOR 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Overview:
|
||||
|
||||
There is a large number of synthesis packages in use or development
|
||||
on the Linux platform at this time. This API (`The Linux Audio
|
||||
Developer's Simple Plugin API') attempts to give programmers the
|
||||
ability to write simple `plugin' audio processors in C/C++ and link
|
||||
them dynamically (`plug') into a range of these packages (`hosts').
|
||||
It should be possible for any host and any plugin to communicate
|
||||
completely through this interface.
|
||||
|
||||
This API is deliberately short and simple. To achieve compatibility
|
||||
with a range of promising Linux sound synthesis packages it
|
||||
attempts to find the `greatest common divisor' in their logical
|
||||
behaviour. Having said this, certain limiting decisions are
|
||||
implicit, notably the use of a fixed type (LADSPA_Data) for all
|
||||
data transfer and absence of a parameterised `initialisation'
|
||||
phase. See below for the LADSPA_Data typedef.
|
||||
|
||||
Plugins are expected to distinguish between control and audio
|
||||
data. Plugins have `ports' that are inputs or outputs for audio or
|
||||
control data and each plugin is `run' for a `block' corresponding
|
||||
to a short time interval measured in samples. Audio data is
|
||||
communicated using arrays of LADSPA_Data, allowing a block of audio
|
||||
to be processed by the plugin in a single pass. Control data is
|
||||
communicated using single LADSPA_Data values. Control data has a
|
||||
single value at the start of a call to the `run()' or `run_adding()'
|
||||
function, and may be considered to remain this value for its
|
||||
duration. The plugin may assume that all its input and output ports
|
||||
have been connected to the relevant data location (see the
|
||||
`connect_port()' function below) before it is asked to run.
|
||||
|
||||
Plugins will reside in shared object files suitable for dynamic
|
||||
linking by dlopen() and family. The file will provide a number of
|
||||
`plugin types' that can be used to instantiate actual plugins
|
||||
(sometimes known as `plugin instances') that can be connected
|
||||
together to perform tasks.
|
||||
|
||||
This API contains very limited error-handling. */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Fundamental data type passed in and out of plugin. This data type
|
||||
is used to communicate audio samples and control values. It is
|
||||
assumed that the plugin will work sensibly given any numeric input
|
||||
value although it may have a preferred range (see hints below).
|
||||
|
||||
For audio it is generally assumed that 1.0f is the `0dB' reference
|
||||
amplitude and is a `normal' signal level. */
|
||||
|
||||
typedef float LADSPA_Data;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Special Plugin Properties:
|
||||
|
||||
Optional features of the plugin type are encapsulated in the
|
||||
LADSPA_Properties type. This is assembled by ORing individual
|
||||
properties together. */
|
||||
|
||||
typedef int LADSPA_Properties;
|
||||
|
||||
/* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a
|
||||
real-time dependency (e.g. listens to a MIDI device) and so its
|
||||
output must not be cached or subject to significant latency. */
|
||||
#define LADSPA_PROPERTY_REALTIME 0x1
|
||||
|
||||
/* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin
|
||||
may cease to work correctly if the host elects to use the same data
|
||||
location for both input and output (see connect_port()). This
|
||||
should be avoided as enabling this flag makes it impossible for
|
||||
hosts to use the plugin to process audio `in-place.' */
|
||||
#define LADSPA_PROPERTY_INPLACE_BROKEN 0x2
|
||||
|
||||
/* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin
|
||||
is capable of running not only in a conventional host but also in a
|
||||
`hard real-time' environment. To qualify for this the plugin must
|
||||
satisfy all of the following:
|
||||
|
||||
(1) The plugin must not use malloc(), free() or other heap memory
|
||||
management within its run() or run_adding() functions. All new
|
||||
memory used in run() must be managed via the stack. These
|
||||
restrictions only apply to the run() function.
|
||||
|
||||
(2) The plugin will not attempt to make use of any library
|
||||
functions with the exceptions of functions in the ANSI standard C
|
||||
and C maths libraries, which the host is expected to provide.
|
||||
|
||||
(3) The plugin will not access files, devices, pipes, sockets, IPC
|
||||
or any other mechanism that might result in process or thread
|
||||
blocking.
|
||||
|
||||
(4) The plugin will take an amount of time to execute a run() or
|
||||
run_adding() call approximately of form (A+B*SampleCount) where A
|
||||
and B depend on the machine and host in use. This amount of time
|
||||
may not depend on input signals or plugin state. The host is left
|
||||
the responsibility to perform timings to estimate upper bounds for
|
||||
A and B. */
|
||||
#define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4
|
||||
|
||||
#define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME)
|
||||
#define LADSPA_IS_INPLACE_BROKEN(x) ((x) & LADSPA_PROPERTY_INPLACE_BROKEN)
|
||||
#define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Plugin Ports:
|
||||
|
||||
Plugins have `ports' that are inputs or outputs for audio or
|
||||
data. Ports can communicate arrays of LADSPA_Data (for audio
|
||||
inputs/outputs) or single LADSPA_Data values (for control
|
||||
input/outputs). This information is encapsulated in the
|
||||
LADSPA_PortDescriptor type which is assembled by ORing individual
|
||||
properties together.
|
||||
|
||||
Note that a port must be an input or an output port but not both
|
||||
and that a port must be a control or audio port but not both. */
|
||||
|
||||
typedef int LADSPA_PortDescriptor;
|
||||
|
||||
/* Property LADSPA_PORT_INPUT indicates that the port is an input. */
|
||||
#define LADSPA_PORT_INPUT 0x1
|
||||
|
||||
/* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */
|
||||
#define LADSPA_PORT_OUTPUT 0x2
|
||||
|
||||
/* Property LADSPA_PORT_CONTROL indicates that the port is a control
|
||||
port. */
|
||||
#define LADSPA_PORT_CONTROL 0x4
|
||||
|
||||
/* Property LADSPA_PORT_AUDIO indicates that the port is a audio
|
||||
port. */
|
||||
#define LADSPA_PORT_AUDIO 0x8
|
||||
|
||||
#define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT)
|
||||
#define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT)
|
||||
#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL)
|
||||
#define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Plugin Port Range Hints:
|
||||
|
||||
The host may wish to provide a representation of data entering or
|
||||
leaving a plugin (e.g. to generate a GUI automatically). To make
|
||||
this more meaningful, the plugin should provide `hints' to the host
|
||||
describing the usual values taken by the data.
|
||||
|
||||
Note that these are only hints. The host may ignore them and the
|
||||
plugin must not assume that data supplied to it is meaningful. If
|
||||
the plugin receives invalid input data it is expected to continue
|
||||
to run without failure and, where possible, produce a sensible
|
||||
output (e.g. a high-pass filter given a negative cutoff frequency
|
||||
might switch to an all-pass mode).
|
||||
|
||||
Hints are meaningful for all input and output ports but hints for
|
||||
input control ports are expected to be particularly useful.
|
||||
|
||||
More hint information is encapsulated in the
|
||||
LADSPA_PortRangeHintDescriptor type which is assembled by ORing
|
||||
individual hint types together. Hints may require further
|
||||
LowerBound and UpperBound information.
|
||||
|
||||
All the hint information for a particular port is aggregated in the
|
||||
LADSPA_PortRangeHint structure. */
|
||||
|
||||
typedef int LADSPA_PortRangeHintDescriptor;
|
||||
|
||||
/* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field
|
||||
of the LADSPA_PortRangeHint should be considered meaningful. The
|
||||
value in this field should be considered the (inclusive) lower
|
||||
bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
|
||||
specified then the value of LowerBound should be multiplied by the
|
||||
sample rate. */
|
||||
#define LADSPA_HINT_BOUNDED_BELOW 0x1
|
||||
|
||||
/* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field
|
||||
of the LADSPA_PortRangeHint should be considered meaningful. The
|
||||
value in this field should be considered the (inclusive) upper
|
||||
bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
|
||||
specified then the value of UpperBound should be multiplied by the
|
||||
sample rate. */
|
||||
#define LADSPA_HINT_BOUNDED_ABOVE 0x2
|
||||
|
||||
/* Hint LADSPA_HINT_TOGGLED indicates that the data item should be
|
||||
considered a Boolean toggle. Data less than or equal to zero should
|
||||
be considered `off' or `false,' and data above zero should be
|
||||
considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in
|
||||
conjunction with any other hint except LADSPA_HINT_DEFAULT_0 or
|
||||
LADSPA_HINT_DEFAULT_1. */
|
||||
#define LADSPA_HINT_TOGGLED 0x4
|
||||
|
||||
/* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified
|
||||
should be interpreted as multiples of the sample rate. For
|
||||
instance, a frequency range from 0Hz to the Nyquist frequency (half
|
||||
the sample rate) could be requested by this hint in conjunction
|
||||
with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds
|
||||
at all must support this hint to retain meaning. */
|
||||
#define LADSPA_HINT_SAMPLE_RATE 0x8
|
||||
|
||||
/* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the
|
||||
user will find it more intuitive to view values using a logarithmic
|
||||
scale. This is particularly useful for frequencies and gains. */
|
||||
#define LADSPA_HINT_LOGARITHMIC 0x10
|
||||
|
||||
/* Hint LADSPA_HINT_INTEGER indicates that a user interface would
|
||||
probably wish to provide a stepped control taking only integer
|
||||
values. Any bounds set should be slightly wider than the actual
|
||||
integer range required to avoid floating point rounding errors. For
|
||||
instance, the integer set {0,1,2,3} might be described as [-0.1,
|
||||
3.1]. */
|
||||
#define LADSPA_HINT_INTEGER 0x20
|
||||
|
||||
/* The various LADSPA_HINT_HAS_DEFAULT_* hints indicate a `normal'
|
||||
value for the port that is sensible as a default. For instance,
|
||||
this value is suitable for use as an initial value in a user
|
||||
interface or as a value the host might assign to a control port
|
||||
when the user has not provided one. Defaults are encoded using a
|
||||
mask so only one default may be specified for a port. Some of the
|
||||
hints make use of lower and upper bounds, in which case the
|
||||
relevant bound or bounds must be available and
|
||||
LADSPA_HINT_SAMPLE_RATE must be applied as usual. The resulting
|
||||
default must be rounded if LADSPA_HINT_INTEGER is present. Default
|
||||
values were introduced in LADSPA v1.1. */
|
||||
#define LADSPA_HINT_DEFAULT_MASK 0x3C0
|
||||
|
||||
/* This default values indicates that no default is provided. */
|
||||
#define LADSPA_HINT_DEFAULT_NONE 0x0
|
||||
|
||||
/* This default hint indicates that the suggested lower bound for the
|
||||
port should be used. */
|
||||
#define LADSPA_HINT_DEFAULT_MINIMUM 0x40
|
||||
|
||||
/* This default hint indicates that a low value between the suggested
|
||||
lower and upper bounds should be chosen. For ports with
|
||||
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.75 +
|
||||
log(upper) * 0.25). Otherwise, this should be (lower * 0.75 + upper
|
||||
* 0.25). */
|
||||
#define LADSPA_HINT_DEFAULT_LOW 0x80
|
||||
|
||||
/* This default hint indicates that a middle value between the
|
||||
suggested lower and upper bounds should be chosen. For ports with
|
||||
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.5 +
|
||||
log(upper) * 0.5). Otherwise, this should be (lower * 0.5 + upper *
|
||||
0.5). */
|
||||
#define LADSPA_HINT_DEFAULT_MIDDLE 0xC0
|
||||
|
||||
/* This default hint indicates that a high value between the suggested
|
||||
lower and upper bounds should be chosen. For ports with
|
||||
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.25 +
|
||||
log(upper) * 0.75). Otherwise, this should be (lower * 0.25 + upper
|
||||
* 0.75). */
|
||||
#define LADSPA_HINT_DEFAULT_HIGH 0x100
|
||||
|
||||
/* This default hint indicates that the suggested upper bound for the
|
||||
port should be used. */
|
||||
#define LADSPA_HINT_DEFAULT_MAXIMUM 0x140
|
||||
|
||||
/* This default hint indicates that the number 0 should be used. Note
|
||||
that this default may be used in conjunction with
|
||||
LADSPA_HINT_TOGGLED. */
|
||||
#define LADSPA_HINT_DEFAULT_0 0x200
|
||||
|
||||
/* This default hint indicates that the number 1 should be used. Note
|
||||
that this default may be used in conjunction with
|
||||
LADSPA_HINT_TOGGLED. */
|
||||
#define LADSPA_HINT_DEFAULT_1 0x240
|
||||
|
||||
/* This default hint indicates that the number 100 should be used. */
|
||||
#define LADSPA_HINT_DEFAULT_100 0x280
|
||||
|
||||
/* This default hint indicates that the Hz frequency of `concert A'
|
||||
should be used. This will be 440 unless the host uses an unusual
|
||||
tuning convention, in which case it may be within a few Hz. */
|
||||
#define LADSPA_HINT_DEFAULT_440 0x2C0
|
||||
|
||||
#define LADSPA_IS_HINT_BOUNDED_BELOW(x) ((x) & LADSPA_HINT_BOUNDED_BELOW)
|
||||
#define LADSPA_IS_HINT_BOUNDED_ABOVE(x) ((x) & LADSPA_HINT_BOUNDED_ABOVE)
|
||||
#define LADSPA_IS_HINT_TOGGLED(x) ((x) & LADSPA_HINT_TOGGLED)
|
||||
#define LADSPA_IS_HINT_SAMPLE_RATE(x) ((x) & LADSPA_HINT_SAMPLE_RATE)
|
||||
#define LADSPA_IS_HINT_LOGARITHMIC(x) ((x) & LADSPA_HINT_LOGARITHMIC)
|
||||
#define LADSPA_IS_HINT_INTEGER(x) ((x) & LADSPA_HINT_INTEGER)
|
||||
|
||||
#define LADSPA_IS_HINT_HAS_DEFAULT(x) ((x) & LADSPA_HINT_DEFAULT_MASK)
|
||||
#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_MINIMUM)
|
||||
#define LADSPA_IS_HINT_DEFAULT_LOW(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_LOW)
|
||||
#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_MIDDLE)
|
||||
#define LADSPA_IS_HINT_DEFAULT_HIGH(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_HIGH)
|
||||
#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_MAXIMUM)
|
||||
#define LADSPA_IS_HINT_DEFAULT_0(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_0)
|
||||
#define LADSPA_IS_HINT_DEFAULT_1(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_1)
|
||||
#define LADSPA_IS_HINT_DEFAULT_100(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_100)
|
||||
#define LADSPA_IS_HINT_DEFAULT_440(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_440)
|
||||
|
||||
typedef struct _LADSPA_PortRangeHint {
|
||||
|
||||
/* Hints about the port. */
|
||||
LADSPA_PortRangeHintDescriptor HintDescriptor;
|
||||
|
||||
/* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When
|
||||
LADSPA_HINT_SAMPLE_RATE is also active then this value should be
|
||||
multiplied by the relevant sample rate. */
|
||||
LADSPA_Data LowerBound;
|
||||
|
||||
/* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When
|
||||
LADSPA_HINT_SAMPLE_RATE is also active then this value should be
|
||||
multiplied by the relevant sample rate. */
|
||||
LADSPA_Data UpperBound;
|
||||
|
||||
} LADSPA_PortRangeHint;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Plugin Handles:
|
||||
|
||||
This plugin handle indicates a particular instance of the plugin
|
||||
concerned. It is valid to compare this to NULL (0 for C++) but
|
||||
otherwise the host should not attempt to interpret it. The plugin
|
||||
may use it to reference internal instance data. */
|
||||
|
||||
typedef void * LADSPA_Handle;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Descriptor for a Type of Plugin:
|
||||
|
||||
This structure is used to describe a plugin type. It provides a
|
||||
number of functions to examine the type, instantiate it, link it to
|
||||
buffers and workspaces and to run it. */
|
||||
|
||||
typedef struct _LADSPA_Descriptor {
|
||||
|
||||
/* This numeric identifier indicates the plugin type
|
||||
uniquely. Plugin programmers may reserve ranges of IDs from a
|
||||
central body to avoid clashes. Hosts may assume that IDs are
|
||||
below 0x1000000. */
|
||||
unsigned long UniqueID;
|
||||
|
||||
/* This identifier can be used as a unique, case-sensitive
|
||||
identifier for the plugin type within the plugin file. Plugin
|
||||
types should be identified by file and label rather than by index
|
||||
or plugin name, which may be changed in new plugin
|
||||
versions. Labels must not contain white-space characters. */
|
||||
const char * Label;
|
||||
|
||||
/* This indicates a number of properties of the plugin. */
|
||||
LADSPA_Properties Properties;
|
||||
|
||||
/* This member points to the null-terminated name of the plugin
|
||||
(e.g. "Sine Oscillator"). */
|
||||
const char * Name;
|
||||
|
||||
/* This member points to the null-terminated string indicating the
|
||||
maker of the plugin. This can be an empty string but not NULL. */
|
||||
const char * Maker;
|
||||
|
||||
/* This member points to the null-terminated string indicating any
|
||||
copyright applying to the plugin. If no Copyright applies the
|
||||
string "None" should be used. */
|
||||
const char * Copyright;
|
||||
|
||||
/* This indicates the number of ports (input AND output) present on
|
||||
the plugin. */
|
||||
unsigned long PortCount;
|
||||
|
||||
/* This member indicates an array of port descriptors. Valid indices
|
||||
vary from 0 to PortCount-1. */
|
||||
const LADSPA_PortDescriptor * PortDescriptors;
|
||||
|
||||
/* This member indicates an array of null-terminated strings
|
||||
describing ports (e.g. "Frequency (Hz)"). Valid indices vary from
|
||||
0 to PortCount-1. */
|
||||
const char * const * PortNames;
|
||||
|
||||
/* This member indicates an array of range hints for each port (see
|
||||
above). Valid indices vary from 0 to PortCount-1. */
|
||||
const LADSPA_PortRangeHint * PortRangeHints;
|
||||
|
||||
/* This may be used by the plugin developer to pass any custom
|
||||
implementation data into an instantiate call. It must not be used
|
||||
or interpreted by the host. It is expected that most plugin
|
||||
writers will not use this facility as LADSPA_Handle should be
|
||||
used to hold instance data. */
|
||||
void * ImplementationData;
|
||||
|
||||
/* This member is a function pointer that instantiates a plugin. A
|
||||
handle is returned indicating the new plugin instance. The
|
||||
instantiation function accepts a sample rate as a parameter. The
|
||||
plugin descriptor from which this instantiate function was found
|
||||
must also be passed. This function must return NULL if
|
||||
instantiation fails.
|
||||
|
||||
Note that instance initialisation should generally occur in
|
||||
activate() rather than here. */
|
||||
LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor,
|
||||
unsigned long SampleRate);
|
||||
|
||||
/* This member is a function pointer that connects a port on an
|
||||
instantiated plugin to a memory location at which a block of data
|
||||
for the port will be read/written. The data location is expected
|
||||
to be an array of LADSPA_Data for audio ports or a single
|
||||
LADSPA_Data value for control ports. Memory issues will be
|
||||
managed by the host. The plugin must read/write the data at these
|
||||
locations every time run() or run_adding() is called and the data
|
||||
present at the time of this connection call should not be
|
||||
considered meaningful.
|
||||
|
||||
connect_port() may be called more than once for a plugin instance
|
||||
to allow the host to change the buffers that the plugin is
|
||||
reading or writing. These calls may be made before or after
|
||||
activate() or deactivate() calls.
|
||||
|
||||
connect_port() must be called at least once for each port before
|
||||
run() or run_adding() is called. When working with blocks of
|
||||
LADSPA_Data the plugin should pay careful attention to the block
|
||||
size passed to the run function as the block allocated may only
|
||||
just be large enough to contain the block of samples.
|
||||
|
||||
Plugin writers should be aware that the host may elect to use the
|
||||
same buffer for more than one port and even use the same buffer
|
||||
for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN).
|
||||
However, overlapped buffers or use of a single buffer for both
|
||||
audio and control data may result in unexpected behaviour. */
|
||||
void (*connect_port)(LADSPA_Handle Instance,
|
||||
unsigned long Port,
|
||||
LADSPA_Data * DataLocation);
|
||||
|
||||
/* This member is a function pointer that initialises a plugin
|
||||
instance and activates it for use. This is separated from
|
||||
instantiate() to aid real-time support and so that hosts can
|
||||
reinitialise a plugin instance by calling deactivate() and then
|
||||
activate(). In this case the plugin instance must reset all state
|
||||
information dependent on the history of the plugin instance
|
||||
except for any data locations provided by connect_port() and any
|
||||
gain set by set_run_adding_gain(). If there is nothing for
|
||||
activate() to do then the plugin writer may provide a NULL rather
|
||||
than an empty function.
|
||||
|
||||
When present, hosts must call this function once before run() (or
|
||||
run_adding()) is called for the first time. This call should be
|
||||
made as close to the run() call as possible and indicates to
|
||||
real-time plugins that they are now live. Plugins should not rely
|
||||
on a prompt call to run() after activate(). activate() may not be
|
||||
called again unless deactivate() is called first. Note that
|
||||
connect_port() may be called before or after a call to
|
||||
activate(). */
|
||||
void (*activate)(LADSPA_Handle Instance);
|
||||
|
||||
/* This method is a function pointer that runs an instance of a
|
||||
plugin for a block. Two parameters are required: the first is a
|
||||
handle to the particular instance to be run and the second
|
||||
indicates the block size (in samples) for which the plugin
|
||||
instance may run.
|
||||
|
||||
Note that if an activate() function exists then it must be called
|
||||
before run() or run_adding(). If deactivate() is called for a
|
||||
plugin instance then the plugin instance may not be reused until
|
||||
activate() has been called again.
|
||||
|
||||
If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE
|
||||
then there are various things that the plugin should not do
|
||||
within the run() or run_adding() functions (see above). */
|
||||
void (*run)(LADSPA_Handle Instance,
|
||||
unsigned long SampleCount);
|
||||
|
||||
/* This method is a function pointer that runs an instance of a
|
||||
plugin for a block. This has identical behaviour to run() except
|
||||
in the way data is output from the plugin. When run() is used,
|
||||
values are written directly to the memory areas associated with
|
||||
the output ports. However when run_adding() is called, values
|
||||
must be added to the values already present in the memory
|
||||
areas. Furthermore, output values written must be scaled by the
|
||||
current gain set by set_run_adding_gain() (see below) before
|
||||
addition.
|
||||
|
||||
run_adding() is optional. When it is not provided by a plugin,
|
||||
this function pointer must be set to NULL. When it is provided,
|
||||
the function set_run_adding_gain() must be provided also. */
|
||||
void (*run_adding)(LADSPA_Handle Instance,
|
||||
unsigned long SampleCount);
|
||||
|
||||
/* This method is a function pointer that sets the output gain for
|
||||
use when run_adding() is called (see above). If this function is
|
||||
never called the gain is assumed to default to 1. Gain
|
||||
information should be retained when activate() or deactivate()
|
||||
are called.
|
||||
|
||||
This function should be provided by the plugin if and only if the
|
||||
run_adding() function is provided. When it is absent this
|
||||
function pointer must be set to NULL. */
|
||||
void (*set_run_adding_gain)(LADSPA_Handle Instance,
|
||||
LADSPA_Data Gain);
|
||||
|
||||
/* This is the counterpart to activate() (see above). If there is
|
||||
nothing for deactivate() to do then the plugin writer may provide
|
||||
a NULL rather than an empty function.
|
||||
|
||||
Hosts must deactivate all activated units after they have been
|
||||
run() (or run_adding()) for the last time. This call should be
|
||||
made as close to the last run() call as possible and indicates to
|
||||
real-time plugins that they are no longer live. Plugins should
|
||||
not rely on prompt deactivation. Note that connect_port() may be
|
||||
called before or after a call to deactivate().
|
||||
|
||||
Deactivation is not similar to pausing as the plugin instance
|
||||
will be reinitialised when activate() is called to reuse it. */
|
||||
void (*deactivate)(LADSPA_Handle Instance);
|
||||
|
||||
/* Once an instance of a plugin has been finished with it can be
|
||||
deleted using the following function. The instance handle passed
|
||||
ceases to be valid after this call.
|
||||
|
||||
If activate() was called for a plugin instance then a
|
||||
corresponding call to deactivate() must be made before cleanup()
|
||||
is called. */
|
||||
void (*cleanup)(LADSPA_Handle Instance);
|
||||
|
||||
} LADSPA_Descriptor;
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/* Accessing a Plugin: */
|
||||
|
||||
/* The exact mechanism by which plugins are loaded is host-dependent,
|
||||
however all most hosts will need to know is the name of shared
|
||||
object file containing the plugin types. To allow multiple hosts to
|
||||
share plugin types, hosts may wish to check for environment
|
||||
variable LADSPA_PATH. If present, this should contain a
|
||||
colon-separated path indicating directories that should be searched
|
||||
(in order) when loading plugin types.
|
||||
|
||||
A plugin programmer must include a function called
|
||||
"ladspa_descriptor" with the following function prototype within
|
||||
the shared object file. This function will have C-style linkage (if
|
||||
you are using C++ this is taken care of by the `extern "C"' clause
|
||||
at the top of the file).
|
||||
|
||||
A host will find the plugin shared object file by one means or
|
||||
another, find the ladspa_descriptor() function, call it, and
|
||||
proceed from there.
|
||||
|
||||
Plugin types are accessed by index (not ID) using values from 0
|
||||
upwards. Out of range indexes must result in this function
|
||||
returning NULL, so the plugin count can be determined by checking
|
||||
for the least index that results in NULL being returned. */
|
||||
|
||||
const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index);
|
||||
|
||||
/* Datatype corresponding to the ladspa_descriptor() function. */
|
||||
typedef const LADSPA_Descriptor *
|
||||
(*LADSPA_Descriptor_Function)(unsigned long Index);
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LADSPA_INCLUDED */
|
||||
|
||||
/* EOF */
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -26,7 +26,6 @@
|
|||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <pulsecore/module.h>
|
||||
|
|
@ -35,6 +34,7 @@
|
|||
#include <pulsecore/sioman.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "module-cli-symdef.h"
|
||||
|
||||
|
|
@ -51,8 +51,8 @@ static const char* const valid_modargs[] = {
|
|||
static void eof_and_unload_cb(pa_cli*c, void *userdata) {
|
||||
pa_module *m = userdata;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(c);
|
||||
pa_assert(m);
|
||||
|
||||
pa_module_unload_request(m);
|
||||
}
|
||||
|
|
@ -60,21 +60,20 @@ static void eof_and_unload_cb(pa_cli*c, void *userdata) {
|
|||
static void eof_and_exit_cb(pa_cli*c, void *userdata) {
|
||||
pa_module *m = userdata;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(c);
|
||||
pa_assert(m);
|
||||
|
||||
m->core->mainloop->quit(m->core->mainloop, 0);
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
pa_iochannel *io;
|
||||
pa_modargs *ma;
|
||||
int exit_on_eof = 0;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (c->running_as_daemon) {
|
||||
if (m->core->running_as_daemon) {
|
||||
pa_log_info("Running as daemon, refusing to load this module.");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -94,12 +93,10 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
io = pa_iochannel_new(c->mainloop, STDIN_FILENO, STDOUT_FILENO);
|
||||
assert(io);
|
||||
io = pa_iochannel_new(m->core->mainloop, STDIN_FILENO, STDOUT_FILENO);
|
||||
pa_iochannel_set_noclose(io, 1);
|
||||
|
||||
m->userdata = pa_cli_new(c, io, m);
|
||||
assert(m->userdata);
|
||||
m->userdata = pa_cli_new(m->core, io, m);
|
||||
|
||||
pa_cli_set_eof_callback(m->userdata, exit_on_eof ? eof_and_exit_cb : eof_and_unload_cb, m);
|
||||
|
||||
|
|
@ -115,11 +112,10 @@ fail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
assert(c);
|
||||
assert(m);
|
||||
void pa__done(pa_module*m) {
|
||||
pa_assert(m);
|
||||
|
||||
if (c->running_as_daemon == 0) {
|
||||
if (m->core->running_as_daemon == 0) {
|
||||
pa_cli_free(m->userdata);
|
||||
pa_stdio_release();
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
103
src/modules/module-default-device-restore.c
Normal file
103
src/modules/module-default-device-restore.c
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/* $Id$ */
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2006 Lennart Poettering
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/module.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/namereg.h>
|
||||
|
||||
#include "module-default-device-restore-symdef.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Lennart Poettering")
|
||||
PA_MODULE_DESCRIPTION("Automatically restore the default sink and source")
|
||||
PA_MODULE_VERSION(PACKAGE_VERSION)
|
||||
|
||||
#define DEFAULT_SINK_FILE "default-sink"
|
||||
#define DEFAULT_SOURCE_FILE "default-source"
|
||||
|
||||
int pa__init(pa_module *m) {
|
||||
FILE *f;
|
||||
|
||||
/* We never overwrite manually configured settings */
|
||||
|
||||
if (m->core->default_sink_name)
|
||||
pa_log_info("Manually configured default sink, not overwriting.");
|
||||
else if ((f = pa_open_config_file(NULL, DEFAULT_SINK_FILE, NULL, NULL, "r"))) {
|
||||
char ln[256] = "";
|
||||
|
||||
fgets(ln, sizeof(ln)-1, f);
|
||||
pa_strip_nl(ln);
|
||||
fclose(f);
|
||||
|
||||
if (!ln[0])
|
||||
pa_log_debug("No previous default sink setting, ignoring.");
|
||||
else if (pa_namereg_get(m->core, ln, PA_NAMEREG_SINK, 1)) {
|
||||
pa_namereg_set_default(m->core, ln, PA_NAMEREG_SINK);
|
||||
pa_log_debug("Restored default sink '%s'.", ln);
|
||||
} else
|
||||
pa_log_info("Saved default sink '%s' not existant, not restoring default sink setting.", ln);
|
||||
}
|
||||
|
||||
if (m->core->default_source_name)
|
||||
pa_log_info("Manually configured default source, not overwriting.");
|
||||
else if ((f = pa_open_config_file(NULL, DEFAULT_SOURCE_FILE, NULL, NULL, "r"))) {
|
||||
char ln[256] = "";
|
||||
|
||||
fgets(ln, sizeof(ln)-1, f);
|
||||
pa_strip_nl(ln);
|
||||
fclose(f);
|
||||
|
||||
if (!ln[0])
|
||||
pa_log_debug("No previous default source setting, ignoring.");
|
||||
else if (pa_namereg_get(m->core, ln, PA_NAMEREG_SOURCE, 1)) {
|
||||
pa_namereg_set_default(m->core, ln, PA_NAMEREG_SOURCE);
|
||||
pa_log_debug("Restored default source '%s'.", ln);
|
||||
} else
|
||||
pa_log_info("Saved default source '%s' not existant, not restoring default source setting.", ln);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pa__done(pa_module*m) {
|
||||
FILE *f;
|
||||
|
||||
if ((f = pa_open_config_file(NULL, DEFAULT_SINK_FILE, NULL, NULL, "w"))) {
|
||||
const char *n = pa_namereg_get_default_sink_name(m->core);
|
||||
fprintf(f, "%s\n", n ? n : "");
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
if ((f = pa_open_config_file(NULL, DEFAULT_SOURCE_FILE, NULL, NULL, "w"))) {
|
||||
const char *n = pa_namereg_get_default_source_name(m->core);
|
||||
fprintf(f, "%s\n", n ? n : "");
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -18,8 +18,8 @@ gen_symbol(pa__get_description)
|
|||
gen_symbol(pa__get_usage)
|
||||
gen_symbol(pa__get_version)
|
||||
|
||||
int pa__init(struct pa_core *c, struct pa_module*m);
|
||||
void pa__done(struct pa_core *c, struct pa_module*m);
|
||||
int pa__init(pa_module*m);
|
||||
void pa__done(pa_module*m);
|
||||
|
||||
const char* pa__get_author(void);
|
||||
const char* pa__get_description(void);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -44,6 +43,7 @@
|
|||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "module-detect-symdef.h"
|
||||
|
||||
|
|
@ -52,6 +52,11 @@ PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers
|
|||
PA_MODULE_VERSION(PACKAGE_VERSION)
|
||||
PA_MODULE_USAGE("just-one=<boolean>")
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"just-one",
|
||||
NULL
|
||||
};
|
||||
|
||||
#ifdef HAVE_ALSA
|
||||
|
||||
static int detect_alsa(pa_core *c, int just_one) {
|
||||
|
|
@ -96,7 +101,7 @@ static int detect_alsa(pa_core *c, int just_one) {
|
|||
if (subdevice != 0)
|
||||
continue;
|
||||
|
||||
snprintf(args, sizeof(args), "device=hw:%u", device);
|
||||
pa_snprintf(args, sizeof(args), "device=hw:%u", device);
|
||||
if (!pa_module_load(c, is_sink ? "module-alsa-sink" : "module-alsa-source", args))
|
||||
continue;
|
||||
|
||||
|
|
@ -139,7 +144,7 @@ static int detect_oss(pa_core *c, int just_one) {
|
|||
line[strcspn(line, "\r\n")] = 0;
|
||||
|
||||
if (!b) {
|
||||
b = strcmp(line, "Audio devices:") == 0 || strcmp(line, "Installed devices:") == 0;
|
||||
b = strcmp(line, "Audio devices:") == 0 || strcmp(line, "Installed devices:") == 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -148,20 +153,20 @@ static int detect_oss(pa_core *c, int just_one) {
|
|||
|
||||
if (sscanf(line, "%u: ", &device) == 1) {
|
||||
if (device == 0)
|
||||
snprintf(args, sizeof(args), "device=/dev/dsp");
|
||||
pa_snprintf(args, sizeof(args), "device=/dev/dsp");
|
||||
else
|
||||
snprintf(args, sizeof(args), "device=/dev/dsp%u", device);
|
||||
pa_snprintf(args, sizeof(args), "device=/dev/dsp%u", device);
|
||||
|
||||
if (!pa_module_load(c, "module-oss", args))
|
||||
continue;
|
||||
|
||||
} else if (sscanf(line, "pcm%u: ", &device) == 1) {
|
||||
} else if (sscanf(line, "pcm%u: ", &device) == 1) {
|
||||
/* FreeBSD support, the devices are named /dev/dsp0.0, dsp0.1 and so on */
|
||||
snprintf(args, sizeof(args), "device=/dev/dsp%u.0", device);
|
||||
pa_snprintf(args, sizeof(args), "device=/dev/dsp%u.0", device);
|
||||
|
||||
if (!pa_module_load(c, "module-oss", args))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
n++;
|
||||
|
||||
|
|
@ -193,7 +198,7 @@ static int detect_solaris(pa_core *c, int just_one) {
|
|||
if (!S_ISCHR(s.st_mode))
|
||||
return 0;
|
||||
|
||||
snprintf(args, sizeof(args), "device=%s", dev);
|
||||
pa_snprintf(args, sizeof(args), "device=%s", dev);
|
||||
|
||||
if (!pa_module_load(c, "module-solaris", args))
|
||||
return 0;
|
||||
|
|
@ -215,17 +220,11 @@ static int detect_waveout(pa_core *c, int just_one) {
|
|||
}
|
||||
#endif
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
int just_one = 0, n = 0;
|
||||
pa_modargs *ma;
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"just-one",
|
||||
NULL
|
||||
};
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments");
|
||||
|
|
@ -238,16 +237,16 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
}
|
||||
|
||||
#if HAVE_ALSA
|
||||
if ((n = detect_alsa(c, just_one)) <= 0)
|
||||
if ((n = detect_alsa(m->core, just_one)) <= 0)
|
||||
#endif
|
||||
#if HAVE_OSS
|
||||
if ((n = detect_oss(c, just_one)) <= 0)
|
||||
if ((n = detect_oss(m->core, just_one)) <= 0)
|
||||
#endif
|
||||
#if HAVE_SOLARIS
|
||||
if ((n = detect_solaris(c, just_one)) <= 0)
|
||||
if ((n = detect_solaris(m->core, just_one)) <= 0)
|
||||
#endif
|
||||
#if OS_IS_WIN32
|
||||
if ((n = detect_waveout(c, just_one)) <= 0)
|
||||
if ((n = detect_waveout(m->core, just_one)) <= 0)
|
||||
#endif
|
||||
{
|
||||
pa_log_warn("failed to detect any sound hardware.");
|
||||
|
|
@ -269,9 +268,3 @@ fail:
|
|||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void pa__done(PA_GCC_UNUSED pa_core *c, PA_GCC_UNUSED pa_module*m) {
|
||||
/* NOP */
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
|
@ -48,23 +47,25 @@ static const char* const valid_modargs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
pa_modargs *ma = NULL;
|
||||
int ret = -1, fd = -1;
|
||||
char x = 1;
|
||||
assert(c && m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs)) ||
|
||||
pa_modargs_get_value_s32(ma, "fd", &fd) < 0 ||
|
||||
fd < 0) {
|
||||
|
||||
pa_log("Failed to parse module arguments");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (pa_loop_write(fd, &x, sizeof(x), NULL) != sizeof(x))
|
||||
pa_log("WARNING: write(%u, 1, 1) failed: %s", fd, pa_cstrerror(errno));
|
||||
pa_log_warn("write(%u, 1, 1) failed: %s", fd, pa_cstrerror(errno));
|
||||
|
||||
close(fd);
|
||||
pa_assert_se(pa_close(fd) == 0);
|
||||
|
||||
pa_module_unload_request(m);
|
||||
|
||||
|
|
@ -76,9 +77,3 @@ finish:
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
assert(c && m);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
|
@ -48,11 +47,12 @@ static const char* const valid_modargs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
pa_modargs *ma = NULL;
|
||||
int ret = -1;
|
||||
uint32_t pid = 0;
|
||||
assert(c && m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs)) ||
|
||||
pa_modargs_get_value_u32(ma, "pid", &pid) < 0 ||
|
||||
|
|
@ -62,7 +62,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
}
|
||||
|
||||
if (kill(pid, SIGUSR1) < 0)
|
||||
pa_log("WARNING: kill(%u) failed: %s", pid, pa_cstrerror(errno));
|
||||
pa_log_warn("kill(%u) failed: %s", pid, pa_cstrerror(errno));
|
||||
|
||||
pa_module_unload_request(m);
|
||||
|
||||
|
|
@ -74,9 +74,3 @@ finish:
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
assert(c && m);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -28,14 +28,23 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <poll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef HAVE_LINUX_SOCKIOS_H
|
||||
#include <linux/sockios.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/timeval.h>
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/iochannel.h>
|
||||
|
|
@ -47,27 +56,37 @@
|
|||
#include <pulsecore/socket-client.h>
|
||||
#include <pulsecore/esound.h>
|
||||
#include <pulsecore/authkey.h>
|
||||
#include <pulsecore/thread-mq.h>
|
||||
#include <pulsecore/thread.h>
|
||||
#include <pulsecore/time-smoother.h>
|
||||
#include <pulsecore/rtclock.h>
|
||||
#include <pulsecore/socket-util.h>
|
||||
|
||||
#include "module-esound-sink-symdef.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Lennart Poettering")
|
||||
PA_MODULE_DESCRIPTION("ESOUND Sink")
|
||||
PA_MODULE_VERSION(PACKAGE_VERSION)
|
||||
PA_MODULE_USAGE("sink_name=<name for the sink> server=<address> cookie=<filename> format=<sample format> channels=<number of channels> rate=<sample rate>")
|
||||
PA_MODULE_USAGE(
|
||||
"sink_name=<name for the sink> "
|
||||
"server=<address> cookie=<filename> "
|
||||
"format=<sample format> "
|
||||
"channels=<number of channels> "
|
||||
"rate=<sample rate>")
|
||||
|
||||
#define DEFAULT_SINK_NAME "esound_output"
|
||||
#define DEFAULT_SINK_NAME "esound_out"
|
||||
|
||||
struct userdata {
|
||||
pa_core *core;
|
||||
|
||||
pa_module *module;
|
||||
pa_sink *sink;
|
||||
pa_iochannel *io;
|
||||
pa_socket_client *client;
|
||||
|
||||
pa_defer_event *defer_event;
|
||||
pa_thread_mq thread_mq;
|
||||
pa_rtpoll *rtpoll;
|
||||
pa_rtpoll_item *rtpoll_item;
|
||||
pa_thread *thread;
|
||||
|
||||
pa_memchunk memchunk;
|
||||
pa_module *module;
|
||||
|
||||
void *write_data;
|
||||
size_t write_length, write_index;
|
||||
|
|
@ -75,12 +94,28 @@ struct userdata {
|
|||
void *read_data;
|
||||
size_t read_length, read_index;
|
||||
|
||||
enum { STATE_AUTH, STATE_LATENCY, STATE_RUNNING, STATE_DEAD } state;
|
||||
enum {
|
||||
STATE_AUTH,
|
||||
STATE_LATENCY,
|
||||
STATE_PREPARE,
|
||||
STATE_RUNNING,
|
||||
STATE_DEAD
|
||||
} state;
|
||||
|
||||
pa_usec_t latency;
|
||||
|
||||
esd_format_t format;
|
||||
int32_t rate;
|
||||
|
||||
pa_smoother *smoother;
|
||||
int fd;
|
||||
|
||||
int64_t offset;
|
||||
|
||||
pa_iochannel *io;
|
||||
pa_socket_client *client;
|
||||
|
||||
size_t block_size;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
|
|
@ -93,42 +128,211 @@ static const char* const valid_modargs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static void cancel(struct userdata *u) {
|
||||
assert(u);
|
||||
enum {
|
||||
SINK_MESSAGE_PASS_SOCKET = PA_SINK_MESSAGE_MAX
|
||||
};
|
||||
|
||||
u->state = STATE_DEAD;
|
||||
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
struct userdata *u = PA_SINK(o)->userdata;
|
||||
|
||||
if (u->io) {
|
||||
pa_iochannel_free(u->io);
|
||||
u->io = NULL;
|
||||
switch (code) {
|
||||
|
||||
case PA_SINK_MESSAGE_SET_STATE:
|
||||
|
||||
switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
|
||||
|
||||
case PA_SINK_SUSPENDED:
|
||||
pa_assert(PA_SINK_OPENED(u->sink->thread_info.state));
|
||||
|
||||
pa_smoother_pause(u->smoother, pa_rtclock_usec());
|
||||
break;
|
||||
|
||||
case PA_SINK_IDLE:
|
||||
case PA_SINK_RUNNING:
|
||||
|
||||
if (u->sink->thread_info.state == PA_SINK_SUSPENDED)
|
||||
pa_smoother_resume(u->smoother, pa_rtclock_usec());
|
||||
|
||||
break;
|
||||
|
||||
case PA_SINK_UNLINKED:
|
||||
case PA_SINK_INIT:
|
||||
;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PA_SINK_MESSAGE_GET_LATENCY: {
|
||||
pa_usec_t w, r;
|
||||
|
||||
r = pa_smoother_get(u->smoother, pa_rtclock_usec());
|
||||
w = pa_bytes_to_usec(u->offset + u->memchunk.length, &u->sink->sample_spec);
|
||||
|
||||
*((pa_usec_t*) data) = w > r ? w - r : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case SINK_MESSAGE_PASS_SOCKET: {
|
||||
struct pollfd *pollfd;
|
||||
|
||||
pa_assert(!u->rtpoll_item);
|
||||
|
||||
u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
|
||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||
pollfd->fd = u->fd;
|
||||
pollfd->events = pollfd->revents = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (u->defer_event) {
|
||||
u->core->mainloop->defer_free(u->defer_event);
|
||||
u->defer_event = NULL;
|
||||
return pa_sink_process_msg(o, code, data, offset, chunk);
|
||||
}
|
||||
|
||||
static void thread_func(void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
int write_type = 0;
|
||||
|
||||
pa_assert(u);
|
||||
|
||||
pa_log_debug("Thread starting up");
|
||||
|
||||
pa_thread_mq_install(&u->thread_mq);
|
||||
pa_rtpoll_install(u->rtpoll);
|
||||
|
||||
pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec());
|
||||
|
||||
for (;;) {
|
||||
int ret;
|
||||
|
||||
if (u->rtpoll_item) {
|
||||
struct pollfd *pollfd;
|
||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||
|
||||
/* Render some data and write it to the fifo */
|
||||
if (PA_SINK_OPENED(u->sink->thread_info.state) && pollfd->revents) {
|
||||
pa_usec_t usec;
|
||||
int64_t n;
|
||||
|
||||
for (;;) {
|
||||
ssize_t l;
|
||||
void *p;
|
||||
|
||||
if (u->memchunk.length <= 0)
|
||||
pa_sink_render(u->sink, u->block_size, &u->memchunk);
|
||||
|
||||
pa_assert(u->memchunk.length > 0);
|
||||
|
||||
p = pa_memblock_acquire(u->memchunk.memblock);
|
||||
l = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, &write_type);
|
||||
pa_memblock_release(u->memchunk.memblock);
|
||||
|
||||
pa_assert(l != 0);
|
||||
|
||||
if (l < 0) {
|
||||
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else if (errno == EAGAIN) {
|
||||
|
||||
/* OK, we filled all socket buffers up
|
||||
* now. */
|
||||
goto filled_up;
|
||||
|
||||
} else {
|
||||
pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
} else {
|
||||
u->offset += l;
|
||||
|
||||
u->memchunk.index += l;
|
||||
u->memchunk.length -= l;
|
||||
|
||||
if (u->memchunk.length <= 0) {
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
pa_memchunk_reset(&u->memchunk);
|
||||
}
|
||||
|
||||
pollfd->revents = 0;
|
||||
|
||||
if (u->memchunk.length > 0)
|
||||
|
||||
/* OK, we wrote less that we asked for,
|
||||
* hence we can assume that the socket
|
||||
* buffers are full now */
|
||||
goto filled_up;
|
||||
}
|
||||
}
|
||||
|
||||
filled_up:
|
||||
|
||||
/* At this spot we know that the socket buffers are
|
||||
* fully filled up. This is the best time to estimate
|
||||
* the playback position of the server */
|
||||
|
||||
n = u->offset;
|
||||
|
||||
#ifdef SIOCOUTQ
|
||||
{
|
||||
int l;
|
||||
if (ioctl(u->fd, SIOCOUTQ, &l) >= 0 && l > 0)
|
||||
n -= l;
|
||||
}
|
||||
#endif
|
||||
|
||||
usec = pa_bytes_to_usec(n, &u->sink->sample_spec);
|
||||
|
||||
if (usec > u->latency)
|
||||
usec -= u->latency;
|
||||
else
|
||||
usec = 0;
|
||||
|
||||
pa_smoother_put(u->smoother, pa_rtclock_usec(), usec);
|
||||
}
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
pollfd->events = PA_SINK_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
|
||||
}
|
||||
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (ret == 0)
|
||||
goto finish;
|
||||
|
||||
if (u->rtpoll_item) {
|
||||
struct pollfd* pollfd;
|
||||
|
||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||
|
||||
if (pollfd->revents & ~POLLOUT) {
|
||||
pa_log("FIFO shutdown.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (u->sink) {
|
||||
pa_sink_disconnect(u->sink);
|
||||
pa_sink_unref(u->sink);
|
||||
u->sink = NULL;
|
||||
}
|
||||
fail:
|
||||
/* If this was no regular exit from the loop we have to continue
|
||||
* processing messages until we received PA_MESSAGE_SHUTDOWN */
|
||||
pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
|
||||
pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
|
||||
|
||||
if (u->module) {
|
||||
pa_module_unload_request(u->module);
|
||||
u->module = NULL;
|
||||
}
|
||||
finish:
|
||||
pa_log_debug("Thread shutting down");
|
||||
}
|
||||
|
||||
static int do_write(struct userdata *u) {
|
||||
ssize_t r;
|
||||
assert(u);
|
||||
pa_assert(u);
|
||||
|
||||
if (!pa_iochannel_is_writable(u->io))
|
||||
return 0;
|
||||
|
||||
if (u->write_data) {
|
||||
assert(u->write_index < u->write_length);
|
||||
pa_assert(u->write_index < u->write_length);
|
||||
|
||||
if ((r = pa_iochannel_write(u->io, (uint8_t*) u->write_data + u->write_index, u->write_length - u->write_index)) <= 0) {
|
||||
pa_log("write() failed: %s", pa_cstrerror(errno));
|
||||
|
|
@ -136,45 +340,44 @@ static int do_write(struct userdata *u) {
|
|||
}
|
||||
|
||||
u->write_index += r;
|
||||
assert(u->write_index <= u->write_length);
|
||||
pa_assert(u->write_index <= u->write_length);
|
||||
|
||||
if (u->write_index == u->write_length) {
|
||||
free(u->write_data);
|
||||
pa_xfree(u->write_data);
|
||||
u->write_data = NULL;
|
||||
u->write_index = u->write_length = 0;
|
||||
}
|
||||
} else if (u->state == STATE_RUNNING) {
|
||||
pa_module_set_used(u->module, pa_sink_used_by(u->sink));
|
||||
}
|
||||
|
||||
if (!u->memchunk.length)
|
||||
if (pa_sink_render(u->sink, 8192, &u->memchunk) < 0)
|
||||
return 0;
|
||||
if (!u->write_data && u->state == STATE_PREPARE) {
|
||||
/* OK, we're done with sending all control data we need to, so
|
||||
* let's hand the socket over to the IO thread now */
|
||||
|
||||
assert(u->memchunk.memblock && u->memchunk.length);
|
||||
pa_assert(u->fd < 0);
|
||||
u->fd = pa_iochannel_get_send_fd(u->io);
|
||||
|
||||
if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) {
|
||||
pa_log("write() failed: %s", pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
pa_iochannel_set_noclose(u->io, TRUE);
|
||||
pa_iochannel_free(u->io);
|
||||
u->io = NULL;
|
||||
|
||||
u->memchunk.index += r;
|
||||
u->memchunk.length -= r;
|
||||
pa_make_tcp_socket_low_delay(u->fd);
|
||||
|
||||
if (u->memchunk.length <= 0) {
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
u->memchunk.memblock = NULL;
|
||||
}
|
||||
pa_log_info("Connection authenticated, handing fd to IO thread...");
|
||||
|
||||
pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_PASS_SOCKET, NULL, 0, NULL, NULL);
|
||||
u->state = STATE_RUNNING;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_response(struct userdata *u) {
|
||||
assert(u);
|
||||
pa_assert(u);
|
||||
|
||||
switch (u->state) {
|
||||
|
||||
case STATE_AUTH:
|
||||
assert(u->read_length == sizeof(int32_t));
|
||||
pa_assert(u->read_length == sizeof(int32_t));
|
||||
|
||||
/* Process auth data */
|
||||
if (!*(int32_t*) u->read_data) {
|
||||
|
|
@ -183,14 +386,14 @@ static int handle_response(struct userdata *u) {
|
|||
}
|
||||
|
||||
/* Request latency data */
|
||||
assert(!u->write_data);
|
||||
pa_assert(!u->write_data);
|
||||
*(int32_t*) (u->write_data = pa_xmalloc(u->write_length = sizeof(int32_t))) = ESD_PROTO_LATENCY;
|
||||
|
||||
u->write_index = 0;
|
||||
u->state = STATE_LATENCY;
|
||||
|
||||
/* Space for next response */
|
||||
assert(u->read_length >= sizeof(int32_t));
|
||||
pa_assert(u->read_length >= sizeof(int32_t));
|
||||
u->read_index = 0;
|
||||
u->read_length = sizeof(int32_t);
|
||||
|
||||
|
|
@ -198,17 +401,17 @@ static int handle_response(struct userdata *u) {
|
|||
|
||||
case STATE_LATENCY: {
|
||||
int32_t *p;
|
||||
assert(u->read_length == sizeof(int32_t));
|
||||
pa_assert(u->read_length == sizeof(int32_t));
|
||||
|
||||
/* Process latency info */
|
||||
u->latency = (pa_usec_t) ((double) (*(int32_t*) u->read_data) * 1000000 / 44100);
|
||||
if (u->latency > 10000000) {
|
||||
pa_log("WARNING! Invalid latency information received from server");
|
||||
pa_log_warn("Invalid latency information received from server");
|
||||
u->latency = 0;
|
||||
}
|
||||
|
||||
/* Create stream */
|
||||
assert(!u->write_data);
|
||||
pa_assert(!u->write_data);
|
||||
p = u->write_data = pa_xmalloc0(u->write_length = sizeof(int32_t)*3+ESD_NAME_MAX);
|
||||
*(p++) = ESD_PROTO_STREAM_PLAY;
|
||||
*(p++) = u->format;
|
||||
|
|
@ -216,7 +419,7 @@ static int handle_response(struct userdata *u) {
|
|||
pa_strlcpy((char*) p, "PulseAudio Tunnel", ESD_NAME_MAX);
|
||||
|
||||
u->write_index = 0;
|
||||
u->state = STATE_RUNNING;
|
||||
u->state = STATE_PREPARE;
|
||||
|
||||
/* Don't read any further */
|
||||
pa_xfree(u->read_data);
|
||||
|
|
@ -227,14 +430,14 @@ static int handle_response(struct userdata *u) {
|
|||
}
|
||||
|
||||
default:
|
||||
abort();
|
||||
pa_assert_not_reached();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_read(struct userdata *u) {
|
||||
assert(u);
|
||||
pa_assert(u);
|
||||
|
||||
if (!pa_iochannel_is_readable(u->io))
|
||||
return 0;
|
||||
|
|
@ -245,16 +448,15 @@ static int do_read(struct userdata *u) {
|
|||
if (!u->read_data)
|
||||
return 0;
|
||||
|
||||
assert(u->read_index < u->read_length);
|
||||
pa_assert(u->read_index < u->read_length);
|
||||
|
||||
if ((r = pa_iochannel_read(u->io, (uint8_t*) u->read_data + u->read_index, u->read_length - u->read_index)) <= 0) {
|
||||
pa_log("read() failed: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
|
||||
cancel(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
u->read_index += r;
|
||||
assert(u->read_index <= u->read_length);
|
||||
pa_assert(u->read_index <= u->read_length);
|
||||
|
||||
if (u->read_index == u->read_length)
|
||||
return handle_response(u);
|
||||
|
|
@ -263,42 +465,19 @@ static int do_read(struct userdata *u) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void do_work(struct userdata *u) {
|
||||
assert(u);
|
||||
|
||||
u->core->mainloop->defer_enable(u->defer_event, 0);
|
||||
|
||||
if (do_read(u) < 0 || do_write(u) < 0)
|
||||
cancel(u);
|
||||
}
|
||||
|
||||
static void notify_cb(pa_sink*s) {
|
||||
struct userdata *u = s->userdata;
|
||||
assert(s && u);
|
||||
|
||||
if (pa_iochannel_is_writable(u->io))
|
||||
u->core->mainloop->defer_enable(u->defer_event, 1);
|
||||
}
|
||||
|
||||
static pa_usec_t get_latency_cb(pa_sink *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
assert(s && u);
|
||||
|
||||
return
|
||||
u->latency +
|
||||
(u->memchunk.memblock ? pa_bytes_to_usec(u->memchunk.length, &s->sample_spec) : 0);
|
||||
}
|
||||
|
||||
static void defer_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event*e, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
assert(u);
|
||||
do_work(u);
|
||||
}
|
||||
|
||||
static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
|
||||
struct userdata *u = userdata;
|
||||
assert(u);
|
||||
do_work(u);
|
||||
pa_assert(u);
|
||||
|
||||
if (do_read(u) < 0 || do_write(u) < 0) {
|
||||
|
||||
if (u->io) {
|
||||
pa_iochannel_free(u->io);
|
||||
u->io = NULL;
|
||||
}
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, void *userdata) {
|
||||
|
|
@ -308,30 +487,34 @@ static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, vo
|
|||
u->client = NULL;
|
||||
|
||||
if (!io) {
|
||||
pa_log("connection failed: %s", pa_cstrerror(errno));
|
||||
cancel(u);
|
||||
pa_log("Connection failed: %s", pa_cstrerror(errno));
|
||||
pa_module_unload_request(u->module);
|
||||
return;
|
||||
}
|
||||
|
||||
pa_assert(!u->io);
|
||||
u->io = io;
|
||||
pa_iochannel_set_callback(u->io, io_callback, u);
|
||||
|
||||
pa_log_info("Connection established, authenticating ...");
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
struct userdata *u = NULL;
|
||||
const char *p;
|
||||
pa_sample_spec ss;
|
||||
pa_modargs *ma = NULL;
|
||||
char *t;
|
||||
const char *espeaker;
|
||||
|
||||
assert(c && m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("failed to parse module arguments");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ss = c->default_sample_spec;
|
||||
ss = m->core->default_sample_spec;
|
||||
if (pa_modargs_get_sample_spec(ma, &ss) < 0) {
|
||||
pa_log("invalid sample format specification");
|
||||
goto fail;
|
||||
|
|
@ -343,37 +526,62 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
u = pa_xmalloc0(sizeof(struct userdata));
|
||||
u->core = c;
|
||||
u = pa_xnew0(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
m->userdata = u;
|
||||
u->fd = -1;
|
||||
u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE);
|
||||
pa_memchunk_reset(&u->memchunk);
|
||||
u->offset = 0;
|
||||
|
||||
pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
|
||||
u->rtpoll = pa_rtpoll_new();
|
||||
pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
|
||||
u->rtpoll_item = NULL;
|
||||
|
||||
u->format =
|
||||
(ss.format == PA_SAMPLE_U8 ? ESD_BITS8 : ESD_BITS16) |
|
||||
(ss.channels == 2 ? ESD_STEREO : ESD_MONO);
|
||||
u->rate = ss.rate;
|
||||
u->sink = NULL;
|
||||
u->client = NULL;
|
||||
u->io = NULL;
|
||||
u->block_size = pa_usec_to_bytes(PA_USEC_PER_SEC/20, &ss);
|
||||
|
||||
u->read_data = u->write_data = NULL;
|
||||
u->read_index = u->write_index = u->read_length = u->write_length = 0;
|
||||
|
||||
u->state = STATE_AUTH;
|
||||
u->latency = 0;
|
||||
|
||||
if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) {
|
||||
if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) {
|
||||
pa_log("failed to create sink.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(u->client = pa_socket_client_new_string(u->core->mainloop, p = pa_modargs_get_value(ma, "server", ESD_UNIX_SOCKET_NAME), ESD_DEFAULT_PORT))) {
|
||||
pa_log("failed to connect to server.");
|
||||
u->sink->parent.process_msg = sink_process_msg;
|
||||
u->sink->userdata = u;
|
||||
u->sink->flags = PA_SINK_LATENCY;
|
||||
|
||||
pa_sink_set_module(u->sink, m);
|
||||
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
|
||||
pa_sink_set_rtpoll(u->sink, u->rtpoll);
|
||||
|
||||
if (!(espeaker = getenv("ESPEAKER")))
|
||||
espeaker = ESD_UNIX_SOCKET_NAME;
|
||||
|
||||
if (!(u->client = pa_socket_client_new_string(u->core->mainloop, p = pa_modargs_get_value(ma, "server", espeaker), ESD_DEFAULT_PORT))) {
|
||||
pa_log("Failed to connect to server.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Esound sink '%s'", p));
|
||||
pa_xfree(t);
|
||||
|
||||
pa_socket_client_set_callback(u->client, on_connection, u);
|
||||
|
||||
/* Prepare the initial request */
|
||||
u->write_data = pa_xmalloc(u->write_length = ESD_KEY_LEN + sizeof(int32_t));
|
||||
if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", ".esd_auth"), u->write_data, ESD_KEY_LEN) < 0) {
|
||||
pa_log("failed to load cookie");
|
||||
pa_log("Failed to load cookie");
|
||||
goto fail;
|
||||
}
|
||||
*(int32_t*) ((uint8_t*) u->write_data + ESD_KEY_LEN) = ESD_ENDIAN_KEY;
|
||||
|
|
@ -381,19 +589,12 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
/* Reserve space for the response */
|
||||
u->read_data = pa_xmalloc(u->read_length = sizeof(int32_t));
|
||||
|
||||
u->sink->notify = notify_cb;
|
||||
u->sink->get_latency = get_latency_cb;
|
||||
u->sink->userdata = u;
|
||||
pa_sink_set_owner(u->sink, m);
|
||||
pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Esound sink '%s'", p));
|
||||
pa_xfree(t);
|
||||
|
||||
u->memchunk.memblock = NULL;
|
||||
u->memchunk.length = 0;
|
||||
|
||||
u->defer_event = c->mainloop->defer_new(c->mainloop, defer_callback, u);
|
||||
c->mainloop->defer_enable(u->defer_event, 0);
|
||||
if (!(u->thread = pa_thread_new(thread_func, u))) {
|
||||
pa_log("Failed to create thread.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pa_sink_put(u->sink);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
||||
|
|
@ -403,20 +604,39 @@ fail:
|
|||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
pa__done(c, m);
|
||||
pa__done(m);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
assert(c && m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
u->module = NULL;
|
||||
cancel(u);
|
||||
if (u->sink)
|
||||
pa_sink_unlink(u->sink);
|
||||
|
||||
if (u->thread) {
|
||||
pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
|
||||
pa_thread_free(u->thread);
|
||||
}
|
||||
|
||||
pa_thread_mq_done(&u->thread_mq);
|
||||
|
||||
if (u->sink)
|
||||
pa_sink_unref(u->sink);
|
||||
|
||||
if (u->io)
|
||||
pa_iochannel_free(u->io);
|
||||
|
||||
if (u->rtpoll_item)
|
||||
pa_rtpoll_item_free(u->rtpoll_item);
|
||||
|
||||
if (u->rtpoll)
|
||||
pa_rtpoll_free(u->rtpoll);
|
||||
|
||||
if (u->memchunk.memblock)
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
|
|
@ -427,8 +647,11 @@ void pa__done(pa_core *c, pa_module*m) {
|
|||
pa_xfree(u->read_data);
|
||||
pa_xfree(u->write_data);
|
||||
|
||||
if (u->smoother)
|
||||
pa_smoother_free(u->smoother);
|
||||
|
||||
if (u->fd >= 0)
|
||||
pa_close(u->fd);
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -28,31 +28,34 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <jack/jack.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/iochannel.h>
|
||||
#include <pulsecore/source.h>
|
||||
#include <pulsecore/module.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulse/mainloop-api.h>
|
||||
#include <pulsecore/thread.h>
|
||||
#include <pulsecore/thread-mq.h>
|
||||
#include <pulsecore/rtpoll.h>
|
||||
#include <pulsecore/sample-util.h>
|
||||
|
||||
#include "module-jack-source-symdef.h"
|
||||
|
||||
/* See module-jack-sink for a few comments how this module basically
|
||||
* works */
|
||||
|
||||
PA_MODULE_AUTHOR("Lennart Poettering")
|
||||
PA_MODULE_DESCRIPTION("Jack Source")
|
||||
PA_MODULE_DESCRIPTION("JACK Source")
|
||||
PA_MODULE_VERSION(PACKAGE_VERSION)
|
||||
PA_MODULE_USAGE(
|
||||
"source_name=<name of source> "
|
||||
|
|
@ -67,7 +70,6 @@ PA_MODULE_USAGE(
|
|||
struct userdata {
|
||||
pa_core *core;
|
||||
pa_module *module;
|
||||
|
||||
pa_source *source;
|
||||
|
||||
unsigned channels;
|
||||
|
|
@ -75,19 +77,15 @@ struct userdata {
|
|||
jack_port_t* port[PA_CHANNELS_MAX];
|
||||
jack_client_t *client;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
pa_thread_mq thread_mq;
|
||||
pa_asyncmsgq *jack_msgq;
|
||||
pa_rtpoll *rtpoll;
|
||||
pa_rtpoll_item *rtpoll_item;
|
||||
|
||||
void * buffer[PA_CHANNELS_MAX];
|
||||
jack_nframes_t frames_posted;
|
||||
int quit_requested;
|
||||
pa_thread *thread;
|
||||
|
||||
int pipe_fds[2];
|
||||
int pipe_fd_type;
|
||||
pa_io_event *io_event;
|
||||
|
||||
jack_nframes_t frames_in_buffer;
|
||||
jack_nframes_t timestamp;
|
||||
jack_nframes_t saved_frame_time;
|
||||
pa_bool_t saved_frame_time_valid;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
|
|
@ -100,141 +98,150 @@ static const char* const valid_modargs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static void stop_source(struct userdata *u) {
|
||||
assert (u);
|
||||
enum {
|
||||
SOURCE_MESSAGE_POST = PA_SOURCE_MESSAGE_MAX,
|
||||
SOURCE_MESSAGE_ON_SHUTDOWN
|
||||
};
|
||||
|
||||
jack_client_close(u->client);
|
||||
u->client = NULL;
|
||||
u->core->mainloop->io_free(u->io_event);
|
||||
u->io_event = NULL;
|
||||
pa_source_disconnect(u->source);
|
||||
pa_source_unref(u->source);
|
||||
u->source = NULL;
|
||||
pa_module_unload_request(u->module);
|
||||
}
|
||||
static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
struct userdata *u = PA_SOURCE(o)->userdata;
|
||||
|
||||
static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
char x;
|
||||
switch (code) {
|
||||
|
||||
assert(m);
|
||||
assert(flags == PA_IO_EVENT_INPUT);
|
||||
assert(u);
|
||||
assert(u->pipe_fds[0] == fd);
|
||||
case SOURCE_MESSAGE_POST:
|
||||
|
||||
pa_read(fd, &x, 1, &u->pipe_fd_type);
|
||||
/* Handle the new block from the JACK thread */
|
||||
pa_assert(chunk);
|
||||
pa_assert(chunk->length > 0);
|
||||
|
||||
if (u->quit_requested) {
|
||||
stop_source(u);
|
||||
u->quit_requested = 0;
|
||||
return;
|
||||
}
|
||||
if (u->source->thread_info.state == PA_SOURCE_RUNNING)
|
||||
pa_source_post(u->source, chunk);
|
||||
|
||||
pthread_mutex_lock(&u->mutex);
|
||||
u->saved_frame_time = offset;
|
||||
u->saved_frame_time_valid = TRUE;
|
||||
|
||||
if (u->frames_posted > 0) {
|
||||
unsigned fs;
|
||||
jack_nframes_t frame_idx;
|
||||
pa_memchunk chunk;
|
||||
return 0;
|
||||
|
||||
fs = pa_frame_size(&u->source->sample_spec);
|
||||
case SOURCE_MESSAGE_ON_SHUTDOWN:
|
||||
pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
|
||||
return 0;
|
||||
|
||||
chunk.memblock = pa_memblock_new(u->core->mempool, chunk.length = u->frames_posted * fs);
|
||||
chunk.index = 0;
|
||||
case PA_SOURCE_MESSAGE_GET_LATENCY: {
|
||||
jack_nframes_t l, ft, d;
|
||||
size_t n;
|
||||
|
||||
for (frame_idx = 0; frame_idx < u->frames_posted; frame_idx ++) {
|
||||
unsigned c;
|
||||
/* This is the "worst-case" latency */
|
||||
l = jack_port_get_total_latency(u->client, u->port[0]);
|
||||
|
||||
for (c = 0; c < u->channels; c++) {
|
||||
float *s = ((float*) u->buffer[c]) + frame_idx;
|
||||
float *d = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c;
|
||||
if (u->saved_frame_time_valid) {
|
||||
/* Adjust the worst case latency by the time that
|
||||
* passed since we last handed data to JACK */
|
||||
|
||||
*d = *s;
|
||||
ft = jack_frame_time(u->client);
|
||||
d = ft > u->saved_frame_time ? ft - u->saved_frame_time : 0;
|
||||
l += d;
|
||||
}
|
||||
|
||||
/* Convert it to usec */
|
||||
n = l * pa_frame_size(&u->source->sample_spec);
|
||||
*((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->source->sample_spec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pa_source_post(u->source, &chunk);
|
||||
pa_memblock_unref(chunk.memblock);
|
||||
|
||||
u->frames_posted = 0;
|
||||
|
||||
pthread_cond_signal(&u->cond);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&u->mutex);
|
||||
}
|
||||
|
||||
static void request_post(struct userdata *u) {
|
||||
char c = 'x';
|
||||
assert(u);
|
||||
|
||||
assert(u->pipe_fds[1] >= 0);
|
||||
pa_write(u->pipe_fds[1], &c, 1, &u->pipe_fd_type);
|
||||
}
|
||||
|
||||
static void jack_shutdown(void *arg) {
|
||||
struct userdata *u = arg;
|
||||
assert(u);
|
||||
|
||||
u->quit_requested = 1;
|
||||
request_post(u);
|
||||
return pa_source_process_msg(o, code, data, offset, chunk);
|
||||
}
|
||||
|
||||
static int jack_process(jack_nframes_t nframes, void *arg) {
|
||||
unsigned c;
|
||||
struct userdata *u = arg;
|
||||
assert(u);
|
||||
const void *buffer[PA_CHANNELS_MAX];
|
||||
void *p;
|
||||
jack_nframes_t frame_time;
|
||||
pa_memchunk chunk;
|
||||
|
||||
if (jack_transport_query(u->client, NULL) == JackTransportRolling) {
|
||||
unsigned c;
|
||||
pa_assert(u);
|
||||
|
||||
pthread_mutex_lock(&u->mutex);
|
||||
for (c = 0; c < u->channels; c++)
|
||||
pa_assert(buffer[c] = jack_port_get_buffer(u->port[c], nframes));
|
||||
|
||||
u->frames_posted = nframes;
|
||||
/* We interleave the data and pass it on to the other RT thread */
|
||||
|
||||
for (c = 0; c < u->channels; c++) {
|
||||
u->buffer[c] = jack_port_get_buffer(u->port[c], nframes);
|
||||
assert(u->buffer[c]);
|
||||
}
|
||||
pa_memchunk_reset(&chunk);
|
||||
chunk.length = nframes * pa_frame_size(&u->source->sample_spec);
|
||||
chunk.memblock = pa_memblock_new(u->core->mempool, chunk.length);
|
||||
p = pa_memblock_acquire(chunk.memblock);
|
||||
pa_interleave(buffer, u->channels, p, sizeof(float), nframes);
|
||||
pa_memblock_release(chunk.memblock);
|
||||
|
||||
request_post(u);
|
||||
frame_time = jack_frame_time(u->client);
|
||||
|
||||
pthread_cond_wait(&u->cond, &u->mutex);
|
||||
pa_asyncmsgq_post(u->jack_msgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_POST, NULL, frame_time, &chunk, NULL);
|
||||
|
||||
u->frames_in_buffer = nframes;
|
||||
u->timestamp = jack_get_current_transport_frame(u->client);
|
||||
|
||||
pthread_mutex_unlock(&u->mutex);
|
||||
}
|
||||
pa_memblock_unref(chunk.memblock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pa_usec_t source_get_latency_cb(pa_source *s) {
|
||||
struct userdata *u;
|
||||
jack_nframes_t n, l, d;
|
||||
static void thread_func(void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
|
||||
assert(s);
|
||||
u = s->userdata;
|
||||
pa_assert(u);
|
||||
|
||||
if (jack_transport_query(u->client, NULL) != JackTransportRolling)
|
||||
return 0;
|
||||
pa_log_debug("Thread starting up");
|
||||
|
||||
n = jack_get_current_transport_frame(u->client);
|
||||
if (u->core->high_priority)
|
||||
pa_make_realtime();
|
||||
|
||||
if (n < u->timestamp)
|
||||
return 0;
|
||||
pa_thread_mq_install(&u->thread_mq);
|
||||
pa_rtpoll_install(u->rtpoll);
|
||||
|
||||
d = n - u->timestamp;
|
||||
l = jack_port_get_total_latency(u->client, u->port[0]);
|
||||
for (;;) {
|
||||
int ret;
|
||||
|
||||
return pa_bytes_to_usec((l + d) * pa_frame_size(&s->sample_spec), &s->sample_spec);
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (ret == 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
fail:
|
||||
/* If this was no regular exit from the loop we have to continue
|
||||
* processing messages until we received PA_MESSAGE_SHUTDOWN */
|
||||
pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
|
||||
pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
|
||||
|
||||
finish:
|
||||
pa_log_debug("Thread shutting down");
|
||||
}
|
||||
|
||||
static void jack_error_func(const char*t) {
|
||||
pa_log_warn("JACK error >%s<", t);
|
||||
char *s;
|
||||
|
||||
s = pa_xstrndup(t, strcspn(t, "\n\r"));
|
||||
pa_log_warn("JACK error >%s<", s);
|
||||
pa_xfree(s);
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
static void jack_init(void *arg) {
|
||||
struct userdata *u = arg;
|
||||
|
||||
pa_log_info("JACK thread starting up.");
|
||||
|
||||
if (u->core->high_priority)
|
||||
pa_make_realtime();
|
||||
}
|
||||
|
||||
static void jack_shutdown(void* arg) {
|
||||
struct userdata *u = arg;
|
||||
|
||||
pa_log_info("JACK thread shutting down..");
|
||||
pa_asyncmsgq_post(u->jack_msgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_ON_SHUTDOWN, NULL, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
struct userdata *u = NULL;
|
||||
pa_sample_spec ss;
|
||||
pa_channel_map map;
|
||||
|
|
@ -247,40 +254,35 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
const char **ports = NULL, **p;
|
||||
char *t;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
jack_set_error_function(jack_error_func);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("failed to parse module arguments.");
|
||||
pa_log("Failed to parse module arguments.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "connect", &do_connect) < 0) {
|
||||
pa_log("failed to parse connect= argument.");
|
||||
pa_log("Failed to parse connect= argument.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
server_name = pa_modargs_get_value(ma, "server_name", NULL);
|
||||
client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio");
|
||||
client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio JACK Source");
|
||||
|
||||
u = pa_xnew0(struct userdata, 1);
|
||||
m->userdata = u;
|
||||
u->core = c;
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
u->pipe_fds[0] = u->pipe_fds[1] = -1;
|
||||
u->pipe_fd_type = 0;
|
||||
m->userdata = u;
|
||||
u->saved_frame_time_valid = FALSE;
|
||||
|
||||
pthread_mutex_init(&u->mutex, NULL);
|
||||
pthread_cond_init(&u->cond, NULL);
|
||||
pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
|
||||
u->rtpoll = pa_rtpoll_new();
|
||||
pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
|
||||
|
||||
if (pipe(u->pipe_fds) < 0) {
|
||||
pa_log("pipe() failed: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pa_make_nonblock_fd(u->pipe_fds[1]);
|
||||
u->jack_msgq = pa_asyncmsgq_new(0);
|
||||
u->rtpoll_item = pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY-1, u->jack_msgq);
|
||||
|
||||
if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) {
|
||||
pa_log("jack_client_open() failed.");
|
||||
|
|
@ -294,7 +296,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
channels++;
|
||||
|
||||
if (!channels)
|
||||
channels = c->default_sample_spec.channels;
|
||||
channels = m->core->default_sample_spec.channels;
|
||||
|
||||
if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) {
|
||||
pa_log("failed to parse channels= argument.");
|
||||
|
|
@ -302,7 +304,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
}
|
||||
|
||||
pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_ALSA);
|
||||
if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) {
|
||||
if (pa_modargs_get_channel_map(ma, NULL, &map) < 0 || map.channels != channels) {
|
||||
pa_log("failed to parse channel_map= argument.");
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -313,7 +315,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
ss.rate = jack_get_sample_rate(u->client);
|
||||
ss.format = PA_SAMPLE_FLOAT32NE;
|
||||
|
||||
assert(pa_sample_spec_valid(&ss));
|
||||
pa_assert(pa_sample_spec_valid(&ss));
|
||||
|
||||
for (i = 0; i < ss.channels; i++) {
|
||||
if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(map.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput|JackPortIsTerminal, 0))) {
|
||||
|
|
@ -322,19 +324,29 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) {
|
||||
if (!(u->source = pa_source_new(m->core, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) {
|
||||
pa_log("failed to create source.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u->source->parent.process_msg = source_process_msg;
|
||||
u->source->userdata = u;
|
||||
pa_source_set_owner(u->source, m);
|
||||
u->source->flags = PA_SOURCE_LATENCY;
|
||||
|
||||
pa_source_set_module(u->source, m);
|
||||
pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
|
||||
pa_source_set_rtpoll(u->source, u->rtpoll);
|
||||
pa_source_set_description(u->source, t = pa_sprintf_malloc("Jack source (%s)", jack_get_client_name(u->client)));
|
||||
pa_xfree(t);
|
||||
u->source->get_latency = source_get_latency_cb;
|
||||
|
||||
jack_set_process_callback(u->client, jack_process, u);
|
||||
jack_on_shutdown(u->client, jack_shutdown, u);
|
||||
jack_set_thread_init_callback(u->client, jack_init, u);
|
||||
|
||||
if (!(u->thread = pa_thread_new(thread_func, u))) {
|
||||
pa_log("Failed to create thread.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (jack_activate(u->client)) {
|
||||
pa_log("jack_activate() failed");
|
||||
|
|
@ -359,7 +371,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
|
||||
}
|
||||
|
||||
u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], PA_IO_EVENT_INPUT, io_event_cb, u);
|
||||
pa_source_put(u->source);
|
||||
|
||||
free(ports);
|
||||
pa_modargs_free(ma);
|
||||
|
|
@ -372,14 +384,14 @@ fail:
|
|||
|
||||
free(ports);
|
||||
|
||||
pa__done(c, m);
|
||||
pa__done(m);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
assert(c && m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
|
@ -387,20 +399,27 @@ void pa__done(pa_core *c, pa_module*m) {
|
|||
if (u->client)
|
||||
jack_client_close(u->client);
|
||||
|
||||
if (u->io_event)
|
||||
c->mainloop->io_free(u->io_event);
|
||||
if (u->source)
|
||||
pa_source_unlink(u->source);
|
||||
|
||||
if (u->source) {
|
||||
pa_source_disconnect(u->source);
|
||||
pa_source_unref(u->source);
|
||||
if (u->thread) {
|
||||
pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
|
||||
pa_thread_free(u->thread);
|
||||
}
|
||||
|
||||
if (u->pipe_fds[0] >= 0)
|
||||
close(u->pipe_fds[0]);
|
||||
if (u->pipe_fds[1] >= 0)
|
||||
close(u->pipe_fds[1]);
|
||||
pa_thread_mq_done(&u->thread_mq);
|
||||
|
||||
if (u->source)
|
||||
pa_source_unref(u->source);
|
||||
|
||||
if (u->rtpoll_item)
|
||||
pa_rtpoll_item_free(u->rtpoll_item);
|
||||
|
||||
if (u->jack_msgq)
|
||||
pa_asyncmsgq_unref(u->jack_msgq);
|
||||
|
||||
if (u->rtpoll)
|
||||
pa_rtpoll_free(u->rtpoll);
|
||||
|
||||
pthread_mutex_destroy(&u->mutex);
|
||||
pthread_cond_destroy(&u->cond);
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
|
|||
673
src/modules/module-ladspa-sink.c
Normal file
673
src/modules/module-ladspa-sink.c
Normal file
|
|
@ -0,0 +1,673 @@
|
|||
/* $Id$ */
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2004-2006 Lennart Poettering
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2 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.
|
||||
***/
|
||||
|
||||
/* TODO: Some plugins cause latency, and some even report it by using a control
|
||||
out port. We don't currently use the latency information. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/namereg.h>
|
||||
#include <pulsecore/sink.h>
|
||||
#include <pulsecore/module.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/thread.h>
|
||||
#include <pulsecore/thread-mq.h>
|
||||
#include <pulsecore/rtpoll.h>
|
||||
#include <pulsecore/sample-util.h>
|
||||
|
||||
#include "module-ladspa-sink-symdef.h"
|
||||
#include "ladspa.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Lennart Poettering")
|
||||
PA_MODULE_DESCRIPTION("Virtual LADSPA sink")
|
||||
PA_MODULE_VERSION(PACKAGE_VERSION)
|
||||
PA_MODULE_USAGE(
|
||||
"sink_name=<name for the sink> "
|
||||
"master=<name of sink to remap> "
|
||||
"format=<sample format> "
|
||||
"channels=<number of channels> "
|
||||
"rate=<sample rate> "
|
||||
"channel_map=<channel map> "
|
||||
"plugin=<ladspa plugin name> "
|
||||
"label=<ladspa plugin label> "
|
||||
"control=<comma seperated list of input control values>")
|
||||
|
||||
struct userdata {
|
||||
pa_core *core;
|
||||
pa_module *module;
|
||||
|
||||
pa_sink *sink, *master;
|
||||
pa_sink_input *sink_input;
|
||||
|
||||
const LADSPA_Descriptor *descriptor;
|
||||
unsigned channels;
|
||||
LADSPA_Handle handle[PA_CHANNELS_MAX];
|
||||
LADSPA_Data *input, *output;
|
||||
size_t block_size;
|
||||
unsigned long input_port, output_port;
|
||||
LADSPA_Data *control;
|
||||
|
||||
/* This is a dummy buffer. Every port must be connected, but we don't care
|
||||
about control out ports. We connect them all to this single buffer. */
|
||||
LADSPA_Data control_out;
|
||||
|
||||
pa_memchunk memchunk;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"sink_name",
|
||||
"master",
|
||||
"format",
|
||||
"channels",
|
||||
"rate",
|
||||
"channel_map",
|
||||
"plugin",
|
||||
"label",
|
||||
"control",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
struct userdata *u = PA_SINK(o)->userdata;
|
||||
|
||||
switch (code) {
|
||||
|
||||
case PA_SINK_MESSAGE_GET_LATENCY: {
|
||||
pa_usec_t usec = 0;
|
||||
|
||||
if (PA_MSGOBJECT(u->master)->process_msg(PA_MSGOBJECT(u->master), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
|
||||
usec = 0;
|
||||
|
||||
*((pa_usec_t*) data) = usec + pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return pa_sink_process_msg(o, code, data, offset, chunk);
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_sink_assert_ref(s);
|
||||
pa_assert_se(u = s->userdata);
|
||||
|
||||
if (PA_SINK_LINKED(state) && u->sink_input && PA_SINK_INPUT_LINKED(pa_sink_input_get_state(u->sink_input)))
|
||||
pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
struct userdata *u = PA_SINK_INPUT(o)->userdata;
|
||||
|
||||
switch (code) {
|
||||
case PA_SINK_INPUT_MESSAGE_GET_LATENCY:
|
||||
*((pa_usec_t*) data) = pa_bytes_to_usec(u->memchunk.length, &u->sink_input->sample_spec);
|
||||
|
||||
/* Fall through, the default handler will add in the extra
|
||||
* latency added by the resampler */
|
||||
break;
|
||||
}
|
||||
|
||||
return pa_sink_input_process_msg(o, code, data, offset, chunk);
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(u = i->userdata);
|
||||
|
||||
if (!u->memchunk.memblock) {
|
||||
pa_memchunk tchunk;
|
||||
float *src, *dst;
|
||||
size_t fs;
|
||||
unsigned n, c;
|
||||
|
||||
pa_sink_render(u->sink, length, &tchunk);
|
||||
|
||||
fs = pa_frame_size(&i->sample_spec);
|
||||
n = tchunk.length / fs;
|
||||
|
||||
pa_assert(n > 0);
|
||||
|
||||
u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, tchunk.length);
|
||||
u->memchunk.index = 0;
|
||||
u->memchunk.length = tchunk.length;
|
||||
|
||||
src = (float*) ((uint8_t*) pa_memblock_acquire(tchunk.memblock) + tchunk.index);
|
||||
dst = (float*) pa_memblock_acquire(u->memchunk.memblock);
|
||||
|
||||
for (c = 0; c < u->channels; c++) {
|
||||
unsigned j;
|
||||
float *p, *q;
|
||||
|
||||
p = src + c;
|
||||
q = u->input;
|
||||
for (j = 0; j < n; j++, p += u->channels, q++)
|
||||
*q = CLAMP(*p, -1.0, 1.0);
|
||||
|
||||
u->descriptor->run(u->handle[c], n);
|
||||
|
||||
q = u->output;
|
||||
p = dst + c;
|
||||
for (j = 0; j < n; j++, q++, p += u->channels)
|
||||
*p = CLAMP(*q, -1.0, 1.0);
|
||||
}
|
||||
|
||||
pa_memblock_release(tchunk.memblock);
|
||||
pa_memblock_release(u->memchunk.memblock);
|
||||
|
||||
pa_memblock_unref(tchunk.memblock);
|
||||
}
|
||||
|
||||
pa_assert(u->memchunk.length > 0);
|
||||
pa_assert(u->memchunk.memblock);
|
||||
|
||||
*chunk = u->memchunk;
|
||||
pa_memblock_ref(chunk->memblock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(u = i->userdata);
|
||||
pa_assert(length > 0);
|
||||
|
||||
if (u->memchunk.memblock) {
|
||||
|
||||
if (length < u->memchunk.length) {
|
||||
u->memchunk.index += length;
|
||||
u->memchunk.length -= length;
|
||||
return;
|
||||
}
|
||||
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
length -= u->memchunk.length;
|
||||
pa_memchunk_reset(&u->memchunk);
|
||||
}
|
||||
|
||||
if (length > 0)
|
||||
pa_sink_skip(u->sink, length);
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static void sink_input_detach_cb(pa_sink_input *i) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(u = i->userdata);
|
||||
|
||||
pa_sink_detach_within_thread(u->sink);
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static void sink_input_attach_cb(pa_sink_input *i) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(u = i->userdata);
|
||||
|
||||
pa_sink_set_asyncmsgq(u->sink, i->sink->asyncmsgq);
|
||||
pa_sink_set_rtpoll(u->sink, i->sink->rtpoll);
|
||||
|
||||
pa_sink_attach_within_thread(u->sink);
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
static void sink_input_kill_cb(pa_sink_input *i) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(u = i->userdata);
|
||||
|
||||
pa_sink_input_unlink(u->sink_input);
|
||||
pa_sink_input_unref(u->sink_input);
|
||||
u->sink_input = NULL;
|
||||
|
||||
pa_sink_unlink(u->sink);
|
||||
pa_sink_unref(u->sink);
|
||||
u->sink = NULL;
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
struct userdata *u;
|
||||
pa_sample_spec ss;
|
||||
pa_channel_map map;
|
||||
pa_modargs *ma;
|
||||
char *t;
|
||||
pa_sink *master;
|
||||
pa_sink_input_new_data data;
|
||||
const char *plugin, *label;
|
||||
LADSPA_Descriptor_Function descriptor_func;
|
||||
const char *e, *cdata;
|
||||
const LADSPA_Descriptor *d;
|
||||
unsigned long input_port, output_port, p, j, n_control;
|
||||
unsigned c;
|
||||
pa_bool_t *use_default = NULL;
|
||||
char *default_sink_name = NULL;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
pa_assert(sizeof(LADSPA_Data) == sizeof(float));
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK, 1))) {
|
||||
pa_log("Master sink not found");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ss = master->sample_spec;
|
||||
ss.format = PA_SAMPLE_FLOAT32;
|
||||
map = master->channel_map;
|
||||
if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
|
||||
pa_log("Invalid sample format specification or channel map");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(plugin = pa_modargs_get_value(ma, "plugin", NULL))) {
|
||||
pa_log("Missing LADSPA plugin name");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(label = pa_modargs_get_value(ma, "label", NULL))) {
|
||||
pa_log("Missing LADSPA plugin label");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cdata = pa_modargs_get_value(ma, "control", NULL);
|
||||
|
||||
u = pa_xnew0(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
m->userdata = u;
|
||||
u->master = master;
|
||||
pa_memchunk_reset(&u->memchunk);
|
||||
|
||||
if (!(e = getenv("LADSPA_PATH")))
|
||||
e = LADSPA_PATH;
|
||||
|
||||
/* FIXME: This is not exactly thread safe */
|
||||
t = pa_xstrdup(lt_dlgetsearchpath());
|
||||
lt_dlsetsearchpath(e);
|
||||
m->dl = lt_dlopenext(plugin);
|
||||
lt_dlsetsearchpath(t);
|
||||
pa_xfree(t);
|
||||
|
||||
if (!m->dl) {
|
||||
pa_log("Failed to load LADSPA plugin: %s", lt_dlerror());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(descriptor_func = (LADSPA_Descriptor_Function) lt_dlsym(m->dl, "ladspa_descriptor"))) {
|
||||
pa_log("LADSPA module lacks ladspa_descriptor() symbol.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (j = 0;; j++) {
|
||||
|
||||
if (!(d = descriptor_func(j))) {
|
||||
pa_log("Failed to find plugin label '%s' in plugin '%s'.", plugin, label);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (strcmp(d->Label, label) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
u->descriptor = d;
|
||||
|
||||
pa_log_debug("Module: %s", plugin);
|
||||
pa_log_debug("Label: %s", d->Label);
|
||||
pa_log_debug("Unique ID: %lu", d->UniqueID);
|
||||
pa_log_debug("Name: %s", d->Name);
|
||||
pa_log_debug("Maker: %s", d->Maker);
|
||||
pa_log_debug("Copyright: %s", d->Copyright);
|
||||
|
||||
input_port = output_port = (unsigned long) -1;
|
||||
n_control = 0;
|
||||
|
||||
for (p = 0; p < d->PortCount; p++) {
|
||||
|
||||
if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) {
|
||||
|
||||
if (strcmp(d->PortNames[p], "Input") == 0) {
|
||||
pa_assert(input_port == (unsigned long) -1);
|
||||
input_port = p;
|
||||
} else {
|
||||
pa_log("Found audio input port on plugin we cannot handle: %s", d->PortNames[p]);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
} else if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) {
|
||||
|
||||
if (strcmp(d->PortNames[p], "Output") == 0) {
|
||||
pa_assert(output_port == (unsigned long) -1);
|
||||
output_port = p;
|
||||
} else {
|
||||
pa_log("Found audio output port on plugin we cannot handle: %s", d->PortNames[p]);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
} else if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]))
|
||||
n_control++;
|
||||
else {
|
||||
pa_assert(LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]));
|
||||
pa_log_info("Ignored port \"%s\", because we ignore all control out ports.", d->PortNames[p]);
|
||||
}
|
||||
}
|
||||
|
||||
if ((input_port == (unsigned long) -1) || (output_port == (unsigned long) -1)) {
|
||||
pa_log("Failed to identify input and output ports. "
|
||||
"Right now this module can only deal with plugins which provide an 'Input' and an 'Output' audio port. "
|
||||
"Patches welcome!");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u->block_size = pa_frame_align(pa_mempool_block_size_max(m->core->mempool), &ss);
|
||||
|
||||
u->input = (LADSPA_Data*) pa_xnew(uint8_t, u->block_size);
|
||||
if (LADSPA_IS_INPLACE_BROKEN(d->Properties))
|
||||
u->output = (LADSPA_Data*) pa_xnew(uint8_t, u->block_size);
|
||||
else
|
||||
u->output = u->input;
|
||||
|
||||
u->channels = ss.channels;
|
||||
|
||||
for (c = 0; c < ss.channels; c++) {
|
||||
if (!(u->handle[c] = d->instantiate(d, ss.rate))) {
|
||||
pa_log("Failed to instantiate plugin %s with label %s for channel %i", plugin, d->Label, c);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
d->connect_port(u->handle[c], input_port, u->input);
|
||||
d->connect_port(u->handle[c], output_port, u->output);
|
||||
}
|
||||
|
||||
if (!cdata && n_control > 0) {
|
||||
pa_log("This plugin requires specification of %lu control parameters.", n_control);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (n_control > 0) {
|
||||
const char *state = NULL;
|
||||
char *k;
|
||||
unsigned long h;
|
||||
|
||||
u->control = pa_xnew(LADSPA_Data, n_control);
|
||||
use_default = pa_xnew(pa_bool_t, n_control);
|
||||
p = 0;
|
||||
|
||||
while ((k = pa_split(cdata, ",", &state))) {
|
||||
float f;
|
||||
|
||||
if (*k == 0) {
|
||||
use_default[p++] = TRUE;
|
||||
pa_xfree(k);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pa_atof(k, &f) < 0) {
|
||||
pa_log("Failed to parse control value '%s'", k);
|
||||
pa_xfree(k);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pa_xfree(k);
|
||||
|
||||
if (p >= n_control) {
|
||||
pa_log("Too many control values passed, %lu expected.", n_control);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
use_default[p] = FALSE;
|
||||
u->control[p++] = f;
|
||||
}
|
||||
|
||||
if (p < n_control) {
|
||||
pa_log("Not enough control values passed, %lu expected, %lu passed.", n_control, p);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
h = 0;
|
||||
for (p = 0; p < d->PortCount; p++) {
|
||||
LADSPA_PortRangeHintDescriptor hint = d->PortRangeHints[p].HintDescriptor;
|
||||
|
||||
if (!LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]))
|
||||
continue;
|
||||
|
||||
if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p])) {
|
||||
for (c = 0; c < ss.channels; c++)
|
||||
d->connect_port(u->handle[c], p, &u->control_out);
|
||||
continue;
|
||||
}
|
||||
|
||||
pa_assert(h < n_control);
|
||||
|
||||
if (use_default[h]) {
|
||||
LADSPA_Data lower, upper;
|
||||
|
||||
if (!LADSPA_IS_HINT_HAS_DEFAULT(hint)) {
|
||||
pa_log("Control port value left empty but plugin defines no default.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
lower = d->PortRangeHints[p].LowerBound;
|
||||
upper = d->PortRangeHints[p].UpperBound;
|
||||
|
||||
if (LADSPA_IS_HINT_SAMPLE_RATE(hint)) {
|
||||
lower *= ss.rate;
|
||||
upper *= ss.rate;
|
||||
}
|
||||
|
||||
switch (hint & LADSPA_HINT_DEFAULT_MASK) {
|
||||
|
||||
case LADSPA_HINT_DEFAULT_MINIMUM:
|
||||
u->control[h] = lower;
|
||||
break;
|
||||
|
||||
case LADSPA_HINT_DEFAULT_MAXIMUM:
|
||||
u->control[h] = upper;
|
||||
break;
|
||||
|
||||
case LADSPA_HINT_DEFAULT_LOW:
|
||||
if (LADSPA_IS_HINT_LOGARITHMIC(hint))
|
||||
u->control[h] = exp(log(lower) * 0.75 + log(upper) * 0.25);
|
||||
else
|
||||
u->control[h] = lower * 0.75 + upper * 0.25;
|
||||
break;
|
||||
|
||||
case LADSPA_HINT_DEFAULT_MIDDLE:
|
||||
if (LADSPA_IS_HINT_LOGARITHMIC(hint))
|
||||
u->control[h] = exp(log(lower) * 0.5 + log(upper) * 0.5);
|
||||
else
|
||||
u->control[h] = lower * 0.5 + upper * 0.5;
|
||||
break;
|
||||
|
||||
case LADSPA_HINT_DEFAULT_HIGH:
|
||||
if (LADSPA_IS_HINT_LOGARITHMIC(hint))
|
||||
u->control[h] = exp(log(lower) * 0.25 + log(upper) * 0.75);
|
||||
else
|
||||
u->control[h] = lower * 0.25 + upper * 0.75;
|
||||
break;
|
||||
|
||||
case LADSPA_HINT_DEFAULT_0:
|
||||
u->control[h] = 0;
|
||||
break;
|
||||
|
||||
case LADSPA_HINT_DEFAULT_1:
|
||||
u->control[h] = 1;
|
||||
break;
|
||||
|
||||
case LADSPA_HINT_DEFAULT_100:
|
||||
u->control[h] = 100;
|
||||
break;
|
||||
|
||||
case LADSPA_HINT_DEFAULT_440:
|
||||
u->control[h] = 440;
|
||||
break;
|
||||
|
||||
default:
|
||||
pa_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
if (LADSPA_IS_HINT_INTEGER(hint))
|
||||
u->control[h] = roundf(u->control[h]);
|
||||
|
||||
pa_log_debug("Binding %f to port %s", u->control[h], d->PortNames[p]);
|
||||
|
||||
for (c = 0; c < ss.channels; c++)
|
||||
d->connect_port(u->handle[c], p, &u->control[h]);
|
||||
|
||||
h++;
|
||||
}
|
||||
|
||||
pa_assert(h == n_control);
|
||||
}
|
||||
|
||||
if (d->activate)
|
||||
for (c = 0; c < u->channels; c++)
|
||||
d->activate(u->handle[c]);
|
||||
|
||||
default_sink_name = pa_sprintf_malloc("%s.ladspa", master->name);
|
||||
|
||||
/* Create sink */
|
||||
if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", default_sink_name), 0, &ss, &map))) {
|
||||
pa_log("Failed to create sink.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u->sink->parent.process_msg = sink_process_msg;
|
||||
u->sink->set_state = sink_set_state;
|
||||
u->sink->userdata = u;
|
||||
u->sink->flags = PA_SINK_LATENCY;
|
||||
|
||||
pa_sink_set_module(u->sink, m);
|
||||
pa_sink_set_description(u->sink, t = pa_sprintf_malloc("LADSPA plugin '%s' on '%s'", label, master->description));
|
||||
pa_xfree(t);
|
||||
pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
|
||||
pa_sink_set_rtpoll(u->sink, master->rtpoll);
|
||||
|
||||
/* Create sink input */
|
||||
pa_sink_input_new_data_init(&data);
|
||||
data.sink = u->master;
|
||||
data.driver = __FILE__;
|
||||
data.name = "LADSPA Stream";
|
||||
pa_sink_input_new_data_set_sample_spec(&data, &ss);
|
||||
pa_sink_input_new_data_set_channel_map(&data, &map);
|
||||
data.module = m;
|
||||
|
||||
if (!(u->sink_input = pa_sink_input_new(m->core, &data, PA_SINK_INPUT_DONT_MOVE)))
|
||||
goto fail;
|
||||
|
||||
u->sink_input->parent.process_msg = sink_input_process_msg;
|
||||
u->sink_input->peek = sink_input_peek_cb;
|
||||
u->sink_input->drop = sink_input_drop_cb;
|
||||
u->sink_input->kill = sink_input_kill_cb;
|
||||
u->sink_input->attach = sink_input_attach_cb;
|
||||
u->sink_input->detach = sink_input_detach_cb;
|
||||
u->sink_input->userdata = u;
|
||||
|
||||
pa_sink_put(u->sink);
|
||||
pa_sink_input_put(u->sink_input);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
||||
pa_xfree(use_default);
|
||||
pa_xfree(default_sink_name);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
pa_xfree(use_default);
|
||||
pa_xfree(default_sink_name);
|
||||
|
||||
pa__done(m);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
unsigned c;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
if (u->sink_input) {
|
||||
pa_sink_input_unlink(u->sink_input);
|
||||
pa_sink_input_unref(u->sink_input);
|
||||
}
|
||||
|
||||
if (u->sink) {
|
||||
pa_sink_unlink(u->sink);
|
||||
pa_sink_unref(u->sink);
|
||||
}
|
||||
|
||||
if (u->memchunk.memblock)
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
|
||||
for (c = 0; c < u->channels; c++)
|
||||
if (u->handle[c]) {
|
||||
if (u->descriptor->deactivate)
|
||||
u->descriptor->deactivate(u->handle[c]);
|
||||
u->descriptor->cleanup(u->handle[c]);
|
||||
}
|
||||
|
||||
if (u->output != u->input)
|
||||
pa_xfree(u->output);
|
||||
|
||||
pa_xfree(u->input);
|
||||
|
||||
pa_xfree(u->control);
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
@ -26,12 +26,12 @@
|
|||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <lirc/lirc_client.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <lirc/lirc_client.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/module.h>
|
||||
|
|
@ -39,6 +39,7 @@
|
|||
#include <pulsecore/namereg.h>
|
||||
#include <pulsecore/sink.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "module-lirc-symdef.h"
|
||||
|
||||
|
|
@ -68,11 +69,12 @@ static int lirc_in_use = 0;
|
|||
static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) {
|
||||
struct userdata *u = userdata;
|
||||
char *name = NULL, *code = NULL;
|
||||
assert(io);
|
||||
assert(u);
|
||||
|
||||
pa_assert(io);
|
||||
pa_assert(u);
|
||||
|
||||
if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) {
|
||||
pa_log("lost connection to LIRC daemon.");
|
||||
pa_log("Lost connection to LIRC daemon.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -86,7 +88,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
|
|||
|
||||
c = pa_xstrdup(code);
|
||||
c[strcspn(c, "\n\r")] = 0;
|
||||
pa_log_debug("raw IR code '%s'", c);
|
||||
pa_log_debug("Raw IR code '%s'", c);
|
||||
pa_xfree(c);
|
||||
|
||||
while (lirc_code2char(u->config, code, &name) == 0 && name) {
|
||||
|
|
@ -99,7 +101,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
|
|||
MUTE_TOGGLE
|
||||
} volchange = INVALID;
|
||||
|
||||
pa_log_info("translated IR code '%s'", name);
|
||||
pa_log_info("Translated IR code '%s'", name);
|
||||
|
||||
if (strcasecmp(name, "volume-up") == 0)
|
||||
volchange = UP;
|
||||
|
|
@ -113,15 +115,15 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
|
|||
volchange = RESET;
|
||||
|
||||
if (volchange == INVALID)
|
||||
pa_log_warn("recieved unknown IR code '%s'", name);
|
||||
pa_log_warn("Recieved unknown IR code '%s'", name);
|
||||
else {
|
||||
pa_sink *s;
|
||||
|
||||
if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1)))
|
||||
pa_log("failed to get sink '%s'", u->sink_name);
|
||||
pa_log("Failed to get sink '%s'", u->sink_name);
|
||||
else {
|
||||
int i;
|
||||
pa_cvolume cv = *pa_sink_get_volume(s, PA_MIXER_HARDWARE);
|
||||
pa_cvolume cv = *pa_sink_get_volume(s);
|
||||
|
||||
#define DELTA (PA_VOLUME_NORM/20)
|
||||
|
||||
|
|
@ -134,7 +136,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
|
|||
cv.values[i] = PA_VOLUME_NORM;
|
||||
}
|
||||
|
||||
pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv);
|
||||
pa_sink_set_volume(s, &cv);
|
||||
break;
|
||||
|
||||
case DOWN:
|
||||
|
|
@ -145,20 +147,20 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
|
|||
cv.values[i] = PA_VOLUME_MUTED;
|
||||
}
|
||||
|
||||
pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv);
|
||||
pa_sink_set_volume(s, &cv);
|
||||
break;
|
||||
|
||||
case MUTE:
|
||||
pa_sink_set_mute(s, PA_MIXER_HARDWARE, 0);
|
||||
pa_sink_set_mute(s, 0);
|
||||
break;
|
||||
|
||||
case RESET:
|
||||
pa_sink_set_mute(s, PA_MIXER_HARDWARE, 1);
|
||||
pa_sink_set_mute(s, 1);
|
||||
break;
|
||||
|
||||
case MUTE_TOGGLE:
|
||||
|
||||
pa_sink_set_mute(s, PA_MIXER_HARDWARE, !pa_sink_get_mute(s, PA_MIXER_HARDWARE));
|
||||
pa_sink_set_mute(s, !pa_sink_get_mute(s));
|
||||
break;
|
||||
|
||||
case INVALID:
|
||||
|
|
@ -179,13 +181,14 @@ fail:
|
|||
|
||||
pa_module_unload_request(u->module);
|
||||
|
||||
free(code);
|
||||
pa_xfree(code);
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
pa_modargs *ma = NULL;
|
||||
struct userdata *u;
|
||||
assert(c && m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (lirc_in_use) {
|
||||
pa_log("module-lirc may no be loaded twice.");
|
||||
|
|
@ -197,7 +200,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
m->userdata = u = pa_xmalloc(sizeof(struct userdata));
|
||||
m->userdata = u = pa_xnew(struct userdata, 1);
|
||||
u->module = m;
|
||||
u->io = NULL;
|
||||
u->config = NULL;
|
||||
|
|
@ -215,7 +218,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
u->io = c->mainloop->io_new(c->mainloop, u->lirc_fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u);
|
||||
u->io = m->core->mainloop->io_new(m->core->mainloop, u->lirc_fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u);
|
||||
|
||||
lirc_in_use = 1;
|
||||
|
||||
|
|
@ -228,14 +231,13 @@ fail:
|
|||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
pa__done(c, m);
|
||||
pa__done(m);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
|
|
@ -80,6 +79,8 @@ static int load_rules(struct userdata *u, const char *filename) {
|
|||
struct rule *end = NULL;
|
||||
char *fn = NULL;
|
||||
|
||||
pa_assert(u);
|
||||
|
||||
f = filename ?
|
||||
fopen(fn = pa_xstrdup(filename), "r") :
|
||||
pa_open_config_file(DEFAULT_MATCH_TABLE_FILE, DEFAULT_MATCH_TABLE_FILE_USER, NULL, &fn, "r");
|
||||
|
|
@ -132,7 +133,7 @@ static int load_rules(struct userdata *u, const char *filename) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
rule = pa_xmalloc(sizeof(struct rule));
|
||||
rule = pa_xnew(struct rule, 1);
|
||||
rule->regex = regex;
|
||||
rule->volume = volume;
|
||||
rule->next = NULL;
|
||||
|
|
@ -164,7 +165,9 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v
|
|||
struct userdata *u = userdata;
|
||||
pa_sink_input *si;
|
||||
struct rule *r;
|
||||
assert(c && u);
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(u);
|
||||
|
||||
if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW))
|
||||
return;
|
||||
|
|
@ -179,23 +182,24 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v
|
|||
if (!regexec(&r->regex, si->name, 0, NULL, 0)) {
|
||||
pa_cvolume cv;
|
||||
pa_log_debug("changing volume of sink input '%s' to 0x%03x", si->name, r->volume);
|
||||
pa_cvolume_set(&cv, r->volume, si->sample_spec.channels);
|
||||
pa_cvolume_set(&cv, si->sample_spec.channels, r->volume);
|
||||
pa_sink_input_set_volume(si, &cv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
pa_modargs *ma = NULL;
|
||||
struct userdata *u;
|
||||
assert(c && m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u = pa_xmalloc(sizeof(struct userdata));
|
||||
u = pa_xnew(struct userdata, 1);
|
||||
u->rules = NULL;
|
||||
u->subscription = NULL;
|
||||
m->userdata = u;
|
||||
|
|
@ -203,23 +207,24 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
if (load_rules(u, pa_modargs_get_value(ma, "table", NULL)) < 0)
|
||||
goto fail;
|
||||
|
||||
u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, callback, u);
|
||||
u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT, callback, u);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
pa__done(c, m);
|
||||
pa__done(m);
|
||||
|
||||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata* u;
|
||||
struct rule *r, *n;
|
||||
assert(c && m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -80,11 +79,12 @@ struct userdata {
|
|||
|
||||
static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) {
|
||||
struct userdata *u = userdata;
|
||||
assert(io);
|
||||
assert(u);
|
||||
|
||||
pa_assert(io);
|
||||
pa_assert(u);
|
||||
|
||||
if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) {
|
||||
pa_log("lost connection to evdev device.");
|
||||
pa_log("Lost connection to evdev device.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -92,14 +92,14 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
|
|||
struct input_event ev;
|
||||
|
||||
if (pa_loop_read(u->fd, &ev, sizeof(ev), &u->fd_type) <= 0) {
|
||||
pa_log("failed to read from event device: %s", pa_cstrerror(errno));
|
||||
pa_log("Failed to read from event device: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ev.type == EV_KEY && (ev.value == 1 || ev.value == 2)) {
|
||||
enum { INVALID, UP, DOWN, MUTE_TOGGLE } volchange = INVALID;
|
||||
|
||||
pa_log_debug("key code=%u, value=%u", ev.code, ev.value);
|
||||
pa_log_debug("Key code=%u, value=%u", ev.code, ev.value);
|
||||
|
||||
switch (ev.code) {
|
||||
case KEY_VOLUMEDOWN: volchange = DOWN; break;
|
||||
|
|
@ -111,10 +111,10 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
|
|||
pa_sink *s;
|
||||
|
||||
if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1)))
|
||||
pa_log("failed to get sink '%s'", u->sink_name);
|
||||
pa_log("Failed to get sink '%s'", u->sink_name);
|
||||
else {
|
||||
int i;
|
||||
pa_cvolume cv = *pa_sink_get_volume(s, PA_MIXER_HARDWARE);
|
||||
pa_cvolume cv = *pa_sink_get_volume(s);
|
||||
|
||||
#define DELTA (PA_VOLUME_NORM/20)
|
||||
|
||||
|
|
@ -127,7 +127,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
|
|||
cv.values[i] = PA_VOLUME_NORM;
|
||||
}
|
||||
|
||||
pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv);
|
||||
pa_sink_set_volume(s, &cv);
|
||||
break;
|
||||
|
||||
case DOWN:
|
||||
|
|
@ -138,12 +138,12 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
|
|||
cv.values[i] = PA_VOLUME_MUTED;
|
||||
}
|
||||
|
||||
pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv);
|
||||
pa_sink_set_volume(s, &cv);
|
||||
break;
|
||||
|
||||
case MUTE_TOGGLE:
|
||||
|
||||
pa_sink_set_mute(s, PA_MIXER_HARDWARE, !pa_sink_get_mute(s, PA_MIXER_HARDWARE));
|
||||
pa_sink_set_mute(s, !pa_sink_get_mute(s));
|
||||
break;
|
||||
|
||||
case INVALID:
|
||||
|
|
@ -165,21 +165,23 @@ fail:
|
|||
|
||||
#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
|
||||
pa_modargs *ma = NULL;
|
||||
struct userdata *u;
|
||||
int version;
|
||||
struct _input_id input_id;
|
||||
char name[256];
|
||||
uint8_t evtype_bitmask[EV_MAX/8 + 1];
|
||||
assert(c && m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
m->userdata = u = pa_xmalloc(sizeof(struct userdata));
|
||||
m->userdata = u = pa_xnew(struct userdata,1);
|
||||
u->module = m;
|
||||
u->io = NULL;
|
||||
u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
|
||||
|
|
@ -221,11 +223,11 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
}
|
||||
|
||||
if (!test_bit(EV_KEY, evtype_bitmask)) {
|
||||
pa_log("device has no keys.");
|
||||
pa_log("Device has no keys.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u->io = c->mainloop->io_new(c->mainloop, u->fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u);
|
||||
u->io = m->core->mainloop->io_new(m->core->mainloop, u->fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
||||
|
|
@ -236,14 +238,14 @@ fail:
|
|||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
pa__done(c, m);
|
||||
pa__done(m);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
assert(c);
|
||||
assert(m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
|
@ -252,7 +254,7 @@ void pa__done(pa_core *c, pa_module*m) {
|
|||
m->core->mainloop->io_free(u->io);
|
||||
|
||||
if (u->fd >= 0)
|
||||
close(u->fd);
|
||||
pa_assert_se(pa_close(u->fd) == 0);
|
||||
|
||||
pa_xfree(u->sink_name);
|
||||
pa_xfree(u);
|
||||
|
|
|
|||
|
|
@ -26,10 +26,10 @@
|
|||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <pulsecore/module.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/iochannel.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/protocol-native.h>
|
||||
|
|
@ -48,25 +48,26 @@ static const char* const valid_modargs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
pa_iochannel *io;
|
||||
pa_modargs *ma;
|
||||
int fd, r = -1;
|
||||
assert(c && m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("failed to parse module arguments.");
|
||||
pa_log("Failed to parse module arguments.");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (pa_modargs_get_value_s32(ma, "fd", &fd) < 0) {
|
||||
pa_log("invalid file descriptor.");
|
||||
pa_log("Invalid file descriptor.");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
io = pa_iochannel_new(c->mainloop, fd, fd);
|
||||
io = pa_iochannel_new(m->core->mainloop, fd, fd);
|
||||
|
||||
if (!(m->userdata = pa_protocol_native_new_iochannel(c, io, m, ma))) {
|
||||
if (!(m->userdata = pa_protocol_native_new_iochannel(m->core, io, m, ma))) {
|
||||
pa_iochannel_free(io);
|
||||
goto finish;
|
||||
}
|
||||
|
|
@ -80,8 +81,8 @@ finish:
|
|||
return r;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
assert(c && m);
|
||||
void pa__done(pa_module*m) {
|
||||
pa_assert(m);
|
||||
|
||||
pa_protocol_native_free(m->userdata);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
|
@ -38,12 +37,17 @@
|
|||
#include <pulse/timeval.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/iochannel.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/sink.h>
|
||||
#include <pulsecore/module.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/thread.h>
|
||||
#include <pulsecore/thread-mq.h>
|
||||
#include <pulsecore/rtpoll.h>
|
||||
#include <pulsecore/rtclock.h>
|
||||
|
||||
#include "module-null-sink-symdef.h"
|
||||
|
||||
|
|
@ -64,11 +68,14 @@ struct userdata {
|
|||
pa_core *core;
|
||||
pa_module *module;
|
||||
pa_sink *sink;
|
||||
pa_time_event *time_event;
|
||||
|
||||
pa_thread *thread;
|
||||
pa_thread_mq thread_mq;
|
||||
pa_rtpoll *rtpoll;
|
||||
|
||||
size_t block_size;
|
||||
|
||||
uint64_t n_bytes;
|
||||
struct timeval start_time;
|
||||
struct timeval timestamp;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
|
|
@ -81,78 +88,132 @@ static const char* const valid_modargs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static void time_callback(pa_mainloop_api *m, pa_time_event*e, const struct timeval *tv, void *userdata) {
|
||||
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
struct userdata *u = PA_SINK(o)->userdata;
|
||||
|
||||
switch (code) {
|
||||
case PA_SINK_MESSAGE_SET_STATE:
|
||||
|
||||
if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING)
|
||||
pa_rtclock_get(&u->timestamp);
|
||||
|
||||
break;
|
||||
|
||||
case PA_SINK_MESSAGE_GET_LATENCY: {
|
||||
struct timeval now;
|
||||
|
||||
pa_rtclock_get(&now);
|
||||
|
||||
if (pa_timeval_cmp(&u->timestamp, &now) > 0)
|
||||
*((pa_usec_t*) data) = 0;
|
||||
else
|
||||
*((pa_usec_t*) data) = pa_timeval_diff(&u->timestamp, &now);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pa_sink_process_msg(o, code, data, offset, chunk);
|
||||
}
|
||||
|
||||
static void thread_func(void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
pa_memchunk chunk;
|
||||
struct timeval ntv = *tv;
|
||||
size_t l;
|
||||
|
||||
assert(u);
|
||||
pa_assert(u);
|
||||
|
||||
if (pa_sink_render(u->sink, u->block_size, &chunk) >= 0) {
|
||||
l = chunk.length;
|
||||
pa_memblock_unref(chunk.memblock);
|
||||
} else
|
||||
l = u->block_size;
|
||||
pa_log_debug("Thread starting up");
|
||||
|
||||
pa_timeval_add(&ntv, pa_bytes_to_usec(l, &u->sink->sample_spec));
|
||||
m->time_restart(e, &ntv);
|
||||
pa_thread_mq_install(&u->thread_mq);
|
||||
pa_rtpoll_install(u->rtpoll);
|
||||
|
||||
u->n_bytes += l;
|
||||
pa_rtclock_get(&u->timestamp);
|
||||
|
||||
for (;;) {
|
||||
int ret;
|
||||
|
||||
/* Render some data and drop it immediately */
|
||||
if (u->sink->thread_info.state == PA_SINK_RUNNING) {
|
||||
struct timeval now;
|
||||
|
||||
pa_rtclock_get(&now);
|
||||
|
||||
if (pa_timeval_cmp(&u->timestamp, &now) <= 0) {
|
||||
pa_sink_skip(u->sink, u->block_size);
|
||||
pa_timeval_add(&u->timestamp, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec));
|
||||
}
|
||||
|
||||
pa_rtpoll_set_timer_absolute(u->rtpoll, &u->timestamp);
|
||||
} else
|
||||
pa_rtpoll_set_timer_disabled(u->rtpoll);
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (ret == 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
fail:
|
||||
/* If this was no regular exit from the loop we have to continue
|
||||
* processing messages until we received PA_MESSAGE_SHUTDOWN */
|
||||
pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
|
||||
pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
|
||||
|
||||
finish:
|
||||
pa_log_debug("Thread shutting down");
|
||||
}
|
||||
|
||||
static pa_usec_t get_latency(pa_sink *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
pa_usec_t a, b;
|
||||
struct timeval now;
|
||||
|
||||
a = pa_timeval_diff(pa_gettimeofday(&now), &u->start_time);
|
||||
b = pa_bytes_to_usec(u->n_bytes, &s->sample_spec);
|
||||
|
||||
return b > a ? b - a : 0;
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
struct userdata *u = NULL;
|
||||
pa_sample_spec ss;
|
||||
pa_channel_map map;
|
||||
pa_modargs *ma = NULL;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("failed to parse module arguments.");
|
||||
pa_log("Failed to parse module arguments.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ss = c->default_sample_spec;
|
||||
ss = m->core->default_sample_spec;
|
||||
if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
|
||||
pa_log("invalid sample format specification or channel map.");
|
||||
pa_log("Invalid sample format specification or channel map");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u = pa_xnew0(struct userdata, 1);
|
||||
u->core = c;
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
m->userdata = u;
|
||||
pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
|
||||
u->rtpoll = pa_rtpoll_new();
|
||||
pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
|
||||
|
||||
if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) {
|
||||
pa_log("failed to create sink.");
|
||||
if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) {
|
||||
pa_log("Failed to create sink.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u->sink->get_latency = get_latency;
|
||||
u->sink->parent.process_msg = sink_process_msg;
|
||||
u->sink->userdata = u;
|
||||
pa_sink_set_owner(u->sink, m);
|
||||
u->sink->flags = PA_SINK_LATENCY;
|
||||
|
||||
pa_sink_set_module(u->sink, m);
|
||||
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
|
||||
pa_sink_set_rtpoll(u->sink, u->rtpoll);
|
||||
pa_sink_set_description(u->sink, pa_modargs_get_value(ma, "description", "NULL sink"));
|
||||
|
||||
u->n_bytes = 0;
|
||||
pa_gettimeofday(&u->start_time);
|
||||
u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */
|
||||
if (u->block_size <= 0)
|
||||
u->block_size = pa_frame_size(&ss);
|
||||
|
||||
u->time_event = c->mainloop->time_new(c->mainloop, &u->start_time, time_callback, u);
|
||||
if (!(u->thread = pa_thread_new(thread_func, u))) {
|
||||
pa_log("Failed to create thread.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u->block_size = pa_bytes_per_second(&ss) / 10;
|
||||
pa_sink_put(u->sink);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
||||
|
|
@ -162,22 +223,34 @@ fail:
|
|||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
pa__done(c, m);
|
||||
pa__done(m);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
assert(c && m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
pa_sink_disconnect(u->sink);
|
||||
pa_sink_unref(u->sink);
|
||||
if (u->sink)
|
||||
pa_sink_unlink(u->sink);
|
||||
|
||||
u->core->mainloop->time_free(u->time_event);
|
||||
if (u->thread) {
|
||||
pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
|
||||
pa_thread_free(u->thread);
|
||||
}
|
||||
|
||||
pa_thread_mq_done(&u->thread_mq);
|
||||
|
||||
if (u->sink)
|
||||
pa_sink_unref(u->sink);
|
||||
|
||||
if (u->rtpoll)
|
||||
pa_rtpoll_free(u->rtpoll);
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,637 +0,0 @@
|
|||
/* $Id$ */
|
||||
|
||||
/***
|
||||
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 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/soundcard.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/util.h>
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/iochannel.h>
|
||||
#include <pulsecore/sink.h>
|
||||
#include <pulsecore/source.h>
|
||||
#include <pulsecore/module.h>
|
||||
#include <pulsecore/sample-util.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/log.h>
|
||||
|
||||
#include "oss-util.h"
|
||||
#include "module-oss-mmap-symdef.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Lennart Poettering")
|
||||
PA_MODULE_DESCRIPTION("OSS Sink/Source (mmap)")
|
||||
PA_MODULE_VERSION(PACKAGE_VERSION)
|
||||
PA_MODULE_USAGE(
|
||||
"sink_name=<name for the sink> "
|
||||
"source_name=<name for the source> "
|
||||
"device=<OSS device> "
|
||||
"record=<enable source?> "
|
||||
"playback=<enable sink?> "
|
||||
"format=<sample format> "
|
||||
"channels=<number of channels> "
|
||||
"rate=<sample rate> "
|
||||
"fragments=<number of fragments> "
|
||||
"fragment_size=<fragment size> "
|
||||
"channel_map=<channel map>")
|
||||
|
||||
struct userdata {
|
||||
pa_sink *sink;
|
||||
pa_source *source;
|
||||
pa_core *core;
|
||||
pa_sample_spec sample_spec;
|
||||
|
||||
size_t in_fragment_size, out_fragment_size;
|
||||
unsigned in_fragments, out_fragments;
|
||||
unsigned out_blocks_saved, in_blocks_saved;
|
||||
|
||||
int fd;
|
||||
|
||||
void *in_mmap, *out_mmap;
|
||||
size_t in_mmap_length, out_mmap_length;
|
||||
|
||||
pa_io_event *io_event;
|
||||
|
||||
pa_memblock **in_memblocks, **out_memblocks;
|
||||
unsigned out_current, in_current;
|
||||
pa_module *module;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"sink_name",
|
||||
"source_name",
|
||||
"device",
|
||||
"record",
|
||||
"playback",
|
||||
"fragments",
|
||||
"fragment_size",
|
||||
"format",
|
||||
"rate",
|
||||
"channels",
|
||||
"channel_map",
|
||||
NULL
|
||||
};
|
||||
|
||||
#define DEFAULT_DEVICE "/dev/dsp"
|
||||
#define DEFAULT_NFRAGS 12
|
||||
#define DEFAULT_FRAGSIZE 1024
|
||||
|
||||
static void update_usage(struct userdata *u) {
|
||||
pa_module_set_used(u->module,
|
||||
(u->sink ? pa_sink_used_by(u->sink) : 0) +
|
||||
(u->source ? pa_source_used_by(u->source) : 0));
|
||||
}
|
||||
|
||||
static void clear_up(struct userdata *u) {
|
||||
assert(u);
|
||||
|
||||
if (u->sink) {
|
||||
pa_sink_disconnect(u->sink);
|
||||
pa_sink_unref(u->sink);
|
||||
u->sink = NULL;
|
||||
}
|
||||
|
||||
if (u->source) {
|
||||
pa_source_disconnect(u->source);
|
||||
pa_source_unref(u->source);
|
||||
u->source = NULL;
|
||||
}
|
||||
|
||||
if (u->in_mmap && u->in_mmap != MAP_FAILED) {
|
||||
munmap(u->in_mmap, u->in_mmap_length);
|
||||
u->in_mmap = NULL;
|
||||
}
|
||||
|
||||
if (u->out_mmap && u->out_mmap != MAP_FAILED) {
|
||||
munmap(u->out_mmap, u->out_mmap_length);
|
||||
u->out_mmap = NULL;
|
||||
}
|
||||
|
||||
if (u->io_event) {
|
||||
u->core->mainloop->io_free(u->io_event);
|
||||
u->io_event = NULL;
|
||||
}
|
||||
|
||||
if (u->fd >= 0) {
|
||||
close(u->fd);
|
||||
u->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void out_fill_memblocks(struct userdata *u, unsigned n) {
|
||||
assert(u && u->out_memblocks);
|
||||
|
||||
while (n > 0) {
|
||||
pa_memchunk chunk;
|
||||
|
||||
if (u->out_memblocks[u->out_current])
|
||||
pa_memblock_unref_fixed(u->out_memblocks[u->out_current]);
|
||||
|
||||
chunk.memblock = u->out_memblocks[u->out_current] =
|
||||
pa_memblock_new_fixed(
|
||||
u->core->mempool,
|
||||
(uint8_t*) u->out_mmap+u->out_fragment_size*u->out_current,
|
||||
u->out_fragment_size,
|
||||
1);
|
||||
assert(chunk.memblock);
|
||||
chunk.length = chunk.memblock->length;
|
||||
chunk.index = 0;
|
||||
|
||||
pa_sink_render_into_full(u->sink, &chunk);
|
||||
|
||||
u->out_current++;
|
||||
while (u->out_current >= u->out_fragments)
|
||||
u->out_current -= u->out_fragments;
|
||||
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_write(struct userdata *u) {
|
||||
struct count_info info;
|
||||
assert(u && u->sink);
|
||||
|
||||
update_usage(u);
|
||||
|
||||
if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) {
|
||||
pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno));
|
||||
|
||||
clear_up(u);
|
||||
pa_module_unload_request(u->module);
|
||||
return;
|
||||
}
|
||||
|
||||
info.blocks += u->out_blocks_saved;
|
||||
u->out_blocks_saved = 0;
|
||||
|
||||
if (!info.blocks)
|
||||
return;
|
||||
|
||||
out_fill_memblocks(u, info.blocks);
|
||||
}
|
||||
|
||||
static void in_post_memblocks(struct userdata *u, unsigned n) {
|
||||
assert(u && u->in_memblocks);
|
||||
|
||||
while (n > 0) {
|
||||
pa_memchunk chunk;
|
||||
|
||||
if (!u->in_memblocks[u->in_current]) {
|
||||
chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed(u->core->mempool, (uint8_t*) u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, 1);
|
||||
chunk.length = chunk.memblock->length;
|
||||
chunk.index = 0;
|
||||
|
||||
pa_source_post(u->source, &chunk);
|
||||
}
|
||||
|
||||
u->in_current++;
|
||||
while (u->in_current >= u->in_fragments)
|
||||
u->in_current -= u->in_fragments;
|
||||
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
static void in_clear_memblocks(struct userdata*u, unsigned n) {
|
||||
unsigned i = u->in_current;
|
||||
assert(u && u->in_memblocks);
|
||||
|
||||
if (n > u->in_fragments)
|
||||
n = u->in_fragments;
|
||||
|
||||
while (n > 0) {
|
||||
if (u->in_memblocks[i]) {
|
||||
pa_memblock_unref_fixed(u->in_memblocks[i]);
|
||||
u->in_memblocks[i] = NULL;
|
||||
}
|
||||
|
||||
i++;
|
||||
while (i >= u->in_fragments)
|
||||
i -= u->in_fragments;
|
||||
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_read(struct userdata *u) {
|
||||
struct count_info info;
|
||||
assert(u && u->source);
|
||||
|
||||
update_usage(u);
|
||||
|
||||
if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) {
|
||||
pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno));
|
||||
|
||||
clear_up(u);
|
||||
pa_module_unload_request(u->module);
|
||||
return;
|
||||
}
|
||||
|
||||
info.blocks += u->in_blocks_saved;
|
||||
u->in_blocks_saved = 0;
|
||||
|
||||
if (!info.blocks)
|
||||
return;
|
||||
|
||||
in_post_memblocks(u, info.blocks);
|
||||
in_clear_memblocks(u, u->in_fragments/2);
|
||||
}
|
||||
|
||||
static void io_callback(pa_mainloop_api *m, pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t f, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
assert (u && u->core->mainloop == m && u->io_event == e);
|
||||
|
||||
if (f & PA_IO_EVENT_ERROR) {
|
||||
clear_up(u);
|
||||
pa_module_unload_request(u->module);
|
||||
return;
|
||||
}
|
||||
|
||||
if (f & PA_IO_EVENT_INPUT)
|
||||
do_read(u);
|
||||
if (f & PA_IO_EVENT_OUTPUT)
|
||||
do_write(u);
|
||||
}
|
||||
|
||||
static pa_usec_t sink_get_latency_cb(pa_sink *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
struct count_info info;
|
||||
size_t bpos, n, total;
|
||||
assert(s && u);
|
||||
|
||||
if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) {
|
||||
pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
u->out_blocks_saved += info.blocks;
|
||||
|
||||
total = u->out_fragments * u->out_fragment_size;
|
||||
bpos = ((u->out_current + u->out_blocks_saved) * u->out_fragment_size) % total;
|
||||
|
||||
if (bpos <= (size_t) info.ptr)
|
||||
n = total - (info.ptr - bpos);
|
||||
else
|
||||
n = bpos - info.ptr;
|
||||
|
||||
/* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->out_fragment_size, u->out_fragments); */
|
||||
|
||||
return pa_bytes_to_usec(n, &s->sample_spec);
|
||||
}
|
||||
|
||||
static pa_usec_t source_get_latency_cb(pa_source *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
struct count_info info;
|
||||
size_t bpos, n, total;
|
||||
assert(s && u);
|
||||
|
||||
if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) {
|
||||
pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
u->in_blocks_saved += info.blocks;
|
||||
|
||||
total = u->in_fragments * u->in_fragment_size;
|
||||
bpos = ((u->in_current + u->in_blocks_saved) * u->in_fragment_size) % total;
|
||||
|
||||
if (bpos <= (size_t) info.ptr)
|
||||
n = info.ptr - bpos;
|
||||
else
|
||||
n = (u->in_fragments * u->in_fragment_size) - bpos + info.ptr;
|
||||
|
||||
/* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->in_fragment_size, u->in_fragments); */
|
||||
|
||||
return pa_bytes_to_usec(n, &s->sample_spec);
|
||||
}
|
||||
|
||||
static int sink_get_hw_volume(pa_sink *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
|
||||
if (pa_oss_get_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) {
|
||||
pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
|
||||
s->get_hw_volume = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sink_set_hw_volume(pa_sink *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
|
||||
if (pa_oss_set_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) {
|
||||
pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
|
||||
s->set_hw_volume = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int source_get_hw_volume(pa_source *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
|
||||
if (pa_oss_get_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) {
|
||||
pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
|
||||
s->get_hw_volume = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int source_set_hw_volume(pa_source *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
|
||||
if (pa_oss_set_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) {
|
||||
pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
|
||||
s->set_hw_volume = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
struct audio_buf_info info;
|
||||
struct userdata *u = NULL;
|
||||
const char *p;
|
||||
int nfrags, frag_size;
|
||||
int mode, caps;
|
||||
int enable_bits = 0, zero = 0;
|
||||
int playback = 1, record = 1;
|
||||
pa_modargs *ma = NULL;
|
||||
char hwdesc[64], *t;
|
||||
pa_channel_map map;
|
||||
const char *name;
|
||||
char *name_buf = NULL;
|
||||
int namereg_fail;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
|
||||
m->userdata = u = pa_xnew0(struct userdata, 1);
|
||||
u->module = m;
|
||||
u->fd = -1;
|
||||
u->core = c;
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("failed to parse module arguments.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
|
||||
pa_log("record= and playback= expect numeric arguments.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!playback && !record) {
|
||||
pa_log("neither playback nor record enabled for device.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
|
||||
|
||||
nfrags = DEFAULT_NFRAGS;
|
||||
frag_size = DEFAULT_FRAGSIZE;
|
||||
if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) {
|
||||
pa_log("failed to parse fragments arguments");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u->sample_spec = c->default_sample_spec;
|
||||
if (pa_modargs_get_sample_spec_and_channel_map(ma, &u->sample_spec, &map, PA_CHANNEL_MAP_OSS) < 0) {
|
||||
pa_log("failed to parse sample specification or channel map");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((u->fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_TRIGGER)) {
|
||||
pa_log("OSS device not mmap capable.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pa_log_info("device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR"));
|
||||
|
||||
if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0)
|
||||
pa_log_info("hardware name is '%s'.", hwdesc);
|
||||
else
|
||||
hwdesc[0] = 0;
|
||||
|
||||
if (nfrags >= 2 && frag_size >= 1)
|
||||
if (pa_oss_set_fragments(u->fd, nfrags, frag_size) < 0)
|
||||
goto fail;
|
||||
|
||||
if (pa_oss_auto_format(u->fd, &u->sample_spec) < 0)
|
||||
goto fail;
|
||||
|
||||
if (mode != O_WRONLY) {
|
||||
if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) {
|
||||
pa_log("SNDCTL_DSP_GETISPACE: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pa_log_info("input -- %u fragments of size %u.", info.fragstotal, info.fragsize);
|
||||
u->in_mmap_length = (u->in_fragment_size = info.fragsize) * (u->in_fragments = info.fragstotal);
|
||||
|
||||
if ((u->in_mmap = mmap(NULL, u->in_mmap_length, PROT_READ, MAP_SHARED, u->fd, 0)) == MAP_FAILED) {
|
||||
if (mode == O_RDWR) {
|
||||
pa_log("mmap failed for input. Changing to O_WRONLY mode.");
|
||||
mode = O_WRONLY;
|
||||
} else {
|
||||
pa_log("mmap(): %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
if ((name = pa_modargs_get_value(ma, "source_name", NULL)))
|
||||
namereg_fail = 1;
|
||||
else {
|
||||
name = name_buf = pa_sprintf_malloc("oss_input.%s", pa_path_get_filename(p));
|
||||
namereg_fail = 0;
|
||||
}
|
||||
|
||||
if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &u->sample_spec, &map)))
|
||||
goto fail;
|
||||
|
||||
u->source->userdata = u;
|
||||
u->source->get_latency = source_get_latency_cb;
|
||||
u->source->get_hw_volume = source_get_hw_volume;
|
||||
u->source->set_hw_volume = source_set_hw_volume;
|
||||
pa_source_set_owner(u->source, m);
|
||||
pa_source_set_description(u->source, t = pa_sprintf_malloc("OSS PCM/mmap() on %s%s%s%s",
|
||||
p,
|
||||
hwdesc[0] ? " (" : "",
|
||||
hwdesc[0] ? hwdesc : "",
|
||||
hwdesc[0] ? ")" : ""));
|
||||
pa_xfree(t);
|
||||
u->source->is_hardware = 1;
|
||||
|
||||
u->in_memblocks = pa_xnew0(pa_memblock*, u->in_fragments);
|
||||
|
||||
enable_bits |= PCM_ENABLE_INPUT;
|
||||
}
|
||||
}
|
||||
|
||||
pa_xfree(name_buf);
|
||||
name_buf = NULL;
|
||||
|
||||
if (mode != O_RDONLY) {
|
||||
if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
|
||||
pa_log("SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pa_log_info("output -- %u fragments of size %u.", info.fragstotal, info.fragsize);
|
||||
u->out_mmap_length = (u->out_fragment_size = info.fragsize) * (u->out_fragments = info.fragstotal);
|
||||
|
||||
if ((u->out_mmap = mmap(NULL, u->out_mmap_length, PROT_WRITE, MAP_SHARED, u->fd, 0)) == MAP_FAILED) {
|
||||
if (mode == O_RDWR) {
|
||||
pa_log("mmap filed for output. Changing to O_RDONLY mode.");
|
||||
mode = O_RDONLY;
|
||||
} else {
|
||||
pa_log("mmap(): %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
pa_silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec);
|
||||
|
||||
if ((name = pa_modargs_get_value(ma, "sink_name", NULL)))
|
||||
namereg_fail = 1;
|
||||
else {
|
||||
name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(p));
|
||||
namereg_fail = 0;
|
||||
}
|
||||
|
||||
if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &u->sample_spec, &map)))
|
||||
goto fail;
|
||||
|
||||
u->sink->get_latency = sink_get_latency_cb;
|
||||
u->sink->get_hw_volume = sink_get_hw_volume;
|
||||
u->sink->set_hw_volume = sink_set_hw_volume;
|
||||
u->sink->userdata = u;
|
||||
pa_sink_set_owner(u->sink, m);
|
||||
pa_sink_set_description(u->sink, t = pa_sprintf_malloc("OSS PCM/mmap() on %s%s%s%s",
|
||||
p,
|
||||
hwdesc[0] ? " (" : "",
|
||||
hwdesc[0] ? hwdesc : "",
|
||||
hwdesc[0] ? ")" : ""));
|
||||
pa_xfree(t);
|
||||
|
||||
u->sink->is_hardware = 1;
|
||||
u->out_memblocks = pa_xmalloc0(sizeof(struct memblock *)*u->out_fragments);
|
||||
|
||||
enable_bits |= PCM_ENABLE_OUTPUT;
|
||||
}
|
||||
}
|
||||
|
||||
pa_xfree(name_buf);
|
||||
name_buf = NULL;
|
||||
|
||||
zero = 0;
|
||||
if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero) < 0) {
|
||||
pa_log("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0) {
|
||||
pa_log("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
assert(u->source || u->sink);
|
||||
|
||||
u->io_event = c->mainloop->io_new(c->mainloop, u->fd, (u->source ? PA_IO_EVENT_INPUT : 0) | (u->sink ? PA_IO_EVENT_OUTPUT : 0), io_callback, u);
|
||||
assert(u->io_event);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
||||
/* Read mixer settings */
|
||||
if (u->source)
|
||||
source_get_hw_volume(u->source);
|
||||
if (u->sink)
|
||||
sink_get_hw_volume(u->sink);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
pa__done(c, m);
|
||||
|
||||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
pa_xfree(name_buf);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
struct userdata *u;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
clear_up(u);
|
||||
|
||||
if (u->out_memblocks) {
|
||||
unsigned i;
|
||||
for (i = 0; i < u->out_fragments; i++)
|
||||
if (u->out_memblocks[i])
|
||||
pa_memblock_unref_fixed(u->out_memblocks[i]);
|
||||
pa_xfree(u->out_memblocks);
|
||||
}
|
||||
|
||||
if (u->in_memblocks) {
|
||||
unsigned i;
|
||||
for (i = 0; i < u->in_fragments; i++)
|
||||
if (u->in_memblocks[i])
|
||||
pa_memblock_unref_fixed(u->in_memblocks[i]);
|
||||
pa_xfree(u->in_memblocks);
|
||||
}
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -28,22 +28,25 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/iochannel.h>
|
||||
#include <pulsecore/sink.h>
|
||||
#include <pulsecore/module.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/thread.h>
|
||||
#include <pulsecore/thread-mq.h>
|
||||
#include <pulsecore/rtpoll.h>
|
||||
|
||||
#include "module-pipe-sink-symdef.h"
|
||||
|
||||
|
|
@ -58,20 +61,24 @@ PA_MODULE_USAGE(
|
|||
"rate=<sample rate>"
|
||||
"channel_map=<channel map>")
|
||||
|
||||
#define DEFAULT_FIFO_NAME "/tmp/music.output"
|
||||
#define DEFAULT_FILE_NAME "/tmp/music.output"
|
||||
#define DEFAULT_SINK_NAME "fifo_output"
|
||||
|
||||
struct userdata {
|
||||
pa_core *core;
|
||||
pa_module *module;
|
||||
pa_sink *sink;
|
||||
|
||||
pa_thread *thread;
|
||||
pa_thread_mq thread_mq;
|
||||
pa_rtpoll *rtpoll;
|
||||
|
||||
char *filename;
|
||||
|
||||
pa_sink *sink;
|
||||
pa_iochannel *io;
|
||||
pa_defer_event *defer_event;
|
||||
int fd;
|
||||
|
||||
pa_memchunk memchunk;
|
||||
pa_module *module;
|
||||
|
||||
pa_rtpoll_item *rtpoll_item;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
|
|
@ -84,133 +91,191 @@ static const char* const valid_modargs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static void do_write(struct userdata *u) {
|
||||
ssize_t r;
|
||||
assert(u);
|
||||
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
struct userdata *u = PA_SINK(o)->userdata;
|
||||
|
||||
u->core->mainloop->defer_enable(u->defer_event, 0);
|
||||
switch (code) {
|
||||
|
||||
if (!pa_iochannel_is_writable(u->io))
|
||||
return;
|
||||
case PA_SINK_MESSAGE_GET_LATENCY: {
|
||||
size_t n = 0;
|
||||
int l;
|
||||
|
||||
pa_module_set_used(u->module, pa_sink_used_by(u->sink));
|
||||
#ifdef TIOCINQ
|
||||
if (ioctl(u->fd, TIOCINQ, &l) >= 0 && l > 0)
|
||||
n = (size_t) l;
|
||||
#endif
|
||||
|
||||
if (!u->memchunk.length)
|
||||
if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0)
|
||||
return;
|
||||
n += u->memchunk.length;
|
||||
|
||||
assert(u->memchunk.memblock && u->memchunk.length);
|
||||
|
||||
if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) {
|
||||
pa_log("write(): %s", pa_cstrerror(errno));
|
||||
return;
|
||||
*((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->sink->sample_spec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u->memchunk.index += r;
|
||||
u->memchunk.length -= r;
|
||||
return pa_sink_process_msg(o, code, data, offset, chunk);
|
||||
}
|
||||
|
||||
if (u->memchunk.length <= 0) {
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
u->memchunk.memblock = NULL;
|
||||
static void thread_func(void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
int write_type = 0;
|
||||
|
||||
pa_assert(u);
|
||||
|
||||
pa_log_debug("Thread starting up");
|
||||
|
||||
pa_thread_mq_install(&u->thread_mq);
|
||||
pa_rtpoll_install(u->rtpoll);
|
||||
|
||||
for (;;) {
|
||||
struct pollfd *pollfd;
|
||||
int ret;
|
||||
|
||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||
|
||||
/* Render some data and write it to the fifo */
|
||||
if (u->sink->thread_info.state == PA_SINK_RUNNING && pollfd->revents) {
|
||||
ssize_t l;
|
||||
void *p;
|
||||
|
||||
if (u->memchunk.length <= 0)
|
||||
pa_sink_render(u->sink, PIPE_BUF, &u->memchunk);
|
||||
|
||||
pa_assert(u->memchunk.length > 0);
|
||||
|
||||
p = pa_memblock_acquire(u->memchunk.memblock);
|
||||
l = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, &write_type);
|
||||
pa_memblock_release(u->memchunk.memblock);
|
||||
|
||||
pa_assert(l != 0);
|
||||
|
||||
if (l < 0) {
|
||||
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else if (errno != EAGAIN) {
|
||||
pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
u->memchunk.index += l;
|
||||
u->memchunk.length -= l;
|
||||
|
||||
if (u->memchunk.length <= 0) {
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
pa_memchunk_reset(&u->memchunk);
|
||||
}
|
||||
|
||||
pollfd->revents = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
pollfd->events = u->sink->thread_info.state == PA_SINK_RUNNING ? POLLOUT : 0;
|
||||
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (ret == 0)
|
||||
goto finish;
|
||||
|
||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||
|
||||
if (pollfd->revents & ~POLLOUT) {
|
||||
pa_log("FIFO shutdown.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
/* If this was no regular exit from the loop we have to continue
|
||||
* processing messages until we received PA_MESSAGE_SHUTDOWN */
|
||||
pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
|
||||
pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
|
||||
|
||||
finish:
|
||||
pa_log_debug("Thread shutting down");
|
||||
}
|
||||
|
||||
static void notify_cb(pa_sink*s) {
|
||||
struct userdata *u = s->userdata;
|
||||
assert(s && u);
|
||||
|
||||
if (pa_iochannel_is_writable(u->io))
|
||||
u->core->mainloop->defer_enable(u->defer_event, 1);
|
||||
}
|
||||
|
||||
static pa_usec_t get_latency_cb(pa_sink *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
assert(s && u);
|
||||
|
||||
return u->memchunk.memblock ? pa_bytes_to_usec(u->memchunk.length, &s->sample_spec) : 0;
|
||||
}
|
||||
|
||||
static void defer_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event*e, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
assert(u);
|
||||
do_write(u);
|
||||
}
|
||||
|
||||
static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
|
||||
struct userdata *u = userdata;
|
||||
assert(u);
|
||||
do_write(u);
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
struct userdata *u = NULL;
|
||||
int pa__init(pa_module*m) {
|
||||
struct userdata *u;
|
||||
struct stat st;
|
||||
const char *p;
|
||||
int fd = -1;
|
||||
pa_sample_spec ss;
|
||||
pa_channel_map map;
|
||||
pa_modargs *ma = NULL;
|
||||
pa_modargs *ma;
|
||||
char *t;
|
||||
struct pollfd *pollfd;
|
||||
|
||||
assert(c && m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("failed to parse module arguments");
|
||||
pa_log("Failed to parse module arguments.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ss = c->default_sample_spec;
|
||||
ss = m->core->default_sample_spec;
|
||||
if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
|
||||
pa_log("invalid sample format specification");
|
||||
pa_log("Invalid sample format specification or channel map");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777);
|
||||
u = pa_xnew0(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
m->userdata = u;
|
||||
pa_memchunk_reset(&u->memchunk);
|
||||
pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
|
||||
u->rtpoll = pa_rtpoll_new();
|
||||
pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
|
||||
|
||||
if ((fd = open(p, O_RDWR)) < 0) {
|
||||
pa_log("open('%s'): %s", p, pa_cstrerror(errno));
|
||||
u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
|
||||
|
||||
mkfifo(u->filename, 0666);
|
||||
if ((u->fd = open(u->filename, O_RDWR|O_NOCTTY)) < 0) {
|
||||
pa_log("open('%s'): %s", u->filename, pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pa_fd_set_cloexec(fd, 1);
|
||||
pa_make_fd_cloexec(u->fd);
|
||||
pa_make_fd_nonblock(u->fd);
|
||||
|
||||
if (fstat(fd, &st) < 0) {
|
||||
pa_log("fstat('%s'): %s", p, pa_cstrerror(errno));
|
||||
if (fstat(u->fd, &st) < 0) {
|
||||
pa_log("fstat('%s'): %s", u->filename, pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!S_ISFIFO(st.st_mode)) {
|
||||
pa_log("'%s' is not a FIFO.", p);
|
||||
pa_log("'%s' is not a FIFO.", u->filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u = pa_xmalloc0(sizeof(struct userdata));
|
||||
u->filename = pa_xstrdup(p);
|
||||
u->core = c;
|
||||
u->module = m;
|
||||
m->userdata = u;
|
||||
|
||||
if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) {
|
||||
pa_log("failed to create sink.");
|
||||
if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) {
|
||||
pa_log("Failed to create sink.");
|
||||
goto fail;
|
||||
}
|
||||
u->sink->notify = notify_cb;
|
||||
u->sink->get_latency = get_latency_cb;
|
||||
|
||||
u->sink->parent.process_msg = sink_process_msg;
|
||||
u->sink->userdata = u;
|
||||
pa_sink_set_owner(u->sink, m);
|
||||
pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Unix FIFO sink '%s'", p));
|
||||
u->sink->flags = PA_SINK_LATENCY;
|
||||
|
||||
pa_sink_set_module(u->sink, m);
|
||||
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
|
||||
pa_sink_set_rtpoll(u->sink, u->rtpoll);
|
||||
pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Unix FIFO sink '%s'", u->filename));
|
||||
pa_xfree(t);
|
||||
|
||||
u->io = pa_iochannel_new(c->mainloop, -1, fd);
|
||||
assert(u->io);
|
||||
pa_iochannel_set_callback(u->io, io_callback, u);
|
||||
u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
|
||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||
pollfd->fd = u->fd;
|
||||
pollfd->events = pollfd->revents = 0;
|
||||
|
||||
u->memchunk.memblock = NULL;
|
||||
u->memchunk.length = 0;
|
||||
if (!(u->thread = pa_thread_new(thread_func, u))) {
|
||||
pa_log("Failed to create thread.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u->defer_event = c->mainloop->defer_new(c->mainloop, defer_callback, u);
|
||||
assert(u->defer_event);
|
||||
c->mainloop->defer_enable(u->defer_event, 0);
|
||||
pa_sink_put(u->sink);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
||||
|
|
@ -220,32 +285,48 @@ fail:
|
|||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
|
||||
pa__done(c, m);
|
||||
pa__done(m);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
assert(c && m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
if (u->sink)
|
||||
pa_sink_unlink(u->sink);
|
||||
|
||||
if (u->thread) {
|
||||
pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
|
||||
pa_thread_free(u->thread);
|
||||
}
|
||||
|
||||
pa_thread_mq_done(&u->thread_mq);
|
||||
|
||||
if (u->sink)
|
||||
pa_sink_unref(u->sink);
|
||||
|
||||
if (u->memchunk.memblock)
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
|
||||
pa_sink_disconnect(u->sink);
|
||||
pa_sink_unref(u->sink);
|
||||
pa_iochannel_free(u->io);
|
||||
u->core->mainloop->defer_free(u->defer_event);
|
||||
if (u->rtpoll_item)
|
||||
pa_rtpoll_item_free(u->rtpoll_item);
|
||||
|
||||
assert(u->filename);
|
||||
unlink(u->filename);
|
||||
pa_xfree(u->filename);
|
||||
if (u->rtpoll)
|
||||
pa_rtpoll_free(u->rtpoll);
|
||||
|
||||
if (u->filename) {
|
||||
unlink(u->filename);
|
||||
pa_xfree(u->filename);
|
||||
}
|
||||
|
||||
if (u->fd >= 0)
|
||||
pa_assert_se(pa_close(u->fd) == 0);
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,22 +28,24 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/iochannel.h>
|
||||
#include <pulsecore/source.h>
|
||||
#include <pulsecore/module.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/thread.h>
|
||||
#include <pulsecore/thread-mq.h>
|
||||
#include <pulsecore/rtpoll.h>
|
||||
|
||||
#include "module-pipe-source-symdef.h"
|
||||
|
||||
|
|
@ -58,18 +60,24 @@ PA_MODULE_USAGE(
|
|||
"rate=<sample rate> "
|
||||
"channel_map=<channel map>")
|
||||
|
||||
#define DEFAULT_FIFO_NAME "/tmp/music.input"
|
||||
#define DEFAULT_FILE_NAME "/tmp/music.input"
|
||||
#define DEFAULT_SOURCE_NAME "fifo_input"
|
||||
|
||||
struct userdata {
|
||||
pa_core *core;
|
||||
pa_module *module;
|
||||
pa_source *source;
|
||||
|
||||
pa_thread *thread;
|
||||
pa_thread_mq thread_mq;
|
||||
pa_rtpoll *rtpoll;
|
||||
|
||||
char *filename;
|
||||
int fd;
|
||||
|
||||
pa_source *source;
|
||||
pa_iochannel *io;
|
||||
pa_module *module;
|
||||
pa_memchunk chunk;
|
||||
pa_memchunk memchunk;
|
||||
|
||||
pa_rtpoll_item *rtpoll_item;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
|
|
@ -82,109 +90,168 @@ static const char* const valid_modargs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static void do_read(struct userdata *u) {
|
||||
ssize_t r;
|
||||
pa_memchunk chunk;
|
||||
assert(u);
|
||||
|
||||
if (!pa_iochannel_is_readable(u->io))
|
||||
return;
|
||||
|
||||
pa_module_set_used(u->module, pa_idxset_size(u->source->outputs));
|
||||
|
||||
if (!u->chunk.memblock) {
|
||||
u->chunk.memblock = pa_memblock_new(u->core->mempool, PIPE_BUF);
|
||||
u->chunk.index = chunk.length = 0;
|
||||
}
|
||||
|
||||
assert(u->chunk.memblock && u->chunk.memblock->length > u->chunk.index);
|
||||
if ((r = pa_iochannel_read(u->io, (uint8_t*) u->chunk.memblock->data + u->chunk.index, u->chunk.memblock->length - u->chunk.index)) <= 0) {
|
||||
pa_log("read(): %s", pa_cstrerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
u->chunk.length = r;
|
||||
pa_source_post(u->source, &u->chunk);
|
||||
u->chunk.index += r;
|
||||
|
||||
if (u->chunk.index >= u->chunk.memblock->length) {
|
||||
u->chunk.index = u->chunk.length = 0;
|
||||
pa_memblock_unref(u->chunk.memblock);
|
||||
u->chunk.memblock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
|
||||
static void thread_func(void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
assert(u);
|
||||
do_read(u);
|
||||
int read_type = 0;
|
||||
|
||||
pa_assert(u);
|
||||
|
||||
pa_log_debug("Thread starting up");
|
||||
|
||||
pa_thread_mq_install(&u->thread_mq);
|
||||
pa_rtpoll_install(u->rtpoll);
|
||||
|
||||
for (;;) {
|
||||
int ret;
|
||||
struct pollfd *pollfd;
|
||||
|
||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||
|
||||
/* Try to read some data and pass it on to the source driver */
|
||||
if (u->source->thread_info.state == PA_SOURCE_RUNNING && pollfd->revents) {
|
||||
ssize_t l;
|
||||
void *p;
|
||||
|
||||
if (!u->memchunk.memblock) {
|
||||
u->memchunk.memblock = pa_memblock_new(u->core->mempool, PIPE_BUF);
|
||||
u->memchunk.index = u->memchunk.length = 0;
|
||||
}
|
||||
|
||||
pa_assert(pa_memblock_get_length(u->memchunk.memblock) > u->memchunk.index);
|
||||
|
||||
p = pa_memblock_acquire(u->memchunk.memblock);
|
||||
l = pa_read(u->fd, (uint8_t*) p + u->memchunk.index, pa_memblock_get_length(u->memchunk.memblock) - u->memchunk.index, &read_type);
|
||||
pa_memblock_release(u->memchunk.memblock);
|
||||
|
||||
pa_assert(l != 0); /* EOF cannot happen, since we opened the fifo for both reading and writing */
|
||||
|
||||
if (l < 0) {
|
||||
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else if (errno != EAGAIN) {
|
||||
pa_log("Faile to read data from FIFO: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
u->memchunk.length = l;
|
||||
pa_source_post(u->source, &u->memchunk);
|
||||
u->memchunk.index += l;
|
||||
|
||||
if (u->memchunk.index >= pa_memblock_get_length(u->memchunk.memblock)) {
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
pa_memchunk_reset(&u->memchunk);
|
||||
}
|
||||
|
||||
pollfd->revents = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
pollfd->events = u->source->thread_info.state == PA_SOURCE_RUNNING ? POLLIN : 0;
|
||||
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (ret == 0)
|
||||
goto finish;
|
||||
|
||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||
if (pollfd->revents & ~POLLIN) {
|
||||
pa_log("FIFO shutdown.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
/* If this was no regular exit from the loop we have to continue
|
||||
* processing messages until we received PA_MESSAGE_SHUTDOWN */
|
||||
pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
|
||||
pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
|
||||
|
||||
finish:
|
||||
pa_log_debug("Thread shutting down");
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
struct userdata *u = NULL;
|
||||
int pa__init(pa_module*m) {
|
||||
struct userdata *u;
|
||||
struct stat st;
|
||||
const char *p;
|
||||
int fd = -1;
|
||||
pa_sample_spec ss;
|
||||
pa_channel_map map;
|
||||
pa_modargs *ma = NULL;
|
||||
pa_modargs *ma;
|
||||
char *t;
|
||||
struct pollfd *pollfd;
|
||||
|
||||
assert(c && m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("failed to parse module arguments");
|
||||
pa_log("failed to parse module arguments.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ss = c->default_sample_spec;
|
||||
ss = m->core->default_sample_spec;
|
||||
if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
|
||||
pa_log("invalid sample format specification or channel map");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777);
|
||||
u = pa_xnew0(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
m->userdata = u;
|
||||
pa_memchunk_reset(&u->memchunk);
|
||||
pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
|
||||
u->rtpoll = pa_rtpoll_new();
|
||||
pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
|
||||
|
||||
if ((fd = open(p, O_RDWR)) < 0) {
|
||||
pa_log("open('%s'): %s", p, pa_cstrerror(errno));
|
||||
u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
|
||||
|
||||
mkfifo(u->filename, 0666);
|
||||
if ((u->fd = open(u->filename, O_RDWR|O_NOCTTY)) < 0) {
|
||||
pa_log("open('%s'): %s", u->filename, pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pa_fd_set_cloexec(fd, 1);
|
||||
pa_make_fd_cloexec(u->fd);
|
||||
pa_make_fd_nonblock(u->fd);
|
||||
|
||||
if (fstat(fd, &st) < 0) {
|
||||
pa_log("fstat('%s'): %s", p, pa_cstrerror(errno));
|
||||
if (fstat(u->fd, &st) < 0) {
|
||||
pa_log("fstat('%s'): %s",u->filename, pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!S_ISFIFO(st.st_mode)) {
|
||||
pa_log("'%s' is not a FIFO.", p);
|
||||
pa_log("'%s' is not a FIFO.", u->filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u = pa_xmalloc0(sizeof(struct userdata));
|
||||
|
||||
u->filename = pa_xstrdup(p);
|
||||
u->core = c;
|
||||
|
||||
if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) {
|
||||
pa_log("failed to create source.");
|
||||
if (!(u->source = pa_source_new(m->core, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) {
|
||||
pa_log("Failed to create source.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u->source->userdata = u;
|
||||
pa_source_set_owner(u->source, m);
|
||||
pa_source_set_description(u->source, t = pa_sprintf_malloc("Unix FIFO source '%s'", p));
|
||||
u->source->flags = 0;
|
||||
|
||||
pa_source_set_module(u->source, m);
|
||||
pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
|
||||
pa_source_set_rtpoll(u->source, u->rtpoll);
|
||||
pa_source_set_description(u->source, t = pa_sprintf_malloc("Unix FIFO source '%s'", u->filename));
|
||||
pa_xfree(t);
|
||||
|
||||
u->io = pa_iochannel_new(c->mainloop, fd, -1);
|
||||
assert(u->io);
|
||||
pa_iochannel_set_callback(u->io, io_callback, u);
|
||||
u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
|
||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||
pollfd->fd = u->fd;
|
||||
pollfd->events = pollfd->revents = 0;
|
||||
|
||||
u->chunk.memblock = NULL;
|
||||
u->chunk.index = u->chunk.length = 0;
|
||||
if (!(u->thread = pa_thread_new(thread_func, u))) {
|
||||
pa_log("Failed to create thread.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u->module = m;
|
||||
m->userdata = u;
|
||||
pa_source_put(u->source);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
||||
|
|
@ -194,31 +261,48 @@ fail:
|
|||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
|
||||
pa__done(c, m);
|
||||
pa__done(m);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
assert(c && m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
if (u->chunk.memblock)
|
||||
pa_memblock_unref(u->chunk.memblock);
|
||||
if (u->source)
|
||||
pa_source_unlink(u->source);
|
||||
|
||||
pa_source_disconnect(u->source);
|
||||
pa_source_unref(u->source);
|
||||
pa_iochannel_free(u->io);
|
||||
if (u->thread) {
|
||||
pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
|
||||
pa_thread_free(u->thread);
|
||||
}
|
||||
|
||||
assert(u->filename);
|
||||
unlink(u->filename);
|
||||
pa_xfree(u->filename);
|
||||
pa_thread_mq_done(&u->thread_mq);
|
||||
|
||||
if (u->source)
|
||||
pa_source_unref(u->source);
|
||||
|
||||
if (u->memchunk.memblock)
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
|
||||
if (u->rtpoll_item)
|
||||
pa_rtpoll_item_free(u->rtpoll_item);
|
||||
|
||||
if (u->rtpoll)
|
||||
pa_rtpoll_free(u->rtpoll);
|
||||
|
||||
if (u->filename) {
|
||||
unlink(u->filename);
|
||||
pa_xfree(u->filename);
|
||||
}
|
||||
|
||||
if (u->fd >= 0)
|
||||
pa_assert_se(pa_close(u->fd) == 0);
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
|
@ -43,10 +42,9 @@
|
|||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "../pulsecore/winsock.h"
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/winsock.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/module.h>
|
||||
#include <pulsecore/socket-server.h>
|
||||
|
|
@ -154,7 +152,6 @@
|
|||
#define protocol_free pa_protocol_esound_free
|
||||
#define TCPWRAP_SERVICE "esound"
|
||||
#define IPV4_PORT ESD_DEFAULT_PORT
|
||||
#define UNIX_SOCKET ESD_UNIX_SOCKET_NAME
|
||||
#define MODULE_ARGUMENTS_COMMON "sink", "source", "auth-anonymous", "cookie",
|
||||
#ifdef USE_TCP_SOCKETS
|
||||
#include "module-esound-protocol-tcp-symdef.h"
|
||||
|
|
@ -205,10 +202,9 @@ struct userdata {
|
|||
#endif
|
||||
};
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
pa_modargs *ma = NULL;
|
||||
int ret = -1;
|
||||
|
||||
struct userdata *u = NULL;
|
||||
|
||||
#if defined(USE_TCP_SOCKETS)
|
||||
|
|
@ -219,9 +215,13 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
pa_socket_server *s;
|
||||
int r;
|
||||
char tmp[PATH_MAX];
|
||||
|
||||
#if defined(USE_PROTOCOL_ESOUND)
|
||||
char tmp2[PATH_MAX];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
assert(c && m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments");
|
||||
|
|
@ -239,22 +239,22 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
listen_on = pa_modargs_get_value(ma, "listen", NULL);
|
||||
|
||||
if (listen_on) {
|
||||
s_ipv6 = pa_socket_server_new_ipv6_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE);
|
||||
s_ipv4 = pa_socket_server_new_ipv4_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE);
|
||||
s_ipv6 = pa_socket_server_new_ipv6_string(m->core->mainloop, listen_on, port, TCPWRAP_SERVICE);
|
||||
s_ipv4 = pa_socket_server_new_ipv4_string(m->core->mainloop, listen_on, port, TCPWRAP_SERVICE);
|
||||
} else {
|
||||
s_ipv6 = pa_socket_server_new_ipv6_any(c->mainloop, port, TCPWRAP_SERVICE);
|
||||
s_ipv4 = pa_socket_server_new_ipv4_any(c->mainloop, port, TCPWRAP_SERVICE);
|
||||
s_ipv6 = pa_socket_server_new_ipv6_any(m->core->mainloop, port, TCPWRAP_SERVICE);
|
||||
s_ipv4 = pa_socket_server_new_ipv4_any(m->core->mainloop, port, TCPWRAP_SERVICE);
|
||||
}
|
||||
|
||||
if (!s_ipv4 && !s_ipv6)
|
||||
goto fail;
|
||||
|
||||
if (s_ipv4)
|
||||
if (!(u->protocol_ipv4 = protocol_new(c, s_ipv4, m, ma)))
|
||||
if (!(u->protocol_ipv4 = protocol_new(m->core, s_ipv4, m, ma)))
|
||||
pa_socket_server_unref(s_ipv4);
|
||||
|
||||
if (s_ipv6)
|
||||
if (!(u->protocol_ipv6 = protocol_new(c, s_ipv6, m, ma)))
|
||||
if (!(u->protocol_ipv6 = protocol_new(m->core, s_ipv6, m, ma)))
|
||||
pa_socket_server_unref(s_ipv6);
|
||||
|
||||
if (!u->protocol_ipv4 && !u->protocol_ipv6)
|
||||
|
|
@ -262,18 +262,23 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
|
||||
#else
|
||||
|
||||
pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET), tmp, sizeof(tmp));
|
||||
u->socket_path = pa_xstrdup(tmp);
|
||||
|
||||
#if defined(USE_PROTOCOL_ESOUND)
|
||||
|
||||
snprintf(tmp2, sizeof(tmp2), "/tmp/.esd-%lu/socket", (unsigned long) getuid());
|
||||
pa_runtime_path(pa_modargs_get_value(ma, "socket", tmp2), tmp, sizeof(tmp));
|
||||
u->socket_path = pa_xstrdup(tmp);
|
||||
|
||||
/* This socket doesn't reside in our own runtime dir but in
|
||||
* /tmp/.esd/, hence we have to create the dir first */
|
||||
|
||||
if (pa_make_secure_parent_dir(u->socket_path, c->is_system_instance ? 0755 : 0700, (uid_t)-1, (gid_t)-1) < 0) {
|
||||
if (pa_make_secure_parent_dir(u->socket_path, m->core->is_system_instance ? 0755 : 0700, (uid_t)-1, (gid_t)-1) < 0) {
|
||||
pa_log("Failed to create socket directory '%s': %s\n", u->socket_path, pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#else
|
||||
pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET), tmp, sizeof(tmp));
|
||||
u->socket_path = pa_xstrdup(tmp);
|
||||
#endif
|
||||
|
||||
if ((r = pa_unix_socket_remove_stale(tmp)) < 0) {
|
||||
|
|
@ -284,10 +289,10 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
if (r)
|
||||
pa_log("Removed stale UNIX socket '%s'.", tmp);
|
||||
|
||||
if (!(s = pa_socket_server_new_unix(c->mainloop, tmp)))
|
||||
if (!(s = pa_socket_server_new_unix(m->core->mainloop, tmp)))
|
||||
goto fail;
|
||||
|
||||
if (!(u->protocol_unix = protocol_new(c, s, m, ma)))
|
||||
if (!(u->protocol_unix = protocol_new(m->core, s, m, ma)))
|
||||
goto fail;
|
||||
|
||||
#endif
|
||||
|
|
@ -333,11 +338,10 @@ fail:
|
|||
goto finish;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
u = m->userdata;
|
||||
|
||||
|
|
@ -358,7 +362,6 @@ void pa__done(pa_core *c, pa_module*m) {
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
pa_xfree(u->socket_path);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
334
src/modules/module-remap-sink.c
Normal file
334
src/modules/module-remap-sink.c
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
/* $Id$ */
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2004-2006 Lennart Poettering
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/namereg.h>
|
||||
#include <pulsecore/sink.h>
|
||||
#include <pulsecore/module.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/thread.h>
|
||||
#include <pulsecore/thread-mq.h>
|
||||
#include <pulsecore/rtpoll.h>
|
||||
|
||||
#include "module-remap-sink-symdef.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Lennart Poettering")
|
||||
PA_MODULE_DESCRIPTION("Virtual channel remapping sink")
|
||||
PA_MODULE_VERSION(PACKAGE_VERSION)
|
||||
PA_MODULE_USAGE(
|
||||
"sink_name=<name for the sink> "
|
||||
"master=<name of sink to remap> "
|
||||
"master_channel_map=<channel map> "
|
||||
"format=<sample format> "
|
||||
"channels=<number of channels> "
|
||||
"rate=<sample rate> "
|
||||
"channel_map=<channel map>")
|
||||
|
||||
struct userdata {
|
||||
pa_core *core;
|
||||
pa_module *module;
|
||||
|
||||
pa_sink *sink, *master;
|
||||
pa_sink_input *sink_input;
|
||||
|
||||
pa_memchunk memchunk;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"sink_name",
|
||||
"master",
|
||||
"master_channel_map",
|
||||
"rate",
|
||||
"format",
|
||||
"channels",
|
||||
"channel_map",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
struct userdata *u = PA_SINK(o)->userdata;
|
||||
|
||||
switch (code) {
|
||||
|
||||
case PA_SINK_MESSAGE_GET_LATENCY: {
|
||||
pa_usec_t usec = 0;
|
||||
|
||||
if (PA_MSGOBJECT(u->master)->process_msg(PA_MSGOBJECT(u->master), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
|
||||
usec = 0;
|
||||
|
||||
*((pa_usec_t*) data) = usec + pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return pa_sink_process_msg(o, code, data, offset, chunk);
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_sink_assert_ref(s);
|
||||
pa_assert_se(u = s->userdata);
|
||||
|
||||
if (PA_SINK_LINKED(state) && u->sink_input && PA_SINK_INPUT_LINKED(pa_sink_input_get_state(u->sink_input)))
|
||||
pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
struct userdata *u = PA_SINK_INPUT(o)->userdata;
|
||||
|
||||
switch (code) {
|
||||
case PA_SINK_INPUT_MESSAGE_GET_LATENCY:
|
||||
*((pa_usec_t*) data) = pa_bytes_to_usec(u->memchunk.length, &u->sink_input->sample_spec);
|
||||
|
||||
/* Fall through, the default handler will add in the extra
|
||||
* latency added by the resampler */
|
||||
break;
|
||||
}
|
||||
|
||||
return pa_sink_input_process_msg(o, code, data, offset, chunk);
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(u = i->userdata);
|
||||
|
||||
if (!u->memchunk.memblock)
|
||||
pa_sink_render(u->sink, length, &u->memchunk);
|
||||
|
||||
pa_assert(u->memchunk.memblock);
|
||||
*chunk = u->memchunk;
|
||||
pa_memblock_ref(chunk->memblock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(u = i->userdata);
|
||||
pa_assert(length > 0);
|
||||
|
||||
if (u->memchunk.memblock) {
|
||||
|
||||
if (length < u->memchunk.length) {
|
||||
u->memchunk.index += length;
|
||||
u->memchunk.length -= length;
|
||||
return;
|
||||
}
|
||||
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
length -= u->memchunk.length;
|
||||
pa_memchunk_reset(&u->memchunk);
|
||||
}
|
||||
|
||||
if (length > 0)
|
||||
pa_sink_skip(u->sink, length);
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static void sink_input_detach_cb(pa_sink_input *i) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(u = i->userdata);
|
||||
|
||||
pa_sink_detach_within_thread(u->sink);
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static void sink_input_attach_cb(pa_sink_input *i) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(u = i->userdata);
|
||||
|
||||
pa_sink_set_asyncmsgq(u->sink, i->sink->asyncmsgq);
|
||||
pa_sink_set_rtpoll(u->sink, i->sink->rtpoll);
|
||||
|
||||
pa_sink_attach_within_thread(u->sink);
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
static void sink_input_kill_cb(pa_sink_input *i) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(u = i->userdata);
|
||||
|
||||
pa_sink_input_unlink(u->sink_input);
|
||||
pa_sink_input_unref(u->sink_input);
|
||||
u->sink_input = NULL;
|
||||
|
||||
pa_sink_unlink(u->sink);
|
||||
pa_sink_unref(u->sink);
|
||||
u->sink = NULL;
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
struct userdata *u;
|
||||
pa_sample_spec ss;
|
||||
pa_channel_map sink_map, stream_map;
|
||||
pa_modargs *ma;
|
||||
char *t;
|
||||
pa_sink *master;
|
||||
pa_sink_input_new_data data;
|
||||
char *default_sink_name = NULL;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK, 1))) {
|
||||
pa_log("Master sink not found");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ss = master->sample_spec;
|
||||
sink_map = master->channel_map;
|
||||
if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &sink_map, PA_CHANNEL_MAP_DEFAULT) < 0) {
|
||||
pa_log("Invalid sample format specification or channel map");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
stream_map = sink_map;
|
||||
if (pa_modargs_get_channel_map(ma, "master_channel_map", &stream_map) < 0) {
|
||||
pa_log("Invalid master hannel map");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (stream_map.channels != ss.channels) {
|
||||
pa_log("Number of channels doesn't match");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u = pa_xnew0(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
m->userdata = u;
|
||||
u->master = master;
|
||||
pa_memchunk_reset(&u->memchunk);
|
||||
|
||||
default_sink_name = pa_sprintf_malloc("%s.remapped", master->name);
|
||||
|
||||
/* Create sink */
|
||||
if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", default_sink_name), 0, &ss, &sink_map))) {
|
||||
pa_log("Failed to create sink.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
u->sink->parent.process_msg = sink_process_msg;
|
||||
u->sink->set_state = sink_set_state;
|
||||
u->sink->userdata = u;
|
||||
u->sink->flags = PA_SINK_LATENCY;
|
||||
|
||||
pa_sink_set_module(u->sink, m);
|
||||
pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Remapped %s", master->description));
|
||||
pa_xfree(t);
|
||||
pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
|
||||
pa_sink_set_rtpoll(u->sink, master->rtpoll);
|
||||
|
||||
/* Create sink input */
|
||||
pa_sink_input_new_data_init(&data);
|
||||
data.sink = u->master;
|
||||
data.driver = __FILE__;
|
||||
data.name = "Remapped Stream";
|
||||
pa_sink_input_new_data_set_sample_spec(&data, &ss);
|
||||
pa_sink_input_new_data_set_channel_map(&data, &stream_map);
|
||||
data.module = m;
|
||||
|
||||
if (!(u->sink_input = pa_sink_input_new(m->core, &data, PA_SINK_INPUT_DONT_MOVE)))
|
||||
goto fail;
|
||||
|
||||
u->sink_input->parent.process_msg = sink_input_process_msg;
|
||||
u->sink_input->peek = sink_input_peek_cb;
|
||||
u->sink_input->drop = sink_input_drop_cb;
|
||||
u->sink_input->kill = sink_input_kill_cb;
|
||||
u->sink_input->attach = sink_input_attach_cb;
|
||||
u->sink_input->detach = sink_input_detach_cb;
|
||||
u->sink_input->userdata = u;
|
||||
|
||||
pa_sink_put(u->sink);
|
||||
pa_sink_input_put(u->sink_input);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
pa_xfree(default_sink_name);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
pa__done(m);
|
||||
|
||||
pa_xfree(default_sink_name);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
if (u->sink_input) {
|
||||
pa_sink_input_unlink(u->sink_input);
|
||||
pa_sink_input_unref(u->sink_input);
|
||||
}
|
||||
|
||||
if (u->sink) {
|
||||
pa_sink_unlink(u->sink);
|
||||
pa_sink_unref(u->sink);
|
||||
}
|
||||
|
||||
if (u->memchunk.memblock)
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
@ -52,20 +52,26 @@ static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* user
|
|||
pa_sink_input *i;
|
||||
pa_sink *target;
|
||||
|
||||
assert(c);
|
||||
assert(sink);
|
||||
pa_assert(c);
|
||||
pa_assert(sink);
|
||||
|
||||
if (!pa_idxset_size(sink->inputs)) {
|
||||
pa_log_debug("No sink inputs to move away.");
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SINK, 0))) {
|
||||
pa_log_info("No evacuation sink found.");
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SINK, 0)) || target == sink) {
|
||||
uint32_t idx;
|
||||
|
||||
assert(target != sink);
|
||||
for (target = pa_idxset_first(c->sinks, &idx); target; target = pa_idxset_next(c->sinks, &idx))
|
||||
if (target != sink)
|
||||
break;
|
||||
|
||||
if (!target) {
|
||||
pa_log_info("No evacuation sink found.");
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
}
|
||||
|
||||
while ((i = pa_idxset_first(sink->inputs, NULL))) {
|
||||
if (pa_sink_input_move_to(i, target, 1) < 0) {
|
||||
|
|
@ -84,20 +90,28 @@ static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void
|
|||
pa_source_output *o;
|
||||
pa_source *target;
|
||||
|
||||
assert(c);
|
||||
assert(source);
|
||||
pa_assert(c);
|
||||
pa_assert(source);
|
||||
|
||||
if (!pa_idxset_size(source->outputs)) {
|
||||
pa_log_debug("No source outputs to move away.");
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SOURCE, 0))) {
|
||||
pa_log_info("No evacuation source found.");
|
||||
return PA_HOOK_OK;
|
||||
if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SOURCE, 0)) || target == source) {
|
||||
uint32_t idx;
|
||||
|
||||
for (target = pa_idxset_first(c->sources, &idx); target; target = pa_idxset_next(c->sources, &idx))
|
||||
if (target != source && !target->monitor_of == !source->monitor_of)
|
||||
break;
|
||||
|
||||
if (!target) {
|
||||
pa_log_info("No evacuation source found.");
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
}
|
||||
|
||||
assert(target != source);
|
||||
pa_assert(target != source);
|
||||
|
||||
while ((o = pa_idxset_first(source->outputs, NULL))) {
|
||||
if (pa_source_output_move_to(o, target) < 0) {
|
||||
|
|
@ -112,12 +126,11 @@ static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void
|
|||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
pa_modargs *ma = NULL;
|
||||
struct userdata *u;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments");
|
||||
|
|
@ -125,18 +138,17 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
}
|
||||
|
||||
m->userdata = u = pa_xnew(struct userdata, 1);
|
||||
u->sink_slot = pa_hook_connect(&c->hook_sink_disconnect, (pa_hook_cb_t) sink_hook_callback, NULL);
|
||||
u->source_slot = pa_hook_connect(&c->hook_source_disconnect, (pa_hook_cb_t) source_hook_callback, NULL);
|
||||
u->sink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], (pa_hook_cb_t) sink_hook_callback, NULL);
|
||||
u->source_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], (pa_hook_cb_t) source_hook_callback, NULL);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!m->userdata)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
|
@ -36,6 +35,7 @@
|
|||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/namereg.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
|
||||
#include "module-sine-symdef.h"
|
||||
|
||||
|
|
@ -58,36 +58,46 @@ static const char* const valid_modargs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
|
||||
static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
|
||||
struct userdata *u;
|
||||
assert(i && chunk && i->userdata);
|
||||
|
||||
pa_assert(i);
|
||||
u = i->userdata;
|
||||
pa_assert(u);
|
||||
pa_assert(chunk);
|
||||
|
||||
chunk->memblock = pa_memblock_ref(u->memblock);
|
||||
chunk->index = u->peek_index;
|
||||
chunk->length = u->memblock->length - u->peek_index;
|
||||
chunk->length = pa_memblock_get_length(u->memblock) - u->peek_index;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
|
||||
static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
|
||||
struct userdata *u;
|
||||
assert(i && chunk && length && i->userdata);
|
||||
u = i->userdata;
|
||||
size_t l;
|
||||
|
||||
assert(chunk->memblock == u->memblock && length <= u->memblock->length-u->peek_index);
|
||||
pa_assert(i);
|
||||
u = i->userdata;
|
||||
pa_assert(u);
|
||||
pa_assert(length > 0);
|
||||
|
||||
u->peek_index += length;
|
||||
|
||||
if (u->peek_index >= u->memblock->length)
|
||||
u->peek_index = 0;
|
||||
l = pa_memblock_get_length(u->memblock);
|
||||
|
||||
while (u->peek_index >= l)
|
||||
u->peek_index -= l;
|
||||
}
|
||||
|
||||
static void sink_input_kill(pa_sink_input *i) {
|
||||
static void sink_input_kill_cb(pa_sink_input *i) {
|
||||
struct userdata *u;
|
||||
assert(i && i->userdata);
|
||||
u = i->userdata;
|
||||
|
||||
pa_sink_input_disconnect(u->sink_input);
|
||||
pa_assert(i);
|
||||
u = i->userdata;
|
||||
pa_assert(u);
|
||||
|
||||
pa_sink_input_unlink(u->sink_input);
|
||||
pa_sink_input_unref(u->sink_input);
|
||||
u->sink_input = NULL;
|
||||
|
||||
|
|
@ -103,14 +113,14 @@ static void calc_sine(float *f, size_t l, float freq) {
|
|||
f[i] = (float) sin((double) i/l*M_PI*2*freq)/2;
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
pa_modargs *ma = NULL;
|
||||
struct userdata *u;
|
||||
pa_sink *sink;
|
||||
const char *sink_name;
|
||||
pa_sample_spec ss;
|
||||
uint32_t frequency;
|
||||
char t[256];
|
||||
void *p;
|
||||
pa_sink_input_new_data data;
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
|
|
@ -118,15 +128,14 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
m->userdata = u = pa_xmalloc(sizeof(struct userdata));
|
||||
u->core = c;
|
||||
m->userdata = u = pa_xnew0(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
u->sink_input = NULL;
|
||||
u->memblock = NULL;
|
||||
u->peek_index = 0;
|
||||
|
||||
sink_name = pa_modargs_get_value(ma, "sink", NULL);
|
||||
|
||||
if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK, 1))) {
|
||||
if (!(sink = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink", NULL), PA_NAMEREG_SINK, 1))) {
|
||||
pa_log("No such sink.");
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -141,10 +150,12 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
u->memblock = pa_memblock_new(c->mempool, pa_bytes_per_second(&ss));
|
||||
calc_sine(u->memblock->data, u->memblock->length, frequency);
|
||||
u->memblock = pa_memblock_new(m->core->mempool, pa_bytes_per_second(&ss));
|
||||
p = pa_memblock_acquire(u->memblock);
|
||||
calc_sine(p, pa_memblock_get_length(u->memblock), frequency);
|
||||
pa_memblock_release(u->memblock);
|
||||
|
||||
snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency);
|
||||
pa_snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency);
|
||||
|
||||
pa_sink_input_new_data_init(&data);
|
||||
data.sink = sink;
|
||||
|
|
@ -153,15 +164,15 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
pa_sink_input_new_data_set_sample_spec(&data, &ss);
|
||||
data.module = m;
|
||||
|
||||
if (!(u->sink_input = pa_sink_input_new(c, &data, 0)))
|
||||
if (!(u->sink_input = pa_sink_input_new(m->core, &data, 0)))
|
||||
goto fail;
|
||||
|
||||
u->sink_input->peek = sink_input_peek;
|
||||
u->sink_input->drop = sink_input_drop;
|
||||
u->sink_input->kill = sink_input_kill;
|
||||
u->sink_input->peek = sink_input_peek_cb;
|
||||
u->sink_input->drop = sink_input_drop_cb;
|
||||
u->sink_input->kill = sink_input_kill_cb;
|
||||
u->sink_input->userdata = u;
|
||||
|
||||
u->peek_index = 0;
|
||||
pa_sink_input_put(u->sink_input);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
return 0;
|
||||
|
|
@ -170,24 +181,26 @@ fail:
|
|||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
pa__done(c, m);
|
||||
pa__done(m);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
struct userdata *u = m->userdata;
|
||||
assert(c && m);
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
|
||||
if (!u)
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
if (u->sink_input) {
|
||||
pa_sink_input_disconnect(u->sink_input);
|
||||
pa_sink_input_unlink(u->sink_input);
|
||||
pa_sink_input_unref(u->sink_input);
|
||||
}
|
||||
|
||||
if (u->memblock)
|
||||
pa_memblock_unref(u->memblock);
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2006 Lennart Poettering
|
||||
Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
||||
Copyright 2006-2007 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
|
||||
|
|
@ -57,6 +57,9 @@
|
|||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/thread-mq.h>
|
||||
#include <pulsecore/rtpoll.h>
|
||||
#include <pulsecore/thread.h>
|
||||
|
||||
#include "module-solaris-symdef.h"
|
||||
|
||||
|
|
@ -75,12 +78,14 @@ PA_MODULE_USAGE(
|
|||
"channel_map=<channel map>")
|
||||
|
||||
struct userdata {
|
||||
pa_core *core;
|
||||
pa_sink *sink;
|
||||
pa_source *source;
|
||||
pa_iochannel *io;
|
||||
pa_core *core;
|
||||
pa_time_event *timer;
|
||||
pa_usec_t poll_timeout;
|
||||
|
||||
pa_thread *thread;
|
||||
pa_thread_mq thread_mq;
|
||||
pa_rtpoll *rtpoll;
|
||||
|
||||
pa_signal_event *sig;
|
||||
|
||||
pa_memchunk memchunk;
|
||||
|
|
@ -90,9 +95,9 @@ struct userdata {
|
|||
uint32_t frame_size;
|
||||
uint32_t buffer_size;
|
||||
unsigned int written_bytes, read_bytes;
|
||||
int sink_underflow;
|
||||
|
||||
int fd;
|
||||
pa_rtpoll_item *rtpoll_item;
|
||||
pa_module *module;
|
||||
};
|
||||
|
||||
|
|
@ -114,309 +119,357 @@ static const char* const valid_modargs[] = {
|
|||
#define DEFAULT_SOURCE_NAME "solaris_input"
|
||||
#define DEFAULT_DEVICE "/dev/audio"
|
||||
|
||||
#define CHUNK_SIZE 2048
|
||||
|
||||
static void update_usage(struct userdata *u) {
|
||||
pa_module_set_used(u->module,
|
||||
(u->sink ? pa_sink_used_by(u->sink) : 0) +
|
||||
(u->source ? pa_source_used_by(u->source) : 0));
|
||||
}
|
||||
|
||||
static void do_write(struct userdata *u) {
|
||||
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
struct userdata *u = PA_SINK(o)->userdata;
|
||||
int err;
|
||||
audio_info_t info;
|
||||
int err;
|
||||
size_t len;
|
||||
ssize_t r;
|
||||
|
||||
assert(u);
|
||||
switch (code) {
|
||||
case PA_SINK_MESSAGE_GET_LATENCY: {
|
||||
pa_usec_t r = 0;
|
||||
|
||||
/* We cannot check pa_iochannel_is_writable() because of our buffer hack */
|
||||
if (!u->sink)
|
||||
return;
|
||||
if (u->fd >= 0) {
|
||||
|
||||
update_usage(u);
|
||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||
pa_assert(err >= 0);
|
||||
|
||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||
assert(err >= 0);
|
||||
r += pa_bytes_to_usec(u->written_bytes, &PA_SINK(o)->sample_spec);
|
||||
r -= pa_bytes_to_usec(info.play.samples * u->frame_size, &PA_SINK(o)->sample_spec);
|
||||
|
||||
/*
|
||||
* Since we cannot modify the size of the output buffer we fake it
|
||||
* by not filling it more than u->buffer_size.
|
||||
*/
|
||||
len = u->buffer_size;
|
||||
len -= u->written_bytes - (info.play.samples * u->frame_size);
|
||||
|
||||
/* The sample counter can sometimes go backwards :( */
|
||||
if (len > u->buffer_size)
|
||||
len = 0;
|
||||
|
||||
if (!u->sink_underflow && (len == u->buffer_size))
|
||||
pa_log_debug("Solaris buffer underflow!");
|
||||
|
||||
len -= len % u->frame_size;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
if (!u->memchunk.length) {
|
||||
if (pa_sink_render(u->sink, len, &u->memchunk) < 0) {
|
||||
u->sink_underflow = 1;
|
||||
return;
|
||||
if (u->memchunk.memblock)
|
||||
r += pa_bytes_to_usec(u->memchunk.length, &PA_SINK(o)->sample_spec);
|
||||
}
|
||||
|
||||
*((pa_usec_t*) data) = r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u->sink_underflow = 0;
|
||||
case PA_SINK_MESSAGE_SET_VOLUME:
|
||||
if (u->fd >= 0) {
|
||||
AUDIO_INITINFO(&info);
|
||||
|
||||
assert(u->memchunk.memblock);
|
||||
assert(u->memchunk.memblock->data);
|
||||
assert(u->memchunk.length);
|
||||
info.play.gain = pa_cvolume_avg((pa_cvolume*)data) * AUDIO_MAX_GAIN / PA_VOLUME_NORM;
|
||||
assert(info.play.gain <= AUDIO_MAX_GAIN);
|
||||
|
||||
if (u->memchunk.length < len) {
|
||||
len = u->memchunk.length;
|
||||
len -= len % u->frame_size;
|
||||
assert(len);
|
||||
if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) {
|
||||
if (errno == EINVAL)
|
||||
pa_log("AUDIO_SETINFO: Unsupported volume.");
|
||||
else
|
||||
pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PA_SINK_MESSAGE_GET_VOLUME:
|
||||
if (u->fd >= 0) {
|
||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||
assert(err >= 0);
|
||||
|
||||
pa_cvolume_set((pa_cvolume*) data, ((pa_cvolume*) data)->channels,
|
||||
info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case PA_SINK_MESSAGE_SET_MUTE:
|
||||
if (u->fd >= 0) {
|
||||
AUDIO_INITINFO(&info);
|
||||
|
||||
info.output_muted = !!PA_PTR_TO_UINT(data);
|
||||
|
||||
if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0)
|
||||
pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case PA_SINK_MESSAGE_GET_MUTE:
|
||||
if (u->fd >= 0) {
|
||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||
pa_assert(err >= 0);
|
||||
|
||||
*(int*)data = !!info.output_muted;
|
||||
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ((r = pa_iochannel_write(u->io,
|
||||
(uint8_t*) u->memchunk.memblock->data + u->memchunk.index, len)) < 0) {
|
||||
pa_log("write() failed: %s", pa_cstrerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
assert(r % u->frame_size == 0);
|
||||
|
||||
u->memchunk.index += r;
|
||||
u->memchunk.length -= r;
|
||||
|
||||
if (u->memchunk.length <= 0) {
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
u->memchunk.memblock = NULL;
|
||||
}
|
||||
|
||||
u->written_bytes += r;
|
||||
return pa_sink_process_msg(o, code, data, offset, chunk);
|
||||
}
|
||||
|
||||
static void do_read(struct userdata *u) {
|
||||
pa_memchunk memchunk;
|
||||
static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
struct userdata *u = PA_SOURCE(o)->userdata;
|
||||
int err;
|
||||
size_t l;
|
||||
ssize_t r;
|
||||
assert(u);
|
||||
audio_info_t info;
|
||||
|
||||
if (!u->source || !pa_iochannel_is_readable(u->io))
|
||||
return;
|
||||
switch (code) {
|
||||
case PA_SOURCE_MESSAGE_GET_LATENCY: {
|
||||
pa_usec_t r = 0;
|
||||
|
||||
update_usage(u);
|
||||
if (u->fd) {
|
||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||
pa_assert(err >= 0);
|
||||
|
||||
err = ioctl(u->fd, I_NREAD, &l);
|
||||
assert(err >= 0);
|
||||
r += pa_bytes_to_usec(info.record.samples * u->frame_size, &PA_SOURCE(o)->sample_spec);
|
||||
r -= pa_bytes_to_usec(u->read_bytes, &PA_SOURCE(o)->sample_spec);
|
||||
}
|
||||
|
||||
/* This is to make sure it fits in the memory pool. Also, a page
|
||||
should be the most efficient transfer size. */
|
||||
if (l > u->page_size)
|
||||
l = u->page_size;
|
||||
*((pa_usec_t*) data) = r;
|
||||
|
||||
memchunk.memblock = pa_memblock_new(u->core->mempool, l);
|
||||
assert(memchunk.memblock);
|
||||
if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) {
|
||||
pa_memblock_unref(memchunk.memblock);
|
||||
if (errno != EAGAIN)
|
||||
pa_log("read() failed: %s", pa_cstrerror(errno));
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case PA_SOURCE_MESSAGE_SET_VOLUME:
|
||||
if (u->fd >= 0) {
|
||||
AUDIO_INITINFO(&info);
|
||||
|
||||
info.record.gain = pa_cvolume_avg((pa_cvolume*) data) * AUDIO_MAX_GAIN / PA_VOLUME_NORM;
|
||||
assert(info.record.gain <= AUDIO_MAX_GAIN);
|
||||
|
||||
if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) {
|
||||
if (errno == EINVAL)
|
||||
pa_log("AUDIO_SETINFO: Unsupported volume.");
|
||||
else
|
||||
pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PA_SOURCE_MESSAGE_GET_VOLUME:
|
||||
if (u->fd >= 0) {
|
||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||
pa_assert(err >= 0);
|
||||
|
||||
pa_cvolume_set((pa_cvolume*) data, ((pa_cvolume*) data)->channels,
|
||||
info.record.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
assert(r <= (ssize_t) memchunk.memblock->length);
|
||||
memchunk.length = memchunk.memblock->length = r;
|
||||
memchunk.index = 0;
|
||||
|
||||
pa_source_post(u->source, &memchunk);
|
||||
pa_memblock_unref(memchunk.memblock);
|
||||
|
||||
u->read_bytes += r;
|
||||
return pa_source_process_msg(o, code, data, offset, chunk);
|
||||
}
|
||||
|
||||
static void io_callback(pa_iochannel *io, void*userdata) {
|
||||
struct userdata *u = userdata;
|
||||
assert(u);
|
||||
do_write(u);
|
||||
do_read(u);
|
||||
static void clear_underflow(struct userdata *u)
|
||||
{
|
||||
audio_info_t info;
|
||||
|
||||
AUDIO_INITINFO(&info);
|
||||
|
||||
info.play.error = 0;
|
||||
|
||||
if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0)
|
||||
pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
|
||||
}
|
||||
|
||||
static void timer_cb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) {
|
||||
static void clear_overflow(struct userdata *u)
|
||||
{
|
||||
audio_info_t info;
|
||||
|
||||
AUDIO_INITINFO(&info);
|
||||
|
||||
info.record.error = 0;
|
||||
|
||||
if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0)
|
||||
pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
|
||||
}
|
||||
|
||||
static void thread_func(void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
struct timeval ntv;
|
||||
unsigned short revents = 0;
|
||||
int ret;
|
||||
|
||||
assert(u);
|
||||
pa_assert(u);
|
||||
|
||||
do_write(u);
|
||||
pa_log_debug("Thread starting up");
|
||||
|
||||
pa_gettimeofday(&ntv);
|
||||
pa_timeval_add(&ntv, u->poll_timeout);
|
||||
if (u->core->high_priority)
|
||||
pa_make_realtime();
|
||||
|
||||
a->time_restart(e, &ntv);
|
||||
pa_thread_mq_install(&u->thread_mq);
|
||||
pa_rtpoll_install(u->rtpoll);
|
||||
|
||||
for (;;) {
|
||||
/* Render some data and write it to the dsp */
|
||||
|
||||
if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state)) {
|
||||
audio_info_t info;
|
||||
int err;
|
||||
size_t len;
|
||||
|
||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||
pa_assert(err >= 0);
|
||||
|
||||
/*
|
||||
* Since we cannot modify the size of the output buffer we fake it
|
||||
* by not filling it more than u->buffer_size.
|
||||
*/
|
||||
len = u->buffer_size;
|
||||
len -= u->written_bytes - (info.play.samples * u->frame_size);
|
||||
|
||||
/* The sample counter can sometimes go backwards :( */
|
||||
if (len > u->buffer_size)
|
||||
len = 0;
|
||||
|
||||
if (info.play.error) {
|
||||
pa_log_debug("Solaris buffer underflow!");
|
||||
clear_underflow(u);
|
||||
}
|
||||
|
||||
len -= len % u->frame_size;
|
||||
|
||||
while (len) {
|
||||
void *p;
|
||||
ssize_t r;
|
||||
|
||||
if (!u->memchunk.length)
|
||||
pa_sink_render(u->sink, len, &u->memchunk);
|
||||
|
||||
pa_assert(u->memchunk.length);
|
||||
|
||||
p = pa_memblock_acquire(u->memchunk.memblock);
|
||||
r = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, NULL);
|
||||
pa_memblock_release(u->memchunk.memblock);
|
||||
|
||||
if (r < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else if (errno != EAGAIN) {
|
||||
pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
pa_assert(r % u->frame_size == 0);
|
||||
|
||||
u->memchunk.index += r;
|
||||
u->memchunk.length -= r;
|
||||
|
||||
if (u->memchunk.length <= 0) {
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
pa_memchunk_reset(&u->memchunk);
|
||||
}
|
||||
|
||||
len -= r;
|
||||
u->written_bytes += r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to read some data and pass it on to the source driver */
|
||||
|
||||
if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state) && ((revents & POLLIN))) {
|
||||
pa_memchunk memchunk;
|
||||
int err;
|
||||
size_t l;
|
||||
void *p;
|
||||
ssize_t r;
|
||||
audio_info_t info;
|
||||
|
||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||
pa_assert(err >= 0);
|
||||
|
||||
if (info.record.error) {
|
||||
pa_log_debug("Solaris buffer overflow!");
|
||||
clear_overflow(u);
|
||||
}
|
||||
|
||||
err = ioctl(u->fd, I_NREAD, &l);
|
||||
pa_assert(err >= 0);
|
||||
|
||||
if (l > 0) {
|
||||
/* This is to make sure it fits in the memory pool. Also, a page
|
||||
should be the most efficient transfer size. */
|
||||
if (l > u->page_size)
|
||||
l = u->page_size;
|
||||
|
||||
memchunk.memblock = pa_memblock_new(u->core->mempool, l);
|
||||
pa_assert(memchunk.memblock);
|
||||
|
||||
p = pa_memblock_acquire(memchunk.memblock);
|
||||
r = pa_read(u->fd, p, l, NULL);
|
||||
pa_memblock_release(memchunk.memblock);
|
||||
|
||||
if (r < 0) {
|
||||
pa_memblock_unref(memchunk.memblock);
|
||||
if (errno != EAGAIN) {
|
||||
pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
memchunk.index = 0;
|
||||
memchunk.length = r;
|
||||
|
||||
pa_source_post(u->source, &memchunk);
|
||||
pa_memblock_unref(memchunk.memblock);
|
||||
|
||||
u->read_bytes += r;
|
||||
|
||||
revents &= ~POLLIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (u->fd >= 0) {
|
||||
struct pollfd *pollfd;
|
||||
|
||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||
pollfd->events =
|
||||
((u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) ? POLLIN : 0);
|
||||
}
|
||||
|
||||
/* Hmm, nothing to do. Let's sleep */
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (ret == 0)
|
||||
goto finish;
|
||||
|
||||
if (u->fd >= 0) {
|
||||
struct pollfd *pollfd;
|
||||
|
||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||
|
||||
if (pollfd->revents & ~(POLLOUT|POLLIN)) {
|
||||
pa_log("DSP shutdown.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
revents = pollfd->revents;
|
||||
} else
|
||||
revents = 0;
|
||||
}
|
||||
|
||||
fail:
|
||||
/* We have to continue processing messages until we receive the
|
||||
* SHUTDOWN message */
|
||||
pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
|
||||
pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
|
||||
|
||||
finish:
|
||||
pa_log_debug("Thread shutting down");
|
||||
}
|
||||
|
||||
static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
pa_cvolume old_vol;
|
||||
|
||||
assert(u);
|
||||
|
||||
if (u->sink) {
|
||||
assert(u->sink->get_hw_volume);
|
||||
memcpy(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume));
|
||||
if (u->sink->get_hw_volume(u->sink) < 0)
|
||||
return;
|
||||
if (memcmp(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)) != 0) {
|
||||
pa_subscription_post(u->sink->core,
|
||||
PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE,
|
||||
u->sink->index);
|
||||
}
|
||||
pa_sink_get_volume(u->sink);
|
||||
pa_sink_get_mute(u->sink);
|
||||
}
|
||||
|
||||
if (u->source) {
|
||||
assert(u->source->get_hw_volume);
|
||||
memcpy(&old_vol, &u->source->hw_volume, sizeof(pa_cvolume));
|
||||
if (u->source->get_hw_volume(u->source) < 0)
|
||||
return;
|
||||
if (memcmp(&old_vol, &u->source->hw_volume, sizeof(pa_cvolume)) != 0) {
|
||||
pa_subscription_post(u->source->core,
|
||||
PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE,
|
||||
u->source->index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static pa_usec_t sink_get_latency_cb(pa_sink *s) {
|
||||
pa_usec_t r = 0;
|
||||
audio_info_t info;
|
||||
int err;
|
||||
struct userdata *u = s->userdata;
|
||||
assert(s && u && u->sink);
|
||||
|
||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||
assert(err >= 0);
|
||||
|
||||
r += pa_bytes_to_usec(u->written_bytes, &s->sample_spec);
|
||||
r -= pa_bytes_to_usec(info.play.samples * u->frame_size, &s->sample_spec);
|
||||
|
||||
if (u->memchunk.memblock)
|
||||
r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static pa_usec_t source_get_latency_cb(pa_source *s) {
|
||||
pa_usec_t r = 0;
|
||||
struct userdata *u = s->userdata;
|
||||
audio_info_t info;
|
||||
int err;
|
||||
assert(s && u && u->source);
|
||||
|
||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||
assert(err >= 0);
|
||||
|
||||
r += pa_bytes_to_usec(info.record.samples * u->frame_size, &s->sample_spec);
|
||||
r -= pa_bytes_to_usec(u->read_bytes, &s->sample_spec);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int sink_get_hw_volume_cb(pa_sink *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
audio_info_t info;
|
||||
int err;
|
||||
|
||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||
assert(err >= 0);
|
||||
|
||||
pa_cvolume_set(&s->hw_volume, s->hw_volume.channels,
|
||||
info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sink_set_hw_volume_cb(pa_sink *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
audio_info_t info;
|
||||
|
||||
AUDIO_INITINFO(&info);
|
||||
|
||||
info.play.gain = pa_cvolume_avg(&s->hw_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM;
|
||||
assert(info.play.gain <= AUDIO_MAX_GAIN);
|
||||
|
||||
if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) {
|
||||
if (errno == EINVAL)
|
||||
pa_log("AUDIO_SETINFO: Unsupported volume.");
|
||||
else
|
||||
pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sink_get_hw_mute_cb(pa_sink *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
audio_info_t info;
|
||||
int err;
|
||||
|
||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||
assert(err >= 0);
|
||||
|
||||
s->hw_muted = !!info.output_muted;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sink_set_hw_mute_cb(pa_sink *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
audio_info_t info;
|
||||
|
||||
AUDIO_INITINFO(&info);
|
||||
|
||||
info.output_muted = !!s->hw_muted;
|
||||
|
||||
if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) {
|
||||
pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int source_get_hw_volume_cb(pa_source *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
audio_info_t info;
|
||||
int err;
|
||||
|
||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||
assert(err >= 0);
|
||||
|
||||
pa_cvolume_set(&s->hw_volume, s->hw_volume.channels,
|
||||
info.record.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int source_set_hw_volume_cb(pa_source *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
audio_info_t info;
|
||||
|
||||
AUDIO_INITINFO(&info);
|
||||
|
||||
info.record.gain = pa_cvolume_avg(&s->hw_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM;
|
||||
assert(info.record.gain <= AUDIO_MAX_GAIN);
|
||||
|
||||
if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) {
|
||||
if (errno == EINVAL)
|
||||
pa_log("AUDIO_SETINFO: Unsupported volume.");
|
||||
else
|
||||
pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (u->source)
|
||||
pa_source_get_volume(u->source);
|
||||
}
|
||||
|
||||
static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) {
|
||||
|
|
@ -490,6 +543,7 @@ static int pa_solaris_set_buffer(int fd, int buffer_size) {
|
|||
|
||||
AUDIO_INITINFO(&info);
|
||||
|
||||
info.play.buffer_size = buffer_size;
|
||||
info.record.buffer_size = buffer_size;
|
||||
|
||||
if (ioctl(fd, AUDIO_SETINFO, &info) < 0) {
|
||||
|
|
@ -503,7 +557,7 @@ static int pa_solaris_set_buffer(int fd, int buffer_size) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module *m) {
|
||||
struct userdata *u = NULL;
|
||||
const char *p;
|
||||
int fd = -1;
|
||||
|
|
@ -513,9 +567,10 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
pa_sample_spec ss;
|
||||
pa_channel_map map;
|
||||
pa_modargs *ma = NULL;
|
||||
struct timeval tv;
|
||||
char *t;
|
||||
assert(c && m);
|
||||
struct pollfd *pollfd;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("failed to parse module arguments.");
|
||||
|
|
@ -540,7 +595,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
ss = c->default_sample_spec;
|
||||
ss = m->core->default_sample_spec;
|
||||
if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
|
||||
pa_log("failed to parse sample specification");
|
||||
goto fail;
|
||||
|
|
@ -554,55 +609,18 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
if (pa_solaris_auto_format(fd, mode, &ss) < 0)
|
||||
goto fail;
|
||||
|
||||
if ((mode != O_WRONLY) && (buffer_size >= 1))
|
||||
if (pa_solaris_set_buffer(fd, buffer_size) < 0)
|
||||
goto fail;
|
||||
if (pa_solaris_set_buffer(fd, buffer_size) < 0)
|
||||
goto fail;
|
||||
|
||||
u = pa_xmalloc(sizeof(struct userdata));
|
||||
u->core = c;
|
||||
u->core = m->core;
|
||||
|
||||
if (mode != O_WRONLY) {
|
||||
u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map);
|
||||
assert(u->source);
|
||||
u->source->userdata = u;
|
||||
u->source->get_latency = source_get_latency_cb;
|
||||
u->source->get_hw_volume = source_get_hw_volume_cb;
|
||||
u->source->set_hw_volume = source_set_hw_volume_cb;
|
||||
pa_source_set_owner(u->source, m);
|
||||
pa_source_set_description(u->source, t = pa_sprintf_malloc("Solaris PCM on '%s'", p));
|
||||
pa_xfree(t);
|
||||
u->source->is_hardware = 1;
|
||||
} else
|
||||
u->source = NULL;
|
||||
|
||||
if (mode != O_RDONLY) {
|
||||
u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map);
|
||||
assert(u->sink);
|
||||
u->sink->get_latency = sink_get_latency_cb;
|
||||
u->sink->get_hw_volume = sink_get_hw_volume_cb;
|
||||
u->sink->set_hw_volume = sink_set_hw_volume_cb;
|
||||
u->sink->get_hw_mute = sink_get_hw_mute_cb;
|
||||
u->sink->set_hw_mute = sink_set_hw_mute_cb;
|
||||
u->sink->userdata = u;
|
||||
pa_sink_set_owner(u->sink, m);
|
||||
pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Solaris PCM on '%s'", p));
|
||||
pa_xfree(t);
|
||||
u->sink->is_hardware = 1;
|
||||
} else
|
||||
u->sink = NULL;
|
||||
|
||||
assert(u->source || u->sink);
|
||||
|
||||
u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : 0);
|
||||
assert(u->io);
|
||||
pa_iochannel_set_callback(u->io, io_callback, u);
|
||||
u->fd = fd;
|
||||
|
||||
u->memchunk.memblock = NULL;
|
||||
u->memchunk.length = 0;
|
||||
pa_memchunk_reset(&u->memchunk);
|
||||
|
||||
/* We use this to get a reasonable chunk size */
|
||||
u->page_size = sysconf(_SC_PAGESIZE);
|
||||
u->page_size = PA_PAGE_SIZE;
|
||||
|
||||
u->frame_size = pa_frame_size(&ss);
|
||||
u->buffer_size = buffer_size;
|
||||
|
|
@ -610,37 +628,91 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
u->written_bytes = 0;
|
||||
u->read_bytes = 0;
|
||||
|
||||
u->sink_underflow = 1;
|
||||
|
||||
u->module = m;
|
||||
m->userdata = u;
|
||||
|
||||
u->poll_timeout = pa_bytes_to_usec(u->buffer_size / 10, &ss);
|
||||
pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
|
||||
|
||||
pa_gettimeofday(&tv);
|
||||
pa_timeval_add(&tv, u->poll_timeout);
|
||||
u->rtpoll = pa_rtpoll_new();
|
||||
pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
|
||||
|
||||
u->timer = c->mainloop->time_new(c->mainloop, &tv, timer_cb, u);
|
||||
assert(u->timer);
|
||||
pa_rtpoll_set_timer_periodic(u->rtpoll, pa_bytes_to_usec(u->buffer_size / 10, &ss));
|
||||
|
||||
u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
|
||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||
pollfd->fd = fd;
|
||||
pollfd->events = 0;
|
||||
pollfd->revents = 0;
|
||||
|
||||
if (mode != O_WRONLY) {
|
||||
u->source = pa_source_new(m->core, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map);
|
||||
pa_assert(u->source);
|
||||
|
||||
u->source->userdata = u;
|
||||
u->source->parent.process_msg = source_process_msg;
|
||||
|
||||
pa_source_set_module(u->source, m);
|
||||
pa_source_set_description(u->source, t = pa_sprintf_malloc("Solaris PCM on '%s'", p));
|
||||
pa_xfree(t);
|
||||
pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
|
||||
pa_source_set_rtpoll(u->source, u->rtpoll);
|
||||
|
||||
u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL;
|
||||
u->source->refresh_volume = 1;
|
||||
} else
|
||||
u->source = NULL;
|
||||
|
||||
if (mode != O_RDONLY) {
|
||||
u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map);
|
||||
pa_assert(u->sink);
|
||||
|
||||
u->sink->userdata = u;
|
||||
u->sink->parent.process_msg = sink_process_msg;
|
||||
|
||||
pa_sink_set_module(u->sink, m);
|
||||
pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Solaris PCM on '%s'", p));
|
||||
pa_xfree(t);
|
||||
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
|
||||
pa_sink_set_rtpoll(u->sink, u->rtpoll);
|
||||
|
||||
u->sink->flags = PA_SINK_HARDWARE|PA_SINK_LATENCY|PA_SINK_HW_VOLUME_CTRL;
|
||||
u->sink->refresh_volume = 1;
|
||||
u->sink->refresh_mute = 1;
|
||||
} else
|
||||
u->sink = NULL;
|
||||
|
||||
pa_assert(u->source || u->sink);
|
||||
|
||||
u->sig = pa_signal_new(SIGPOLL, sig_callback, u);
|
||||
assert(u->sig);
|
||||
pa_assert(u->sig);
|
||||
ioctl(u->fd, I_SETSIG, S_MSG);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
if (!(u->thread = pa_thread_new(thread_func, u))) {
|
||||
pa_log("Failed to create thread.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Read mixer settings */
|
||||
if (u->source)
|
||||
source_get_hw_volume_cb(u->source);
|
||||
pa_asyncmsgq_send(u->thread_mq.inq, PA_MSGOBJECT(u->source), PA_SOURCE_MESSAGE_GET_VOLUME, &u->source->volume, 0, NULL);
|
||||
if (u->sink) {
|
||||
sink_get_hw_volume_cb(u->sink);
|
||||
sink_get_hw_mute_cb(u->sink);
|
||||
pa_asyncmsgq_send(u->thread_mq.inq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_VOLUME, &u->sink->volume, 0, NULL);
|
||||
pa_asyncmsgq_send(u->thread_mq.inq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_MUTE, &u->sink->muted, 0, NULL);
|
||||
}
|
||||
|
||||
if (u->sink)
|
||||
pa_sink_put(u->sink);
|
||||
if (u->source)
|
||||
pa_source_put(u->source);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (fd >= 0)
|
||||
if (u)
|
||||
pa__done(m);
|
||||
else if (fd >= 0)
|
||||
close(fd);
|
||||
|
||||
if (ma)
|
||||
|
|
@ -649,31 +721,47 @@ fail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module *m) {
|
||||
struct userdata *u;
|
||||
assert(c && m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
if (u->timer)
|
||||
c->mainloop->time_free(u->timer);
|
||||
ioctl(u->fd, I_SETSIG, 0);
|
||||
pa_signal_free(u->sig);
|
||||
|
||||
if (u->memchunk.memblock)
|
||||
if (u->sink)
|
||||
pa_sink_unlink(u->sink);
|
||||
|
||||
if (u->source)
|
||||
pa_source_unlink(u->source);
|
||||
|
||||
if (u->thread) {
|
||||
pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
|
||||
pa_thread_free(u->thread);
|
||||
}
|
||||
|
||||
pa_thread_mq_done(&u->thread_mq);
|
||||
|
||||
if (u->sink)
|
||||
pa_sink_unref(u->sink);
|
||||
|
||||
if (u->source)
|
||||
pa_source_unref(u->source);
|
||||
|
||||
if (u->memchunk.memblock)
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
|
||||
if (u->sink) {
|
||||
pa_sink_disconnect(u->sink);
|
||||
pa_sink_unref(u->sink);
|
||||
}
|
||||
if (u->rtpoll_item)
|
||||
pa_rtpoll_item_free(u->rtpoll_item);
|
||||
|
||||
if (u->source) {
|
||||
pa_source_disconnect(u->source);
|
||||
pa_source_unref(u->source);
|
||||
}
|
||||
if (u->rtpoll)
|
||||
pa_rtpoll_free(u->rtpoll);
|
||||
|
||||
if (u->fd >= 0)
|
||||
close(u->fd);
|
||||
|
||||
pa_iochannel_free(u->io);
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
|
|||
473
src/modules/module-suspend-on-idle.c
Normal file
473
src/modules/module-suspend-on-idle.c
Normal file
|
|
@ -0,0 +1,473 @@
|
|||
/* $Id$ */
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2006 Lennart Poettering
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/timeval.h>
|
||||
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/sink-input.h>
|
||||
#include <pulsecore/source-output.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/namereg.h>
|
||||
|
||||
#include "module-suspend-on-idle-symdef.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Lennart Poettering")
|
||||
PA_MODULE_DESCRIPTION("When a sink/source is idle for too long, suspend it")
|
||||
PA_MODULE_VERSION(PACKAGE_VERSION)
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"timeout",
|
||||
NULL,
|
||||
};
|
||||
|
||||
struct userdata {
|
||||
pa_core *core;
|
||||
pa_usec_t timeout;
|
||||
pa_hashmap *device_infos;
|
||||
pa_hook_slot
|
||||
*sink_new_slot,
|
||||
*source_new_slot,
|
||||
*sink_unlink_slot,
|
||||
*source_unlink_slot,
|
||||
*sink_state_changed_slot,
|
||||
*source_state_changed_slot;
|
||||
|
||||
pa_hook_slot
|
||||
*sink_input_new_slot,
|
||||
*source_output_new_slot,
|
||||
*sink_input_unlink_slot,
|
||||
*source_output_unlink_slot,
|
||||
*sink_input_move_slot,
|
||||
*source_output_move_slot,
|
||||
*sink_input_move_post_slot,
|
||||
*source_output_move_post_slot,
|
||||
*sink_input_state_changed_slot,
|
||||
*source_output_state_changed_slot;
|
||||
};
|
||||
|
||||
struct device_info {
|
||||
struct userdata *userdata;
|
||||
pa_sink *sink;
|
||||
pa_source *source;
|
||||
struct timeval last_use;
|
||||
pa_time_event *time_event;
|
||||
};
|
||||
|
||||
static void timeout_cb(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) {
|
||||
struct device_info *d = userdata;
|
||||
|
||||
pa_assert(d);
|
||||
|
||||
d->userdata->core->mainloop->time_restart(d->time_event, NULL);
|
||||
|
||||
if (d->sink && pa_sink_used_by(d->sink) <= 0 && pa_sink_get_state(d->sink) != PA_SINK_SUSPENDED) {
|
||||
pa_log_info("Sink %s idle for too long, suspending ...", d->sink->name);
|
||||
pa_sink_suspend(d->sink, TRUE);
|
||||
}
|
||||
|
||||
if (d->source && pa_source_used_by(d->source) <= 0 && pa_source_get_state(d->source) != PA_SOURCE_SUSPENDED) {
|
||||
pa_log_info("Source %s idle for too long, suspending ...", d->source->name);
|
||||
pa_source_suspend(d->source, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void restart(struct device_info *d) {
|
||||
struct timeval tv;
|
||||
pa_assert(d);
|
||||
|
||||
pa_gettimeofday(&tv);
|
||||
d->last_use = tv;
|
||||
pa_timeval_add(&tv, d->userdata->timeout*1000000);
|
||||
d->userdata->core->mainloop->time_restart(d->time_event, &tv);
|
||||
|
||||
if (d->sink)
|
||||
pa_log_debug("Sink %s becomes idle.", d->sink->name);
|
||||
if (d->source)
|
||||
pa_log_debug("Source %s becomes idle.", d->source->name);
|
||||
}
|
||||
|
||||
static void resume(struct device_info *d) {
|
||||
pa_assert(d);
|
||||
|
||||
d->userdata->core->mainloop->time_restart(d->time_event, NULL);
|
||||
|
||||
if (d->sink) {
|
||||
pa_sink_suspend(d->sink, FALSE);
|
||||
|
||||
pa_log_debug("Sink %s becomes busy.", d->sink->name);
|
||||
}
|
||||
|
||||
if (d->source) {
|
||||
pa_source_suspend(d->source, FALSE);
|
||||
|
||||
pa_log_debug("Source %s becomes busy.", d->source->name);
|
||||
}
|
||||
}
|
||||
|
||||
static pa_hook_result_t sink_input_new_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) {
|
||||
struct device_info *d;
|
||||
|
||||
pa_assert(c);
|
||||
pa_sink_input_assert_ref(s);
|
||||
pa_assert(u);
|
||||
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->sink)))
|
||||
resume(d);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t source_output_new_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) {
|
||||
struct device_info *d;
|
||||
|
||||
pa_assert(c);
|
||||
pa_source_output_assert_ref(s);
|
||||
pa_assert(u);
|
||||
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->source)))
|
||||
resume(d);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t sink_input_unlink_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) {
|
||||
pa_assert(c);
|
||||
pa_sink_input_assert_ref(s);
|
||||
pa_assert(u);
|
||||
|
||||
if (pa_sink_used_by(s->sink) <= 0) {
|
||||
struct device_info *d;
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->sink)))
|
||||
restart(d);
|
||||
}
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t source_output_unlink_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) {
|
||||
pa_assert(c);
|
||||
pa_source_output_assert_ref(s);
|
||||
pa_assert(u);
|
||||
|
||||
if (pa_source_used_by(s->source) <= 0) {
|
||||
struct device_info *d;
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->source)))
|
||||
restart(d);
|
||||
}
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t sink_input_move_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) {
|
||||
pa_assert(c);
|
||||
pa_sink_input_assert_ref(s);
|
||||
pa_assert(u);
|
||||
|
||||
if (pa_sink_used_by(s->sink) <= 1) {
|
||||
struct device_info *d;
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->sink)))
|
||||
restart(d);
|
||||
}
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t sink_input_move_post_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) {
|
||||
struct device_info *d;
|
||||
pa_assert(c);
|
||||
pa_sink_input_assert_ref(s);
|
||||
pa_assert(u);
|
||||
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->sink)))
|
||||
resume(d);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t source_output_move_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) {
|
||||
pa_assert(c);
|
||||
pa_source_output_assert_ref(s);
|
||||
pa_assert(u);
|
||||
|
||||
if (pa_source_used_by(s->source) <= 1) {
|
||||
struct device_info *d;
|
||||
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->source)))
|
||||
restart(d);
|
||||
}
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t source_output_move_post_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) {
|
||||
struct device_info *d;
|
||||
pa_assert(c);
|
||||
pa_source_output_assert_ref(s);
|
||||
pa_assert(u);
|
||||
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->source)))
|
||||
resume(d);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t sink_input_state_changed_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) {
|
||||
struct device_info *d;
|
||||
pa_sink_input_state_t state;
|
||||
pa_assert(c);
|
||||
pa_sink_input_assert_ref(s);
|
||||
pa_assert(u);
|
||||
|
||||
state = pa_sink_input_get_state(s);
|
||||
if (state == PA_SINK_INPUT_RUNNING || state == PA_SINK_INPUT_DRAINED)
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->sink)))
|
||||
resume(d);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t source_output_state_changed_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) {
|
||||
struct device_info *d;
|
||||
pa_source_output_state_t state;
|
||||
pa_assert(c);
|
||||
pa_source_output_assert_ref(s);
|
||||
pa_assert(u);
|
||||
|
||||
state = pa_source_output_get_state(s);
|
||||
if (state == PA_SOURCE_OUTPUT_RUNNING)
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->source)))
|
||||
resume(d);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t device_new_hook_cb(pa_core *c, pa_object *o, struct userdata *u) {
|
||||
struct device_info *d;
|
||||
pa_source *source;
|
||||
pa_sink *sink;
|
||||
|
||||
pa_assert(c);
|
||||
pa_object_assert_ref(o);
|
||||
pa_assert(u);
|
||||
|
||||
source = pa_source_isinstance(o) ? PA_SOURCE(o) : NULL;
|
||||
sink = pa_sink_isinstance(o) ? PA_SINK(o) : NULL;
|
||||
|
||||
pa_assert(source || sink);
|
||||
|
||||
d = pa_xnew(struct device_info, 1);
|
||||
d->userdata = u;
|
||||
d->source = source ? pa_source_ref(source) : NULL;
|
||||
d->sink = sink ? pa_sink_ref(sink) : NULL;
|
||||
d->time_event = c->mainloop->time_new(c->mainloop, NULL, timeout_cb, d);
|
||||
pa_hashmap_put(u->device_infos, o, d);
|
||||
|
||||
if ((d->sink && pa_sink_used_by(d->sink) <= 0) ||
|
||||
(d->source && pa_source_used_by(d->source) <= 0))
|
||||
restart(d);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static void device_info_free(struct device_info *d) {
|
||||
pa_assert(d);
|
||||
|
||||
if (d->source)
|
||||
pa_source_unref(d->source);
|
||||
if (d->sink)
|
||||
pa_sink_unref(d->sink);
|
||||
|
||||
d->userdata->core->mainloop->time_free(d->time_event);
|
||||
|
||||
pa_xfree(d);
|
||||
}
|
||||
|
||||
static pa_hook_result_t device_unlink_hook_cb(pa_core *c, pa_object *o, struct userdata *u) {
|
||||
struct device_info *d;
|
||||
|
||||
pa_assert(c);
|
||||
pa_object_assert_ref(o);
|
||||
pa_assert(u);
|
||||
|
||||
if ((d = pa_hashmap_remove(u->device_infos, o)))
|
||||
device_info_free(d);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, struct userdata *u) {
|
||||
struct device_info *d;
|
||||
|
||||
pa_assert(c);
|
||||
pa_object_assert_ref(o);
|
||||
pa_assert(u);
|
||||
|
||||
if (!(d = pa_hashmap_get(u->device_infos, o)))
|
||||
return PA_HOOK_OK;
|
||||
|
||||
if (pa_sink_isinstance(o)) {
|
||||
pa_sink *s = PA_SINK(o);
|
||||
pa_sink_state_t state = pa_sink_get_state(s);
|
||||
|
||||
if (pa_sink_used_by(s) <= 0) {
|
||||
|
||||
if (PA_SINK_OPENED(state))
|
||||
restart(d);
|
||||
|
||||
}
|
||||
|
||||
} else if (pa_source_isinstance(o)) {
|
||||
pa_source *s = PA_SOURCE(o);
|
||||
pa_source_state_t state = pa_source_get_state(s);
|
||||
|
||||
if (pa_source_used_by(s) <= 0) {
|
||||
|
||||
if (PA_SOURCE_OPENED(state))
|
||||
restart(d);
|
||||
}
|
||||
}
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
pa_modargs *ma = NULL;
|
||||
struct userdata *u;
|
||||
uint32_t timeout = 1;
|
||||
uint32_t idx;
|
||||
pa_sink *sink;
|
||||
pa_source *source;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (pa_modargs_get_value_u32(ma, "timeout", &timeout) < 0) {
|
||||
pa_log("Failed to parse timeout value.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
m->userdata = u = pa_xnew(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->timeout = timeout;
|
||||
u->device_infos = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
|
||||
|
||||
for (sink = pa_idxset_first(m->core->sinks, &idx); sink; sink = pa_idxset_next(m->core->sinks, &idx))
|
||||
device_new_hook_cb(m->core, PA_OBJECT(sink), u);
|
||||
|
||||
for (source = pa_idxset_first(m->core->sources, &idx); source; source = pa_idxset_next(m->core->sources, &idx))
|
||||
device_new_hook_cb(m->core, PA_OBJECT(source), u);
|
||||
|
||||
u->sink_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_NEW_POST], (pa_hook_cb_t) device_new_hook_cb, u);
|
||||
u->source_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_NEW_POST], (pa_hook_cb_t) device_new_hook_cb, u);
|
||||
u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], (pa_hook_cb_t) device_unlink_hook_cb, u);
|
||||
u->source_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], (pa_hook_cb_t) device_unlink_hook_cb, u);
|
||||
u->sink_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], (pa_hook_cb_t) device_state_changed_hook_cb, u);
|
||||
u->source_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], (pa_hook_cb_t) device_state_changed_hook_cb, u);
|
||||
|
||||
u->sink_input_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], (pa_hook_cb_t) sink_input_new_hook_cb, u);
|
||||
u->source_output_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], (pa_hook_cb_t) source_output_new_hook_cb, u);
|
||||
u->sink_input_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], (pa_hook_cb_t) sink_input_unlink_hook_cb, u);
|
||||
u->source_output_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], (pa_hook_cb_t) source_output_unlink_hook_cb, u);
|
||||
u->sink_input_move_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE], (pa_hook_cb_t) sink_input_move_hook_cb, u);
|
||||
u->source_output_move_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE], (pa_hook_cb_t) source_output_move_hook_cb, u);
|
||||
u->sink_input_move_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_POST], (pa_hook_cb_t) sink_input_move_post_hook_cb, u);
|
||||
u->source_output_move_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST], (pa_hook_cb_t) source_output_move_post_hook_cb, u);
|
||||
u->sink_input_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], (pa_hook_cb_t) sink_input_state_changed_hook_cb, u);
|
||||
u->source_output_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED], (pa_hook_cb_t) source_output_state_changed_hook_cb, u);
|
||||
|
||||
|
||||
pa_modargs_free(ma);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
||||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
struct device_info *d;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!m->userdata)
|
||||
return;
|
||||
|
||||
u = m->userdata;
|
||||
|
||||
if (u->sink_new_slot)
|
||||
pa_hook_slot_free(u->sink_new_slot);
|
||||
if (u->sink_unlink_slot)
|
||||
pa_hook_slot_free(u->sink_unlink_slot);
|
||||
if (u->sink_state_changed_slot)
|
||||
pa_hook_slot_free(u->sink_state_changed_slot);
|
||||
|
||||
if (u->source_new_slot)
|
||||
pa_hook_slot_free(u->source_new_slot);
|
||||
if (u->source_unlink_slot)
|
||||
pa_hook_slot_free(u->source_unlink_slot);
|
||||
if (u->source_state_changed_slot)
|
||||
pa_hook_slot_free(u->source_state_changed_slot);
|
||||
|
||||
if (u->sink_input_new_slot)
|
||||
pa_hook_slot_free(u->sink_input_new_slot);
|
||||
if (u->sink_input_unlink_slot)
|
||||
pa_hook_slot_free(u->sink_input_unlink_slot);
|
||||
if (u->sink_input_move_slot)
|
||||
pa_hook_slot_free(u->sink_input_move_slot);
|
||||
if (u->sink_input_move_post_slot)
|
||||
pa_hook_slot_free(u->sink_input_move_post_slot);
|
||||
if (u->sink_input_state_changed_slot)
|
||||
pa_hook_slot_free(u->sink_input_state_changed_slot);
|
||||
|
||||
if (u->source_output_new_slot)
|
||||
pa_hook_slot_free(u->source_output_new_slot);
|
||||
if (u->source_output_unlink_slot)
|
||||
pa_hook_slot_free(u->source_output_unlink_slot);
|
||||
if (u->source_output_move_slot)
|
||||
pa_hook_slot_free(u->source_output_move_slot);
|
||||
if (u->source_output_move_post_slot)
|
||||
pa_hook_slot_free(u->source_output_move_post_slot);
|
||||
if (u->source_output_state_changed_slot)
|
||||
pa_hook_slot_free(u->source_output_state_changed_slot);
|
||||
|
||||
while ((d = pa_hashmap_steal_first(u->device_infos)))
|
||||
device_info_free(d);
|
||||
|
||||
pa_hashmap_free(u->device_infos, NULL, NULL);
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
@ -596,12 +596,12 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
|
|||
}
|
||||
|
||||
#ifdef TUNNEL_SINK
|
||||
snprintf(name, sizeof(name), "Tunnel from host %s, user %s, sink %s",
|
||||
pa_snprintf(name, sizeof(name), "Tunnel from host %s, user %s, sink %s",
|
||||
pa_get_host_name(hn, sizeof(hn)),
|
||||
pa_get_user_name(un, sizeof(un)),
|
||||
u->sink->name);
|
||||
#else
|
||||
snprintf(name, sizeof(name), "Tunnel from host %s, user %s, source %s",
|
||||
pa_snprintf(name, sizeof(name), "Tunnel from host %s, user %s, source %s",
|
||||
pa_get_host_name(hn, sizeof(hn)),
|
||||
pa_get_user_name(un, sizeof(un)),
|
||||
u->source->name);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
|
|
@ -35,6 +34,7 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/volume.h>
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/module.h>
|
||||
|
|
@ -44,9 +44,7 @@
|
|||
#include <pulsecore/core-subscribe.h>
|
||||
#include <pulsecore/sink-input.h>
|
||||
#include <pulsecore/source-output.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/namereg.h>
|
||||
#include <pulse/volume.h>
|
||||
|
||||
#include "module-volume-restore-symdef.h"
|
||||
|
||||
|
|
@ -85,8 +83,8 @@ static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) {
|
|||
long k;
|
||||
unsigned i;
|
||||
|
||||
assert(s);
|
||||
assert(v);
|
||||
pa_assert(s);
|
||||
pa_assert(v);
|
||||
|
||||
if (!isdigit(*s))
|
||||
return NULL;
|
||||
|
|
@ -170,7 +168,7 @@ static int load_rules(struct userdata *u) {
|
|||
continue;
|
||||
}
|
||||
|
||||
assert(ln == buf_source);
|
||||
pa_assert(ln == buf_source);
|
||||
|
||||
if (buf_volume[0]) {
|
||||
if (!parse_volume(buf_volume, &v)) {
|
||||
|
|
@ -297,8 +295,8 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
struct rule *r;
|
||||
char *name;
|
||||
|
||||
assert(c);
|
||||
assert(u);
|
||||
pa_assert(c);
|
||||
pa_assert(u);
|
||||
|
||||
if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
|
||||
t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) &&
|
||||
|
|
@ -313,7 +311,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
if (!si->client || !(name = client_name(si->client)))
|
||||
return;
|
||||
} else {
|
||||
assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT);
|
||||
pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT);
|
||||
|
||||
if (!(so = pa_idxset_get_by_index(c->source_outputs, idx)))
|
||||
return;
|
||||
|
|
@ -341,7 +339,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
u->modified = 1;
|
||||
}
|
||||
} else {
|
||||
assert(so);
|
||||
pa_assert(so);
|
||||
|
||||
if (!r->source || strcmp(so->source->name, r->source) != 0) {
|
||||
pa_log_info("Saving source for <%s>", r->name);
|
||||
|
|
@ -363,7 +361,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
|
|||
r->sink = pa_xstrdup(si->sink->name);
|
||||
r->source = NULL;
|
||||
} else {
|
||||
assert(so);
|
||||
pa_assert(so);
|
||||
r->volume_is_set = 0;
|
||||
r->sink = NULL;
|
||||
r->source = pa_xstrdup(so->source->name);
|
||||
|
|
@ -378,7 +376,7 @@ static pa_hook_result_t sink_input_hook_callback(pa_core *c, pa_sink_input_new_d
|
|||
struct rule *r;
|
||||
char *name;
|
||||
|
||||
assert(data);
|
||||
pa_assert(data);
|
||||
|
||||
if (!data->client || !(name = client_name(data->client)))
|
||||
return PA_HOOK_OK;
|
||||
|
|
@ -396,6 +394,8 @@ static pa_hook_result_t sink_input_hook_callback(pa_core *c, pa_sink_input_new_d
|
|||
}
|
||||
}
|
||||
|
||||
pa_xfree(name);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
|
|
@ -403,7 +403,7 @@ static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output
|
|||
struct rule *r;
|
||||
char *name;
|
||||
|
||||
assert(data);
|
||||
pa_assert(data);
|
||||
|
||||
if (!data->client || !(name = client_name(data->client)))
|
||||
return PA_HOOK_OK;
|
||||
|
|
@ -418,12 +418,11 @@ static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output
|
|||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
pa_modargs *ma = NULL;
|
||||
struct userdata *u;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments");
|
||||
|
|
@ -442,16 +441,15 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
if (load_rules(u) < 0)
|
||||
goto fail;
|
||||
|
||||
u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
|
||||
u->sink_input_hook_slot = pa_hook_connect(&c->hook_sink_input_new, (pa_hook_cb_t) sink_input_hook_callback, u);
|
||||
u->source_output_hook_slot = pa_hook_connect(&c->hook_source_output_new, (pa_hook_cb_t) source_output_hook_callback, u);
|
||||
u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
|
||||
u->sink_input_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], (pa_hook_cb_t) sink_input_hook_callback, u);
|
||||
u->source_output_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], (pa_hook_cb_t) source_output_hook_callback, u);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
pa__done(c, m);
|
||||
|
||||
pa__done(m);
|
||||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
|
|
@ -460,7 +458,7 @@ fail:
|
|||
|
||||
static void free_func(void *p, void *userdata) {
|
||||
struct rule *r = p;
|
||||
assert(r);
|
||||
pa_assert(r);
|
||||
|
||||
pa_xfree(r->name);
|
||||
pa_xfree(r->sink);
|
||||
|
|
@ -468,11 +466,10 @@ static void free_func(void *p, void *userdata) {
|
|||
pa_xfree(r);
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata* u;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
@ -67,30 +66,21 @@ static const char* const valid_modargs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static int ring_bell(struct userdata *u, int percent) {
|
||||
pa_sink *s;
|
||||
assert(u);
|
||||
|
||||
if (!(s = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) {
|
||||
pa_log("Invalid sink: %s", u->sink_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pa_scache_play_item(u->core, u->scache_item, s, (percent*PA_VOLUME_NORM)/100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int x11_event_callback(pa_x11_wrapper *w, XEvent *e, void *userdata) {
|
||||
XkbBellNotifyEvent *bne;
|
||||
struct userdata *u = userdata;
|
||||
assert(w && e && u && u->x11_wrapper == w);
|
||||
|
||||
pa_assert(w);
|
||||
pa_assert(e);
|
||||
pa_assert(u);
|
||||
pa_assert(u->x11_wrapper == w);
|
||||
|
||||
if (((XkbEvent*) e)->any.xkb_type != XkbBellNotify)
|
||||
return 0;
|
||||
|
||||
bne = (XkbBellNotifyEvent*) e;
|
||||
|
||||
if (ring_bell(u, bne->percent) < 0) {
|
||||
if (pa_scache_play_item_by_name(u->core, u->scache_item, u->sink_name, (bne->percent*PA_VOLUME_NORM)/100, 1) < 0) {
|
||||
pa_log_info("Ringing bell failed, reverting to X11 device bell.");
|
||||
XkbForceDeviceBell(pa_x11_wrapper_get_display(w), bne->device, bne->bell_class, bne->bell_id, bne->percent);
|
||||
}
|
||||
|
|
@ -98,25 +88,27 @@ static int x11_event_callback(pa_x11_wrapper *w, XEvent *e, void *userdata) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
|
||||
struct userdata *u = NULL;
|
||||
pa_modargs *ma = NULL;
|
||||
int major, minor;
|
||||
unsigned int auto_ctrls, auto_values;
|
||||
assert(c && m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("failed to parse module arguments");
|
||||
pa_log("Failed to parse module arguments");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
m->userdata = u = pa_xmalloc(sizeof(struct userdata));
|
||||
u->core = c;
|
||||
m->userdata = u = pa_xnew(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->scache_item = pa_xstrdup(pa_modargs_get_value(ma, "sample", "x11-bell"));
|
||||
u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
|
||||
u->x11_client = NULL;
|
||||
|
||||
if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL))))
|
||||
if (!(u->x11_wrapper = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL))))
|
||||
goto fail;
|
||||
|
||||
major = XkbMajorVersion;
|
||||
|
|
@ -130,7 +122,6 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
major = XkbMajorVersion;
|
||||
minor = XkbMinorVersion;
|
||||
|
||||
|
||||
if (!XkbQueryExtension(pa_x11_wrapper_get_display(u->x11_wrapper), NULL, &u->xkb_event_base, NULL, &major, &minor)) {
|
||||
pa_log("XkbQueryExtension() failed");
|
||||
goto fail;
|
||||
|
|
@ -150,14 +141,21 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
fail:
|
||||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
if (m->userdata)
|
||||
pa__done(c, m);
|
||||
|
||||
pa__done(m);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
struct userdata *u = m->userdata;
|
||||
assert(c && m && u);
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!m->userdata)
|
||||
return;
|
||||
|
||||
u = m->userdata;
|
||||
|
||||
pa_xfree(u->scache_item);
|
||||
pa_xfree(u->sink_name);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -76,7 +75,7 @@ struct userdata {
|
|||
};
|
||||
|
||||
static int load_key(struct userdata *u, const char*fn) {
|
||||
assert(u);
|
||||
pa_assert(u);
|
||||
|
||||
u->auth_cookie_in_property = 0;
|
||||
|
||||
|
|
@ -93,7 +92,7 @@ static int load_key(struct userdata *u, const char*fn) {
|
|||
if (pa_authkey_load_auto(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0)
|
||||
return -1;
|
||||
|
||||
pa_log_debug("loading cookie from disk.");
|
||||
pa_log_debug("Loading cookie from disk.");
|
||||
|
||||
if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0)
|
||||
u->auth_cookie_in_property = 1;
|
||||
|
|
@ -101,7 +100,7 @@ static int load_key(struct userdata *u, const char*fn) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
struct userdata *u;
|
||||
pa_modargs *ma = NULL;
|
||||
char hn[256], un[128];
|
||||
|
|
@ -110,23 +109,25 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
char *s;
|
||||
pa_strlist *l;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("failed to parse module arguments");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
m->userdata = u = pa_xmalloc(sizeof(struct userdata));
|
||||
u->core = c;
|
||||
u->core = m->core;
|
||||
u->id = NULL;
|
||||
u->auth_cookie_in_property = 0;
|
||||
|
||||
if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL))))
|
||||
if (!(u->x11_wrapper = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL))))
|
||||
goto fail;
|
||||
|
||||
if (!(l = pa_property_get(c, PA_NATIVE_SERVER_PROPERTY_NAME)))
|
||||
if (!(l = pa_property_get(m->core, PA_NATIVE_SERVER_PROPERTY_NAME)))
|
||||
goto fail;
|
||||
|
||||
s = pa_strlist_tostring(l);
|
||||
|
|
@ -154,13 +155,14 @@ fail:
|
|||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
pa__done(c, m);
|
||||
pa__done(m);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata*u;
|
||||
assert(c && m);
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
|
@ -185,7 +187,7 @@ void pa__done(pa_core *c, pa_module*m) {
|
|||
pa_x11_wrapper_unref(u->x11_wrapper);
|
||||
|
||||
if (u->auth_cookie_in_property)
|
||||
pa_authkey_prop_unref(c, PA_NATIVE_COOKIE_PROPERTY_NAME);
|
||||
pa_authkey_prop_unref(m->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
|
||||
|
||||
pa_xfree(u->id);
|
||||
pa_xfree(u);
|
||||
|
|
|
|||
195
src/modules/module-x11-xsmp.c
Normal file
195
src/modules/module-x11-xsmp.c
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
/* $Id$ */
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2004-2006 Lennart Poettering
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/SM/SMlib.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/util.h>
|
||||
|
||||
#include <pulsecore/iochannel.h>
|
||||
#include <pulsecore/sink.h>
|
||||
#include <pulsecore/core-scache.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/namereg.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
|
||||
#include "module-x11-xsmp-symdef.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Lennart Poettering")
|
||||
PA_MODULE_DESCRIPTION("X11 session management")
|
||||
PA_MODULE_VERSION(PACKAGE_VERSION)
|
||||
|
||||
static int ice_in_use = 0;
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static void die_cb(SmcConn connection, SmPointer client_data){
|
||||
pa_core *c = PA_CORE(client_data);
|
||||
|
||||
pa_log_debug("Got die message from XSM. Exiting...");
|
||||
|
||||
pa_core_assert_ref(c);
|
||||
c->mainloop->quit(c->mainloop, 0);
|
||||
}
|
||||
|
||||
static void save_complete_cb(SmcConn connection, SmPointer client_data) {
|
||||
}
|
||||
|
||||
static void shutdown_cancelled_cb(SmcConn connection, SmPointer client_data) {
|
||||
SmcSaveYourselfDone(connection, True);
|
||||
}
|
||||
|
||||
static void save_yourself_cb(SmcConn connection, SmPointer client_data, int save_type, Bool _shutdown, int interact_style, Bool fast) {
|
||||
SmcSaveYourselfDone(connection, True);
|
||||
}
|
||||
|
||||
static void ice_io_cb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) {
|
||||
IceConn connection = userdata;
|
||||
|
||||
if (IceProcessMessages(connection, NULL, NULL) == IceProcessMessagesIOError) {
|
||||
IceSetShutdownNegotiation(connection, False);
|
||||
IceCloseConnection(connection);
|
||||
}
|
||||
}
|
||||
|
||||
static void new_ice_connection(IceConn connection, IcePointer client_data, Bool opening, IcePointer *watch_data) {
|
||||
pa_core *c = client_data;
|
||||
|
||||
pa_assert(c);
|
||||
|
||||
if (opening)
|
||||
*watch_data = c->mainloop->io_new(c->mainloop, IceConnectionNumber(connection), PA_IO_EVENT_INPUT, ice_io_cb, connection);
|
||||
else
|
||||
c->mainloop->io_free(*watch_data);
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
|
||||
pa_modargs *ma = NULL;
|
||||
char t[256], *vendor, *client_id;
|
||||
SmcCallbacks callbacks;
|
||||
SmProp prop_program, prop_user;
|
||||
SmProp *prop_list[2];
|
||||
SmPropValue val_program, val_user;
|
||||
SmcConn connection;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (ice_in_use) {
|
||||
pa_log("module-x11-xsmp may no be loaded twice.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
IceAddConnectionWatch(new_ice_connection, m->core);
|
||||
ice_in_use = 1;
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!getenv("SESSION_MANAGER")) {
|
||||
pa_log("X11 session manager not running.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.die.callback = die_cb;
|
||||
callbacks.die.client_data = m->core;
|
||||
callbacks.save_yourself.callback = save_yourself_cb;
|
||||
callbacks.save_yourself.client_data = m->core;
|
||||
callbacks.save_complete.callback = save_complete_cb;
|
||||
callbacks.save_complete.client_data = m->core;
|
||||
callbacks.shutdown_cancelled.callback = shutdown_cancelled_cb;
|
||||
callbacks.shutdown_cancelled.client_data = m->core;
|
||||
|
||||
if (!(m->userdata = connection = SmcOpenConnection(
|
||||
NULL, m->core,
|
||||
SmProtoMajor, SmProtoMinor,
|
||||
SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
|
||||
&callbacks, NULL, &client_id,
|
||||
sizeof(t), t))) {
|
||||
|
||||
pa_log("Failed to open connection to session manager: %s", t);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
prop_program.name = (char*) SmProgram;
|
||||
prop_program.type = (char*) SmARRAY8;
|
||||
val_program.value = (char*) PACKAGE_NAME;
|
||||
val_program.length = strlen(val_program.value);
|
||||
prop_program.num_vals = 1;
|
||||
prop_program.vals = &val_program;
|
||||
prop_list[0] = &prop_program;
|
||||
|
||||
prop_user.name = (char*) SmUserID;
|
||||
prop_user.type = (char*) SmARRAY8;
|
||||
pa_get_user_name(t, sizeof(t));
|
||||
val_user.value = t;
|
||||
val_user.length = strlen(val_user.value);
|
||||
prop_user.num_vals = 1;
|
||||
prop_user.vals = &val_user;
|
||||
prop_list[1] = &prop_user;
|
||||
|
||||
SmcSetProperties(connection, PA_ELEMENTSOF(prop_list), prop_list);
|
||||
|
||||
pa_log_info("Connected to session manager '%s' as '%s'.", vendor = SmcVendor(connection), client_id);
|
||||
free(vendor);
|
||||
free(client_id);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
||||
pa__done(m);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_module*m) {
|
||||
pa_assert(m);
|
||||
|
||||
if (m->userdata)
|
||||
SmcCloseConnection(m->userdata, 0, NULL);
|
||||
|
||||
if (ice_in_use) {
|
||||
IceRemoveConnectionWatch(new_ice_connection, m->core);
|
||||
ice_in_use = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +26,6 @@
|
|||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -35,11 +34,11 @@
|
|||
#include <avahi-client/publish.h>
|
||||
#include <avahi-common/alternative.h>
|
||||
#include <avahi-common/error.h>
|
||||
#include <avahi-common/domain.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/util.h>
|
||||
|
||||
#include <pulsecore/autoload.h>
|
||||
#include <pulsecore/sink.h>
|
||||
#include <pulsecore/source.h>
|
||||
#include <pulsecore/native-common.h>
|
||||
|
|
@ -71,56 +70,52 @@ struct service {
|
|||
struct userdata *userdata;
|
||||
AvahiEntryGroup *entry_group;
|
||||
char *service_name;
|
||||
char *name;
|
||||
enum { UNPUBLISHED, PUBLISHED_REAL, PUBLISHED_AUTOLOAD } published ;
|
||||
|
||||
struct {
|
||||
int valid;
|
||||
pa_namereg_type_t type;
|
||||
uint32_t index;
|
||||
} loaded;
|
||||
|
||||
struct {
|
||||
int valid;
|
||||
pa_namereg_type_t type;
|
||||
uint32_t index;
|
||||
} autoload;
|
||||
pa_object *device;
|
||||
};
|
||||
|
||||
struct userdata {
|
||||
pa_core *core;
|
||||
AvahiPoll *avahi_poll;
|
||||
AvahiClient *client;
|
||||
|
||||
pa_hashmap *services;
|
||||
pa_dynarray *sink_dynarray, *source_dynarray, *autoload_dynarray;
|
||||
pa_subscription *subscription;
|
||||
char *service_name;
|
||||
|
||||
AvahiEntryGroup *main_entry_group;
|
||||
|
||||
uint16_t port;
|
||||
|
||||
pa_hook_slot *sink_new_slot, *source_new_slot, *sink_unlink_slot, *source_unlink_slot, *sink_changed_slot, *source_changed_slot;
|
||||
};
|
||||
|
||||
static void get_service_data(struct userdata *u, struct service *s, pa_sample_spec *ret_ss, char **ret_description) {
|
||||
assert(u && s && s->loaded.valid && ret_ss && ret_description);
|
||||
static void get_service_data(struct service *s, pa_sample_spec *ret_ss, pa_channel_map *ret_map, const char **ret_name, const char **ret_description) {
|
||||
pa_assert(s);
|
||||
pa_assert(ret_ss);
|
||||
pa_assert(ret_description);
|
||||
|
||||
if (pa_sink_isinstance(s->device)) {
|
||||
pa_sink *sink = PA_SINK(s->device);
|
||||
|
||||
if (s->loaded.type == PA_NAMEREG_SINK) {
|
||||
pa_sink *sink = pa_idxset_get_by_index(u->core->sinks, s->loaded.index);
|
||||
assert(sink);
|
||||
*ret_ss = sink->sample_spec;
|
||||
*ret_map = sink->channel_map;
|
||||
*ret_name = sink->name;
|
||||
*ret_description = sink->description;
|
||||
} else if (s->loaded.type == PA_NAMEREG_SOURCE) {
|
||||
pa_source *source = pa_idxset_get_by_index(u->core->sources, s->loaded.index);
|
||||
assert(source);
|
||||
|
||||
} else if (pa_source_isinstance(s->device)) {
|
||||
pa_source *source = PA_SOURCE(s->device);
|
||||
|
||||
*ret_ss = source->sample_spec;
|
||||
*ret_map = source->channel_map;
|
||||
*ret_name = source->name;
|
||||
*ret_description = source->description;
|
||||
} else
|
||||
assert(0);
|
||||
pa_assert_not_reached();
|
||||
}
|
||||
|
||||
static AvahiStringList* txt_record_server_data(pa_core *c, AvahiStringList *l) {
|
||||
char s[128];
|
||||
assert(c);
|
||||
|
||||
pa_assert(c);
|
||||
|
||||
l = avahi_string_list_add_pair(l, "server-version", PACKAGE_NAME" "PACKAGE_VERSION);
|
||||
l = avahi_string_list_add_pair(l, "user-name", pa_get_user_name(s, sizeof(s)));
|
||||
|
|
@ -130,325 +125,217 @@ static AvahiStringList* txt_record_server_data(pa_core *c, AvahiStringList *l) {
|
|||
return l;
|
||||
}
|
||||
|
||||
static int publish_service(struct userdata *u, struct service *s);
|
||||
static int publish_service(struct service *s);
|
||||
|
||||
static void service_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) {
|
||||
struct service *s = userdata;
|
||||
|
||||
if (state == AVAHI_ENTRY_GROUP_COLLISION) {
|
||||
char *t;
|
||||
pa_assert(s);
|
||||
|
||||
t = avahi_alternative_service_name(s->service_name);
|
||||
pa_xfree(s->service_name);
|
||||
s->service_name = t;
|
||||
switch (state) {
|
||||
|
||||
publish_service(s->userdata, s);
|
||||
case AVAHI_ENTRY_GROUP_ESTABLISHED:
|
||||
pa_log_info("Successfully established service %s.", s->service_name);
|
||||
break;
|
||||
|
||||
case AVAHI_ENTRY_GROUP_COLLISION: {
|
||||
char *t;
|
||||
|
||||
t = avahi_alternative_service_name(s->service_name);
|
||||
pa_log_info("Name collision, renaming %s to %s.", s->service_name, t);
|
||||
pa_xfree(s->service_name);
|
||||
s->service_name = t;
|
||||
|
||||
publish_service(s);
|
||||
break;
|
||||
}
|
||||
|
||||
case AVAHI_ENTRY_GROUP_FAILURE: {
|
||||
pa_log("Failed to register service: %s", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
|
||||
|
||||
avahi_entry_group_free(g);
|
||||
s->entry_group = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case AVAHI_ENTRY_GROUP_UNCOMMITED:
|
||||
case AVAHI_ENTRY_GROUP_REGISTERING:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static int publish_service(struct userdata *u, struct service *s) {
|
||||
static void service_free(struct service *s);
|
||||
|
||||
static int publish_service(struct service *s) {
|
||||
int r = -1;
|
||||
AvahiStringList *txt = NULL;
|
||||
const char *description = NULL, *name = NULL;
|
||||
pa_sample_spec ss;
|
||||
pa_channel_map map;
|
||||
char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
|
||||
|
||||
assert(u);
|
||||
assert(s);
|
||||
pa_assert(s);
|
||||
|
||||
if (!u->client || avahi_client_get_state(u->client) != AVAHI_CLIENT_S_RUNNING)
|
||||
if (!s->userdata->client || avahi_client_get_state(s->userdata->client) != AVAHI_CLIENT_S_RUNNING)
|
||||
return 0;
|
||||
|
||||
if ((s->published == PUBLISHED_REAL && s->loaded.valid) ||
|
||||
(s->published == PUBLISHED_AUTOLOAD && s->autoload.valid && !s->loaded.valid))
|
||||
return 0;
|
||||
|
||||
if (s->published != UNPUBLISHED) {
|
||||
if (!s->entry_group) {
|
||||
if (!(s->entry_group = avahi_entry_group_new(s->userdata->client, service_entry_group_callback, s))) {
|
||||
pa_log("avahi_entry_group_new(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
|
||||
goto finish;
|
||||
}
|
||||
} else
|
||||
avahi_entry_group_reset(s->entry_group);
|
||||
s->published = UNPUBLISHED;
|
||||
|
||||
txt = txt_record_server_data(s->userdata->core, txt);
|
||||
|
||||
get_service_data(s, &ss, &map, &name, &description);
|
||||
txt = avahi_string_list_add_pair(txt, "device", name);
|
||||
txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate);
|
||||
txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels);
|
||||
txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format));
|
||||
txt = avahi_string_list_add_pair(txt, "channel_map", pa_channel_map_snprint(cm, sizeof(cm), &map));
|
||||
|
||||
if (avahi_entry_group_add_service_strlst(
|
||||
s->entry_group,
|
||||
AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
|
||||
0,
|
||||
s->service_name,
|
||||
pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE,
|
||||
NULL,
|
||||
NULL,
|
||||
s->userdata->port,
|
||||
txt) < 0) {
|
||||
|
||||
pa_log("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (s->loaded.valid || s->autoload.valid) {
|
||||
pa_namereg_type_t type;
|
||||
|
||||
if (!s->entry_group) {
|
||||
if (!(s->entry_group = avahi_entry_group_new(u->client, service_entry_group_callback, s))) {
|
||||
pa_log("avahi_entry_group_new(): %s", avahi_strerror(avahi_client_errno(u->client)));
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
txt = avahi_string_list_add_pair(txt, "device", s->name);
|
||||
txt = txt_record_server_data(u->core, txt);
|
||||
|
||||
if (s->loaded.valid) {
|
||||
char *description;
|
||||
pa_sample_spec ss;
|
||||
|
||||
get_service_data(u, s, &ss, &description);
|
||||
|
||||
txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate);
|
||||
txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels);
|
||||
txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format));
|
||||
if (description)
|
||||
txt = avahi_string_list_add_pair(txt, "description", description);
|
||||
|
||||
type = s->loaded.type;
|
||||
} else if (s->autoload.valid)
|
||||
type = s->autoload.type;
|
||||
|
||||
if (avahi_entry_group_add_service_strlst(
|
||||
s->entry_group,
|
||||
AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
|
||||
0,
|
||||
s->service_name,
|
||||
type == PA_NAMEREG_SINK ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE,
|
||||
NULL,
|
||||
NULL,
|
||||
u->port,
|
||||
txt) < 0) {
|
||||
|
||||
pa_log("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(u->client)));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (avahi_entry_group_commit(s->entry_group) < 0) {
|
||||
pa_log("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(u->client)));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (s->loaded.valid)
|
||||
s->published = PUBLISHED_REAL;
|
||||
else if (s->autoload.valid)
|
||||
s->published = PUBLISHED_AUTOLOAD;
|
||||
if (avahi_entry_group_commit(s->entry_group) < 0) {
|
||||
pa_log("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
pa_log_debug("Successfully created entry group for %s.", s->service_name);
|
||||
|
||||
finish:
|
||||
|
||||
if (s->published == UNPUBLISHED) {
|
||||
/* Remove this service */
|
||||
/* Remove this service */
|
||||
if (r < 0)
|
||||
service_free(s);
|
||||
|
||||
if (s->entry_group)
|
||||
avahi_entry_group_free(s->entry_group);
|
||||
|
||||
pa_hashmap_remove(u->services, s->name);
|
||||
pa_xfree(s->name);
|
||||
pa_xfree(s->service_name);
|
||||
pa_xfree(s);
|
||||
}
|
||||
|
||||
if (txt)
|
||||
avahi_string_list_free(txt);
|
||||
avahi_string_list_free(txt);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct service *get_service(struct userdata *u, const char *name, const char *description) {
|
||||
static struct service *get_service(struct userdata *u, pa_object *device) {
|
||||
struct service *s;
|
||||
char hn[64];
|
||||
char hn[64], un[64];
|
||||
const char *n;
|
||||
|
||||
if ((s = pa_hashmap_get(u->services, name)))
|
||||
pa_assert(u);
|
||||
pa_object_assert_ref(device);
|
||||
|
||||
if ((s = pa_hashmap_get(u->services, device)))
|
||||
return s;
|
||||
|
||||
s = pa_xnew(struct service, 1);
|
||||
s->userdata = u;
|
||||
s->entry_group = NULL;
|
||||
s->published = UNPUBLISHED;
|
||||
s->name = pa_xstrdup(name);
|
||||
s->loaded.valid = s->autoload.valid = 0;
|
||||
s->service_name = pa_sprintf_malloc("%s on %s", description ? description : s->name, pa_get_host_name(hn, sizeof(hn)));
|
||||
s->device = device;
|
||||
|
||||
pa_hashmap_put(u->services, s->name, s);
|
||||
if (pa_sink_isinstance(device)) {
|
||||
if (!(n = PA_SINK(device)->description))
|
||||
n = PA_SINK(device)->name;
|
||||
} else {
|
||||
if (!(n = PA_SOURCE(device)->description))
|
||||
n = PA_SOURCE(device)->name;
|
||||
}
|
||||
|
||||
s->service_name = pa_truncate_utf8(pa_sprintf_malloc("%s@%s: %s",
|
||||
pa_get_user_name(un, sizeof(un)),
|
||||
pa_get_host_name(hn, sizeof(hn)),
|
||||
n),
|
||||
AVAHI_LABEL_MAX-1);
|
||||
|
||||
pa_hashmap_put(u->services, s->device, s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static int publish_sink(struct userdata *u, pa_sink *s) {
|
||||
struct service *svc;
|
||||
int ret;
|
||||
assert(u && s);
|
||||
static void service_free(struct service *s) {
|
||||
pa_assert(s);
|
||||
|
||||
svc = get_service(u, s->name, s->description);
|
||||
if (svc->loaded.valid)
|
||||
return publish_service(u, svc);
|
||||
pa_hashmap_remove(s->userdata->services, s->device);
|
||||
|
||||
svc->loaded.valid = 1;
|
||||
svc->loaded.type = PA_NAMEREG_SINK;
|
||||
svc->loaded.index = s->index;
|
||||
|
||||
if ((ret = publish_service(u, svc)) < 0)
|
||||
return ret;
|
||||
|
||||
pa_dynarray_put(u->sink_dynarray, s->index, svc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int publish_source(struct userdata *u, pa_source *s) {
|
||||
struct service *svc;
|
||||
int ret;
|
||||
|
||||
assert(u && s);
|
||||
|
||||
svc = get_service(u, s->name, s->description);
|
||||
if (svc->loaded.valid)
|
||||
return publish_service(u, svc);
|
||||
|
||||
svc->loaded.valid = 1;
|
||||
svc->loaded.type = PA_NAMEREG_SOURCE;
|
||||
svc->loaded.index = s->index;
|
||||
|
||||
pa_dynarray_put(u->source_dynarray, s->index, svc);
|
||||
|
||||
if ((ret = publish_service(u, svc)) < 0)
|
||||
return ret;
|
||||
|
||||
pa_dynarray_put(u->sink_dynarray, s->index, svc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int publish_autoload(struct userdata *u, pa_autoload_entry *s) {
|
||||
struct service *svc;
|
||||
int ret;
|
||||
|
||||
assert(u && s);
|
||||
|
||||
svc = get_service(u, s->name, NULL);
|
||||
if (svc->autoload.valid)
|
||||
return publish_service(u, svc);
|
||||
|
||||
svc->autoload.valid = 1;
|
||||
svc->autoload.type = s->type;
|
||||
svc->autoload.index = s->index;
|
||||
|
||||
if ((ret = publish_service(u, svc)) < 0)
|
||||
return ret;
|
||||
|
||||
pa_dynarray_put(u->autoload_dynarray, s->index, svc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int remove_sink(struct userdata *u, uint32_t idx) {
|
||||
struct service *svc;
|
||||
assert(u && idx != PA_INVALID_INDEX);
|
||||
|
||||
if (!(svc = pa_dynarray_get(u->sink_dynarray, idx)))
|
||||
return 0;
|
||||
|
||||
if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SINK)
|
||||
return 0;
|
||||
|
||||
svc->loaded.valid = 0;
|
||||
pa_dynarray_put(u->sink_dynarray, idx, NULL);
|
||||
|
||||
return publish_service(u, svc);
|
||||
}
|
||||
|
||||
static int remove_source(struct userdata *u, uint32_t idx) {
|
||||
struct service *svc;
|
||||
assert(u && idx != PA_INVALID_INDEX);
|
||||
|
||||
if (!(svc = pa_dynarray_get(u->source_dynarray, idx)))
|
||||
return 0;
|
||||
|
||||
if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SOURCE)
|
||||
return 0;
|
||||
|
||||
svc->loaded.valid = 0;
|
||||
pa_dynarray_put(u->source_dynarray, idx, NULL);
|
||||
|
||||
return publish_service(u, svc);
|
||||
}
|
||||
|
||||
static int remove_autoload(struct userdata *u, uint32_t idx) {
|
||||
struct service *svc;
|
||||
assert(u && idx != PA_INVALID_INDEX);
|
||||
|
||||
if (!(svc = pa_dynarray_get(u->autoload_dynarray, idx)))
|
||||
return 0;
|
||||
|
||||
if (!svc->autoload.valid)
|
||||
return 0;
|
||||
|
||||
svc->autoload.valid = 0;
|
||||
pa_dynarray_put(u->autoload_dynarray, idx, NULL);
|
||||
|
||||
return publish_service(u, svc);
|
||||
}
|
||||
|
||||
static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
assert(u && c);
|
||||
|
||||
switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)
|
||||
case PA_SUBSCRIPTION_EVENT_SINK: {
|
||||
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
|
||||
pa_sink *sink;
|
||||
|
||||
if ((sink = pa_idxset_get_by_index(c->sinks, idx))) {
|
||||
if (publish_sink(u, sink) < 0)
|
||||
goto fail;
|
||||
}
|
||||
} else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
|
||||
if (remove_sink(u, idx) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PA_SUBSCRIPTION_EVENT_SOURCE:
|
||||
|
||||
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
|
||||
pa_source *source;
|
||||
|
||||
if ((source = pa_idxset_get_by_index(c->sources, idx))) {
|
||||
if (publish_source(u, source) < 0)
|
||||
goto fail;
|
||||
}
|
||||
} else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
|
||||
if (remove_source(u, idx) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PA_SUBSCRIPTION_EVENT_AUTOLOAD:
|
||||
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
|
||||
pa_autoload_entry *autoload;
|
||||
|
||||
if ((autoload = pa_idxset_get_by_index(c->autoload_idxset, idx))) {
|
||||
if (publish_autoload(u, autoload) < 0)
|
||||
goto fail;
|
||||
}
|
||||
} else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
|
||||
if (remove_autoload(u, idx) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
if (s->entry_group) {
|
||||
pa_log_debug("Removing entry group for %s.", s->service_name);
|
||||
avahi_entry_group_free(s->entry_group);
|
||||
}
|
||||
|
||||
return;
|
||||
pa_xfree(s->service_name);
|
||||
pa_xfree(s);
|
||||
}
|
||||
|
||||
fail:
|
||||
if (u->subscription) {
|
||||
pa_subscription_free(u->subscription);
|
||||
u->subscription = NULL;
|
||||
}
|
||||
static pa_hook_result_t device_new_or_changed_cb(pa_core *c, pa_object *o, struct userdata *u) {
|
||||
pa_assert(c);
|
||||
pa_object_assert_ref(o);
|
||||
|
||||
publish_service(get_service(u, o));
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t device_unlink_cb(pa_core *c, pa_object *o, struct userdata *u) {
|
||||
struct service *s;
|
||||
|
||||
pa_assert(c);
|
||||
pa_object_assert_ref(o);
|
||||
|
||||
if ((s = pa_hashmap_get(u->services, o)))
|
||||
service_free(s);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static int publish_main_service(struct userdata *u);
|
||||
|
||||
static void main_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
assert(u);
|
||||
pa_assert(u);
|
||||
|
||||
if (state == AVAHI_ENTRY_GROUP_COLLISION) {
|
||||
char *t;
|
||||
switch (state) {
|
||||
|
||||
t = avahi_alternative_service_name(u->service_name);
|
||||
pa_xfree(u->service_name);
|
||||
u->service_name = t;
|
||||
case AVAHI_ENTRY_GROUP_ESTABLISHED:
|
||||
pa_log_info("Successfully established main service.");
|
||||
break;
|
||||
|
||||
publish_main_service(u);
|
||||
case AVAHI_ENTRY_GROUP_COLLISION: {
|
||||
char *t;
|
||||
|
||||
t = avahi_alternative_service_name(u->service_name);
|
||||
pa_log_info("Name collision: renaming main service %s to %s.", u->service_name, t);
|
||||
pa_xfree(u->service_name);
|
||||
u->service_name = t;
|
||||
|
||||
publish_main_service(u);
|
||||
break;
|
||||
}
|
||||
|
||||
case AVAHI_ENTRY_GROUP_FAILURE: {
|
||||
pa_log("Failed to register main service: %s", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
|
||||
|
||||
avahi_entry_group_free(g);
|
||||
u->main_entry_group = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
case AVAHI_ENTRY_GROUP_UNCOMMITED:
|
||||
case AVAHI_ENTRY_GROUP_REGISTERING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -456,6 +343,8 @@ static int publish_main_service(struct userdata *u) {
|
|||
AvahiStringList *txt = NULL;
|
||||
int r = -1;
|
||||
|
||||
pa_assert(u);
|
||||
|
||||
if (!u->main_entry_group) {
|
||||
if (!(u->main_entry_group = avahi_entry_group_new(u->client, main_entry_group_callback, u))) {
|
||||
pa_log("avahi_entry_group_new() failed: %s", avahi_strerror(avahi_client_errno(u->client)));
|
||||
|
|
@ -464,7 +353,7 @@ static int publish_main_service(struct userdata *u) {
|
|||
} else
|
||||
avahi_entry_group_reset(u->main_entry_group);
|
||||
|
||||
txt = txt_record_server_data(u->core, NULL);
|
||||
txt = txt_record_server_data(u->core, txt);
|
||||
|
||||
if (avahi_entry_group_add_service_strlst(
|
||||
u->main_entry_group,
|
||||
|
|
@ -497,26 +386,18 @@ fail:
|
|||
static int publish_all_services(struct userdata *u) {
|
||||
pa_sink *sink;
|
||||
pa_source *source;
|
||||
pa_autoload_entry *autoload;
|
||||
int r = -1;
|
||||
uint32_t idx;
|
||||
|
||||
assert(u);
|
||||
pa_assert(u);
|
||||
|
||||
pa_log_debug("Publishing services in Zeroconf");
|
||||
|
||||
for (sink = pa_idxset_first(u->core->sinks, &idx); sink; sink = pa_idxset_next(u->core->sinks, &idx))
|
||||
if (publish_sink(u, sink) < 0)
|
||||
goto fail;
|
||||
for (sink = PA_SINK(pa_idxset_first(u->core->sinks, &idx)); sink; sink = PA_SINK(pa_idxset_next(u->core->sinks, &idx)))
|
||||
publish_service(get_service(u, PA_OBJECT(sink)));
|
||||
|
||||
for (source = pa_idxset_first(u->core->sources, &idx); source; source = pa_idxset_next(u->core->sources, &idx))
|
||||
if (publish_source(u, source) < 0)
|
||||
goto fail;
|
||||
|
||||
if (u->core->autoload_idxset)
|
||||
for (autoload = pa_idxset_first(u->core->autoload_idxset, &idx); autoload; autoload = pa_idxset_next(u->core->autoload_idxset, &idx))
|
||||
if (publish_autoload(u, autoload) < 0)
|
||||
goto fail;
|
||||
for (source = PA_SOURCE(pa_idxset_first(u->core->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(u->core->sources, &idx)))
|
||||
publish_service(get_service(u, PA_OBJECT(source)));
|
||||
|
||||
if (publish_main_service(u) < 0)
|
||||
goto fail;
|
||||
|
|
@ -527,38 +408,44 @@ fail:
|
|||
return r;
|
||||
}
|
||||
|
||||
static void unpublish_all_services(struct userdata *u, int rem) {
|
||||
static void unpublish_all_services(struct userdata *u, pa_bool_t rem) {
|
||||
void *state = NULL;
|
||||
struct service *s;
|
||||
|
||||
assert(u);
|
||||
pa_assert(u);
|
||||
|
||||
pa_log_debug("Unpublishing services in Zeroconf");
|
||||
|
||||
while ((s = pa_hashmap_iterate(u->services, &state, NULL))) {
|
||||
if (s->entry_group) {
|
||||
if (rem) {
|
||||
pa_log_debug("Removing entry group for %s.", s->service_name);
|
||||
avahi_entry_group_free(s->entry_group);
|
||||
s->entry_group = NULL;
|
||||
} else
|
||||
} else {
|
||||
avahi_entry_group_reset(s->entry_group);
|
||||
pa_log_debug("Resetting entry group for %s.", s->service_name);
|
||||
}
|
||||
}
|
||||
|
||||
s->published = UNPUBLISHED;
|
||||
}
|
||||
|
||||
if (u->main_entry_group) {
|
||||
if (rem) {
|
||||
pa_log_debug("Removing main entry group.");
|
||||
avahi_entry_group_free(u->main_entry_group);
|
||||
u->main_entry_group = NULL;
|
||||
} else
|
||||
} else {
|
||||
avahi_entry_group_reset(u->main_entry_group);
|
||||
pa_log_debug("Resetting main entry group.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void client_callback(AvahiClient *c, AvahiClientState state, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
assert(c);
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(u);
|
||||
|
||||
u->client = c;
|
||||
|
||||
|
|
@ -568,13 +455,17 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda
|
|||
break;
|
||||
|
||||
case AVAHI_CLIENT_S_COLLISION:
|
||||
unpublish_all_services(u, 0);
|
||||
pa_log_debug("Host name collision");
|
||||
unpublish_all_services(u, FALSE);
|
||||
break;
|
||||
|
||||
case AVAHI_CLIENT_FAILURE:
|
||||
if (avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) {
|
||||
int error;
|
||||
unpublish_all_services(u, 1);
|
||||
|
||||
pa_log_debug("Avahi daemon disconnected.");
|
||||
|
||||
unpublish_all_services(u, TRUE);
|
||||
avahi_client_free(u->client);
|
||||
|
||||
if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error)))
|
||||
|
|
@ -587,11 +478,12 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda
|
|||
}
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
|
||||
struct userdata *u;
|
||||
uint32_t port = PA_NATIVE_DEFAULT_PORT;
|
||||
pa_modargs *ma = NULL;
|
||||
char hn[256];
|
||||
char hn[256], un[256];
|
||||
int error;
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
|
|
@ -599,30 +491,29 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port == 0 || port >= 0xFFFF) {
|
||||
if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port <= 0 || port > 0xFFFF) {
|
||||
pa_log("invalid port specified.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
m->userdata = u = pa_xnew(struct userdata, 1);
|
||||
u->core = c;
|
||||
u->core = m->core;
|
||||
u->port = (uint16_t) port;
|
||||
|
||||
u->avahi_poll = pa_avahi_poll_new(c->mainloop);
|
||||
u->avahi_poll = pa_avahi_poll_new(m->core->mainloop);
|
||||
|
||||
u->services = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
|
||||
u->sink_dynarray = pa_dynarray_new();
|
||||
u->source_dynarray = pa_dynarray_new();
|
||||
u->autoload_dynarray = pa_dynarray_new();
|
||||
u->services = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
|
||||
|
||||
u->subscription = pa_subscription_new(c,
|
||||
PA_SUBSCRIPTION_MASK_SINK|
|
||||
PA_SUBSCRIPTION_MASK_SOURCE|
|
||||
PA_SUBSCRIPTION_MASK_AUTOLOAD, subscribe_callback, u);
|
||||
u->sink_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_NEW_POST], (pa_hook_cb_t) device_new_or_changed_cb, u);
|
||||
u->sink_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_DESCRIPTION_CHANGED], (pa_hook_cb_t) device_new_or_changed_cb, u);
|
||||
u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], (pa_hook_cb_t) device_unlink_cb, u);
|
||||
u->source_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_NEW_POST], (pa_hook_cb_t) device_new_or_changed_cb, u);
|
||||
u->source_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_DESCRIPTION_CHANGED], (pa_hook_cb_t) device_new_or_changed_cb, u);
|
||||
u->source_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], (pa_hook_cb_t) device_unlink_cb, u);
|
||||
|
||||
u->main_entry_group = NULL;
|
||||
|
||||
u->service_name = pa_xstrdup(pa_get_host_name(hn, sizeof(hn)));
|
||||
u->service_name = pa_truncate_utf8(pa_sprintf_malloc("%s@%s", pa_get_user_name(un, sizeof(un)), pa_get_host_name(hn, sizeof(hn))), AVAHI_LABEL_MAX);
|
||||
|
||||
if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) {
|
||||
pa_log("pa_avahi_client_new() failed: %s", avahi_strerror(error));
|
||||
|
|
@ -634,7 +525,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
pa__done(c, m);
|
||||
pa__done(m);
|
||||
|
||||
if (ma)
|
||||
pa_modargs_free(ma);
|
||||
|
|
@ -642,41 +533,34 @@ fail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void service_free(void *p, void *userdata) {
|
||||
struct service *s = p;
|
||||
struct userdata *u = userdata;
|
||||
|
||||
assert(s);
|
||||
assert(u);
|
||||
|
||||
if (s->entry_group)
|
||||
avahi_entry_group_free(s->entry_group);
|
||||
|
||||
pa_xfree(s->service_name);
|
||||
pa_xfree(s->name);
|
||||
pa_xfree(s);
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata*u;
|
||||
assert(c && m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
if (u->services)
|
||||
pa_hashmap_free(u->services, service_free, u);
|
||||
if (u->services) {
|
||||
struct service *s;
|
||||
|
||||
if (u->subscription)
|
||||
pa_subscription_free(u->subscription);
|
||||
while ((s = pa_hashmap_get_first(u->services)))
|
||||
service_free(s);
|
||||
|
||||
if (u->sink_dynarray)
|
||||
pa_dynarray_free(u->sink_dynarray, NULL, NULL);
|
||||
if (u->source_dynarray)
|
||||
pa_dynarray_free(u->source_dynarray, NULL, NULL);
|
||||
if (u->autoload_dynarray)
|
||||
pa_dynarray_free(u->autoload_dynarray, NULL, NULL);
|
||||
pa_hashmap_free(u->services, NULL, NULL);
|
||||
}
|
||||
|
||||
if (u->sink_new_slot)
|
||||
pa_hook_slot_free(u->sink_new_slot);
|
||||
if (u->source_new_slot)
|
||||
pa_hook_slot_free(u->source_new_slot);
|
||||
if (u->sink_changed_slot)
|
||||
pa_hook_slot_free(u->sink_changed_slot);
|
||||
if (u->source_changed_slot)
|
||||
pa_hook_slot_free(u->source_changed_slot);
|
||||
if (u->sink_unlink_slot)
|
||||
pa_hook_slot_free(u->sink_unlink_slot);
|
||||
if (u->source_unlink_slot)
|
||||
pa_hook_slot_free(u->source_unlink_slot);
|
||||
|
||||
if (u->main_entry_group)
|
||||
avahi_entry_group_free(u->main_entry_group);
|
||||
|
|
@ -690,4 +574,3 @@ void pa__done(pa_core *c, pa_module*m) {
|
|||
pa_xfree(u->service_name);
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/soundcard.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -37,9 +36,11 @@
|
|||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "oss-util.h"
|
||||
|
||||
|
|
@ -47,46 +48,43 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) {
|
|||
int fd = -1;
|
||||
int caps;
|
||||
|
||||
assert(device && mode && (*mode == O_RDWR || *mode == O_RDONLY || *mode == O_WRONLY));
|
||||
pa_assert(device);
|
||||
pa_assert(mode);
|
||||
pa_assert(*mode == O_RDWR || *mode == O_RDONLY || *mode == O_WRONLY);
|
||||
|
||||
if(!pcaps)
|
||||
pcaps = ∩︀
|
||||
|
||||
if (*mode == O_RDWR) {
|
||||
if ((fd = open(device, O_RDWR|O_NDELAY)) >= 0) {
|
||||
int dcaps, *tcaps;
|
||||
if ((fd = open(device, O_RDWR|O_NDELAY|O_NOCTTY)) >= 0) {
|
||||
ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
|
||||
|
||||
tcaps = pcaps ? pcaps : &dcaps;
|
||||
|
||||
if (ioctl(fd, SNDCTL_DSP_GETCAPS, tcaps) < 0) {
|
||||
if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) {
|
||||
pa_log("SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (*tcaps & DSP_CAP_DUPLEX)
|
||||
if (*pcaps & DSP_CAP_DUPLEX)
|
||||
goto success;
|
||||
|
||||
pa_log_warn("'%s' doesn't support full duplex", device);
|
||||
|
||||
close(fd);
|
||||
pa_close(fd);
|
||||
}
|
||||
|
||||
if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY)) < 0) {
|
||||
if ((fd = open(device, (*mode = O_RDONLY)|O_NDELAY)) < 0) {
|
||||
if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY|O_NOCTTY)) < 0) {
|
||||
if ((fd = open(device, (*mode = O_RDONLY)|O_NDELAY|O_NOCTTY)) < 0) {
|
||||
pa_log("open('%s'): %s", device, pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((fd = open(device, *mode|O_NDELAY)) < 0) {
|
||||
if ((fd = open(device, *mode|O_NDELAY|O_NOCTTY)) < 0) {
|
||||
pa_log("open('%s'): %s", device, pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
success:
|
||||
|
||||
*pcaps = 0;
|
||||
|
||||
if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) {
|
||||
|
|
@ -94,12 +92,14 @@ success:
|
|||
goto fail;
|
||||
}
|
||||
|
||||
success:
|
||||
|
||||
pa_log_debug("capabilities:%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
*pcaps & DSP_CAP_BATCH ? " BATCH" : "",
|
||||
#ifdef DSP_CAP_BIND
|
||||
*pcaps & DSP_CAP_BIND ? " BIND" : "",
|
||||
#else
|
||||
"",
|
||||
"",
|
||||
#endif
|
||||
*pcaps & DSP_CAP_COPROC ? " COPROC" : "",
|
||||
*pcaps & DSP_CAP_DUPLEX ? " DUPLEX" : "",
|
||||
|
|
@ -122,7 +122,7 @@ success:
|
|||
#ifdef DSP_CAP_MULTI
|
||||
*pcaps & DSP_CAP_MULTI ? " MULTI" : "",
|
||||
#else
|
||||
"",
|
||||
"",
|
||||
#endif
|
||||
#ifdef DSP_CAP_OUTPUT
|
||||
*pcaps & DSP_CAP_OUTPUT ? " OUTPUT" : "",
|
||||
|
|
@ -142,13 +142,13 @@ success:
|
|||
#endif
|
||||
*pcaps & DSP_CAP_TRIGGER ? " TRIGGER" : "");
|
||||
|
||||
pa_fd_set_cloexec(fd, 1);
|
||||
pa_make_fd_cloexec(fd);
|
||||
|
||||
return fd;
|
||||
|
||||
fail:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
pa_close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +166,8 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) {
|
|||
[PA_SAMPLE_FLOAT32BE] = AFMT_QUERY, /* not supported */
|
||||
};
|
||||
|
||||
assert(fd >= 0 && ss);
|
||||
pa_assert(fd >= 0);
|
||||
pa_assert(ss);
|
||||
|
||||
orig_format = ss->format;
|
||||
|
||||
|
|
@ -199,7 +200,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) {
|
|||
pa_log("SNDCTL_DSP_CHANNELS: %s", pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
assert(channels > 0);
|
||||
pa_assert(channels > 0);
|
||||
|
||||
if (ss->channels != channels) {
|
||||
pa_log_warn("device doesn't support %i channels, using %i channels.", ss->channels, channels);
|
||||
|
|
@ -211,7 +212,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) {
|
|||
pa_log("SNDCTL_DSP_SPEED: %s", pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
assert(speed > 0);
|
||||
pa_assert(speed > 0);
|
||||
|
||||
if (ss->rate != (unsigned) speed) {
|
||||
pa_log_warn("device doesn't support %i Hz, changed to %i Hz.", ss->rate, speed);
|
||||
|
|
@ -248,27 +249,29 @@ int pa_oss_set_fragments(int fd, int nfrags, int frag_size) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvolume *volume) {
|
||||
int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvolume *volume) {
|
||||
char cv[PA_CVOLUME_SNPRINT_MAX];
|
||||
unsigned vol;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ss);
|
||||
assert(volume);
|
||||
pa_assert(fd >= 0);
|
||||
pa_assert(ss);
|
||||
pa_assert(volume);
|
||||
|
||||
if (ioctl(fd, mixer, &vol) < 0)
|
||||
return -1;
|
||||
|
||||
pa_cvolume_reset(volume, ss->channels);
|
||||
|
||||
volume->values[0] = ((vol & 0xFF) * PA_VOLUME_NORM) / 100;
|
||||
|
||||
if ((volume->channels = ss->channels) >= 2)
|
||||
if (volume->channels >= 2)
|
||||
volume->values[1] = (((vol >> 8) & 0xFF) * PA_VOLUME_NORM) / 100;
|
||||
|
||||
pa_log_debug("Read mixer settings: %s", pa_cvolume_snprint(cv, sizeof(cv), volume));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pa_oss_set_volume(int fd, int mixer, const pa_sample_spec *ss, const pa_cvolume *volume) {
|
||||
int pa_oss_set_volume(int fd, long mixer, const pa_sample_spec *ss, const pa_cvolume *volume) {
|
||||
char cv[PA_CVOLUME_SNPRINT_MAX];
|
||||
unsigned vol;
|
||||
pa_volume_t l, r;
|
||||
|
|
@ -289,40 +292,38 @@ static int pa_oss_set_volume(int fd, int mixer, const pa_sample_spec *ss, const
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pa_oss_get_pcm_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume) {
|
||||
return pa_oss_get_volume(fd, SOUND_MIXER_READ_PCM, ss, volume);
|
||||
}
|
||||
static int get_device_number(const char *dev) {
|
||||
char buf[PATH_MAX];
|
||||
const char *p, *e;
|
||||
|
||||
int pa_oss_set_pcm_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume) {
|
||||
return pa_oss_set_volume(fd, SOUND_MIXER_WRITE_PCM, ss, volume);
|
||||
}
|
||||
if (readlink(dev, buf, sizeof(buf)) < 0) {
|
||||
if (errno != EINVAL && errno != ENOLINK)
|
||||
return -1;
|
||||
|
||||
int pa_oss_get_input_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume) {
|
||||
return pa_oss_get_volume(fd, SOUND_MIXER_READ_IGAIN, ss, volume);
|
||||
}
|
||||
p = dev;
|
||||
} else
|
||||
p = buf;
|
||||
|
||||
int pa_oss_set_input_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume) {
|
||||
return pa_oss_set_volume(fd, SOUND_MIXER_WRITE_IGAIN, ss, volume);
|
||||
if ((e = strrchr(p, '/')))
|
||||
p = e+1;
|
||||
|
||||
if (p == 0)
|
||||
return 0;
|
||||
|
||||
p = strchr(p, 0) -1;
|
||||
|
||||
if (*p >= '0' && *p <= '9')
|
||||
return *p - '0';
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pa_oss_get_hw_description(const char *dev, char *name, size_t l) {
|
||||
FILE *f;
|
||||
const char *e = NULL;
|
||||
int n, r = -1;
|
||||
int b = 0;
|
||||
|
||||
if (strncmp(dev, "/dev/dsp", 8) == 0)
|
||||
e = dev+8;
|
||||
else if (strncmp(dev, "/dev/adsp", 9) == 0)
|
||||
e = dev+9;
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (*e == 0)
|
||||
n = 0;
|
||||
else if (*e >= '0' && *e <= '9' && *(e+1) == 0)
|
||||
n = *e - '0';
|
||||
else
|
||||
if ((n = get_device_number(dev)) < 0)
|
||||
return -1;
|
||||
|
||||
if (!(f = fopen("/dev/sndstat", "r")) &&
|
||||
|
|
@ -357,7 +358,7 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) {
|
|||
|
||||
if (device == n) {
|
||||
char *k = strchr(line, ':');
|
||||
assert(k);
|
||||
pa_assert(k);
|
||||
k++;
|
||||
k += strspn(k, " ");
|
||||
|
||||
|
|
@ -373,3 +374,34 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) {
|
|||
fclose(f);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int open_mixer(const char *mixer) {
|
||||
int fd;
|
||||
|
||||
if ((fd = open(mixer, O_RDWR|O_NDELAY|O_NOCTTY)) >= 0)
|
||||
return fd;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pa_oss_open_mixer_for_device(const char *device) {
|
||||
int n;
|
||||
char *fn;
|
||||
int fd;
|
||||
|
||||
if ((n = get_device_number(device)) < 0)
|
||||
return -1;
|
||||
|
||||
if (n == 0)
|
||||
if ((fd = open_mixer("/dev/mixer")) >= 0)
|
||||
return fd;
|
||||
|
||||
fn = pa_sprintf_malloc("/dev/mixer%i", n);
|
||||
fd = open_mixer(fn);
|
||||
pa_xfree(fn);
|
||||
|
||||
if (fd < 0)
|
||||
pa_log_warn("Failed to open mixer '%s': %s", device, pa_cstrerror(errno));
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,12 +33,11 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss);
|
|||
|
||||
int pa_oss_set_fragments(int fd, int frags, int frag_size);
|
||||
|
||||
int pa_oss_get_pcm_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume);
|
||||
int pa_oss_set_pcm_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume);
|
||||
|
||||
int pa_oss_get_input_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume);
|
||||
int pa_oss_set_input_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume);
|
||||
int pa_oss_set_volume(int fd, long mixer, const pa_sample_spec *ss, const pa_cvolume *volume);
|
||||
int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvolume *volume);
|
||||
|
||||
int pa_oss_get_hw_description(const char *dev, char *name, size_t l);
|
||||
|
||||
int pa_oss_open_mixer_for_device(const char *device);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
|
@ -32,6 +31,7 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
|
|
@ -47,6 +47,10 @@
|
|||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/namereg.h>
|
||||
#include <pulsecore/sample-util.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/atomic.h>
|
||||
#include <pulsecore/rtclock.h>
|
||||
#include <pulsecore/atomic.h>
|
||||
|
||||
#include "module-rtp-recv-symdef.h"
|
||||
|
||||
|
|
@ -66,7 +70,7 @@ PA_MODULE_USAGE(
|
|||
#define DEFAULT_SAP_ADDRESS "224.0.0.56"
|
||||
#define MEMBLOCKQ_MAXLENGTH (1024*170)
|
||||
#define MAX_SESSIONS 16
|
||||
#define DEATH_TIMEOUT 20000000
|
||||
#define DEATH_TIMEOUT 20
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"sink",
|
||||
|
|
@ -76,102 +80,126 @@ static const char* const valid_modargs[] = {
|
|||
|
||||
struct session {
|
||||
struct userdata *userdata;
|
||||
PA_LLIST_FIELDS(struct session);
|
||||
|
||||
pa_sink_input *sink_input;
|
||||
pa_memblockq *memblockq;
|
||||
|
||||
pa_time_event *death_event;
|
||||
|
||||
int first_packet;
|
||||
pa_bool_t first_packet;
|
||||
uint32_t ssrc;
|
||||
uint32_t offset;
|
||||
|
||||
struct pa_sdp_info sdp_info;
|
||||
|
||||
pa_rtp_context rtp_context;
|
||||
pa_io_event* rtp_event;
|
||||
|
||||
pa_rtpoll_item *rtpoll_item;
|
||||
|
||||
pa_atomic_t timestamp;
|
||||
};
|
||||
|
||||
struct userdata {
|
||||
pa_module *module;
|
||||
pa_core *core;
|
||||
|
||||
pa_sap_context sap_context;
|
||||
pa_io_event* sap_event;
|
||||
|
||||
pa_hashmap *by_origin;
|
||||
pa_time_event *check_death_event;
|
||||
|
||||
char *sink_name;
|
||||
|
||||
PA_LLIST_HEAD(struct session, sessions);
|
||||
pa_hashmap *by_origin;
|
||||
int n_sessions;
|
||||
};
|
||||
|
||||
static void session_free(struct session *s, int from_hash);
|
||||
static void session_free(struct session *s);
|
||||
|
||||
static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
|
||||
/* Called from I/O thread context */
|
||||
static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
struct session *s = PA_SINK_INPUT(o)->userdata;
|
||||
|
||||
switch (code) {
|
||||
case PA_SINK_INPUT_MESSAGE_GET_LATENCY:
|
||||
*((pa_usec_t*) data) = pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec);
|
||||
|
||||
/* Fall through, the default handler will add in the extra
|
||||
* latency added by the resampler */
|
||||
break;
|
||||
}
|
||||
|
||||
return pa_sink_input_process_msg(o, code, data, offset, chunk);
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static int sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
|
||||
struct session *s;
|
||||
assert(i);
|
||||
s = i->userdata;
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(s = i->userdata);
|
||||
|
||||
return pa_memblockq_peek(s->memblockq, chunk);
|
||||
}
|
||||
|
||||
static void sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
|
||||
/* Called from I/O thread context */
|
||||
static void sink_input_drop(pa_sink_input *i, size_t length) {
|
||||
struct session *s;
|
||||
assert(i);
|
||||
s = i->userdata;
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(s = i->userdata);
|
||||
|
||||
pa_memblockq_drop(s->memblockq, chunk, length);
|
||||
pa_memblockq_drop(s->memblockq, length);
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
static void sink_input_kill(pa_sink_input* i) {
|
||||
struct session *s;
|
||||
assert(i);
|
||||
s = i->userdata;
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(s = i->userdata);
|
||||
|
||||
session_free(s, 1);
|
||||
session_free(s);
|
||||
}
|
||||
|
||||
static pa_usec_t sink_input_get_latency(pa_sink_input *i) {
|
||||
struct session *s;
|
||||
assert(i);
|
||||
s = i->userdata;
|
||||
|
||||
return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->sample_spec);
|
||||
}
|
||||
|
||||
static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) {
|
||||
struct session *s = userdata;
|
||||
/* Called from I/O thread context */
|
||||
static int rtpoll_work_cb(pa_rtpoll_item *i) {
|
||||
pa_memchunk chunk;
|
||||
int64_t k, j, delta;
|
||||
struct timeval tv;
|
||||
struct timeval now;
|
||||
struct session *s;
|
||||
struct pollfd *p;
|
||||
|
||||
assert(m);
|
||||
assert(e);
|
||||
assert(s);
|
||||
assert(fd == s->rtp_context.fd);
|
||||
assert(flags == PA_IO_EVENT_INPUT);
|
||||
pa_assert_se(s = pa_rtpoll_item_get_userdata(i));
|
||||
|
||||
if (pa_rtp_recv(&s->rtp_context, &chunk, s->userdata->core->mempool) < 0)
|
||||
return;
|
||||
p = pa_rtpoll_item_get_pollfd(i, NULL);
|
||||
|
||||
if (p->revents & (POLLERR|POLLNVAL|POLLHUP|POLLOUT)) {
|
||||
pa_log("poll() signalled bad revents.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((p->revents & POLLIN) == 0)
|
||||
return 0;
|
||||
|
||||
p->revents = 0;
|
||||
|
||||
if (pa_rtp_recv(&s->rtp_context, &chunk, s->userdata->module->core->mempool) < 0)
|
||||
return 0;
|
||||
|
||||
if (s->sdp_info.payload != s->rtp_context.payload) {
|
||||
pa_memblock_unref(chunk.memblock);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s->first_packet) {
|
||||
s->first_packet = 1;
|
||||
s->first_packet = TRUE;
|
||||
|
||||
s->ssrc = s->rtp_context.ssrc;
|
||||
s->offset = s->rtp_context.timestamp;
|
||||
|
||||
if (s->ssrc == s->userdata->core->cookie)
|
||||
pa_log_warn("WARNING! Detected RTP packet loop!");
|
||||
if (s->ssrc == s->userdata->module->core->cookie)
|
||||
pa_log_warn("Detected RTP packet loop!");
|
||||
} else {
|
||||
if (s->ssrc != s->rtp_context.ssrc) {
|
||||
pa_memblock_unref(chunk.memblock);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -197,26 +225,49 @@ static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event
|
|||
|
||||
pa_memblock_unref(chunk.memblock);
|
||||
|
||||
/* Reset death timer */
|
||||
pa_gettimeofday(&tv);
|
||||
pa_timeval_add(&tv, DEATH_TIMEOUT);
|
||||
m->time_restart(s->death_event, &tv);
|
||||
pa_rtclock_get(&now);
|
||||
pa_atomic_store(&s->timestamp, now.tv_sec);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void death_event_cb(pa_mainloop_api *m, pa_time_event *t, const struct timeval *tv, void *userdata) {
|
||||
struct session *s = userdata;
|
||||
/* Called from I/O thread context */
|
||||
static void sink_input_attach(pa_sink_input *i) {
|
||||
struct session *s;
|
||||
struct pollfd *p;
|
||||
|
||||
assert(m);
|
||||
assert(t);
|
||||
assert(tv);
|
||||
assert(s);
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(s = i->userdata);
|
||||
|
||||
session_free(s, 1);
|
||||
pa_assert(!s->rtpoll_item);
|
||||
s->rtpoll_item = pa_rtpoll_item_new(i->sink->rtpoll, PA_RTPOLL_LATE, 1);
|
||||
|
||||
p = pa_rtpoll_item_get_pollfd(s->rtpoll_item, NULL);
|
||||
p->fd = s->rtp_context.fd;
|
||||
p->events = POLLIN;
|
||||
p->revents = 0;
|
||||
|
||||
pa_rtpoll_item_set_work_callback(s->rtpoll_item, rtpoll_work_cb);
|
||||
pa_rtpoll_item_set_userdata(s->rtpoll_item, s);
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static void sink_input_detach(pa_sink_input *i) {
|
||||
struct session *s;
|
||||
pa_sink_input_assert_ref(i);
|
||||
pa_assert_se(s = i->userdata);
|
||||
|
||||
pa_assert(s->rtpoll_item);
|
||||
pa_rtpoll_item_free(s->rtpoll_item);
|
||||
s->rtpoll_item = NULL;
|
||||
}
|
||||
|
||||
static int mcast_socket(const struct sockaddr* sa, socklen_t salen) {
|
||||
int af, fd = -1, r, one;
|
||||
|
||||
pa_assert(sa);
|
||||
pa_assert(salen > 0);
|
||||
|
||||
af = sa->sa_family;
|
||||
if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) {
|
||||
pa_log("Failed to create socket: %s", pa_cstrerror(errno));
|
||||
|
|
@ -262,27 +313,34 @@ fail:
|
|||
|
||||
static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_info) {
|
||||
struct session *s = NULL;
|
||||
struct timeval tv;
|
||||
char *c;
|
||||
pa_sink *sink;
|
||||
int fd = -1;
|
||||
pa_memblock *silence;
|
||||
pa_sink_input_new_data data;
|
||||
struct timeval now;
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(sdp_info);
|
||||
|
||||
if (u->n_sessions >= MAX_SESSIONS) {
|
||||
pa_log("session limit reached.");
|
||||
pa_log("Session limit reached.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(sink = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) {
|
||||
pa_log("sink does not exist.");
|
||||
if (!(sink = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) {
|
||||
pa_log("Sink does not exist.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
s = pa_xnew0(struct session, 1);
|
||||
s->userdata = u;
|
||||
s->first_packet = 0;
|
||||
s->first_packet = FALSE;
|
||||
s->sdp_info = *sdp_info;
|
||||
s->rtpoll_item = NULL;
|
||||
|
||||
pa_rtclock_get(&now);
|
||||
pa_atomic_store(&s->timestamp, now.tv_sec);
|
||||
|
||||
if ((fd = mcast_socket((const struct sockaddr*) &sdp_info->sa, sdp_info->salen)) < 0)
|
||||
goto fail;
|
||||
|
|
@ -299,25 +357,27 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
|
|||
data.module = u->module;
|
||||
pa_sink_input_new_data_set_sample_spec(&data, &sdp_info->sample_spec);
|
||||
|
||||
s->sink_input = pa_sink_input_new(u->core, &data, 0);
|
||||
s->sink_input = pa_sink_input_new(u->module->core, &data, 0);
|
||||
pa_xfree(c);
|
||||
|
||||
if (!s->sink_input) {
|
||||
pa_log("failed to create sink input.");
|
||||
pa_log("Failed to create sink input.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
s->sink_input->userdata = s;
|
||||
|
||||
s->sink_input->parent.process_msg = sink_input_process_msg;
|
||||
s->sink_input->peek = sink_input_peek;
|
||||
s->sink_input->drop = sink_input_drop;
|
||||
s->sink_input->kill = sink_input_kill;
|
||||
s->sink_input->get_latency = sink_input_get_latency;
|
||||
s->sink_input->attach = sink_input_attach;
|
||||
s->sink_input->detach = sink_input_detach;
|
||||
|
||||
silence = pa_silence_memblock_new(s->userdata->core->mempool,
|
||||
&s->sink_input->sample_spec,
|
||||
(pa_bytes_per_second(&s->sink_input->sample_spec)/128/pa_frame_size(&s->sink_input->sample_spec))*
|
||||
pa_frame_size(&s->sink_input->sample_spec));
|
||||
silence = pa_silence_memblock_new(
|
||||
s->userdata->module->core->mempool,
|
||||
&s->sink_input->sample_spec,
|
||||
pa_frame_align(pa_bytes_per_second(&s->sink_input->sample_spec)/128, &s->sink_input->sample_spec));
|
||||
|
||||
s->memblockq = pa_memblockq_new(
|
||||
0,
|
||||
|
|
@ -330,54 +390,44 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
|
|||
|
||||
pa_memblock_unref(silence);
|
||||
|
||||
s->rtp_event = u->core->mainloop->io_new(u->core->mainloop, fd, PA_IO_EVENT_INPUT, rtp_event_cb, s);
|
||||
|
||||
pa_gettimeofday(&tv);
|
||||
pa_timeval_add(&tv, DEATH_TIMEOUT);
|
||||
s->death_event = u->core->mainloop->time_new(u->core->mainloop, &tv, death_event_cb, s);
|
||||
|
||||
pa_hashmap_put(s->userdata->by_origin, s->sdp_info.origin, s);
|
||||
|
||||
pa_rtp_context_init_recv(&s->rtp_context, fd, pa_frame_size(&s->sdp_info.sample_spec));
|
||||
|
||||
pa_log_info("Found new session '%s'", s->sdp_info.session_name);
|
||||
|
||||
pa_hashmap_put(s->userdata->by_origin, s->sdp_info.origin, s);
|
||||
u->n_sessions++;
|
||||
PA_LLIST_PREPEND(struct session, s->userdata->sessions, s);
|
||||
|
||||
pa_sink_input_put(s->sink_input);
|
||||
|
||||
pa_log_info("New session '%s'", s->sdp_info.session_name);
|
||||
|
||||
return s;
|
||||
|
||||
fail:
|
||||
if (s) {
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
pa_xfree(s);
|
||||
|
||||
pa_xfree(s);
|
||||
}
|
||||
if (fd >= 0)
|
||||
pa_close(fd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void session_free(struct session *s, int from_hash) {
|
||||
assert(s);
|
||||
static void session_free(struct session *s) {
|
||||
pa_assert(s);
|
||||
|
||||
pa_log_info("Freeing session '%s'", s->sdp_info.session_name);
|
||||
|
||||
s->userdata->core->mainloop->time_free(s->death_event);
|
||||
s->userdata->core->mainloop->io_free(s->rtp_event);
|
||||
|
||||
if (from_hash)
|
||||
pa_hashmap_remove(s->userdata->by_origin, s->sdp_info.origin);
|
||||
|
||||
pa_sink_input_disconnect(s->sink_input);
|
||||
pa_sink_input_unlink(s->sink_input);
|
||||
pa_sink_input_unref(s->sink_input);
|
||||
|
||||
PA_LLIST_REMOVE(struct session, s->userdata->sessions, s);
|
||||
pa_assert(s->userdata->n_sessions >= 1);
|
||||
s->userdata->n_sessions--;
|
||||
pa_hashmap_remove(s->userdata->by_origin, s->sdp_info.origin);
|
||||
|
||||
pa_memblockq_free(s->memblockq);
|
||||
pa_sdp_info_destroy(&s->sdp_info);
|
||||
pa_rtp_context_destroy(&s->rtp_context);
|
||||
|
||||
assert(s->userdata->n_sessions >= 1);
|
||||
s->userdata->n_sessions--;
|
||||
|
||||
pa_xfree(s);
|
||||
}
|
||||
|
||||
|
|
@ -387,11 +437,11 @@ static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event
|
|||
pa_sdp_info info;
|
||||
struct session *s;
|
||||
|
||||
assert(m);
|
||||
assert(e);
|
||||
assert(u);
|
||||
assert(fd == u->sap_context.fd);
|
||||
assert(flags == PA_IO_EVENT_INPUT);
|
||||
pa_assert(m);
|
||||
pa_assert(e);
|
||||
pa_assert(u);
|
||||
pa_assert(fd == u->sap_context.fd);
|
||||
pa_assert(flags == PA_IO_EVENT_INPUT);
|
||||
|
||||
if (pa_sap_recv(&u->sap_context, &goodbye) < 0)
|
||||
return;
|
||||
|
|
@ -402,7 +452,7 @@ static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event
|
|||
if (goodbye) {
|
||||
|
||||
if ((s = pa_hashmap_get(u->by_origin, info.origin)))
|
||||
session_free(s, 1);
|
||||
session_free(s);
|
||||
|
||||
pa_sdp_info_destroy(&info);
|
||||
} else {
|
||||
|
|
@ -412,18 +462,47 @@ static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event
|
|||
pa_sdp_info_destroy(&info);
|
||||
|
||||
} else {
|
||||
struct timeval tv;
|
||||
|
||||
pa_gettimeofday(&tv);
|
||||
pa_timeval_add(&tv, DEATH_TIMEOUT);
|
||||
m->time_restart(s->death_event, &tv);
|
||||
struct timeval now;
|
||||
pa_rtclock_get(&now);
|
||||
pa_atomic_store(&s->timestamp, now.tv_sec);
|
||||
|
||||
pa_sdp_info_destroy(&info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
static void check_death_event_cb(pa_mainloop_api *m, pa_time_event *t, const struct timeval *ptv, void *userdata) {
|
||||
struct session *s, *n;
|
||||
struct userdata *u = userdata;
|
||||
struct timeval now;
|
||||
struct timeval tv;
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(t);
|
||||
pa_assert(ptv);
|
||||
pa_assert(u);
|
||||
|
||||
pa_rtclock_get(&now);
|
||||
|
||||
pa_log_debug("Checking for dead streams ...");
|
||||
|
||||
for (s = u->sessions; s; s = n) {
|
||||
int k;
|
||||
n = s->next;
|
||||
|
||||
k = pa_atomic_load(&s->timestamp);
|
||||
|
||||
if (k + DEATH_TIMEOUT < now.tv_sec)
|
||||
session_free(s);
|
||||
}
|
||||
|
||||
/* Restart timer */
|
||||
pa_gettimeofday(&tv);
|
||||
pa_timeval_add(&tv, DEATH_TIMEOUT*PA_USEC_PER_SEC);
|
||||
m->time_restart(t, &tv);
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
struct userdata *u;
|
||||
pa_modargs *ma = NULL;
|
||||
struct sockaddr_in sa4;
|
||||
|
|
@ -432,9 +511,9 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
socklen_t salen;
|
||||
const char *sap_address;
|
||||
int fd = -1;
|
||||
struct timeval tv;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("failed to parse module arguments");
|
||||
|
|
@ -454,7 +533,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
sa = (struct sockaddr*) &sa4;
|
||||
salen = sizeof(sa4);
|
||||
} else {
|
||||
pa_log("invalid SAP address '%s'", sap_address);
|
||||
pa_log("Invalid SAP address '%s'", sap_address);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -464,15 +543,18 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
u = pa_xnew(struct userdata, 1);
|
||||
m->userdata = u;
|
||||
u->module = m;
|
||||
u->core = c;
|
||||
u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
|
||||
|
||||
u->sap_event = m->core->mainloop->io_new(m->core->mainloop, fd, PA_IO_EVENT_INPUT, sap_event_cb, u);
|
||||
pa_sap_context_init_recv(&u->sap_context, fd);
|
||||
|
||||
PA_LLIST_HEAD_INIT(struct session, u->sessions);
|
||||
u->n_sessions = 0;
|
||||
|
||||
u->sap_event = c->mainloop->io_new(c->mainloop, fd, PA_IO_EVENT_INPUT, sap_event_cb, u);
|
||||
|
||||
u->by_origin = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
|
||||
|
||||
pa_sap_context_init_recv(&u->sap_context, fd);
|
||||
pa_gettimeofday(&tv);
|
||||
pa_timeval_add(&tv, DEATH_TIMEOUT * PA_USEC_PER_SEC);
|
||||
u->check_death_event = m->core->mainloop->time_new(m->core->mainloop, &tv, check_death_event_cb, u);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
||||
|
|
@ -483,27 +565,34 @@ fail:
|
|||
pa_modargs_free(ma);
|
||||
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
pa_close(fd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void free_func(void *p, PA_GCC_UNUSED void *userdata) {
|
||||
session_free(p, 0);
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
assert(c);
|
||||
assert(m);
|
||||
struct session *s;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
c->mainloop->io_free(u->sap_event);
|
||||
if (u->sap_event)
|
||||
m->core->mainloop->io_free(u->sap_event);
|
||||
|
||||
if (u->check_death_event)
|
||||
m->core->mainloop->time_free(u->check_death_event);
|
||||
|
||||
pa_sap_context_destroy(&u->sap_context);
|
||||
|
||||
pa_hashmap_free(u->by_origin, free_func, NULL);
|
||||
if (u->by_origin) {
|
||||
while ((s = pa_hashmap_get_first(u->by_origin)))
|
||||
session_free(s);
|
||||
|
||||
pa_hashmap_free(u->by_origin, NULL, NULL);
|
||||
}
|
||||
|
||||
pa_xfree(u->sink_name);
|
||||
pa_xfree(u);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
|
@ -48,6 +47,9 @@
|
|||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/namereg.h>
|
||||
#include <pulsecore/sample-util.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/socket-util.h>
|
||||
|
||||
#include "module-rtp-send-symdef.h"
|
||||
|
||||
|
|
@ -74,7 +76,7 @@ PA_MODULE_USAGE(
|
|||
#define DEFAULT_DESTINATION "224.0.0.56"
|
||||
#define MEMBLOCKQ_MAXLENGTH (1024*170)
|
||||
#define DEFAULT_MTU 1280
|
||||
#define SAP_INTERVAL 5000000
|
||||
#define SAP_INTERVAL 5
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"source",
|
||||
|
|
@ -90,7 +92,6 @@ static const char* const valid_modargs[] = {
|
|||
|
||||
struct userdata {
|
||||
pa_module *module;
|
||||
pa_core *core;
|
||||
|
||||
pa_source_output *source_output;
|
||||
pa_memblockq *memblockq;
|
||||
|
|
@ -102,56 +103,67 @@ struct userdata {
|
|||
pa_time_event *sap_event;
|
||||
};
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static int source_output_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
struct userdata *u;
|
||||
pa_assert_se(u = PA_SOURCE_OUTPUT(o)->userdata);
|
||||
|
||||
switch (code) {
|
||||
case PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY:
|
||||
*((pa_usec_t*) data) = pa_bytes_to_usec(pa_memblockq_get_length(u->memblockq), &u->source_output->sample_spec);
|
||||
|
||||
/* Fall through, the default handler will add in the extra
|
||||
* latency added by the resampler */
|
||||
break;
|
||||
}
|
||||
|
||||
return pa_source_output_process_msg(o, code, data, offset, chunk);
|
||||
}
|
||||
|
||||
/* Called from I/O thread context */
|
||||
static void source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
|
||||
struct userdata *u;
|
||||
assert(o);
|
||||
u = o->userdata;
|
||||
pa_source_output_assert_ref(o);
|
||||
pa_assert_se(u = o->userdata);
|
||||
|
||||
if (pa_memblockq_push(u->memblockq, chunk) < 0) {
|
||||
pa_log("Failed to push chunk into memblockq.");
|
||||
pa_log_warn("Failed to push chunk into memblockq.");
|
||||
return;
|
||||
}
|
||||
|
||||
pa_rtp_send(&u->rtp_context, u->mtu, u->memblockq);
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
static void source_output_kill(pa_source_output* o) {
|
||||
struct userdata *u;
|
||||
assert(o);
|
||||
u = o->userdata;
|
||||
pa_source_output_assert_ref(o);
|
||||
pa_assert_se(u = o->userdata);
|
||||
|
||||
pa_module_unload_request(u->module);
|
||||
|
||||
pa_source_output_disconnect(u->source_output);
|
||||
pa_source_output_unlink(u->source_output);
|
||||
pa_source_output_unref(u->source_output);
|
||||
u->source_output = NULL;
|
||||
}
|
||||
|
||||
static pa_usec_t source_output_get_latency (pa_source_output *o) {
|
||||
struct userdata *u;
|
||||
assert(o);
|
||||
u = o->userdata;
|
||||
|
||||
return pa_bytes_to_usec(pa_memblockq_get_length(u->memblockq), &o->sample_spec);
|
||||
}
|
||||
|
||||
static void sap_event_cb(pa_mainloop_api *m, pa_time_event *t, const struct timeval *tv, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
struct timeval next;
|
||||
|
||||
assert(m);
|
||||
assert(t);
|
||||
assert(tv);
|
||||
assert(u);
|
||||
pa_assert(m);
|
||||
pa_assert(t);
|
||||
pa_assert(tv);
|
||||
pa_assert(u);
|
||||
|
||||
pa_sap_send(&u->sap_context, 0);
|
||||
|
||||
pa_gettimeofday(&next);
|
||||
pa_timeval_add(&next, SAP_INTERVAL);
|
||||
pa_timeval_add(&next, SAP_INTERVAL * PA_USEC_PER_SEC);
|
||||
m->time_restart(t, &next);
|
||||
}
|
||||
|
||||
int pa__init(pa_core *c, pa_module*m) {
|
||||
int pa__init(pa_module*m) {
|
||||
struct userdata *u;
|
||||
pa_modargs *ma = NULL;
|
||||
const char *dest;
|
||||
|
|
@ -173,21 +185,20 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
int loop = 0;
|
||||
pa_source_output_new_data data;
|
||||
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("failed to parse module arguments");
|
||||
pa_log("Failed to parse module arguments");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(s = pa_namereg_get(m->core, pa_modargs_get_value(ma, "source", NULL), PA_NAMEREG_SOURCE, 1))) {
|
||||
pa_log("source does not exist.");
|
||||
pa_log("Source does not exist.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "loop", &loop) < 0) {
|
||||
pa_log("failed to parse \"loop\" parameter.");
|
||||
pa_log("Failed to parse \"loop\" parameter.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -195,12 +206,12 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
pa_rtp_sample_spec_fixup(&ss);
|
||||
cm = s->channel_map;
|
||||
if (pa_modargs_get_sample_spec(ma, &ss) < 0) {
|
||||
pa_log("failed to parse sample specification");
|
||||
pa_log("Failed to parse sample specification");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!pa_rtp_sample_spec_valid(&ss)) {
|
||||
pa_log("specified sample type not compatible with RTP");
|
||||
pa_log("Specified sample type not compatible with RTP");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -209,10 +220,10 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
|
||||
payload = pa_rtp_payload_from_sample_spec(&ss);
|
||||
|
||||
mtu = (DEFAULT_MTU/pa_frame_size(&ss))*pa_frame_size(&ss);
|
||||
mtu = pa_frame_align(DEFAULT_MTU, &ss);
|
||||
|
||||
if (pa_modargs_get_value_u32(ma, "mtu", &mtu) < 0 || mtu < 1 || mtu % pa_frame_size(&ss) != 0) {
|
||||
pa_log("invalid mtu.");
|
||||
pa_log("Invalid MTU.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -223,7 +234,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
}
|
||||
|
||||
if (port & 1)
|
||||
pa_log_warn("WARNING: port number not even as suggested in RFC3550!");
|
||||
pa_log_warn("Port number not even as suggested in RFC3550!");
|
||||
|
||||
dest = pa_modargs_get_value(ma, "destination", DEFAULT_DESTINATION);
|
||||
|
||||
|
|
@ -238,7 +249,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
sap_sa4 = sa4;
|
||||
sap_sa4.sin_port = htons(SAP_PORT);
|
||||
} else {
|
||||
pa_log("invalid destination '%s'", dest);
|
||||
pa_log("Invalid destination '%s'", dest);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -268,6 +279,12 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
/* If the socket queue is full, let's drop packets */
|
||||
pa_make_fd_nonblock(fd);
|
||||
pa_make_udp_socket_low_delay(fd);
|
||||
pa_make_fd_cloexec(fd);
|
||||
pa_make_fd_cloexec(sap_fd);
|
||||
|
||||
pa_source_output_new_data_init(&data);
|
||||
data.name = "RTP Monitor Stream";
|
||||
data.driver = __FILE__;
|
||||
|
|
@ -276,21 +293,20 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
pa_source_output_new_data_set_sample_spec(&data, &ss);
|
||||
pa_source_output_new_data_set_channel_map(&data, &cm);
|
||||
|
||||
if (!(o = pa_source_output_new(c, &data, 0))) {
|
||||
if (!(o = pa_source_output_new(m->core, &data, 0))) {
|
||||
pa_log("failed to create source output.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
o->parent.process_msg = source_output_process_msg;
|
||||
o->push = source_output_push;
|
||||
o->kill = source_output_kill;
|
||||
o->get_latency = source_output_get_latency;
|
||||
|
||||
u = pa_xnew(struct userdata, 1);
|
||||
m->userdata = u;
|
||||
o->userdata = u;
|
||||
|
||||
u->module = m;
|
||||
u->core = c;
|
||||
u->source_output = o;
|
||||
|
||||
u->memblockq = pa_memblockq_new(
|
||||
|
|
@ -305,8 +321,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
u->mtu = mtu;
|
||||
|
||||
k = sizeof(sa_dst);
|
||||
r = getsockname(fd, (struct sockaddr*) &sa_dst, &k);
|
||||
assert(r >= 0);
|
||||
pa_assert_se((r = getsockname(fd, (struct sockaddr*) &sa_dst, &k)) >= 0);
|
||||
|
||||
n = pa_sprintf_malloc("PulseAudio RTP Stream on %s", pa_get_fqdn(hn, sizeof(hn)));
|
||||
|
||||
|
|
@ -317,17 +332,19 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
|
||||
pa_xfree(n);
|
||||
|
||||
pa_rtp_context_init_send(&u->rtp_context, fd, c->cookie, payload, pa_frame_size(&ss));
|
||||
pa_rtp_context_init_send(&u->rtp_context, fd, m->core->cookie, payload, pa_frame_size(&ss));
|
||||
pa_sap_context_init_send(&u->sap_context, sap_fd, p);
|
||||
|
||||
pa_log_info("RTP stream initialized with mtu %u on %s:%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, u->rtp_context.ssrc, payload, u->rtp_context.sequence);
|
||||
pa_log_info("SDP-Data:\n%s\n"__FILE__": EOF", p);
|
||||
pa_log_info("SDP-Data:\n%s\nEOF", p);
|
||||
|
||||
pa_sap_send(&u->sap_context, 0);
|
||||
|
||||
pa_gettimeofday(&tv);
|
||||
pa_timeval_add(&tv, SAP_INTERVAL);
|
||||
u->sap_event = c->mainloop->time_new(c->mainloop, &tv, sap_event_cb, u);
|
||||
pa_timeval_add(&tv, SAP_INTERVAL * PA_USEC_PER_SEC);
|
||||
u->sap_event = m->core->mainloop->time_new(m->core->mainloop, &tv, sap_event_cb, u);
|
||||
|
||||
pa_source_output_put(u->source_output);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
||||
|
|
@ -338,31 +355,31 @@ fail:
|
|||
pa_modargs_free(ma);
|
||||
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
pa_close(fd);
|
||||
|
||||
if (sap_fd >= 0)
|
||||
close(sap_fd);
|
||||
pa_close(sap_fd);
|
||||
|
||||
if (o) {
|
||||
pa_source_output_disconnect(o);
|
||||
pa_source_output_unlink(o);
|
||||
pa_source_output_unref(o);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_core *c, pa_module*m) {
|
||||
void pa__done(pa_module*m) {
|
||||
struct userdata *u;
|
||||
assert(c);
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
c->mainloop->time_free(u->sap_event);
|
||||
if (u->sap_event)
|
||||
m->core->mainloop->time_free(u->sap_event);
|
||||
|
||||
if (u->source_output) {
|
||||
pa_source_output_disconnect(u->source_output);
|
||||
pa_source_output_unlink(u->source_output);
|
||||
pa_source_output_unref(u->source_output);
|
||||
}
|
||||
|
||||
|
|
@ -371,7 +388,8 @@ void pa__done(pa_core *c, pa_module*m) {
|
|||
pa_sap_send(&u->sap_context, 1);
|
||||
pa_sap_context_destroy(&u->sap_context);
|
||||
|
||||
pa_memblockq_free(u->memblockq);
|
||||
if (u->memblockq)
|
||||
pa_memblockq_free(u->memblockq);
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
@ -40,12 +39,14 @@
|
|||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
|
||||
#include "rtp.h"
|
||||
|
||||
pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload, size_t frame_size) {
|
||||
assert(c);
|
||||
assert(fd >= 0);
|
||||
pa_assert(c);
|
||||
pa_assert(fd >= 0);
|
||||
|
||||
c->fd = fd;
|
||||
c->sequence = (uint16_t) (rand()*rand());
|
||||
|
|
@ -63,11 +64,11 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
|
|||
struct iovec iov[MAX_IOVECS];
|
||||
pa_memblock* mb[MAX_IOVECS];
|
||||
int iov_idx = 1;
|
||||
size_t n = 0, skip = 0;
|
||||
size_t n = 0;
|
||||
|
||||
assert(c);
|
||||
assert(size > 0);
|
||||
assert(q);
|
||||
pa_assert(c);
|
||||
pa_assert(size > 0);
|
||||
pa_assert(q);
|
||||
|
||||
if (pa_memblockq_get_length(q) < size)
|
||||
return 0;
|
||||
|
|
@ -76,24 +77,26 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
|
|||
int r;
|
||||
pa_memchunk chunk;
|
||||
|
||||
pa_memchunk_reset(&chunk);
|
||||
|
||||
if ((r = pa_memblockq_peek(q, &chunk)) >= 0) {
|
||||
|
||||
size_t k = n + chunk.length > size ? size - n : chunk.length;
|
||||
|
||||
if (chunk.memblock) {
|
||||
iov[iov_idx].iov_base = (void*)((uint8_t*) chunk.memblock->data + chunk.index);
|
||||
iov[iov_idx].iov_len = k;
|
||||
mb[iov_idx] = chunk.memblock;
|
||||
iov_idx ++;
|
||||
pa_assert(chunk.memblock);
|
||||
|
||||
n += k;
|
||||
}
|
||||
iov[iov_idx].iov_base = ((uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index);
|
||||
iov[iov_idx].iov_len = k;
|
||||
mb[iov_idx] = chunk.memblock;
|
||||
iov_idx ++;
|
||||
|
||||
skip += k;
|
||||
pa_memblockq_drop(q, &chunk, k);
|
||||
n += k;
|
||||
pa_memblockq_drop(q, k);
|
||||
}
|
||||
|
||||
if (r < 0 || !chunk.memblock || n >= size || iov_idx >= MAX_IOVECS) {
|
||||
pa_assert(n % c->frame_size == 0);
|
||||
|
||||
if (r < 0 || n >= size || iov_idx >= MAX_IOVECS) {
|
||||
uint32_t header[3];
|
||||
struct msghdr m;
|
||||
int k, i;
|
||||
|
|
@ -116,17 +119,19 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
|
|||
|
||||
k = sendmsg(c->fd, &m, MSG_DONTWAIT);
|
||||
|
||||
for (i = 1; i < iov_idx; i++)
|
||||
for (i = 1; i < iov_idx; i++) {
|
||||
pa_memblock_release(mb[i]);
|
||||
pa_memblock_unref(mb[i]);
|
||||
}
|
||||
|
||||
c->sequence++;
|
||||
} else
|
||||
k = 0;
|
||||
|
||||
c->timestamp += skip/c->frame_size;
|
||||
c->timestamp += n/c->frame_size;
|
||||
|
||||
if (k < 0) {
|
||||
if (errno != EAGAIN) /* If the queue is full, just ignore it */
|
||||
if (errno != EAGAIN && errno != EINTR) /* If the queue is full, just ignore it */
|
||||
pa_log("sendmsg() failed: %s", pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -135,7 +140,6 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
|
|||
break;
|
||||
|
||||
n = 0;
|
||||
skip = 0;
|
||||
iov_idx = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -144,7 +148,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
|
|||
}
|
||||
|
||||
pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame_size) {
|
||||
assert(c);
|
||||
pa_assert(c);
|
||||
|
||||
c->fd = fd;
|
||||
c->frame_size = frame_size;
|
||||
|
|
@ -159,13 +163,13 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
|
|||
int cc;
|
||||
ssize_t r;
|
||||
|
||||
assert(c);
|
||||
assert(chunk);
|
||||
pa_assert(c);
|
||||
pa_assert(chunk);
|
||||
|
||||
chunk->memblock = NULL;
|
||||
pa_memchunk_reset(chunk);
|
||||
|
||||
if (ioctl(c->fd, FIONREAD, &size) < 0) {
|
||||
pa_log("FIONREAD failed: %s", pa_cstrerror(errno));
|
||||
pa_log_warn("FIONREAD failed: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -174,7 +178,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
|
|||
|
||||
chunk->memblock = pa_memblock_new(pool, size);
|
||||
|
||||
iov.iov_base = chunk->memblock->data;
|
||||
iov.iov_base = pa_memblock_acquire(chunk->memblock);
|
||||
iov.iov_len = size;
|
||||
|
||||
m.msg_name = NULL;
|
||||
|
|
@ -185,36 +189,41 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
|
|||
m.msg_controllen = 0;
|
||||
m.msg_flags = 0;
|
||||
|
||||
if ((r = recvmsg(c->fd, &m, 0)) != size) {
|
||||
pa_log("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch");
|
||||
r = recvmsg(c->fd, &m, 0);
|
||||
pa_memblock_release(chunk->memblock);
|
||||
|
||||
if (r != size) {
|
||||
if (r < 0 && errno != EAGAIN && errno != EINTR)
|
||||
pa_log_warn("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch");
|
||||
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (size < 12) {
|
||||
pa_log("RTP packet too short.");
|
||||
pa_log_warn("RTP packet too short.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
memcpy(&header, chunk->memblock->data, sizeof(uint32_t));
|
||||
memcpy(&c->timestamp, (uint8_t*) chunk->memblock->data + 4, sizeof(uint32_t));
|
||||
memcpy(&c->ssrc, (uint8_t*) chunk->memblock->data + 8, sizeof(uint32_t));
|
||||
memcpy(&header, iov.iov_base, sizeof(uint32_t));
|
||||
memcpy(&c->timestamp, (uint8_t*) iov.iov_base + 4, sizeof(uint32_t));
|
||||
memcpy(&c->ssrc, (uint8_t*) iov.iov_base + 8, sizeof(uint32_t));
|
||||
|
||||
header = ntohl(header);
|
||||
c->timestamp = ntohl(c->timestamp);
|
||||
c->ssrc = ntohl(c->ssrc);
|
||||
|
||||
if ((header >> 30) != 2) {
|
||||
pa_log("Unsupported RTP version.");
|
||||
pa_log_warn("Unsupported RTP version.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((header >> 29) & 1) {
|
||||
pa_log("RTP padding not supported.");
|
||||
pa_log_warn("RTP padding not supported.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((header >> 28) & 1) {
|
||||
pa_log("RTP header extensions not supported.");
|
||||
pa_log_warn("RTP header extensions not supported.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -223,7 +232,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
|
|||
c->sequence = header & 0xFFFF;
|
||||
|
||||
if (12 + cc*4 > size) {
|
||||
pa_log("RTP packet too short. (CSRC)");
|
||||
pa_log_warn("RTP packet too short. (CSRC)");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -231,7 +240,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
|
|||
chunk->length = size - chunk->index;
|
||||
|
||||
if (chunk->length % c->frame_size != 0) {
|
||||
pa_log("Vad RTP packet size.");
|
||||
pa_log_warn("Bad RTP packet size.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +254,7 @@ fail:
|
|||
}
|
||||
|
||||
uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) {
|
||||
assert(ss);
|
||||
pa_assert(ss);
|
||||
|
||||
if (ss->format == PA_SAMPLE_ULAW && ss->rate == 8000 && ss->channels == 1)
|
||||
return 0;
|
||||
|
|
@ -260,7 +269,7 @@ uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) {
|
|||
}
|
||||
|
||||
pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec *ss) {
|
||||
assert(ss);
|
||||
pa_assert(ss);
|
||||
|
||||
switch (payload) {
|
||||
case 0:
|
||||
|
|
@ -295,17 +304,17 @@ pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec
|
|||
}
|
||||
|
||||
pa_sample_spec *pa_rtp_sample_spec_fixup(pa_sample_spec * ss) {
|
||||
assert(ss);
|
||||
pa_assert(ss);
|
||||
|
||||
if (!pa_rtp_sample_spec_valid(ss))
|
||||
ss->format = PA_SAMPLE_S16BE;
|
||||
|
||||
assert(pa_rtp_sample_spec_valid(ss));
|
||||
pa_assert(pa_rtp_sample_spec_valid(ss));
|
||||
return ss;
|
||||
}
|
||||
|
||||
int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) {
|
||||
assert(ss);
|
||||
pa_assert(ss);
|
||||
|
||||
if (!pa_sample_spec_valid(ss))
|
||||
return 0;
|
||||
|
|
@ -318,9 +327,9 @@ int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) {
|
|||
}
|
||||
|
||||
void pa_rtp_context_destroy(pa_rtp_context *c) {
|
||||
assert(c);
|
||||
pa_assert(c);
|
||||
|
||||
close(c->fd);
|
||||
pa_close(c->fd);
|
||||
}
|
||||
|
||||
const char* pa_rtp_format_to_string(pa_sample_format_t f) {
|
||||
|
|
@ -339,7 +348,7 @@ const char* pa_rtp_format_to_string(pa_sample_format_t f) {
|
|||
}
|
||||
|
||||
pa_sample_format_t pa_rtp_string_to_format(const char *s) {
|
||||
assert(s);
|
||||
pa_assert(s);
|
||||
|
||||
if (!(strcmp(s, "L16")))
|
||||
return PA_SAMPLE_S16BE;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
|
@ -46,6 +45,7 @@
|
|||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "sap.h"
|
||||
#include "sdp.h"
|
||||
|
|
@ -53,9 +53,9 @@
|
|||
#define MIME_TYPE "application/sdp"
|
||||
|
||||
pa_sap_context* pa_sap_context_init_send(pa_sap_context *c, int fd, char *sdp_data) {
|
||||
assert(c);
|
||||
assert(fd >= 0);
|
||||
assert(sdp_data);
|
||||
pa_assert(c);
|
||||
pa_assert(fd >= 0);
|
||||
pa_assert(sdp_data);
|
||||
|
||||
c->fd = fd;
|
||||
c->sdp_data = sdp_data;
|
||||
|
|
@ -65,9 +65,9 @@ pa_sap_context* pa_sap_context_init_send(pa_sap_context *c, int fd, char *sdp_da
|
|||
}
|
||||
|
||||
void pa_sap_context_destroy(pa_sap_context *c) {
|
||||
assert(c);
|
||||
pa_assert(c);
|
||||
|
||||
close(c->fd);
|
||||
pa_close(c->fd);
|
||||
pa_xfree(c->sdp_data);
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ int pa_sap_send(pa_sap_context *c, int goodbye) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6);
|
||||
pa_assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6);
|
||||
|
||||
header = htonl(((uint32_t) 1 << 29) |
|
||||
(sa->sa_family == AF_INET6 ? (uint32_t) 1 << 28 : 0) |
|
||||
|
|
@ -113,14 +113,14 @@ int pa_sap_send(pa_sap_context *c, int goodbye) {
|
|||
m.msg_flags = 0;
|
||||
|
||||
if ((k = sendmsg(c->fd, &m, MSG_DONTWAIT)) < 0)
|
||||
pa_log("sendmsg() failed: %s\n", pa_cstrerror(errno));
|
||||
pa_log_warn("sendmsg() failed: %s\n", pa_cstrerror(errno));
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
pa_sap_context* pa_sap_context_init_recv(pa_sap_context *c, int fd) {
|
||||
assert(c);
|
||||
assert(fd >= 0);
|
||||
pa_assert(c);
|
||||
pa_assert(fd >= 0);
|
||||
|
||||
c->fd = fd;
|
||||
c->sdp_data = NULL;
|
||||
|
|
@ -136,11 +136,11 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) {
|
|||
int six, ac;
|
||||
ssize_t r;
|
||||
|
||||
assert(c);
|
||||
assert(goodbye);
|
||||
pa_assert(c);
|
||||
pa_assert(goodbye);
|
||||
|
||||
if (ioctl(c->fd, FIONREAD, &size) < 0) {
|
||||
pa_log("FIONREAD failed: %s", pa_cstrerror(errno));
|
||||
pa_log_warn("FIONREAD failed: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -159,12 +159,12 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) {
|
|||
m.msg_flags = 0;
|
||||
|
||||
if ((r = recvmsg(c->fd, &m, 0)) != size) {
|
||||
pa_log("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch");
|
||||
pa_log_warn("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (size < 4) {
|
||||
pa_log("SAP packet too short.");
|
||||
pa_log_warn("SAP packet too short.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -172,17 +172,17 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) {
|
|||
header = ntohl(header);
|
||||
|
||||
if (header >> 29 != 1) {
|
||||
pa_log("Unsupported SAP version.");
|
||||
pa_log_warn("Unsupported SAP version.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((header >> 25) & 1) {
|
||||
pa_log("Encrypted SAP not supported.");
|
||||
pa_log_warn("Encrypted SAP not supported.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((header >> 24) & 1) {
|
||||
pa_log("Compressed SAP not supported.");
|
||||
pa_log_warn("Compressed SAP not supported.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -191,7 +191,7 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) {
|
|||
|
||||
k = 4 + (six ? 16 : 4) + ac*4;
|
||||
if (size < k) {
|
||||
pa_log("SAP packet too short (AD).");
|
||||
pa_log_warn("SAP packet too short (AD).");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +202,7 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) {
|
|||
e += sizeof(MIME_TYPE);
|
||||
size -= sizeof(MIME_TYPE);
|
||||
} else if ((unsigned) size < sizeof(PA_SDP_HEADER)-1 || strncmp(e, PA_SDP_HEADER, sizeof(PA_SDP_HEADER)-1)) {
|
||||
pa_log("Invalid SDP header.");
|
||||
pa_log_warn("Invalid SDP header.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
|
@ -35,36 +34,33 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/util.h>
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "sdp.h"
|
||||
#include "rtp.h"
|
||||
|
||||
|
||||
char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, uint16_t port, uint8_t payload, const pa_sample_spec *ss) {
|
||||
uint32_t ntp;
|
||||
char buf_src[64], buf_dst[64];
|
||||
char buf_src[64], buf_dst[64], un[64];
|
||||
const char *u, *f, *a;
|
||||
|
||||
assert(src);
|
||||
assert(dst);
|
||||
assert(af == AF_INET || af == AF_INET6);
|
||||
pa_assert(src);
|
||||
pa_assert(dst);
|
||||
pa_assert(af == AF_INET || af == AF_INET6);
|
||||
|
||||
f = pa_rtp_format_to_string(ss->format);
|
||||
assert(f);
|
||||
pa_assert_se(f = pa_rtp_format_to_string(ss->format));
|
||||
|
||||
if (!(u = getenv("USER")))
|
||||
if (!(u = getenv("USERNAME")))
|
||||
u = "-";
|
||||
if (!(u = pa_get_user_name(un, sizeof(un))))
|
||||
u = "-";
|
||||
|
||||
ntp = time(NULL) + 2208988800U;
|
||||
|
||||
a = inet_ntop(af, src, buf_src, sizeof(buf_src));
|
||||
assert(a);
|
||||
a = inet_ntop(af, dst, buf_dst, sizeof(buf_dst));
|
||||
assert(a);
|
||||
pa_assert_se(a = inet_ntop(af, src, buf_src, sizeof(buf_src)));
|
||||
pa_assert_se(a = inet_ntop(af, dst, buf_dst, sizeof(buf_dst)));
|
||||
|
||||
return pa_sprintf_malloc(
|
||||
PA_SDP_HEADER
|
||||
|
|
@ -86,8 +82,8 @@ char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, u
|
|||
|
||||
static pa_sample_spec *parse_sdp_sample_spec(pa_sample_spec *ss, char *c) {
|
||||
unsigned rate, channels;
|
||||
assert(ss);
|
||||
assert(c);
|
||||
pa_assert(ss);
|
||||
pa_assert(c);
|
||||
|
||||
if (pa_startswith(c, "L16/")) {
|
||||
ss->format = PA_SAMPLE_S16BE;
|
||||
|
|
@ -123,8 +119,8 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) {
|
|||
uint16_t port = 0;
|
||||
int ss_valid = 0;
|
||||
|
||||
assert(t);
|
||||
assert(i);
|
||||
pa_assert(t);
|
||||
pa_assert(i);
|
||||
|
||||
i->origin = i->session_name = NULL;
|
||||
i->salen = 0;
|
||||
|
|
@ -258,7 +254,7 @@ fail:
|
|||
}
|
||||
|
||||
void pa_sdp_info_destroy(pa_sdp_info *i) {
|
||||
assert(i);
|
||||
pa_assert(i);
|
||||
|
||||
pa_xfree(i->origin);
|
||||
pa_xfree(i->session_name);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <avahi-client/lookup.h>
|
||||
|
|
@ -36,8 +35,9 @@
|
|||
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
|
||||
#include <pulsecore/avahi-wrap.h>
|
||||
#include <pulsecore/refcnt.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "browser.h"
|
||||
|
||||
|
|
@ -46,7 +46,8 @@
|
|||
#define SERVICE_TYPE_SERVER "_pulse-server._tcp."
|
||||
|
||||
struct pa_browser {
|
||||
int ref;
|
||||
PA_REFCNT_DECLARE;
|
||||
|
||||
pa_mainloop_api *mainloop;
|
||||
AvahiPoll* avahi_poll;
|
||||
|
||||
|
|
@ -62,6 +63,7 @@ struct pa_browser {
|
|||
};
|
||||
|
||||
static int map_to_opcode(const char *type, int new) {
|
||||
|
||||
if (avahi_domain_equal(type, SERVICE_TYPE_SINK))
|
||||
return new ? PA_BROWSE_NEW_SINK : PA_BROWSE_REMOVE_SINK;
|
||||
else if (avahi_domain_equal(type, SERVICE_TYPE_SOURCE))
|
||||
|
|
@ -97,7 +99,8 @@ static void resolve_callback(
|
|||
int ss_valid = 0;
|
||||
char *key = NULL, *value = NULL;
|
||||
|
||||
assert(b);
|
||||
pa_assert(b);
|
||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
||||
|
||||
memset(&i, 0, sizeof(i));
|
||||
i.name = name;
|
||||
|
|
@ -109,13 +112,13 @@ static void resolve_callback(
|
|||
goto fail;
|
||||
|
||||
opcode = map_to_opcode(type, 1);
|
||||
assert(opcode >= 0);
|
||||
pa_assert(opcode >= 0);
|
||||
|
||||
if (aa->proto == AVAHI_PROTO_INET)
|
||||
snprintf(a, sizeof(a), "tcp:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port);
|
||||
pa_snprintf(a, sizeof(a), "tcp:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port);
|
||||
else {
|
||||
assert(aa->proto == AVAHI_PROTO_INET6);
|
||||
snprintf(a, sizeof(a), "tcp6:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port);
|
||||
pa_assert(aa->proto == AVAHI_PROTO_INET6);
|
||||
pa_snprintf(a, sizeof(a), "tcp6:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port);
|
||||
}
|
||||
i.server = a;
|
||||
|
||||
|
|
@ -146,7 +149,7 @@ static void resolve_callback(
|
|||
value = NULL;
|
||||
|
||||
l = strlen(a);
|
||||
assert(l+1 <= sizeof(a));
|
||||
pa_assert(l+1 <= sizeof(a));
|
||||
strncat(a, " ", sizeof(a)-l-1);
|
||||
strncat(a, i.fqdn, sizeof(a)-l-2);
|
||||
} else if (!strcmp(key, "cookie")) {
|
||||
|
|
@ -211,7 +214,9 @@ fail:
|
|||
|
||||
static void handle_failure(pa_browser *b) {
|
||||
const char *e = NULL;
|
||||
assert(b);
|
||||
|
||||
pa_assert(b);
|
||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
||||
|
||||
if (b->sink_browser)
|
||||
avahi_service_browser_free(b->sink_browser);
|
||||
|
|
@ -245,7 +250,9 @@ static void browse_callback(
|
|||
void *userdata) {
|
||||
|
||||
pa_browser *b = userdata;
|
||||
assert(b);
|
||||
|
||||
pa_assert(b);
|
||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
||||
|
||||
switch (event) {
|
||||
case AVAHI_BROWSER_NEW: {
|
||||
|
|
@ -276,7 +283,7 @@ static void browse_callback(
|
|||
i.name = name;
|
||||
|
||||
opcode = map_to_opcode(type, 0);
|
||||
assert(opcode >= 0);
|
||||
pa_assert(opcode >= 0);
|
||||
|
||||
b->callback(b, opcode, &i, b->userdata);
|
||||
}
|
||||
|
|
@ -295,7 +302,10 @@ static void browse_callback(
|
|||
|
||||
static void client_callback(AvahiClient *s, AvahiClientState state, void *userdata) {
|
||||
pa_browser *b = userdata;
|
||||
assert(s);
|
||||
|
||||
pa_assert(s);
|
||||
pa_assert(b);
|
||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
||||
|
||||
if (state == AVAHI_CLIENT_FAILURE)
|
||||
handle_failure(b);
|
||||
|
|
@ -311,14 +321,14 @@ pa_browser *pa_browser_new_full(pa_mainloop_api *mainloop, pa_browse_flags_t fla
|
|||
pa_browser *b;
|
||||
int error;
|
||||
|
||||
assert(mainloop);
|
||||
pa_assert(mainloop);
|
||||
|
||||
if (flags & ~(PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES) || flags == 0)
|
||||
return NULL;
|
||||
|
||||
b = pa_xnew(pa_browser, 1);
|
||||
b->mainloop = mainloop;
|
||||
b->ref = 1;
|
||||
PA_REFCNT_INIT(b);
|
||||
b->callback = NULL;
|
||||
b->userdata = NULL;
|
||||
b->error_callback = NULL;
|
||||
|
|
@ -391,7 +401,8 @@ fail:
|
|||
}
|
||||
|
||||
static void browser_free(pa_browser *b) {
|
||||
assert(b && b->mainloop);
|
||||
pa_assert(b);
|
||||
pa_assert(b->mainloop);
|
||||
|
||||
if (b->sink_browser)
|
||||
avahi_service_browser_free(b->sink_browser);
|
||||
|
|
@ -410,29 +421,32 @@ static void browser_free(pa_browser *b) {
|
|||
}
|
||||
|
||||
pa_browser *pa_browser_ref(pa_browser *b) {
|
||||
assert(b);
|
||||
assert(b->ref >= 1);
|
||||
b->ref++;
|
||||
pa_assert(b);
|
||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
||||
|
||||
PA_REFCNT_INC(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
void pa_browser_unref(pa_browser *b) {
|
||||
assert(b);
|
||||
assert(b->ref >= 1);
|
||||
pa_assert(b);
|
||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
||||
|
||||
if ((-- (b->ref)) <= 0)
|
||||
if (PA_REFCNT_DEC(b) <= 0)
|
||||
browser_free(b);
|
||||
}
|
||||
|
||||
void pa_browser_set_callback(pa_browser *b, pa_browse_cb_t cb, void *userdata) {
|
||||
assert(b);
|
||||
pa_assert(b);
|
||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
||||
|
||||
b->callback = cb;
|
||||
b->userdata = userdata;
|
||||
}
|
||||
|
||||
void pa_browser_set_error_callback(pa_browser *b, pa_browser_error_cb_t cb, void *userdata) {
|
||||
assert(b);
|
||||
pa_assert(b);
|
||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
||||
|
||||
b->error_callback = cb;
|
||||
b->error_userdata = userdata;
|
||||
|
|
|
|||
|
|
@ -41,4 +41,22 @@
|
|||
|
||||
#endif
|
||||
|
||||
#ifndef PA_GCC_PURE
|
||||
#ifdef __GNUCC__
|
||||
#define PA_GCC_PURE __attribute__ ((pure))
|
||||
#else
|
||||
/** This function's return value depends only the arguments list and global state **/
|
||||
#define PA_GCC_PURE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PA_GCC_CONST
|
||||
#ifdef __GNUCC__
|
||||
#define PA_GCC_CONST __attribute__ ((pure))
|
||||
#else
|
||||
/** This function's return value depends only the arguments list (stricter version of PA_GCC_CONST) **/
|
||||
#define PA_GCC_CONST
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -27,12 +27,12 @@
|
|||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "channelmap.h"
|
||||
|
||||
|
|
@ -90,18 +90,81 @@ const char *const table[] = {
|
|||
|
||||
[PA_CHANNEL_POSITION_TOP_CENTER] = "top-center",
|
||||
|
||||
[PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "top-front-center",
|
||||
[PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = "top-front-left",
|
||||
[PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = "top-front-right",
|
||||
[PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "top-front-center",
|
||||
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_CENTER] = "top-rear-center",
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_LEFT] = "top-rear-left",
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = "top-rear-right",
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_CENTER] = "top-rear-center"
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = "top-rear-right"
|
||||
};
|
||||
|
||||
const char *const pretty_table[] = {
|
||||
[PA_CHANNEL_POSITION_MONO] = "Mono",
|
||||
|
||||
[PA_CHANNEL_POSITION_FRONT_CENTER] = "Front Center",
|
||||
[PA_CHANNEL_POSITION_FRONT_LEFT] = "Front Left",
|
||||
[PA_CHANNEL_POSITION_FRONT_RIGHT] = "Front Right",
|
||||
|
||||
[PA_CHANNEL_POSITION_REAR_CENTER] = "Rear Center",
|
||||
[PA_CHANNEL_POSITION_REAR_LEFT] = "Rear Left",
|
||||
[PA_CHANNEL_POSITION_REAR_RIGHT] = "Rear Right",
|
||||
|
||||
[PA_CHANNEL_POSITION_LFE] = "Low Frequency Emmiter",
|
||||
|
||||
[PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = "Front Left-of-center",
|
||||
[PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = "Front Right-of-center",
|
||||
|
||||
[PA_CHANNEL_POSITION_SIDE_LEFT] = "Side Left",
|
||||
[PA_CHANNEL_POSITION_SIDE_RIGHT] = "Side Right",
|
||||
|
||||
[PA_CHANNEL_POSITION_AUX0] = "Auxiliary 0",
|
||||
[PA_CHANNEL_POSITION_AUX1] = "Auxiliary 1",
|
||||
[PA_CHANNEL_POSITION_AUX2] = "Auxiliary 2",
|
||||
[PA_CHANNEL_POSITION_AUX3] = "Auxiliary 3",
|
||||
[PA_CHANNEL_POSITION_AUX4] = "Auxiliary 4",
|
||||
[PA_CHANNEL_POSITION_AUX5] = "Auxiliary 5",
|
||||
[PA_CHANNEL_POSITION_AUX6] = "Auxiliary 6",
|
||||
[PA_CHANNEL_POSITION_AUX7] = "Auxiliary 7",
|
||||
[PA_CHANNEL_POSITION_AUX8] = "Auxiliary 8",
|
||||
[PA_CHANNEL_POSITION_AUX9] = "Auxiliary 9",
|
||||
[PA_CHANNEL_POSITION_AUX10] = "Auxiliary 10",
|
||||
[PA_CHANNEL_POSITION_AUX11] = "Auxiliary 11",
|
||||
[PA_CHANNEL_POSITION_AUX12] = "Auxiliary 12",
|
||||
[PA_CHANNEL_POSITION_AUX13] = "Auxiliary 13",
|
||||
[PA_CHANNEL_POSITION_AUX14] = "Auxiliary 14",
|
||||
[PA_CHANNEL_POSITION_AUX15] = "Auxiliary 15",
|
||||
[PA_CHANNEL_POSITION_AUX16] = "Auxiliary 16",
|
||||
[PA_CHANNEL_POSITION_AUX17] = "Auxiliary 17",
|
||||
[PA_CHANNEL_POSITION_AUX18] = "Auxiliary 18",
|
||||
[PA_CHANNEL_POSITION_AUX19] = "Auxiliary 19",
|
||||
[PA_CHANNEL_POSITION_AUX20] = "Auxiliary 20",
|
||||
[PA_CHANNEL_POSITION_AUX21] = "Auxiliary 21",
|
||||
[PA_CHANNEL_POSITION_AUX22] = "Auxiliary 22",
|
||||
[PA_CHANNEL_POSITION_AUX23] = "Auxiliary 23",
|
||||
[PA_CHANNEL_POSITION_AUX24] = "Auxiliary 24",
|
||||
[PA_CHANNEL_POSITION_AUX25] = "Auxiliary 25",
|
||||
[PA_CHANNEL_POSITION_AUX26] = "Auxiliary 26",
|
||||
[PA_CHANNEL_POSITION_AUX27] = "Auxiliary 27",
|
||||
[PA_CHANNEL_POSITION_AUX28] = "Auxiliary 28",
|
||||
[PA_CHANNEL_POSITION_AUX29] = "Auxiliary 29",
|
||||
[PA_CHANNEL_POSITION_AUX30] = "Auxiliary 30",
|
||||
[PA_CHANNEL_POSITION_AUX31] = "Auxiliary 31",
|
||||
|
||||
[PA_CHANNEL_POSITION_TOP_CENTER] = "Top Center",
|
||||
|
||||
[PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "Top Front Center",
|
||||
[PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = "Top Front Left",
|
||||
[PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = "Top Front Right",
|
||||
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_CENTER] = "Top Rear Center",
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_LEFT] = "Top Rear left",
|
||||
[PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = "Top Rear Right"
|
||||
};
|
||||
|
||||
pa_channel_map* pa_channel_map_init(pa_channel_map *m) {
|
||||
unsigned c;
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
m->channels = 0;
|
||||
|
||||
|
|
@ -112,7 +175,7 @@ pa_channel_map* pa_channel_map_init(pa_channel_map *m) {
|
|||
}
|
||||
|
||||
pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m) {
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
pa_channel_map_init(m);
|
||||
|
||||
|
|
@ -122,7 +185,7 @@ pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m) {
|
|||
}
|
||||
|
||||
pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) {
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
pa_channel_map_init(m);
|
||||
|
||||
|
|
@ -133,9 +196,9 @@ pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) {
|
|||
}
|
||||
|
||||
pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def) {
|
||||
assert(m);
|
||||
assert(channels > 0);
|
||||
assert(channels <= PA_CHANNELS_MAX);
|
||||
pa_assert(m);
|
||||
pa_assert(channels > 0);
|
||||
pa_assert(channels <= PA_CHANNELS_MAX);
|
||||
|
||||
pa_channel_map_init(m);
|
||||
|
||||
|
|
@ -342,11 +405,18 @@ const char* pa_channel_position_to_string(pa_channel_position_t pos) {
|
|||
return table[pos];
|
||||
}
|
||||
|
||||
const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos) {
|
||||
if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
|
||||
return NULL;
|
||||
|
||||
return pretty_table[pos];
|
||||
}
|
||||
|
||||
int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) {
|
||||
unsigned c;
|
||||
|
||||
assert(a);
|
||||
assert(b);
|
||||
pa_assert(a);
|
||||
pa_assert(b);
|
||||
|
||||
if (a->channels != b->channels)
|
||||
return 0;
|
||||
|
|
@ -363,14 +433,14 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
|
|||
int first = 1;
|
||||
char *e;
|
||||
|
||||
assert(s);
|
||||
assert(l > 0);
|
||||
assert(map);
|
||||
pa_assert(s);
|
||||
pa_assert(l > 0);
|
||||
pa_assert(map);
|
||||
|
||||
*(e = s) = 0;
|
||||
|
||||
for (channel = 0; channel < map->channels && l > 1; channel++) {
|
||||
l -= snprintf(e, l, "%s%s",
|
||||
l -= pa_snprintf(e, l, "%s%s",
|
||||
first ? "" : ",",
|
||||
pa_channel_position_to_string(map->map[channel]));
|
||||
|
||||
|
|
@ -386,8 +456,8 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) {
|
|||
pa_channel_map map;
|
||||
char *p;
|
||||
|
||||
assert(rmap);
|
||||
assert(s);
|
||||
pa_assert(rmap);
|
||||
pa_assert(s);
|
||||
|
||||
memset(&map, 0, sizeof(map));
|
||||
|
||||
|
|
@ -447,7 +517,7 @@ finish:
|
|||
int pa_channel_map_valid(const pa_channel_map *map) {
|
||||
unsigned c;
|
||||
|
||||
assert(map);
|
||||
pa_assert(map);
|
||||
|
||||
if (map->channels <= 0 || map->channels > PA_CHANNELS_MAX)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -172,7 +172,10 @@ pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m);
|
|||
pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def);
|
||||
|
||||
/** Return a text label for the specified channel position */
|
||||
const char* pa_channel_position_to_string(pa_channel_position_t pos);
|
||||
const char* pa_channel_position_to_string(pa_channel_position_t pos) PA_GCC_PURE;
|
||||
|
||||
/** Return a human readable text label for the specified channel position. \since 0.9.7 */
|
||||
const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos);
|
||||
|
||||
/** The maximum length of strings returned by pa_channel_map_snprint() */
|
||||
#define PA_CHANNEL_MAP_SNPRINT_MAX 336
|
||||
|
|
@ -184,10 +187,10 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map);
|
|||
pa_channel_map *pa_channel_map_parse(pa_channel_map *map, const char *s);
|
||||
|
||||
/** Compare two channel maps. Return 1 if both match. */
|
||||
int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b);
|
||||
int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) PA_GCC_PURE;
|
||||
|
||||
/** Return non-zero of the specified channel map is considered valid */
|
||||
int pa_channel_map_valid(const pa_channel_map *map);
|
||||
int pa_channel_map_valid(const pa_channel_map *map) PA_GCC_PURE;
|
||||
|
||||
PA_C_DECL_END
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
|
@ -36,6 +35,7 @@
|
|||
#include <pulsecore/x11prop.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "client-conf-x11.h"
|
||||
|
||||
|
|
@ -44,6 +44,8 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) {
|
|||
int ret = -1;
|
||||
char t[1024];
|
||||
|
||||
pa_assert(c);
|
||||
|
||||
if (!dname && (!(dname = getenv("DISPLAY")) || *dname == '\0'))
|
||||
goto finish;
|
||||
|
||||
|
|
@ -75,7 +77,7 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
assert(sizeof(cookie) == sizeof(c->cookie));
|
||||
pa_assert(sizeof(cookie) == sizeof(c->cookie));
|
||||
memcpy(c->cookie, cookie, sizeof(cookie));
|
||||
|
||||
c->cookie_valid = 1;
|
||||
|
|
|
|||
|
|
@ -27,14 +27,14 @@
|
|||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/conf-parser.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
|
|
@ -42,13 +42,7 @@
|
|||
|
||||
#include "client-conf.h"
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
# define PATH_SEP "/"
|
||||
#else
|
||||
# define PATH_SEP "\\"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_CLIENT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "client.conf"
|
||||
#define DEFAULT_CLIENT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "client.conf"
|
||||
#define DEFAULT_CLIENT_CONFIG_FILE_USER "client.conf"
|
||||
|
||||
#define ENV_CLIENT_CONFIG_FILE "PULSE_CLIENTCONFIG"
|
||||
|
|
@ -81,7 +75,7 @@ pa_client_conf *pa_client_conf_new(void) {
|
|||
}
|
||||
|
||||
void pa_client_conf_free(pa_client_conf *c) {
|
||||
assert(c);
|
||||
pa_assert(c);
|
||||
pa_xfree(c->daemon_binary);
|
||||
pa_xfree(c->extra_arguments);
|
||||
pa_xfree(c->default_sink);
|
||||
|
|
@ -90,6 +84,7 @@ void pa_client_conf_free(pa_client_conf *c) {
|
|||
pa_xfree(c->cookie_file);
|
||||
pa_xfree(c);
|
||||
}
|
||||
|
||||
int pa_client_conf_load(pa_client_conf *c, const char *filename) {
|
||||
FILE *f = NULL;
|
||||
char *fn = NULL;
|
||||
|
|
@ -122,7 +117,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
|
|||
pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn, "r");
|
||||
|
||||
if (!f && errno != EINTR) {
|
||||
pa_log("WARNING: failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
|
||||
pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +170,7 @@ int pa_client_conf_env(pa_client_conf *c) {
|
|||
}
|
||||
|
||||
int pa_client_conf_load_cookie(pa_client_conf* c) {
|
||||
assert(c);
|
||||
pa_assert(c);
|
||||
|
||||
c->cookie_valid = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
|
@ -67,6 +66,7 @@
|
|||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/socket-util.h>
|
||||
#include <pulsecore/creds.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
|
|||
};
|
||||
|
||||
static void unlock_autospawn_lock_file(pa_context *c) {
|
||||
assert(c);
|
||||
pa_assert(c);
|
||||
|
||||
if (c->autospawn_lock_fd >= 0) {
|
||||
char lf[PATH_MAX];
|
||||
|
|
@ -106,11 +106,11 @@ static void context_free(pa_context *c);
|
|||
pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
|
||||
pa_context *c;
|
||||
|
||||
assert(mainloop);
|
||||
assert(name);
|
||||
pa_assert(mainloop);
|
||||
pa_assert(name);
|
||||
|
||||
c = pa_xnew(pa_context, 1);
|
||||
c->ref = 1;
|
||||
PA_REFCNT_INIT(c);
|
||||
c->name = pa_xstrdup(name);
|
||||
c->mainloop = mainloop;
|
||||
c->client = NULL;
|
||||
|
|
@ -168,7 +168,7 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
|
|||
}
|
||||
|
||||
static void context_free(pa_context *c) {
|
||||
assert(c);
|
||||
pa_assert(c);
|
||||
|
||||
unlock_autospawn_lock_file(c);
|
||||
|
||||
|
|
@ -183,7 +183,7 @@ static void context_free(pa_context *c) {
|
|||
if (c->pdispatch)
|
||||
pa_pdispatch_unref(c->pdispatch);
|
||||
if (c->pstream) {
|
||||
pa_pstream_close(c->pstream);
|
||||
pa_pstream_unlink(c->pstream);
|
||||
pa_pstream_unref(c->pstream);
|
||||
}
|
||||
|
||||
|
|
@ -206,24 +206,24 @@ static void context_free(pa_context *c) {
|
|||
}
|
||||
|
||||
pa_context* pa_context_ref(pa_context *c) {
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
c->ref++;
|
||||
PA_REFCNT_INC(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
void pa_context_unref(pa_context *c) {
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
if (--c->ref <= 0)
|
||||
if (PA_REFCNT_DEC(c) <= 0)
|
||||
context_free(c);
|
||||
}
|
||||
|
||||
void pa_context_set_state(pa_context *c, pa_context_state_t st) {
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
if (c->state == st)
|
||||
return;
|
||||
|
|
@ -250,7 +250,7 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) {
|
|||
c->pdispatch = NULL;
|
||||
|
||||
if (c->pstream) {
|
||||
pa_pstream_close(c->pstream);
|
||||
pa_pstream_unlink(c->pstream);
|
||||
pa_pstream_unref(c->pstream);
|
||||
}
|
||||
c->pstream = NULL;
|
||||
|
|
@ -264,16 +264,16 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) {
|
|||
}
|
||||
|
||||
void pa_context_fail(pa_context *c, int error) {
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
pa_context_set_error(c, error);
|
||||
pa_context_set_state(c, PA_CONTEXT_FAILED);
|
||||
}
|
||||
|
||||
int pa_context_set_error(pa_context *c, int error) {
|
||||
assert(error >= 0);
|
||||
assert(error < PA_ERR_MAX);
|
||||
pa_assert(error >= 0);
|
||||
pa_assert(error < PA_ERR_MAX);
|
||||
|
||||
if (c)
|
||||
c->error = error;
|
||||
|
|
@ -284,8 +284,8 @@ int pa_context_set_error(pa_context *c, int error) {
|
|||
static void pstream_die_callback(pa_pstream *p, void *userdata) {
|
||||
pa_context *c = userdata;
|
||||
|
||||
assert(p);
|
||||
assert(c);
|
||||
pa_assert(p);
|
||||
pa_assert(c);
|
||||
|
||||
pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED);
|
||||
}
|
||||
|
|
@ -293,9 +293,9 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) {
|
|||
static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
|
||||
pa_context *c = userdata;
|
||||
|
||||
assert(p);
|
||||
assert(packet);
|
||||
assert(c);
|
||||
pa_assert(p);
|
||||
pa_assert(packet);
|
||||
pa_assert(c);
|
||||
|
||||
pa_context_ref(c);
|
||||
|
||||
|
|
@ -309,18 +309,19 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
|
|||
pa_context *c = userdata;
|
||||
pa_stream *s;
|
||||
|
||||
assert(p);
|
||||
assert(chunk);
|
||||
assert(chunk->memblock);
|
||||
assert(chunk->length);
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(p);
|
||||
pa_assert(chunk);
|
||||
pa_assert(chunk->memblock);
|
||||
pa_assert(chunk->length);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
pa_context_ref(c);
|
||||
|
||||
if ((s = pa_dynarray_get(c->record_streams, channel))) {
|
||||
|
||||
assert(seek == PA_SEEK_RELATIVE && offset == 0);
|
||||
pa_assert(seek == PA_SEEK_RELATIVE);
|
||||
pa_assert(offset == 0);
|
||||
|
||||
pa_memblockq_seek(s->record_memblockq, offset, seek);
|
||||
pa_memblockq_push_align(s->record_memblockq, chunk);
|
||||
|
|
@ -337,11 +338,11 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
|
|||
}
|
||||
|
||||
int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) {
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
if (command == PA_COMMAND_ERROR) {
|
||||
assert(t);
|
||||
pa_assert(t);
|
||||
|
||||
if (pa_tagstruct_getu32(t, &c->error) < 0) {
|
||||
pa_context_fail(c, PA_ERR_PROTOCOL);
|
||||
|
|
@ -361,9 +362,9 @@ int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) {
|
|||
static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_context *c = userdata;
|
||||
|
||||
assert(pd);
|
||||
assert(c);
|
||||
assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME);
|
||||
pa_assert(pd);
|
||||
pa_assert(c);
|
||||
pa_assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME);
|
||||
|
||||
pa_context_ref(c);
|
||||
|
||||
|
|
@ -423,7 +424,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
|
|||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
pa_assert(0);
|
||||
}
|
||||
|
||||
finish:
|
||||
|
|
@ -434,19 +435,19 @@ static void setup_context(pa_context *c, pa_iochannel *io) {
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(io);
|
||||
pa_assert(c);
|
||||
pa_assert(io);
|
||||
|
||||
pa_context_ref(c);
|
||||
|
||||
assert(!c->pstream);
|
||||
pa_assert(!c->pstream);
|
||||
c->pstream = pa_pstream_new(c->mainloop, io, c->mempool);
|
||||
|
||||
pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
|
||||
pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
|
||||
pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
|
||||
|
||||
assert(!c->pdispatch);
|
||||
pa_assert(!c->pdispatch);
|
||||
c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
|
||||
|
||||
if (!c->conf->cookie_valid)
|
||||
|
|
@ -497,10 +498,10 @@ static int context_connect_spawn(pa_context *c) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
pa_fd_set_cloexec(fds[0], 1);
|
||||
pa_make_fd_cloexec(fds[0]);
|
||||
|
||||
pa_socket_low_delay(fds[0]);
|
||||
pa_socket_low_delay(fds[1]);
|
||||
pa_make_socket_low_delay(fds[0]);
|
||||
pa_make_socket_low_delay(fds[1]);
|
||||
|
||||
if (c->spawn_api.prefork)
|
||||
c->spawn_api.prefork();
|
||||
|
|
@ -523,7 +524,7 @@ static int context_connect_spawn(pa_context *c) {
|
|||
int n;
|
||||
|
||||
/* Not required, since fds[0] has CLOEXEC enabled anyway */
|
||||
close(fds[0]);
|
||||
pa_assert_se(pa_close(fds[0]) == 0);
|
||||
|
||||
if (c->spawn_api.atfork)
|
||||
c->spawn_api.atfork();
|
||||
|
|
@ -535,7 +536,7 @@ static int context_connect_spawn(pa_context *c) {
|
|||
argv[n++] = c->conf->daemon_binary;
|
||||
argv[n++] = "--daemonize=yes";
|
||||
|
||||
snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]);
|
||||
pa_snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]);
|
||||
argv[n++] = strdup(t);
|
||||
|
||||
while (n < MAX_ARGS) {
|
||||
|
|
@ -570,7 +571,7 @@ static int context_connect_spawn(pa_context *c) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
close(fds[1]);
|
||||
pa_assert_se(pa_close(fds[1]) == 0);
|
||||
|
||||
c->is_local = 1;
|
||||
|
||||
|
|
@ -584,10 +585,7 @@ static int context_connect_spawn(pa_context *c) {
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
if (fds[0] != -1)
|
||||
close(fds[0]);
|
||||
if (fds[1] != -1)
|
||||
close(fds[1]);
|
||||
pa_close_pipe(fds);
|
||||
|
||||
unlock_autospawn_lock_file(c);
|
||||
|
||||
|
|
@ -602,8 +600,8 @@ static int try_next_connection(pa_context *c) {
|
|||
char *u = NULL;
|
||||
int r = -1;
|
||||
|
||||
assert(c);
|
||||
assert(!c->client);
|
||||
pa_assert(c);
|
||||
pa_assert(!c->client);
|
||||
|
||||
for (;;) {
|
||||
pa_xfree(u);
|
||||
|
|
@ -648,9 +646,9 @@ finish:
|
|||
static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) {
|
||||
pa_context *c = userdata;
|
||||
|
||||
assert(client);
|
||||
assert(c);
|
||||
assert(c->state == PA_CONTEXT_CONNECTING);
|
||||
pa_assert(client);
|
||||
pa_assert(c);
|
||||
pa_assert(c->state == PA_CONTEXT_CONNECTING);
|
||||
|
||||
pa_context_ref(c);
|
||||
|
||||
|
|
@ -683,8 +681,8 @@ int pa_context_connect(
|
|||
|
||||
int r = -1;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY(c, !(flags & ~PA_CONTEXT_NOAUTOSPAWN), PA_ERR_INVALID);
|
||||
|
|
@ -695,7 +693,7 @@ int pa_context_connect(
|
|||
|
||||
pa_context_ref(c);
|
||||
|
||||
assert(!c->server_list);
|
||||
pa_assert(!c->server_list);
|
||||
|
||||
if (server) {
|
||||
if (!(c->server_list = pa_strlist_parse(server))) {
|
||||
|
|
@ -735,7 +733,7 @@ int pa_context_connect(
|
|||
|
||||
pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf));
|
||||
pa_make_secure_parent_dir(lf, 0700, (uid_t)-1, (gid_t)-1);
|
||||
assert(c->autospawn_lock_fd <= 0);
|
||||
pa_assert(c->autospawn_lock_fd <= 0);
|
||||
c->autospawn_lock_fd = pa_lock_lockfile(lf);
|
||||
|
||||
if (api)
|
||||
|
|
@ -755,37 +753,37 @@ finish:
|
|||
}
|
||||
|
||||
void pa_context_disconnect(pa_context *c) {
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
pa_context_set_state(c, PA_CONTEXT_TERMINATED);
|
||||
}
|
||||
|
||||
pa_context_state_t pa_context_get_state(pa_context *c) {
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
return c->state;
|
||||
}
|
||||
|
||||
int pa_context_errno(pa_context *c) {
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
return c->error;
|
||||
}
|
||||
|
||||
void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
c->state_callback = cb;
|
||||
c->state_userdata = userdata;
|
||||
}
|
||||
|
||||
int pa_context_is_pending(pa_context *c) {
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY(c,
|
||||
c->state == PA_CONTEXT_CONNECTING ||
|
||||
|
|
@ -811,11 +809,11 @@ static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream *s, void *userdata)
|
|||
static void set_dispatch_callbacks(pa_operation *o) {
|
||||
int done = 1;
|
||||
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
assert(o->context);
|
||||
assert(o->context->ref >= 1);
|
||||
assert(o->context->state == PA_CONTEXT_READY);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
pa_assert(o->context);
|
||||
pa_assert(PA_REFCNT_VALUE(o->context) >= 1);
|
||||
pa_assert(o->context->state == PA_CONTEXT_READY);
|
||||
|
||||
pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL);
|
||||
pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL);
|
||||
|
|
@ -844,8 +842,8 @@ static void set_dispatch_callbacks(pa_operation *o) {
|
|||
pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
|
||||
pa_operation *o;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, pa_context_is_pending(c), PA_ERR_BADSTATE);
|
||||
|
|
@ -860,9 +858,9 @@ void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_U
|
|||
pa_operation *o = userdata;
|
||||
int success = 1;
|
||||
|
||||
assert(pd);
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
|
@ -892,8 +890,8 @@ pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb,
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
|
||||
|
|
@ -911,8 +909,8 @@ pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
|
||||
|
|
@ -930,8 +928,8 @@ pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_co
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
|
||||
|
|
@ -950,8 +948,8 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
|
||||
|
|
@ -966,7 +964,7 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_
|
|||
}
|
||||
|
||||
int pa_context_is_local(pa_context *c) {
|
||||
assert(c);
|
||||
pa_assert(c);
|
||||
|
||||
return c->is_local;
|
||||
}
|
||||
|
|
@ -976,9 +974,9 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(name);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(name);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
|
||||
|
|
@ -997,8 +995,8 @@ const char* pa_get_library_version(void) {
|
|||
}
|
||||
|
||||
const char* pa_context_get_server(pa_context *c) {
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
if (!c->server)
|
||||
return NULL;
|
||||
|
|
@ -1016,8 +1014,8 @@ uint32_t pa_context_get_protocol_version(PA_GCC_UNUSED pa_context *c) {
|
|||
}
|
||||
|
||||
uint32_t pa_context_get_server_protocol_version(pa_context *c) {
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
return c->version;
|
||||
}
|
||||
|
|
@ -1025,8 +1023,8 @@ uint32_t pa_context_get_server_protocol_version(pa_context *c) {
|
|||
pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag) {
|
||||
pa_tagstruct *t;
|
||||
|
||||
assert(c);
|
||||
assert(tag);
|
||||
pa_assert(c);
|
||||
pa_assert(tag);
|
||||
|
||||
t = pa_tagstruct_new(NULL, 0);
|
||||
pa_tagstruct_putu32(t, command);
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/timeval.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -41,13 +41,14 @@
|
|||
#include <pulsecore/mcalign.h>
|
||||
#include <pulsecore/memblockq.h>
|
||||
#include <pulsecore/hashmap.h>
|
||||
#include <pulsecore/refcnt.h>
|
||||
|
||||
#include "client-conf.h"
|
||||
|
||||
#define DEFAULT_TIMEOUT (30)
|
||||
|
||||
struct pa_context {
|
||||
int ref;
|
||||
PA_REFCNT_DECLARE;
|
||||
|
||||
char *name;
|
||||
pa_mainloop_api* mainloop;
|
||||
|
|
@ -96,7 +97,7 @@ typedef struct pa_index_correction {
|
|||
} pa_index_correction;
|
||||
|
||||
struct pa_stream {
|
||||
int ref;
|
||||
PA_REFCNT_DECLARE;
|
||||
pa_context *context;
|
||||
pa_mainloop_api *mainloop;
|
||||
PA_LLIST_FIELDS(pa_stream);
|
||||
|
|
@ -116,6 +117,7 @@ struct pa_stream {
|
|||
uint32_t requested_bytes;
|
||||
|
||||
pa_memchunk peek_memchunk;
|
||||
void *peek_data;
|
||||
pa_memblockq *record_memblockq;
|
||||
|
||||
int corked;
|
||||
|
|
@ -160,7 +162,8 @@ struct pa_stream {
|
|||
typedef void (*pa_operation_cb_t)(void);
|
||||
|
||||
struct pa_operation {
|
||||
int ref;
|
||||
PA_REFCNT_DECLARE;
|
||||
|
||||
pa_context *context;
|
||||
pa_stream *stream;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,11 +26,10 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <pulse/context.h>
|
||||
|
||||
#include <pulsecore/gccmacro.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/pstream-util.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
|
@ -43,9 +42,11 @@ static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNU
|
|||
pa_operation *o = userdata;
|
||||
pa_stat_info i, *p = &i;
|
||||
|
||||
assert(pd);
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
|
@ -59,8 +60,7 @@ static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNU
|
|||
pa_tagstruct_getu32(t, &i.memblock_total_size) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.memblock_allocated) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.memblock_allocated_size) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.scache_size) < 0 ||
|
||||
!pa_tagstruct_eof(t)) {
|
||||
pa_tagstruct_getu32(t, &i.scache_size) < 0) {
|
||||
pa_context_fail(o->context, PA_ERR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
|
@ -85,9 +85,11 @@ static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command,
|
|||
pa_operation *o = userdata;
|
||||
pa_server_info i, *p = &i;
|
||||
|
||||
assert(pd);
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
|
@ -104,8 +106,7 @@ static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command,
|
|||
pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.default_sink_name) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.default_source_name) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.cookie) < 0 ||
|
||||
!pa_tagstruct_eof(t)) {
|
||||
pa_tagstruct_getu32(t, &i.cookie) < 0) {
|
||||
|
||||
pa_context_fail(o->context, PA_ERR_PROTOCOL);
|
||||
goto finish;
|
||||
|
|
@ -131,9 +132,9 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
|
|||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
assert(pd);
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
|
@ -148,6 +149,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
|
|||
|
||||
while (!pa_tagstruct_eof(t)) {
|
||||
pa_sink_info i;
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
||||
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.name) < 0 ||
|
||||
|
|
@ -195,9 +197,9 @@ pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, pa_
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(cb);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(cb);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
|
||||
|
|
@ -217,9 +219,9 @@ pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name,
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(cb);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(cb);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
|
||||
|
|
@ -241,9 +243,9 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
|
|||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
assert(pd);
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
|
@ -258,6 +260,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
|
|||
while (!pa_tagstruct_eof(t)) {
|
||||
pa_source_info i;
|
||||
uint32_t flags;
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
||||
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.name) < 0 ||
|
||||
|
|
@ -305,9 +308,9 @@ pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, p
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(cb);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(cb);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
|
||||
|
|
@ -327,9 +330,9 @@ pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(cb);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(cb);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
|
||||
|
|
@ -351,9 +354,9 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command,
|
|||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
assert(pd);
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
|
@ -367,6 +370,7 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command,
|
|||
|
||||
while (!pa_tagstruct_eof(t)) {
|
||||
pa_client_info i;
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
||||
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.name) < 0 ||
|
||||
|
|
@ -398,9 +402,9 @@ pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(cb);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(cb);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
|
||||
|
|
@ -425,9 +429,9 @@ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command,
|
|||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
assert(pd);
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
|
@ -441,6 +445,7 @@ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command,
|
|||
|
||||
while (!pa_tagstruct_eof(t)) {
|
||||
pa_module_info i;
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
||||
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.name) < 0 ||
|
||||
|
|
@ -473,9 +478,9 @@ pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(cb);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(cb);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
|
||||
|
|
@ -500,9 +505,9 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
|
|||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
assert(pd);
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
|
@ -516,6 +521,7 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
|
|||
|
||||
while (!pa_tagstruct_eof(t)) {
|
||||
pa_sink_input_info i;
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
||||
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.name) < 0 ||
|
||||
|
|
@ -528,7 +534,8 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
|
|||
pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
|
||||
pa_tagstruct_get_usec(t, &i.sink_usec) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.resample_method) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.driver) < 0) {
|
||||
pa_tagstruct_gets(t, &i.driver) < 0 ||
|
||||
(o->context->version >= 11 && pa_tagstruct_get_boolean(t, &i.mute) < 0)) {
|
||||
|
||||
pa_context_fail(o->context, PA_ERR_PROTOCOL);
|
||||
goto finish;
|
||||
|
|
@ -556,9 +563,9 @@ pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sin
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(cb);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(cb);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
|
||||
|
|
@ -583,9 +590,9 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c
|
|||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
assert(pd);
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
|
@ -600,6 +607,8 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c
|
|||
while (!pa_tagstruct_eof(t)) {
|
||||
pa_source_output_info i;
|
||||
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
||||
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.name) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
|
||||
|
|
@ -638,9 +647,9 @@ pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(cb);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(cb);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
|
||||
|
|
@ -666,9 +675,9 @@ pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, c
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(volume);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(volume);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
|
||||
|
|
@ -690,10 +699,10 @@ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(name);
|
||||
assert(volume);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(name);
|
||||
pa_assert(volume);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
|
||||
|
|
@ -716,8 +725,8 @@ pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
|
||||
|
|
@ -738,9 +747,9 @@ pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name,
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(name);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(name);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
|
||||
|
|
@ -762,9 +771,9 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(volume);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(volume);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
|
||||
|
|
@ -781,14 +790,37 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons
|
|||
return o;
|
||||
}
|
||||
|
||||
pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) {
|
||||
pa_operation *o;
|
||||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
|
||||
|
||||
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
|
||||
|
||||
t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_INPUT_MUTE, &tag);
|
||||
pa_tagstruct_putu32(t, idx);
|
||||
pa_tagstruct_put_boolean(t, mute);
|
||||
pa_pstream_send_tagstruct(c->pstream, t);
|
||||
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) {
|
||||
pa_operation *o;
|
||||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(volume);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(volume);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
|
||||
|
|
@ -810,10 +842,10 @@ pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *na
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(name);
|
||||
assert(volume);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(name);
|
||||
pa_assert(volume);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
|
||||
|
|
@ -836,8 +868,8 @@ pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, i
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
|
||||
|
|
@ -858,9 +890,9 @@ pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(name);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(name);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
|
||||
|
|
@ -883,9 +915,9 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
|
|||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
assert(pd);
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
|
@ -900,6 +932,8 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
|
|||
while (!pa_tagstruct_eof(t)) {
|
||||
pa_sample_info i;
|
||||
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
||||
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.name) < 0 ||
|
||||
pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
|
||||
|
|
@ -936,9 +970,9 @@ pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(cb);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(cb);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
|
||||
|
|
@ -959,9 +993,9 @@ pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, p
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(cb);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(cb);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
|
||||
|
|
@ -986,8 +1020,8 @@ static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx,
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
|
||||
|
|
@ -1018,9 +1052,9 @@ static void context_index_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN
|
|||
pa_operation *o = userdata;
|
||||
uint32_t idx;
|
||||
|
||||
assert(pd);
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
|
@ -1052,8 +1086,8 @@ pa_operation* pa_context_load_module(pa_context *c, const char*name, const char
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
|
||||
|
|
@ -1079,9 +1113,9 @@ static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t comman
|
|||
pa_operation *o = userdata;
|
||||
int eol = 1;
|
||||
|
||||
assert(pd);
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(pd);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if (!o->context)
|
||||
goto finish;
|
||||
|
|
@ -1096,6 +1130,8 @@ static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t comman
|
|||
while (!pa_tagstruct_eof(t)) {
|
||||
pa_autoload_info i;
|
||||
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
||||
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.name) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.type) < 0 ||
|
||||
|
|
@ -1127,9 +1163,9 @@ pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *na
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(cb);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(cb);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
|
||||
|
|
@ -1151,9 +1187,9 @@ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx,
|
|||
pa_operation *o;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
assert(cb);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(cb);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
|
||||
|
|
@ -1177,8 +1213,8 @@ pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autolo
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
|
||||
|
|
@ -1203,8 +1239,8 @@ pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
|
||||
|
|
@ -1226,8 +1262,8 @@ pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, p
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
|
||||
|
|
@ -1247,8 +1283,8 @@ pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, ch
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
|
||||
|
|
@ -1272,8 +1308,8 @@ pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, u
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
|
||||
|
|
@ -1297,8 +1333,8 @@ pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx,
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
|
||||
|
|
@ -1322,8 +1358,8 @@ pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx
|
|||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
assert(c);
|
||||
assert(c->ref >= 1);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
|
||||
|
|
@ -1341,3 +1377,97 @@ pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx
|
|||
|
||||
return o;
|
||||
}
|
||||
|
||||
pa_operation* pa_context_suspend_sink_by_name(pa_context *c, char *sink_name, int suspend, pa_context_success_cb_t cb, void* userdata) {
|
||||
pa_operation *o;
|
||||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, !sink_name || *sink_name, PA_ERR_INVALID);
|
||||
|
||||
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
|
||||
|
||||
t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SINK, &tag);
|
||||
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
|
||||
pa_tagstruct_puts(t, sink_name);
|
||||
pa_tagstruct_put_boolean(t, suspend);
|
||||
pa_pstream_send_tagstruct(c->pstream, t);
|
||||
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
pa_operation* pa_context_suspend_sink_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata) {
|
||||
pa_operation *o;
|
||||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
|
||||
|
||||
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
|
||||
|
||||
t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SINK, &tag);
|
||||
pa_tagstruct_putu32(t, idx);
|
||||
pa_tagstruct_puts(t, idx == PA_INVALID_INDEX ? "" : NULL);
|
||||
pa_tagstruct_put_boolean(t, suspend);
|
||||
pa_pstream_send_tagstruct(c->pstream, t);
|
||||
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
pa_operation* pa_context_suspend_source_by_name(pa_context *c, char *source_name, int suspend, pa_context_success_cb_t cb, void* userdata) {
|
||||
pa_operation *o;
|
||||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, !source_name || *source_name, PA_ERR_INVALID);
|
||||
|
||||
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
|
||||
|
||||
t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SOURCE, &tag);
|
||||
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
|
||||
pa_tagstruct_puts(t, source_name);
|
||||
pa_tagstruct_put_boolean(t, suspend);
|
||||
pa_pstream_send_tagstruct(c->pstream, t);
|
||||
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata) {
|
||||
pa_operation *o;
|
||||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
|
||||
|
||||
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
|
||||
|
||||
t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SOURCE, &tag);
|
||||
pa_tagstruct_putu32(t, idx);
|
||||
pa_tagstruct_puts(t, idx == PA_INVALID_INDEX ? "" : NULL);
|
||||
pa_tagstruct_put_boolean(t, suspend);
|
||||
pa_pstream_send_tagstruct(c->pstream, t);
|
||||
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -331,6 +331,7 @@ typedef struct pa_sink_input_info {
|
|||
pa_usec_t sink_usec; /**< Latency of the sink device, see pa_latency_info for details */
|
||||
const char *resample_method; /**< Thre resampling method used by this sink input. \since 0.7 */
|
||||
const char *driver; /**< Driver name \since 0.8 */
|
||||
int mute; /**< Stream muted \since 0.9.7 */
|
||||
} pa_sink_input_info;
|
||||
|
||||
/** Callback prototype for pa_context_get_sink_input_info() and firends*/
|
||||
|
|
@ -381,6 +382,9 @@ pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name,
|
|||
/** Set the volume of a sink input stream */
|
||||
pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
|
||||
|
||||
/** Set the mute switch of a sink input stream \since 0.9.7 */
|
||||
pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata);
|
||||
|
||||
/** Set the volume of a source device specified by its index \since 0.8 */
|
||||
pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
|
||||
|
||||
|
|
@ -499,6 +503,18 @@ pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx,
|
|||
/** Move the specified source output to a different source. \since 0.9.5 */
|
||||
pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx, uint32_t source_idx, pa_context_success_cb_t cb, void* userdata);
|
||||
|
||||
/** Suspend/Resume a sink. \since 0.9.7 */
|
||||
pa_operation* pa_context_suspend_sink_by_name(pa_context *c, char *sink_name, int suspend, pa_context_success_cb_t cb, void* userdata);
|
||||
|
||||
/** Suspend/Resume a sink. If idx is PA_INVALID_INDEX all sinks will be suspended. \since 0.9.7 */
|
||||
pa_operation* pa_context_suspend_sink_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata);
|
||||
|
||||
/** Suspend/Resume a source. \since 0.9.7 */
|
||||
pa_operation* pa_context_suspend_source_by_name(pa_context *c, char *source_name, int suspend, pa_context_success_cb_t cb, void* userdata);
|
||||
|
||||
/** Suspend/Resume a source. If idx is PA_INVALID_INDEX all sources will be suspended. \since 0.9.7 */
|
||||
pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata);
|
||||
|
||||
PA_C_DECL_END
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/gccmacro.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "mainloop-api.h"
|
||||
|
||||
|
|
@ -41,32 +41,38 @@ struct once_info {
|
|||
|
||||
static void once_callback(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
|
||||
struct once_info *i = userdata;
|
||||
assert(m && i && i->callback);
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(i);
|
||||
|
||||
pa_assert(i->callback);
|
||||
i->callback(m, i->userdata);
|
||||
|
||||
assert(m->defer_free);
|
||||
pa_assert(m->defer_free);
|
||||
m->defer_free(e);
|
||||
}
|
||||
|
||||
static void free_callback(pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event *e, void *userdata) {
|
||||
struct once_info *i = userdata;
|
||||
assert(m && i);
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(i);
|
||||
pa_xfree(i);
|
||||
}
|
||||
|
||||
void pa_mainloop_api_once(pa_mainloop_api* m, void (*callback)(pa_mainloop_api *m, void *userdata), void *userdata) {
|
||||
struct once_info *i;
|
||||
pa_defer_event *e;
|
||||
assert(m && callback);
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(callback);
|
||||
|
||||
i = pa_xnew(struct once_info, 1);
|
||||
i->callback = callback;
|
||||
i->userdata = userdata;
|
||||
|
||||
assert(m->defer_new);
|
||||
e = m->defer_new(m, once_callback, i);
|
||||
assert(e);
|
||||
pa_assert(m->defer_new);
|
||||
pa_assert_se(e = m->defer_new(m, once_callback, i));
|
||||
m->defer_set_destroy(e, free_callback);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -39,12 +38,13 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/gccmacro.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "mainloop-signal.h"
|
||||
|
||||
|
|
@ -74,11 +74,11 @@ static void signal_handler(int sig) {
|
|||
}
|
||||
|
||||
static void dispatch(pa_mainloop_api*a, int sig) {
|
||||
pa_signal_event*s;
|
||||
pa_signal_event *s;
|
||||
|
||||
for (s = signals; s; s = s->next)
|
||||
if (s->sig == sig) {
|
||||
assert(s->callback);
|
||||
pa_assert(s->callback);
|
||||
s->callback(a, s, sig, s->userdata);
|
||||
break;
|
||||
}
|
||||
|
|
@ -87,7 +87,12 @@ static void dispatch(pa_mainloop_api*a, int sig) {
|
|||
static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t f, PA_GCC_UNUSED void *userdata) {
|
||||
ssize_t r;
|
||||
int sig;
|
||||
assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]);
|
||||
|
||||
pa_assert(a);
|
||||
pa_assert(e);
|
||||
pa_assert(f == PA_IO_EVENT_INPUT);
|
||||
pa_assert(e == io_event);
|
||||
pa_assert(fd == signal_pipe[0]);
|
||||
|
||||
if ((r = pa_read(signal_pipe[0], &sig, sizeof(sig), NULL)) < 0) {
|
||||
if (errno == EAGAIN)
|
||||
|
|
@ -107,28 +112,34 @@ static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags
|
|||
|
||||
int pa_signal_init(pa_mainloop_api *a) {
|
||||
|
||||
assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event);
|
||||
pa_assert(a);
|
||||
pa_assert(!api);
|
||||
pa_assert(signal_pipe[0] == -1);
|
||||
pa_assert(signal_pipe[1] == -1);
|
||||
pa_assert(!io_event);
|
||||
|
||||
if (pipe(signal_pipe) < 0) {
|
||||
pa_log("pipe(): %s", pa_cstrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
pa_make_nonblock_fd(signal_pipe[0]);
|
||||
pa_make_nonblock_fd(signal_pipe[1]);
|
||||
pa_fd_set_cloexec(signal_pipe[0], 1);
|
||||
pa_fd_set_cloexec(signal_pipe[1], 1);
|
||||
pa_make_fd_nonblock(signal_pipe[0]);
|
||||
pa_make_fd_nonblock(signal_pipe[1]);
|
||||
pa_make_fd_cloexec(signal_pipe[0]);
|
||||
pa_make_fd_cloexec(signal_pipe[1]);
|
||||
|
||||
api = a;
|
||||
|
||||
io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL);
|
||||
assert(io_event);
|
||||
pa_assert_se(io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pa_signal_done(void) {
|
||||
assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && io_event);
|
||||
pa_assert(api);
|
||||
pa_assert(signal_pipe[0] >= 0);
|
||||
pa_assert(signal_pipe[1] >= 0);
|
||||
pa_assert(io_event);
|
||||
|
||||
while (signals)
|
||||
pa_signal_free(signals);
|
||||
|
|
@ -136,9 +147,7 @@ void pa_signal_done(void) {
|
|||
api->io_free(io_event);
|
||||
io_event = NULL;
|
||||
|
||||
close(signal_pipe[0]);
|
||||
close(signal_pipe[1]);
|
||||
signal_pipe[0] = signal_pipe[1] = -1;
|
||||
pa_close_pipe(signal_pipe);
|
||||
|
||||
api = NULL;
|
||||
}
|
||||
|
|
@ -150,13 +159,14 @@ pa_signal_event* pa_signal_new(int sig, void (*_callback) (pa_mainloop_api *api,
|
|||
struct sigaction sa;
|
||||
#endif
|
||||
|
||||
assert(sig > 0 && _callback);
|
||||
pa_assert(sig > 0);
|
||||
pa_assert(_callback);
|
||||
|
||||
for (e = signals; e; e = e->next)
|
||||
if (e->sig == sig)
|
||||
goto fail;
|
||||
|
||||
e = pa_xmalloc(sizeof(pa_signal_event));
|
||||
e = pa_xnew(pa_signal_event, 1);
|
||||
e->sig = sig;
|
||||
e->callback = _callback;
|
||||
e->userdata = userdata;
|
||||
|
|
@ -186,7 +196,7 @@ fail:
|
|||
}
|
||||
|
||||
void pa_signal_free(pa_signal_event *e) {
|
||||
assert(e);
|
||||
pa_assert(e);
|
||||
|
||||
if (e->next)
|
||||
e->next->previous = e->previous;
|
||||
|
|
@ -196,9 +206,9 @@ void pa_signal_free(pa_signal_event *e) {
|
|||
signals = e->next;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
sigaction(e->sig, &e->saved_sigaction, NULL);
|
||||
pa_assert_se(sigaction(e->sig, &e->saved_sigaction, NULL) == 0);
|
||||
#else
|
||||
signal(e->sig, e->saved_handler);
|
||||
pa_assert_se(signal(e->sig, e->saved_handler) == signal_handler);
|
||||
#endif
|
||||
|
||||
if (e->destroy_callback)
|
||||
|
|
@ -208,6 +218,7 @@ void pa_signal_free(pa_signal_event *e) {
|
|||
}
|
||||
|
||||
void pa_signal_set_destroy(pa_signal_event *e, void (*_callback) (pa_mainloop_api *api, pa_signal_event*e, void *userdata)) {
|
||||
assert(e);
|
||||
pa_assert(e);
|
||||
|
||||
e->destroy_callback = _callback;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,29 +31,28 @@
|
|||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_SYS_POLL_H
|
||||
#include <sys/poll.h>
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
#else
|
||||
#include "../pulsecore/poll.h"
|
||||
#include <pulsecore/poll.h>
|
||||
#endif
|
||||
|
||||
#include "../pulsecore/winsock.h"
|
||||
|
||||
#ifndef HAVE_PIPE
|
||||
#include "../pulsecore/pipe.h"
|
||||
#include <pulsecore/pipe.h>
|
||||
#endif
|
||||
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/llist.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/winsock.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "mainloop.h"
|
||||
|
||||
|
|
@ -161,13 +160,13 @@ static pa_io_event* mainloop_io_new(
|
|||
pa_mainloop *m;
|
||||
pa_io_event *e;
|
||||
|
||||
assert(a);
|
||||
assert(a->userdata);
|
||||
assert(fd >= 0);
|
||||
assert(callback);
|
||||
pa_assert(a);
|
||||
pa_assert(a->userdata);
|
||||
pa_assert(fd >= 0);
|
||||
pa_assert(callback);
|
||||
|
||||
m = a->userdata;
|
||||
assert(a == &m->api);
|
||||
pa_assert(a == &m->api);
|
||||
|
||||
e = pa_xnew(pa_io_event, 1);
|
||||
e->mainloop = m;
|
||||
|
|
@ -195,7 +194,7 @@ static pa_io_event* mainloop_io_new(
|
|||
if ((select((SELECT_TYPE_ARG1) fd, NULL, NULL, SELECT_TYPE_ARG234 &xset,
|
||||
SELECT_TYPE_ARG5 &tv) == -1) &&
|
||||
(WSAGetLastError() == WSAENOTSOCK)) {
|
||||
pa_log_warn("WARNING: cannot monitor non-socket file descriptors.");
|
||||
pa_log_warn("Cannot monitor non-socket file descriptors.");
|
||||
e->dead = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -211,8 +210,8 @@ static pa_io_event* mainloop_io_new(
|
|||
}
|
||||
|
||||
static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) {
|
||||
assert(e);
|
||||
assert(!e->dead);
|
||||
pa_assert(e);
|
||||
pa_assert(!e->dead);
|
||||
|
||||
if (e->events == events)
|
||||
return;
|
||||
|
|
@ -228,8 +227,8 @@ static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) {
|
|||
}
|
||||
|
||||
static void mainloop_io_free(pa_io_event *e) {
|
||||
assert(e);
|
||||
assert(!e->dead);
|
||||
pa_assert(e);
|
||||
pa_assert(!e->dead);
|
||||
|
||||
e->dead = 1;
|
||||
e->mainloop->io_events_please_scan ++;
|
||||
|
|
@ -241,7 +240,7 @@ static void mainloop_io_free(pa_io_event *e) {
|
|||
}
|
||||
|
||||
static void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t callback) {
|
||||
assert(e);
|
||||
pa_assert(e);
|
||||
|
||||
e->destroy_callback = callback;
|
||||
}
|
||||
|
|
@ -255,12 +254,12 @@ static pa_defer_event* mainloop_defer_new(
|
|||
pa_mainloop *m;
|
||||
pa_defer_event *e;
|
||||
|
||||
assert(a);
|
||||
assert(a->userdata);
|
||||
assert(callback);
|
||||
pa_assert(a);
|
||||
pa_assert(a->userdata);
|
||||
pa_assert(callback);
|
||||
|
||||
m = a->userdata;
|
||||
assert(a == &m->api);
|
||||
pa_assert(a == &m->api);
|
||||
|
||||
e = pa_xnew(pa_defer_event, 1);
|
||||
e->mainloop = m;
|
||||
|
|
@ -281,11 +280,11 @@ static pa_defer_event* mainloop_defer_new(
|
|||
}
|
||||
|
||||
static void mainloop_defer_enable(pa_defer_event *e, int b) {
|
||||
assert(e);
|
||||
assert(!e->dead);
|
||||
pa_assert(e);
|
||||
pa_assert(!e->dead);
|
||||
|
||||
if (e->enabled && !b) {
|
||||
assert(e->mainloop->n_enabled_defer_events > 0);
|
||||
pa_assert(e->mainloop->n_enabled_defer_events > 0);
|
||||
e->mainloop->n_enabled_defer_events--;
|
||||
} else if (!e->enabled && b) {
|
||||
e->mainloop->n_enabled_defer_events++;
|
||||
|
|
@ -296,21 +295,22 @@ static void mainloop_defer_enable(pa_defer_event *e, int b) {
|
|||
}
|
||||
|
||||
static void mainloop_defer_free(pa_defer_event *e) {
|
||||
assert(e);
|
||||
assert(!e->dead);
|
||||
pa_assert(e);
|
||||
pa_assert(!e->dead);
|
||||
|
||||
e->dead = 1;
|
||||
e->mainloop->defer_events_please_scan ++;
|
||||
|
||||
if (e->enabled) {
|
||||
assert(e->mainloop->n_enabled_defer_events > 0);
|
||||
pa_assert(e->mainloop->n_enabled_defer_events > 0);
|
||||
e->mainloop->n_enabled_defer_events--;
|
||||
e->enabled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t callback) {
|
||||
assert(e);
|
||||
assert(!e->dead);
|
||||
pa_assert(e);
|
||||
pa_assert(!e->dead);
|
||||
|
||||
e->destroy_callback = callback;
|
||||
}
|
||||
|
|
@ -325,12 +325,12 @@ static pa_time_event* mainloop_time_new(
|
|||
pa_mainloop *m;
|
||||
pa_time_event *e;
|
||||
|
||||
assert(a);
|
||||
assert(a->userdata);
|
||||
assert(callback);
|
||||
pa_assert(a);
|
||||
pa_assert(a->userdata);
|
||||
pa_assert(callback);
|
||||
|
||||
m = a->userdata;
|
||||
assert(a == &m->api);
|
||||
pa_assert(a == &m->api);
|
||||
|
||||
e = pa_xnew(pa_time_event, 1);
|
||||
e->mainloop = m;
|
||||
|
|
@ -342,7 +342,7 @@ static pa_time_event* mainloop_time_new(
|
|||
m->n_enabled_time_events++;
|
||||
|
||||
if (m->cached_next_time_event) {
|
||||
assert(m->cached_next_time_event->enabled);
|
||||
pa_assert(m->cached_next_time_event->enabled);
|
||||
|
||||
if (pa_timeval_cmp(tv, &m->cached_next_time_event->timeval) < 0)
|
||||
m->cached_next_time_event = e;
|
||||
|
|
@ -362,11 +362,11 @@ static pa_time_event* mainloop_time_new(
|
|||
}
|
||||
|
||||
static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
|
||||
assert(e);
|
||||
assert(!e->dead);
|
||||
pa_assert(e);
|
||||
pa_assert(!e->dead);
|
||||
|
||||
if (e->enabled && !tv) {
|
||||
assert(e->mainloop->n_enabled_time_events > 0);
|
||||
pa_assert(e->mainloop->n_enabled_time_events > 0);
|
||||
e->mainloop->n_enabled_time_events--;
|
||||
} else if (!e->enabled && tv)
|
||||
e->mainloop->n_enabled_time_events++;
|
||||
|
|
@ -377,7 +377,7 @@ static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
|
|||
}
|
||||
|
||||
if (e->mainloop->cached_next_time_event && e->enabled) {
|
||||
assert(e->mainloop->cached_next_time_event->enabled);
|
||||
pa_assert(e->mainloop->cached_next_time_event->enabled);
|
||||
|
||||
if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0)
|
||||
e->mainloop->cached_next_time_event = e;
|
||||
|
|
@ -386,15 +386,16 @@ static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
|
|||
}
|
||||
|
||||
static void mainloop_time_free(pa_time_event *e) {
|
||||
assert(e);
|
||||
assert(!e->dead);
|
||||
pa_assert(e);
|
||||
pa_assert(!e->dead);
|
||||
|
||||
e->dead = 1;
|
||||
e->mainloop->time_events_please_scan ++;
|
||||
|
||||
if (e->enabled) {
|
||||
assert(e->mainloop->n_enabled_time_events > 0);
|
||||
pa_assert(e->mainloop->n_enabled_time_events > 0);
|
||||
e->mainloop->n_enabled_time_events--;
|
||||
e->enabled = 0;
|
||||
}
|
||||
|
||||
if (e->mainloop->cached_next_time_event == e)
|
||||
|
|
@ -404,8 +405,8 @@ static void mainloop_time_free(pa_time_event *e) {
|
|||
}
|
||||
|
||||
static void mainloop_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t callback) {
|
||||
assert(e);
|
||||
assert(!e->dead);
|
||||
pa_assert(e);
|
||||
pa_assert(!e->dead);
|
||||
|
||||
e->destroy_callback = callback;
|
||||
}
|
||||
|
|
@ -415,10 +416,10 @@ static void mainloop_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb
|
|||
static void mainloop_quit(pa_mainloop_api*a, int retval) {
|
||||
pa_mainloop *m;
|
||||
|
||||
assert(a);
|
||||
assert(a->userdata);
|
||||
pa_assert(a);
|
||||
pa_assert(a->userdata);
|
||||
m = a->userdata;
|
||||
assert(a == &m->api);
|
||||
pa_assert(a == &m->api);
|
||||
|
||||
pa_mainloop_quit(m, retval);
|
||||
}
|
||||
|
|
@ -456,8 +457,10 @@ pa_mainloop *pa_mainloop_new(void) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
pa_make_nonblock_fd(m->wakeup_pipe[0]);
|
||||
pa_make_nonblock_fd(m->wakeup_pipe[1]);
|
||||
pa_make_fd_nonblock(m->wakeup_pipe[0]);
|
||||
pa_make_fd_nonblock(m->wakeup_pipe[1]);
|
||||
pa_make_fd_cloexec(m->wakeup_pipe[0]);
|
||||
pa_make_fd_cloexec(m->wakeup_pipe[1]);
|
||||
m->wakeup_requested = 0;
|
||||
|
||||
PA_LLIST_HEAD_INIT(pa_io_event, m->io_events);
|
||||
|
|
@ -502,7 +505,7 @@ static void cleanup_io_events(pa_mainloop *m, int force) {
|
|||
PA_LLIST_REMOVE(pa_io_event, m->io_events, e);
|
||||
|
||||
if (e->dead) {
|
||||
assert(m->io_events_please_scan > 0);
|
||||
pa_assert(m->io_events_please_scan > 0);
|
||||
m->io_events_please_scan--;
|
||||
}
|
||||
|
||||
|
|
@ -517,7 +520,7 @@ static void cleanup_io_events(pa_mainloop *m, int force) {
|
|||
e = n;
|
||||
}
|
||||
|
||||
assert(m->io_events_please_scan == 0);
|
||||
pa_assert(m->io_events_please_scan == 0);
|
||||
}
|
||||
|
||||
static void cleanup_time_events(pa_mainloop *m, int force) {
|
||||
|
|
@ -534,13 +537,14 @@ static void cleanup_time_events(pa_mainloop *m, int force) {
|
|||
PA_LLIST_REMOVE(pa_time_event, m->time_events, e);
|
||||
|
||||
if (e->dead) {
|
||||
assert(m->time_events_please_scan > 0);
|
||||
pa_assert(m->time_events_please_scan > 0);
|
||||
m->time_events_please_scan--;
|
||||
}
|
||||
|
||||
if (!e->dead && e->enabled) {
|
||||
assert(m->n_enabled_time_events > 0);
|
||||
pa_assert(m->n_enabled_time_events > 0);
|
||||
m->n_enabled_time_events--;
|
||||
e->enabled = 0;
|
||||
}
|
||||
|
||||
if (e->destroy_callback)
|
||||
|
|
@ -552,7 +556,7 @@ static void cleanup_time_events(pa_mainloop *m, int force) {
|
|||
e = n;
|
||||
}
|
||||
|
||||
assert(m->time_events_please_scan == 0);
|
||||
pa_assert(m->time_events_please_scan == 0);
|
||||
}
|
||||
|
||||
static void cleanup_defer_events(pa_mainloop *m, int force) {
|
||||
|
|
@ -569,13 +573,14 @@ static void cleanup_defer_events(pa_mainloop *m, int force) {
|
|||
PA_LLIST_REMOVE(pa_defer_event, m->defer_events, e);
|
||||
|
||||
if (e->dead) {
|
||||
assert(m->defer_events_please_scan > 0);
|
||||
pa_assert(m->defer_events_please_scan > 0);
|
||||
m->defer_events_please_scan--;
|
||||
}
|
||||
|
||||
if (!e->dead && e->enabled) {
|
||||
assert(m->n_enabled_defer_events > 0);
|
||||
pa_assert(m->n_enabled_defer_events > 0);
|
||||
m->n_enabled_defer_events--;
|
||||
e->enabled = 0;
|
||||
}
|
||||
|
||||
if (e->destroy_callback)
|
||||
|
|
@ -587,12 +592,12 @@ static void cleanup_defer_events(pa_mainloop *m, int force) {
|
|||
e = n;
|
||||
}
|
||||
|
||||
assert(m->defer_events_please_scan == 0);
|
||||
pa_assert(m->defer_events_please_scan == 0);
|
||||
}
|
||||
|
||||
|
||||
void pa_mainloop_free(pa_mainloop* m) {
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
cleanup_io_events(m, 1);
|
||||
cleanup_defer_events(m, 1);
|
||||
|
|
@ -600,16 +605,13 @@ void pa_mainloop_free(pa_mainloop* m) {
|
|||
|
||||
pa_xfree(m->pollfds);
|
||||
|
||||
if (m->wakeup_pipe[0] >= 0)
|
||||
close(m->wakeup_pipe[0]);
|
||||
if (m->wakeup_pipe[1] >= 0)
|
||||
close(m->wakeup_pipe[1]);
|
||||
pa_close_pipe(m->wakeup_pipe);
|
||||
|
||||
pa_xfree(m);
|
||||
}
|
||||
|
||||
static void scan_dead(pa_mainloop *m) {
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (m->io_events_please_scan)
|
||||
cleanup_io_events(m, 0);
|
||||
|
|
@ -666,13 +668,14 @@ static int dispatch_pollfds(pa_mainloop *m) {
|
|||
pa_io_event *e;
|
||||
int r = 0, k;
|
||||
|
||||
assert(m->poll_func_ret > 0);
|
||||
pa_assert(m->poll_func_ret > 0);
|
||||
|
||||
for (e = m->io_events, k = m->poll_func_ret; e && !m->quit && k > 0; e = e->next) {
|
||||
if (e->dead || !e->pollfd || !e->pollfd->revents)
|
||||
continue;
|
||||
|
||||
assert(e->pollfd->fd == e->fd && e->callback);
|
||||
pa_assert(e->pollfd->fd == e->fd);
|
||||
pa_assert(e->callback);
|
||||
e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata);
|
||||
e->pollfd->revents = 0;
|
||||
r++;
|
||||
|
|
@ -694,7 +697,7 @@ static int dispatch_defer(pa_mainloop *m) {
|
|||
if (e->dead || !e->enabled)
|
||||
continue;
|
||||
|
||||
assert(e->callback);
|
||||
pa_assert(e->callback);
|
||||
e->callback(&m->api, e, e->userdata);
|
||||
r++;
|
||||
}
|
||||
|
|
@ -704,7 +707,7 @@ static int dispatch_defer(pa_mainloop *m) {
|
|||
|
||||
static pa_time_event* find_next_time_event(pa_mainloop *m) {
|
||||
pa_time_event *t, *n = NULL;
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (m->cached_next_time_event)
|
||||
return m->cached_next_time_event;
|
||||
|
|
@ -736,7 +739,7 @@ static int calc_next_timeout(pa_mainloop *m) {
|
|||
return -1;
|
||||
|
||||
t = find_next_time_event(m);
|
||||
assert(t);
|
||||
pa_assert(t);
|
||||
|
||||
if (t->timeval.tv_sec <= 0)
|
||||
return 0;
|
||||
|
|
@ -754,7 +757,7 @@ static int dispatch_timeout(pa_mainloop *m) {
|
|||
pa_time_event *e;
|
||||
struct timeval now;
|
||||
int r = 0;
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (m->n_enabled_time_events <= 0)
|
||||
return 0;
|
||||
|
|
@ -767,7 +770,7 @@ static int dispatch_timeout(pa_mainloop *m) {
|
|||
continue;
|
||||
|
||||
if (pa_timeval_cmp(&e->timeval, &now) <= 0) {
|
||||
assert(e->callback);
|
||||
pa_assert(e->callback);
|
||||
|
||||
/* Disable time event */
|
||||
mainloop_time_restart(e, NULL);
|
||||
|
|
@ -783,7 +786,7 @@ static int dispatch_timeout(pa_mainloop *m) {
|
|||
|
||||
void pa_mainloop_wakeup(pa_mainloop *m) {
|
||||
char c = 'W';
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (m->wakeup_pipe[1] >= 0 && m->state == STATE_POLLING) {
|
||||
pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type);
|
||||
|
|
@ -794,7 +797,7 @@ void pa_mainloop_wakeup(pa_mainloop *m) {
|
|||
static void clear_wakeup(pa_mainloop *m) {
|
||||
char c[10];
|
||||
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if (m->wakeup_pipe[0] < 0)
|
||||
return;
|
||||
|
|
@ -806,8 +809,8 @@ static void clear_wakeup(pa_mainloop *m) {
|
|||
}
|
||||
|
||||
int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
|
||||
assert(m);
|
||||
assert(m->state == STATE_PASSIVE);
|
||||
pa_assert(m);
|
||||
pa_assert(m->state == STATE_PASSIVE);
|
||||
|
||||
clear_wakeup(m);
|
||||
scan_dead(m);
|
||||
|
|
@ -833,8 +836,8 @@ quit:
|
|||
}
|
||||
|
||||
int pa_mainloop_poll(pa_mainloop *m) {
|
||||
assert(m);
|
||||
assert(m->state == STATE_PREPARED);
|
||||
pa_assert(m);
|
||||
pa_assert(m->state == STATE_PREPARED);
|
||||
|
||||
if (m->quit)
|
||||
goto quit;
|
||||
|
|
@ -844,7 +847,7 @@ int pa_mainloop_poll(pa_mainloop *m) {
|
|||
if (m->n_enabled_defer_events )
|
||||
m->poll_func_ret = 0;
|
||||
else {
|
||||
assert(!m->rebuild_pollfds);
|
||||
pa_assert(!m->rebuild_pollfds);
|
||||
|
||||
if (m->poll_func)
|
||||
m->poll_func_ret = m->poll_func(m->pollfds, m->n_pollfds, m->prepared_timeout, m->poll_func_userdata);
|
||||
|
|
@ -870,8 +873,8 @@ quit:
|
|||
int pa_mainloop_dispatch(pa_mainloop *m) {
|
||||
int dispatched = 0;
|
||||
|
||||
assert(m);
|
||||
assert(m->state == STATE_POLLED);
|
||||
pa_assert(m);
|
||||
pa_assert(m->state == STATE_POLLED);
|
||||
|
||||
if (m->quit)
|
||||
goto quit;
|
||||
|
|
@ -902,13 +905,13 @@ quit:
|
|||
}
|
||||
|
||||
int pa_mainloop_get_retval(pa_mainloop *m) {
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
return m->retval;
|
||||
}
|
||||
|
||||
int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) {
|
||||
int r;
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0)
|
||||
goto quit;
|
||||
|
|
@ -942,7 +945,7 @@ int pa_mainloop_run(pa_mainloop *m, int *retval) {
|
|||
}
|
||||
|
||||
void pa_mainloop_quit(pa_mainloop *m, int retval) {
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
m->quit = 1;
|
||||
m->retval = retval;
|
||||
|
|
@ -950,12 +953,12 @@ void pa_mainloop_quit(pa_mainloop *m, int retval) {
|
|||
}
|
||||
|
||||
pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) {
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
return &m->api;
|
||||
}
|
||||
|
||||
void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) {
|
||||
assert(m);
|
||||
pa_assert(m);
|
||||
|
||||
m->poll_func = poll_func;
|
||||
m->poll_func_userdata = userdata;
|
||||
|
|
|
|||
|
|
@ -25,19 +25,18 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "operation.h"
|
||||
|
||||
pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb, void *userdata) {
|
||||
pa_operation *o;
|
||||
assert(c);
|
||||
pa_assert(c);
|
||||
|
||||
o = pa_xnew(pa_operation, 1);
|
||||
o->ref = 1;
|
||||
PA_REFCNT_INIT(o);
|
||||
o->context = c;
|
||||
o->stream = s;
|
||||
|
||||
|
|
@ -53,27 +52,27 @@ pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb
|
|||
}
|
||||
|
||||
pa_operation *pa_operation_ref(pa_operation *o) {
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
o->ref++;
|
||||
PA_REFCNT_INC(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
void pa_operation_unref(pa_operation *o) {
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if ((--(o->ref)) == 0) {
|
||||
assert(!o->context);
|
||||
assert(!o->stream);
|
||||
if (PA_REFCNT_DEC(o) <= 0) {
|
||||
pa_assert(!o->context);
|
||||
pa_assert(!o->stream);
|
||||
pa_xfree(o);
|
||||
}
|
||||
}
|
||||
|
||||
static void operation_set_state(pa_operation *o, pa_operation_state_t st) {
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
if (st == o->state)
|
||||
return;
|
||||
|
|
@ -85,7 +84,7 @@ static void operation_set_state(pa_operation *o, pa_operation_state_t st) {
|
|||
if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) {
|
||||
|
||||
if (o->context) {
|
||||
assert(o->ref >= 2);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 2);
|
||||
|
||||
PA_LLIST_REMOVE(pa_operation, o->context->operations, o);
|
||||
pa_operation_unref(o);
|
||||
|
|
@ -101,22 +100,22 @@ static void operation_set_state(pa_operation *o, pa_operation_state_t st) {
|
|||
}
|
||||
|
||||
void pa_operation_cancel(pa_operation *o) {
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
operation_set_state(o, PA_OPERATION_CANCELED);
|
||||
}
|
||||
|
||||
void pa_operation_done(pa_operation *o) {
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
operation_set_state(o, PA_OPERATION_DONE);
|
||||
}
|
||||
|
||||
pa_operation_state_t pa_operation_get_state(pa_operation *o) {
|
||||
assert(o);
|
||||
assert(o->ref >= 1);
|
||||
pa_assert(o);
|
||||
pa_assert(PA_REFCNT_VALUE(o) >= 1);
|
||||
|
||||
return o->state;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,57 +27,58 @@
|
|||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "sample.h"
|
||||
|
||||
size_t pa_sample_size(const pa_sample_spec *spec) {
|
||||
assert(spec);
|
||||
|
||||
switch (spec->format) {
|
||||
case PA_SAMPLE_U8:
|
||||
case PA_SAMPLE_ULAW:
|
||||
case PA_SAMPLE_ALAW:
|
||||
return 1;
|
||||
case PA_SAMPLE_S16LE:
|
||||
case PA_SAMPLE_S16BE:
|
||||
return 2;
|
||||
case PA_SAMPLE_FLOAT32LE:
|
||||
case PA_SAMPLE_FLOAT32BE:
|
||||
return 4;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
static const size_t table[] = {
|
||||
[PA_SAMPLE_U8] = 1,
|
||||
[PA_SAMPLE_ULAW] = 1,
|
||||
[PA_SAMPLE_ALAW] = 1,
|
||||
[PA_SAMPLE_S16LE] = 2,
|
||||
[PA_SAMPLE_S16BE] = 2,
|
||||
[PA_SAMPLE_FLOAT32LE] = 4,
|
||||
[PA_SAMPLE_FLOAT32BE] = 4
|
||||
};
|
||||
|
||||
pa_assert(spec);
|
||||
pa_assert(spec->format >= 0);
|
||||
pa_assert(spec->format < PA_SAMPLE_MAX);
|
||||
|
||||
return table[spec->format];
|
||||
}
|
||||
|
||||
size_t pa_frame_size(const pa_sample_spec *spec) {
|
||||
assert(spec);
|
||||
pa_assert(spec);
|
||||
|
||||
return pa_sample_size(spec) * spec->channels;
|
||||
}
|
||||
|
||||
size_t pa_bytes_per_second(const pa_sample_spec *spec) {
|
||||
assert(spec);
|
||||
pa_assert(spec);
|
||||
return spec->rate*pa_frame_size(spec);
|
||||
}
|
||||
|
||||
pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) {
|
||||
assert(spec);
|
||||
pa_assert(spec);
|
||||
|
||||
return (pa_usec_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate);
|
||||
}
|
||||
|
||||
size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) {
|
||||
assert(spec);
|
||||
pa_assert(spec);
|
||||
|
||||
return (size_t) (((double) t * spec->rate / 1000000))*pa_frame_size(spec);
|
||||
}
|
||||
|
||||
int pa_sample_spec_valid(const pa_sample_spec *spec) {
|
||||
assert(spec);
|
||||
pa_assert(spec);
|
||||
|
||||
if (spec->rate <= 0 ||
|
||||
spec->rate > PA_RATE_MAX ||
|
||||
|
|
@ -91,7 +92,8 @@ int pa_sample_spec_valid(const pa_sample_spec *spec) {
|
|||
}
|
||||
|
||||
int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b) {
|
||||
assert(a && b);
|
||||
pa_assert(a);
|
||||
pa_assert(b);
|
||||
|
||||
return (a->format == b->format) && (a->rate == b->rate) && (a->channels == b->channels);
|
||||
}
|
||||
|
|
@ -107,37 +109,42 @@ const char *pa_sample_format_to_string(pa_sample_format_t f) {
|
|||
[PA_SAMPLE_FLOAT32BE] = "float32be",
|
||||
};
|
||||
|
||||
if (f >= PA_SAMPLE_MAX)
|
||||
if (f < 0 || f >= PA_SAMPLE_MAX)
|
||||
return NULL;
|
||||
|
||||
return table[f];
|
||||
}
|
||||
|
||||
char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
|
||||
assert(s && l && spec);
|
||||
pa_assert(s);
|
||||
pa_assert(l);
|
||||
pa_assert(spec);
|
||||
|
||||
if (!pa_sample_spec_valid(spec))
|
||||
snprintf(s, l, "Invalid");
|
||||
pa_snprintf(s, l, "Invalid");
|
||||
else
|
||||
snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate);
|
||||
pa_snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
char* pa_bytes_snprint(char *s, size_t l, unsigned v) {
|
||||
pa_assert(s);
|
||||
|
||||
if (v >= ((unsigned) 1024)*1024*1024)
|
||||
snprintf(s, l, "%0.1f GiB", ((double) v)/1024/1024/1024);
|
||||
pa_snprintf(s, l, "%0.1f GiB", ((double) v)/1024/1024/1024);
|
||||
else if (v >= ((unsigned) 1024)*1024)
|
||||
snprintf(s, l, "%0.1f MiB", ((double) v)/1024/1024);
|
||||
pa_snprintf(s, l, "%0.1f MiB", ((double) v)/1024/1024);
|
||||
else if (v >= (unsigned) 1024)
|
||||
snprintf(s, l, "%0.1f KiB", ((double) v)/1024);
|
||||
pa_snprintf(s, l, "%0.1f KiB", ((double) v)/1024);
|
||||
else
|
||||
snprintf(s, l, "%u B", (unsigned) v);
|
||||
pa_snprintf(s, l, "%u B", (unsigned) v);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
pa_sample_format_t pa_parse_sample_format(const char *format) {
|
||||
pa_assert(format);
|
||||
|
||||
if (strcasecmp(format, "s16le") == 0)
|
||||
return PA_SAMPLE_S16LE;
|
||||
|
|
@ -145,15 +152,19 @@ pa_sample_format_t pa_parse_sample_format(const char *format) {
|
|||
return PA_SAMPLE_S16BE;
|
||||
else if (strcasecmp(format, "s16ne") == 0 || strcasecmp(format, "s16") == 0 || strcasecmp(format, "16") == 0)
|
||||
return PA_SAMPLE_S16NE;
|
||||
else if (strcasecmp(format, "s16re") == 0)
|
||||
return PA_SAMPLE_S16RE;
|
||||
else if (strcasecmp(format, "u8") == 0 || strcasecmp(format, "8") == 0)
|
||||
return PA_SAMPLE_U8;
|
||||
else if (strcasecmp(format, "float32") == 0 || strcasecmp(format, "float32ne") == 0)
|
||||
return PA_SAMPLE_FLOAT32;
|
||||
return PA_SAMPLE_FLOAT32NE;
|
||||
else if (strcasecmp(format, "float32re") == 0)
|
||||
return PA_SAMPLE_FLOAT32RE;
|
||||
else if (strcasecmp(format, "float32le") == 0)
|
||||
return PA_SAMPLE_FLOAT32LE;
|
||||
else if (strcasecmp(format, "float32be") == 0)
|
||||
return PA_SAMPLE_FLOAT32BE;
|
||||
else if (strcasecmp(format, "ulaw") == 0)
|
||||
else if (strcasecmp(format, "ulaw") == 0 || strcasecmp(format, "mulaw") == 0)
|
||||
return PA_SAMPLE_ULAW;
|
||||
else if (strcasecmp(format, "alaw") == 0)
|
||||
return PA_SAMPLE_ALAW;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue