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:
Lennart Poettering 2007-10-28 19:13:50 +00:00
parent 6687dd0131
commit a67c21f093
294 changed files with 79057 additions and 11614 deletions

View file

@ -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

View file

@ -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 "$@"

View file

@ -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,7 +93,7 @@ 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])
@ -106,15 +106,51 @@ if test "x$GCC" = "xyes" ; then
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,6 +395,41 @@ 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],
@ -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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

875
libltdl/aclocal.m4 vendored Normal file
View 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
View 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

File diff suppressed because it is too large Load diff

196
libltdl/config.h Normal file
View 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

File diff suppressed because it is too large Load diff

23853
libltdl/configure vendored Executable file

File diff suppressed because it is too large Load diff

79
libltdl/configure.ac Normal file
View 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
View 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

File diff suppressed because it is too large Load diff

367
libltdl/ltdl.h Normal file
View 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

File diff suppressed because it is too large Load diff

360
libltdl/missing Executable file
View 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
View 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
View file

@ -0,0 +1 @@
timestamp for config.h

388
pulseaudio-text.svg Normal file
View 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 &lt;ossman@cendio.se&gt; 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

View file

@ -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

View file

@ -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;
}

View file

@ -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");

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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 */

View file

@ -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

View file

@ -1,5 +1,4 @@
#!@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

View file

@ -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
View 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;
}

View 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

View file

@ -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;
}

View 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=

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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
View 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

View file

@ -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

View 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);
}
}

View file

@ -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);

View file

@ -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 */
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}

View 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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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

View 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);
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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);
}

View 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);
}

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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);

View 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;
}
}

View file

@ -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);
}

View file

@ -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 = &caps;
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;
}

View file

@ -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

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -25,8 +25,6 @@
#include <config.h>
#endif
#include <assert.h>
#include <pulse/xmalloc.h>
#include <pulse/timeval.h>

View file

@ -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;

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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