]> code.delx.au - pulseaudio/commitdiff
merge 'lennart' branch back into trunk.
authorLennart Poettering <lennart@poettering.net>
Sun, 28 Oct 2007 19:13:50 +0000 (19:13 +0000)
committerLennart Poettering <lennart@poettering.net>
Sun, 28 Oct 2007 19:13:50 +0000 (19:13 +0000)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1971 fefdeb5f-60dc-0310-8127-8f9354f1896f

294 files changed:
Makefile.am
bootstrap.sh
configure.ac
libltdl/COPYING.LIB [new file with mode: 0644]
libltdl/Makefile.am [new file with mode: 0644]
libltdl/Makefile.in [new file with mode: 0644]
libltdl/README [new file with mode: 0644]
libltdl/acinclude.m4 [new file with mode: 0644]
libltdl/aclocal.m4 [new file with mode: 0644]
libltdl/config-h.in [new file with mode: 0644]
libltdl/config.guess [new file with mode: 0755]
libltdl/config.h [new file with mode: 0644]
libltdl/config.sub [new file with mode: 0755]
libltdl/configure [new file with mode: 0755]
libltdl/configure.ac [new file with mode: 0644]
libltdl/install-sh [new file with mode: 0755]
libltdl/ltdl.c [new file with mode: 0644]
libltdl/ltdl.h [new file with mode: 0644]
libltdl/ltmain.sh [new file with mode: 0644]
libltdl/missing [new file with mode: 0755]
libltdl/mkinstalldirs [new file with mode: 0755]
libltdl/stamp-h1 [new file with mode: 0644]
pulseaudio-text.svg [new file with mode: 0644]
src/Makefile.am
src/daemon/caps.c
src/daemon/cmdline.c
src/daemon/cpulimit.c
src/daemon/daemon-conf.c
src/daemon/daemon-conf.h
src/daemon/daemon.conf.in
src/daemon/default.pa.in
src/daemon/dumpmodules.c
src/daemon/ltdl-bind-now.c [new file with mode: 0644]
src/daemon/ltdl-bind-now.h [new file with mode: 0644]
src/daemon/main.c
src/daemon/pulseaudio-module-xsmp.desktop [new file with mode: 0644]
src/modules/alsa-util.c
src/modules/alsa-util.h
src/modules/dbus-util.c
src/modules/gconf/gconf-helper.c
src/modules/gconf/module-gconf.c
src/modules/ladspa.h [new file with mode: 0644]
src/modules/module-alsa-sink.c
src/modules/module-alsa-source.c
src/modules/module-cli.c
src/modules/module-combine.c
src/modules/module-default-device-restore.c [new file with mode: 0644]
src/modules/module-defs.h.m4
src/modules/module-detect.c
src/modules/module-esound-compat-spawnfd.c
src/modules/module-esound-compat-spawnpid.c
src/modules/module-esound-sink.c
src/modules/module-hal-detect.c
src/modules/module-jack-sink.c
src/modules/module-jack-source.c
src/modules/module-ladspa-sink.c [new file with mode: 0644]
src/modules/module-lirc.c
src/modules/module-match.c
src/modules/module-mmkbd-evdev.c
src/modules/module-native-protocol-fd.c
src/modules/module-null-sink.c
src/modules/module-oss-mmap.c [deleted file]
src/modules/module-oss.c
src/modules/module-pipe-sink.c
src/modules/module-pipe-source.c
src/modules/module-protocol-stub.c
src/modules/module-remap-sink.c [new file with mode: 0644]
src/modules/module-rescue-streams.c
src/modules/module-sine.c
src/modules/module-solaris.c
src/modules/module-suspend-on-idle.c [new file with mode: 0644]
src/modules/module-tunnel.c
src/modules/module-volume-restore.c
src/modules/module-x11-bell.c
src/modules/module-x11-publish.c
src/modules/module-x11-xsmp.c [new file with mode: 0644]
src/modules/module-zeroconf-publish.c
src/modules/oss-util.c
src/modules/oss-util.h
src/modules/rtp/module-rtp-recv.c
src/modules/rtp/module-rtp-send.c
src/modules/rtp/rtp.c
src/modules/rtp/sap.c
src/modules/rtp/sdp.c
src/pulse/browser.c
src/pulse/cdecl.h
src/pulse/channelmap.c
src/pulse/channelmap.h
src/pulse/client-conf-x11.c
src/pulse/client-conf.c
src/pulse/context.c
src/pulse/glib-mainloop.c
src/pulse/internal.h
src/pulse/introspect.c
src/pulse/introspect.h
src/pulse/mainloop-api.c
src/pulse/mainloop-signal.c
src/pulse/mainloop.c
src/pulse/operation.c
src/pulse/sample.c
src/pulse/sample.h
src/pulse/scache.c
src/pulse/simple.c
src/pulse/simple.h
src/pulse/stream.c
src/pulse/subscribe.c
src/pulse/thread-mainloop.c
src/pulse/thread-mainloop.h
src/pulse/timeval.c
src/pulse/timeval.h
src/pulse/utf8.c
src/pulse/utf8.h
src/pulse/util.c
src/pulse/util.h
src/pulse/volume.c
src/pulse/volume.h
src/pulse/xmalloc.c
src/pulse/xmalloc.h
src/pulsecore/anotify.c [deleted file]
src/pulsecore/asyncmsgq.c [new file with mode: 0644]
src/pulsecore/asyncmsgq.h [new file with mode: 0644]
src/pulsecore/asyncq.c [new file with mode: 0644]
src/pulsecore/asyncq.h [new file with mode: 0644]
src/pulsecore/atomic.h
src/pulsecore/authkey-prop.c
src/pulsecore/authkey.c
src/pulsecore/autoload.c
src/pulsecore/avahi-wrap.c
src/pulsecore/cli-command.c
src/pulsecore/cli-text.c
src/pulsecore/cli.c
src/pulsecore/client.c
src/pulsecore/conf-parser.c
src/pulsecore/core-def.h
src/pulsecore/core-error.c
src/pulsecore/core-scache.c
src/pulsecore/core-scache.h
src/pulsecore/core-subscribe.c
src/pulsecore/core-util.c
src/pulsecore/core-util.h
src/pulsecore/core.c
src/pulsecore/core.h
src/pulsecore/creds.h
src/pulsecore/dynarray.c
src/pulsecore/endianmacros.h
src/pulsecore/esound.h
src/pulsecore/fdsem.c [new file with mode: 0644]
src/pulsecore/fdsem.h [new file with mode: 0644]
src/pulsecore/ffmpeg/Makefile [new file with mode: 0644]
src/pulsecore/ffmpeg/avcodec.h [new file with mode: 0644]
src/pulsecore/ffmpeg/dsputil.h [new file with mode: 0644]
src/pulsecore/ffmpeg/resample2.c [new file with mode: 0644]
src/pulsecore/flist.c
src/pulsecore/flist.h
src/pulsecore/g711.c
src/pulsecore/gccmacro.h
src/pulsecore/hashmap.c
src/pulsecore/hashmap.h
src/pulsecore/hook-list.c
src/pulsecore/idxset.c
src/pulsecore/idxset.h
src/pulsecore/inet_ntop.c
src/pulsecore/iochannel.c
src/pulsecore/iochannel.h
src/pulsecore/ioline.c
src/pulsecore/ipacl.c
src/pulsecore/llist.h
src/pulsecore/log.c
src/pulsecore/ltdl-helper.c [new file with mode: 0644]
src/pulsecore/ltdl-helper.h [new file with mode: 0644]
src/pulsecore/macro.h [new file with mode: 0644]
src/pulsecore/mcalign.c
src/pulsecore/memblock.c
src/pulsecore/memblock.h
src/pulsecore/memblockq.c
src/pulsecore/memblockq.h
src/pulsecore/memchunk.c
src/pulsecore/memchunk.h
src/pulsecore/modargs.c
src/pulsecore/modargs.h
src/pulsecore/modinfo.c
src/pulsecore/modinfo.h
src/pulsecore/module.c
src/pulsecore/module.h
src/pulsecore/msgobject.c [new file with mode: 0644]
src/pulsecore/msgobject.h [new file with mode: 0644]
src/pulsecore/mutex-posix.c
src/pulsecore/mutex-win32.c
src/pulsecore/mutex.h
src/pulsecore/namereg.c
src/pulsecore/native-common.h
src/pulsecore/object.c [new file with mode: 0644]
src/pulsecore/object.h [new file with mode: 0644]
src/pulsecore/once-posix.c [deleted file]
src/pulsecore/once-win32.c [deleted file]
src/pulsecore/once.c [new file with mode: 0644]
src/pulsecore/once.h
src/pulsecore/packet.c
src/pulsecore/packet.h
src/pulsecore/parseaddr.c
src/pulsecore/pdispatch.c
src/pulsecore/pid.c
src/pulsecore/pipe.c
src/pulsecore/play-memblockq.c
src/pulsecore/play-memblockq.h
src/pulsecore/play-memchunk.c
src/pulsecore/poll.c
src/pulsecore/props.c
src/pulsecore/protocol-cli.c
src/pulsecore/protocol-esound.c
src/pulsecore/protocol-http.c
src/pulsecore/protocol-native.c
src/pulsecore/protocol-simple.c
src/pulsecore/pstream-util.c
src/pulsecore/pstream.c
src/pulsecore/pstream.h
src/pulsecore/queue.c
src/pulsecore/random.c
src/pulsecore/refcnt.h
src/pulsecore/resampler.c
src/pulsecore/resampler.h
src/pulsecore/rtclock.c [new file with mode: 0644]
src/pulsecore/rtclock.h [new file with mode: 0644]
src/pulsecore/rtpoll.c [new file with mode: 0644]
src/pulsecore/rtpoll.h [new file with mode: 0644]
src/pulsecore/rtsig.c [new file with mode: 0644]
src/pulsecore/rtsig.h [new file with mode: 0644]
src/pulsecore/sample-util.c
src/pulsecore/sample-util.h
src/pulsecore/sconv-s16be.c
src/pulsecore/sconv-s16be.h
src/pulsecore/sconv-s16le.c
src/pulsecore/sconv-s16le.h
src/pulsecore/sconv.c
src/pulsecore/sconv.h
src/pulsecore/semaphore-posix.c [new file with mode: 0644]
src/pulsecore/semaphore-win32.c [new file with mode: 0644]
src/pulsecore/semaphore.h [moved from src/pulsecore/anotify.h with 64% similarity]
src/pulsecore/shm.c
src/pulsecore/shm.h
src/pulsecore/sink-input.c
src/pulsecore/sink-input.h
src/pulsecore/sink.c
src/pulsecore/sink.h
src/pulsecore/sioman.c
src/pulsecore/socket-client.c
src/pulsecore/socket-server.c
src/pulsecore/socket-util.c
src/pulsecore/socket-util.h
src/pulsecore/sound-file-stream.c
src/pulsecore/sound-file.c
src/pulsecore/source-output.c
src/pulsecore/source-output.h
src/pulsecore/source.c
src/pulsecore/source.h
src/pulsecore/speex/Makefile [new file with mode: 0644]
src/pulsecore/speex/arch.h [new file with mode: 0644]
src/pulsecore/speex/fixed_generic.h [new file with mode: 0644]
src/pulsecore/speex/resample.c [new file with mode: 0644]
src/pulsecore/speex/speex_resampler.h [new file with mode: 0644]
src/pulsecore/speexwrap.h [new file with mode: 0644]
src/pulsecore/strbuf.c
src/pulsecore/strlist.c
src/pulsecore/tagstruct.c
src/pulsecore/thread-mq.c [new file with mode: 0644]
src/pulsecore/thread-mq.h [new file with mode: 0644]
src/pulsecore/thread-posix.c
src/pulsecore/thread-win32.c
src/pulsecore/thread.h
src/pulsecore/time-smoother.c [new file with mode: 0644]
src/pulsecore/time-smoother.h [new file with mode: 0644]
src/pulsecore/tokenizer.c
src/pulsecore/winsock.h
src/pulsecore/x11prop.c
src/pulsecore/x11wrap.c
src/tests/asyncmsgq-test.c [new file with mode: 0644]
src/tests/asyncq-test.c [new file with mode: 0644]
src/tests/hook-list-test.c
src/tests/interpol-test.c
src/tests/mcalign-test.c
src/tests/memblock-test.c
src/tests/memblockq-test.c
src/tests/queue-test.c [new file with mode: 0644]
src/tests/resampler-test.c [new file with mode: 0644]
src/tests/rtpoll-test.c [new file with mode: 0644]
src/tests/sig2str-test.c [new file with mode: 0644]
src/tests/smoother-test.c [new file with mode: 0644]
src/tests/thread-mainloop-test.c
src/tests/thread-test.c
src/utils/pactl.c
src/utils/padsp.c
src/utils/paplay.c
src/utils/pasuspender.c [new file with mode: 0644]
todo

index abc3d7760011535c0fb442df4618121589606f35..288c24efa16fe40517cb5454315358656d3d6b60 100644 (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
index b85f025eb39d6c5fc51364efc9233dae2362b38e..f23acbfef647a18461c22988d91cc151d084a1f0 100755 (executable)
@@ -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 "$@" 
index a195da2027dbfac52c0bd10927569e71b1770714..567dc4ede45b6340c9fa2536a6166080b92eb0d1 100644 (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,28 +93,64 @@ if test "x$GCC" = "xyes" ; then
 
     # We use gnu99 instead of c99 because many have interpreted the standard
     # in a way that int64_t isn't defined on non-64 bit platforms.
-    DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter"
+    DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter -ffast-math"
 
     for flag in $DESIRED_FLAGS ; do
         AC_MSG_CHECKING([whether $CC accepts $flag])
-        if test_gcc_flag $flag ; then 
+        if test_gcc_flag $flag ; then
            CFLAGS="$CFLAGS $flag"
            AC_MSG_RESULT([yes])
         else
            AC_MSG_RESULT([no])
         fi
-    done 
+    done
+fi
+
+AC_MSG_CHECKING([whether $CC knows __sync_bool_compare_and_swap()])
+AC_LANG_CONFTEST([int main() { int a = 4; __sync_bool_compare_and_swap(&a, 4, 5); }])
+$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null
+ret=$?
+rm -f conftest.o conftest
+if test $ret -eq 0 ; then
+    AC_DEFINE([HAVE_ATOMIC_BUILTINS], 1, [Have __sync_bool_compare_and_swap() and friends.])
+    AC_MSG_RESULT([yes])
+else
+    AC_MSG_RESULT([no])
+fi
+
+AC_MSG_CHECKING([whether $CC knows __thread])
+AC_LANG_CONFTEST([static __thread int a = 6; int main() { a = 5; }])
+$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null
+ret=$?
+rm -f conftest.o conftest
+if test $ret -eq 0 ; then
+    AC_DEFINE([HAVE_TLS_BUILTIN], 1, [Have __thread().])
+    AC_MSG_RESULT([yes])
+else
+    AC_MSG_RESULT([no])
+fi
+
+AC_MSG_CHECKING([whether $CC knows _Bool])
+AC_LANG_CONFTEST([int main() { _Bool b; }])
+$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null
+ret=$?
+rm -f conftest.o conftest
+if test $ret -eq 0 ; then
+    AC_DEFINE([HAVE_STD_BOOL], 1, [Have _Bool.])
+    AC_MSG_RESULT([yes])
+else
+    AC_MSG_RESULT([no])
 fi
 
 #### libtool stuff ####
 
 AC_LTDL_ENABLE_INSTALL
 AC_LIBLTDL_INSTALLABLE
-AC_SUBST(LTDLINCL)
-AC_SUBST(LIBLTDL)
 AC_LIBTOOL_DLOPEN
 AC_LIBTOOL_WIN32_DLL
 AC_PROG_LIBTOOL
+AC_SUBST(LTDLINCL)
+AC_SUBST(LIBLTDL)
 AC_CONFIG_SUBDIRS(libltdl)
 
 if test "x$enable_ltdl_install" = "xno" && test "x$ac_cv_lib_ltdl_lt_dlinit" = "xno" ; then
@@ -149,9 +185,9 @@ AC_HEADER_STDC
 
 # POSIX
 AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h netdb.h netinet/in.h \
-    netinet/in_systm.h netinet/tcp.h pwd.h sched.h \
+    netinet/in_systm.h netinet/tcp.h poll.h pwd.h sched.h \
     sys/mman.h sys/resource.h sys/select.h sys/socket.h sys/wait.h \
-    syslog.h])
+    syslog.h sys/dl.h dlfcn.h linux/sockios.h])
 AC_CHECK_HEADERS([netinet/ip.h], [], [],
                 [#include <sys/types.h>
                  #if HAVE_NETINET_IN_H
@@ -167,9 +203,6 @@ AC_CHECK_HEADERS([sys/un.h], [HAVE_AF_UNIX=1], [HAVE_AF_UNIX=0])
 AM_CONDITIONAL(HAVE_REGEX, test "x$HAVE_REGEX" = "x1")
 AM_CONDITIONAL(HAVE_AF_UNIX, test "x$HAVE_AF_UNIX" = "x1")
 
-# XPG4-UNIX
-AC_CHECK_HEADERS([sys/poll.h])
-
 # Linux
 AC_CHECK_HEADERS([linux/input.h], [HAVE_EVDEV=1], [HAVE_EVDEV=0])
 
@@ -185,6 +218,8 @@ AC_CHECK_HEADERS([windows.h winsock2.h ws2tcpip.h])
 
 # Other
 AC_CHECK_HEADERS([sys/ioctl.h])
+AC_CHECK_HEADERS([byteswap.h])
+AC_CHECK_HEADERS([sys/syscall.h])
 
 #### Typdefs, structures, etc. ####
 
@@ -235,13 +270,17 @@ AC_CHECK_FUNCS([getopt_long], [], [AC_CHECK_LIB([iberty], [getopt_long])])
 
 #### Check for functions ####
 
+# ISO
+AC_CHECK_FUNCS([lrintf strtof])
+
 # POSIX
 AC_FUNC_FORK
 AC_FUNC_GETGROUPS
 AC_FUNC_SELECT_ARGTYPES
-AC_CHECK_FUNCS([chmod chown getaddrinfo getgrgid_r getpwuid_r gettimeofday \
-    getuid inet_ntop inet_pton nanosleep pipe posix_memalign setpgid setsid \
-    shm_open sigaction sleep sysconf])
+AC_CHECK_FUNCS([chmod chown clock_gettime getaddrinfo getgrgid_r \
+    getpwuid_r gettimeofday getuid inet_ntop inet_pton mlock nanosleep \
+    pipe posix_fadvise posix_madvise posix_memalign setpgid setsid shm_open \
+    sigaction sleep sysconf])
 AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0])
 
 AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1")
@@ -260,7 +299,22 @@ AC_CHECK_FUNCS([lstat])
 
 # Non-standard
 
-AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid])
+AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid ppoll strsignal sig2str strtof_l])
+
+AC_MSG_CHECKING([for PTHREAD_PRIO_INHERIT])
+AC_LANG_CONFTEST([AC_LANG_SOURCE([[
+#include <pthread.h>
+int main() { int i = PTHREAD_PRIO_INHERIT; }]])])
+$PTHREAD_CC conftest.c $PTHREAD_CFLAGS $CFLAGS $PTHREAD_LIBS -o conftest > /dev/null 2> /dev/null
+ret=$?
+rm -f conftest.o conftest
+
+if test $ret -eq 0 ; then
+    AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.])
+    AC_MSG_RESULT([yes])
+else
+    AC_MSG_RESULT([no])
+fi
 
 #### Large File-Support (LFS) ####
 
@@ -324,12 +378,6 @@ fi
 
 PKG_PROG_PKG_CONFIG
 
-#### Sample rate conversion ####
-
-PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ])
-AC_SUBST(LIBSAMPLERATE_CFLAGS)
-AC_SUBST(LIBSAMPLERATE_LIBS)
-
 #### Sound file ####
 
 PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.10 ])
@@ -347,10 +395,45 @@ if test "x$os_is_win32" != "x1" ; then
     LIBS="$LIBS -latomic_ops"
 fi
 
+#### Libsamplerate support (optional) ####
+
+AC_ARG_ENABLE([samplerate],
+    AC_HELP_STRING([--disable-samplerate], [Disable optional libsamplerate support]),
+        [
+            case "${enableval}" in
+                yes) samplerate=yes ;;
+                no) samplerate=no ;;
+                *) AC_MSG_ERROR(bad value ${enableval} for --disable-samplerate) ;;
+            esac
+        ],
+        [samplerate=auto])
+
+if test "x${samplerate}" != xno ; then
+    PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ],
+        HAVE_LIBSAMPLERATE=1,
+        [
+            HAVE_LIBSAMPLERATE=0
+            if test "x$samplerate" = xyes ; then
+                AC_MSG_ERROR([*** Libsamplerate not found])
+            fi
+        ])
+else
+    HAVE_LIBSAMPLERATE=0
+fi
+
+if test "x${HAVE_LIBSAMPLERATE}" = x1 ; then
+   AC_DEFINE([HAVE_LIBSAMPLERATE], 1, [Have libsamplerate?])
+fi
+
+AC_SUBST(LIBSAMPLERATE_CFLAGS)
+AC_SUBST(LIBSAMPLERATE_LIBS)
+AC_SUBST(HAVE_LIBSAMPLERATE)
+AM_CONDITIONAL([HAVE_LIBSAMPLERATE], [test "x$HAVE_LIBSAMPLERATE" = x1])
+
 #### OSS support (optional) ####
 
-AC_ARG_ENABLE([oss], 
-    AC_HELP_STRING([--disable-oss], [Disable optional OSS support]), 
+AC_ARG_ENABLE([oss],
+    AC_HELP_STRING([--disable-oss], [Disable optional OSS support]),
         [
             case "${enableval}" in
                 yes) oss=yes ;;
@@ -382,8 +465,8 @@ AM_CONDITIONAL([HAVE_OSS], [test "x$HAVE_OSS" = x1])
 
 #### ALSA support (optional) ####
 
-AC_ARG_ENABLE([alsa], 
-    AC_HELP_STRING([--disable-alsa], [Disable optional ALSA support]), 
+AC_ARG_ENABLE([alsa],
+    AC_HELP_STRING([--disable-alsa], [Disable optional ALSA support]),
         [
             case "${enableval}" in
                 yes) alsa=yes ;;
@@ -410,14 +493,14 @@ else
 fi
 
 AC_SUBST(ASOUNDLIB_CFLAGS)
-AC_SUBST(ASOUNDLIB_LIBS) 
+AC_SUBST(ASOUNDLIB_LIBS)
 AC_SUBST(HAVE_ALSA)
 AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1])
 
 #### Solaris audio support (optional) ####
 
-AC_ARG_ENABLE([solaris], 
-    AC_HELP_STRING([--disable-solaris], [Disable optional Solaris audio support]), 
+AC_ARG_ENABLE([solaris],
+    AC_HELP_STRING([--disable-solaris], [Disable optional Solaris audio support]),
         [
             case "${enableval}" in
                 yes) solaris=yes ;;
@@ -448,8 +531,8 @@ AM_CONDITIONAL([HAVE_SOLARIS], [test "x$HAVE_SOLARIS" = x1])
 
 #### GLib 2 support (optional) ####
 
-AC_ARG_ENABLE([glib2], 
-    AC_HELP_STRING([--disable-glib2], [Disable optional GLib 2 support]), 
+AC_ARG_ENABLE([glib2],
+    AC_HELP_STRING([--disable-glib2], [Disable optional GLib 2 support]),
         [
             case "${enableval}" in
                 yes) glib2=yes ;;
@@ -479,8 +562,8 @@ AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1])
 
 #### GConf support (optional) ####
 
-AC_ARG_ENABLE([gconf], 
-    AC_HELP_STRING([--disable-gconf], [Disable optional GConf support]), 
+AC_ARG_ENABLE([gconf],
+    AC_HELP_STRING([--disable-gconf], [Disable optional GConf support]),
         [
             case "${enableval}" in
                 yes) gconf=yes ;;
@@ -510,8 +593,8 @@ AM_CONDITIONAL([HAVE_GCONF], [test "x$HAVE_GCONF" = x1])
 
 #### Avahi support (optional) ####
 
-AC_ARG_ENABLE([avahi], 
-    AC_HELP_STRING([--disable-avahi], [Disable optional Avahi support]), 
+AC_ARG_ENABLE([avahi],
+    AC_HELP_STRING([--disable-avahi], [Disable optional Avahi support]),
         [
             case "${enableval}" in
                 yes) avahi=yes ;;
@@ -547,8 +630,8 @@ AC_SUBST(LIBOIL_LIBS)
 
 ### JACK (optional) ####
 
-AC_ARG_ENABLE([jack], 
-    AC_HELP_STRING([--disable-jack], [Disable optional JACK support]), 
+AC_ARG_ENABLE([jack],
+    AC_HELP_STRING([--disable-jack], [Disable optional JACK support]),
         [
             case "${enableval}" in
                 yes) jack=yes ;;
@@ -578,8 +661,8 @@ AM_CONDITIONAL([HAVE_JACK], [test "x$HAVE_JACK" = x1])
 
 #### Async DNS support (optional) ####
 
-AC_ARG_ENABLE([asyncns], 
-    AC_HELP_STRING([--disable-asyncns], [Disable optional Async DNS support]), 
+AC_ARG_ENABLE([asyncns],
+    AC_HELP_STRING([--disable-asyncns], [Disable optional Async DNS support]),
         [
             case "${enableval}" in
                 yes) asyncns=yes ;;
@@ -613,8 +696,8 @@ fi
 
 #### TCP wrappers (optional) ####
 
-AC_ARG_ENABLE([tcpwrap], 
-    AC_HELP_STRING([--disable-tcpwrap], [Disable optional TCP wrappers support]), 
+AC_ARG_ENABLE([tcpwrap],
+    AC_HELP_STRING([--disable-tcpwrap], [Disable optional TCP wrappers support]),
         [
             case "${enableval}" in
                 yes) tcpwrap=yes ;;
@@ -637,8 +720,8 @@ AC_SUBST(LIBWRAP_LIBS)
 
 #### LIRC support (optional) ####
 
-AC_ARG_ENABLE([lirc], 
-    AC_HELP_STRING([--disable-lirc], [Disable optional LIRC support]), 
+AC_ARG_ENABLE([lirc],
+    AC_HELP_STRING([--disable-lirc], [Disable optional LIRC support]),
         [
             case "${enableval}" in
                 yes) lirc=yes ;;
@@ -663,8 +746,8 @@ AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1])
 
 #### HAL support (optional) ####
 
-AC_ARG_ENABLE([hal], 
-    AC_HELP_STRING([--disable-hal], [Disable optional HAL support]), 
+AC_ARG_ENABLE([hal],
+    AC_HELP_STRING([--disable-hal], [Disable optional HAL support]),
         [
             case "${enableval}" in
                 yes) hal=yes ;;
@@ -673,7 +756,6 @@ AC_ARG_ENABLE([hal],
             esac
         ],
         [hal=auto])
-
 if test "x${hal}" != xno -a \( "x$HAVE_OSS" = "x1" -o "x$HAVE_ALSA" = "x1" \) ; then
     PKG_CHECK_MODULES(HAL, [ hal >= 0.5.7 ],
         HAVE_HAL=1,
@@ -692,6 +774,49 @@ AC_SUBST(HAL_LIBS)
 AC_SUBST(HAVE_HAL)
 AM_CONDITIONAL([HAVE_HAL], [test "x$HAVE_HAL" = x1])
 
+#### D-Bus support (optional) ####
+
+AC_ARG_ENABLE([dbus],
+    AC_HELP_STRING([--disable-dbus], [Disable optional D-Bus support]),
+        [
+            case "${enableval}" in
+                yes) dbus=yes ;;
+                no) dbus=no ;;
+                *) AC_MSG_ERROR(bad value ${enableval} for --disable-dbus) ;;
+            esac
+        ],
+        [dbus=auto])
+
+if test "x$HAVE_HAL" = x1 ; then
+   dbus=yes
+fi
+
+if test "x${dbus}" != xno ; then
+
+    PKG_CHECK_MODULES(DBUS, [ dbus-1 >= 1.0.0 ],
+        [
+            HAVE_DBUS=1
+            saved_LIBS="$LIBS"
+            LIBS="$LIBS $DBUS_LIBS"
+            AC_CHECK_FUNCS(dbus_watch_get_unix_fd)
+            LIBS="$saved_LIBS"
+            AC_DEFINE([HAVE_DBUS], 1, [Have D-Bus.])
+        ],
+        [
+            HAVE_DBUS=0
+            if test "x$dbus" = xyes ; then
+                AC_MSG_ERROR([*** D-Bus support not found])
+            fi
+        ])
+else
+    HAVE_DBUS=0
+fi
+
+AC_SUBST(DBUS_CFLAGS)
+AC_SUBST(DBUS_LIBS)
+AC_SUBST(HAVE_DBUS)
+AM_CONDITIONAL([HAVE_DBUS], [test "x$HAVE_DBUS" = x1])
+
 #### PulseAudio system group & user  #####
 
 AC_ARG_WITH(system_user, AS_HELP_STRING([--with-system-user=<user>],[User for running the PulseAudio daemon as a system-wide instance (pulse)]))
@@ -845,6 +970,11 @@ if test "x${LIBWRAP_LIBS}" != x ; then
    ENABLE_TCPWRAP=yes
 fi
 
+ENABLE_LIBSAMPLERATE=no
+if test "x${HAVE_LIBSAMPLERATE}" = "x1" ; then
+   ENABLE_LIBSAMPLERATE=yes
+fi
+
 echo "
  ---{ $PACKAGE_NAME $VERSION }---
 
@@ -866,6 +996,7 @@ echo "
     Enable LIRC:            ${ENABLE_LIRC}
     Enable HAL:             ${ENABLE_HAL}
     Enable TCP Wrappers:    ${ENABLE_TCPWRAP}
+    Enable libsamplerate:   ${ENABLE_LIBSAMPLERATE}
     System User:            ${PA_SYSTEM_USER}
     System Group:           ${PA_SYSTEM_GROUP}
     Realtime Group:         ${PA_REALTIME_GROUP}
diff --git a/libltdl/COPYING.LIB b/libltdl/COPYING.LIB
new file mode 100644 (file)
index 0000000..ba2be48
--- /dev/null
@@ -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.
+\f
+  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!
+
+
diff --git a/libltdl/Makefile.am b/libltdl/Makefile.am
new file mode 100644 (file)
index 0000000..2a1e701
--- /dev/null
@@ -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
diff --git a/libltdl/Makefile.in b/libltdl/Makefile.in
new file mode 100644 (file)
index 0000000..4319156
--- /dev/null
@@ -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:
diff --git a/libltdl/README b/libltdl/README
new file mode 100644 (file)
index 0000000..da0a449
--- /dev/null
@@ -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
diff --git a/libltdl/acinclude.m4 b/libltdl/acinclude.m4
new file mode 100644 (file)
index 0000000..79d9486
--- /dev/null
@@ -0,0 +1,7025 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007
+## Free Software Foundation, Inc.
+## Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+##
+## 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 51 Debian 1.5.24-1 AC_PROG_LIBTOOL
+
+
+# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
+# -----------------------------------------------------------
+# If this macro is not defined by Autoconf, define it here.
+m4_ifdef([AC_PROVIDE_IFELSE],
+         [],
+         [m4_define([AC_PROVIDE_IFELSE],
+                [m4_ifdef([AC_PROVIDE_$1],
+                          [$2], [$3])])])
+
+
+# AC_PROG_LIBTOOL
+# ---------------
+AC_DEFUN([AC_PROG_LIBTOOL],
+[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl
+dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX
+dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX.
+  AC_PROVIDE_IFELSE([AC_PROG_CXX],
+    [AC_LIBTOOL_CXX],
+    [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX
+  ])])
+dnl And a similar setup for Fortran 77 support
+  AC_PROVIDE_IFELSE([AC_PROG_F77],
+    [AC_LIBTOOL_F77],
+    [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77
+])])
+
+dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly.
+dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run
+dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both.
+  AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+    [AC_LIBTOOL_GCJ],
+    [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+      [AC_LIBTOOL_GCJ],
+      [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],
+       [AC_LIBTOOL_GCJ],
+      [ifdef([AC_PROG_GCJ],
+            [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+       ifdef([A][M_PROG_GCJ],
+            [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+       ifdef([LT_AC_PROG_GCJ],
+            [define([LT_AC_PROG_GCJ],
+               defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])])
+])])# AC_PROG_LIBTOOL
+
+
+# _AC_PROG_LIBTOOL
+# ----------------
+AC_DEFUN([_AC_PROG_LIBTOOL],
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Prevent multiple expansion
+define([AC_PROG_LIBTOOL], [])
+])# _AC_PROG_LIBTOOL
+
+
+# AC_LIBTOOL_SETUP
+# ----------------
+AC_DEFUN([AC_LIBTOOL_SETUP],
+[AC_PREREQ(2.50)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+
+AC_REQUIRE([AC_PROG_LN_S])dnl
+AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+AC_REQUIRE([AC_OBJEXT])dnl
+AC_REQUIRE([AC_EXEEXT])dnl
+dnl
+
+AC_LIBTOOL_SYS_MAX_CMD_LEN
+AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+AC_LIBTOOL_OBJDIR
+
+AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+_LT_AC_PROG_ECHO_BACKSLASH
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g']
+
+# Same as above, but do not quote variable references.
+[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g']
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+AC_CHECK_TOOL(AR, ar, false)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(STRIP, strip, :)
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    AC_PATH_MAGIC
+  fi
+  ;;
+esac
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+enable_win32_dll=yes, enable_win32_dll=no)
+
+AC_ARG_ENABLE([libtool-lock],
+    [AC_HELP_STRING([--disable-libtool-lock],
+       [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+AC_ARG_WITH([pic],
+    [AC_HELP_STRING([--with-pic],
+       [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+    [pic_mode="$withval"],
+    [pic_mode=default])
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+AC_LIBTOOL_LANG_C_CONFIG
+_LT_AC_TAGCONFIG
+])# AC_LIBTOOL_SETUP
+
+
+# _LT_AC_SYS_COMPILER
+# -------------------
+AC_DEFUN([_LT_AC_SYS_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_AC_SYS_COMPILER
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+AC_DEFUN([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+  case $cc_temp in
+    compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+    distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+])
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+AC_DEFUN([_LT_COMPILER_BOILERPLATE],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+AC_DEFUN([_LT_LINKER_BOILERPLATE],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+])# _LT_LINKER_BOILERPLATE
+
+
+# _LT_AC_SYS_LIBPATH_AIX
+# ----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_AC_SYS_LIBPATH_AIX
+
+
+# _LT_AC_SHELL_INIT(ARG)
+# ----------------------
+AC_DEFUN([_LT_AC_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+            [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+        [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_AC_SHELL_INIT
+
+
+# _LT_AC_PROG_ECHO_BACKSLASH
+# --------------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+[_LT_AC_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+  ;;
+esac
+
+echo=${ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X[$]1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+[$]*
+EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+  for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+    if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+       echo_test_string=`eval $cmd` &&
+       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+    then
+      break
+    fi
+  done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+   echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+   test "X$echo_testing_string" = "X$echo_test_string"; then
+  :
+else
+  # The Solaris, AIX, and Digital Unix default echo programs unquote
+  # backslashes.  This makes it impossible to quote backslashes using
+  #   echo "$something" | sed 's/\\/\\\\/g'
+  #
+  # So, first we look for a working echo in the user's PATH.
+
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for dir in $PATH /usr/ucb; do
+    IFS="$lt_save_ifs"
+    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      echo="$dir/echo"
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+
+  if test "X$echo" = Xecho; then
+    # We didn't find a better echo, so look for alternatives.
+    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      # This shell has a builtin print -r that does the trick.
+      echo='print -r'
+    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+        test "X$CONFIG_SHELL" != X/bin/ksh; then
+      # If we have ksh, try running configure again with it.
+      ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+      export ORIGINAL_CONFIG_SHELL
+      CONFIG_SHELL=/bin/ksh
+      export CONFIG_SHELL
+      exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+    else
+      # Try using printf.
+      echo='printf %s\n'
+      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+        echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+        test "X$echo_testing_string" = "X$echo_test_string"; then
+       # Cool, printf works
+       :
+      elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+       export CONFIG_SHELL
+       SHELL="$CONFIG_SHELL"
+       export SHELL
+       echo="$CONFIG_SHELL [$]0 --fallback-echo"
+      elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       echo="$CONFIG_SHELL [$]0 --fallback-echo"
+      else
+       # maybe with a smaller string...
+       prev=:
+
+       for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+         if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+         then
+           break
+         fi
+         prev="$cmd"
+       done
+
+       if test "$prev" != 'sed 50q "[$]0"'; then
+         echo_test_string=`eval $prev`
+         export echo_test_string
+         exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+       else
+         # Oops.  We lost completely, so just stick with echo.
+         echo=echo
+       fi
+      fi
+    fi
+  fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+   ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(ECHO)
+])])# _LT_AC_PROG_ECHO_BACKSLASH
+
+
+# _LT_AC_LOCK
+# -----------
+AC_DEFUN([_LT_AC_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+    [AC_HELP_STRING([--disable-libtool-lock],
+       [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *ELF-32*)
+      HPUX_IA64_MODE="32"
+      ;;
+    *ELF-64*)
+      HPUX_IA64_MODE="64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+   if test "$lt_cv_prog_gnu_ld" = yes; then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -melf32bsmip"
+      ;;
+    *N32*)
+      LD="${LD-ld} -melf32bmipn32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -melf64bmip"
+      ;;
+    esac
+   else
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+   fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+    *32-bit*)
+      case $host in
+        x86_64-*kfreebsd*-gnu)
+          LD="${LD-ld} -m elf_i386_fbsd"
+          ;;
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_i386"
+          ;;
+        ppc64-*linux*|powerpc64-*linux*)
+          LD="${LD-ld} -m elf32ppclinux"
+          ;;
+        s390x-*linux*)
+          LD="${LD-ld} -m elf_s390"
+          ;;
+        sparc64-*linux*)
+          LD="${LD-ld} -m elf32_sparc"
+          ;;
+      esac
+      ;;
+    *64-bit*)
+      case $host in
+        x86_64-*kfreebsd*-gnu)
+          LD="${LD-ld} -m elf_x86_64_fbsd"
+          ;;
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        ppc*-*linux*|powerpc*-*linux*)
+          LD="${LD-ld} -m elf64ppc"
+          ;;
+        s390*-*linux*)
+          LD="${LD-ld} -m elf64_s390"
+          ;;
+        sparc*-*linux*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_PUSH(C)
+     AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_POP])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+sparc*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+      *)    LD="${LD-ld} -64" ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+  ])
+esac
+
+need_locks="$enable_libtool_lock"
+
+])# _LT_AC_LOCK
+
+
+# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#              [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION],
+[AC_REQUIRE([LT_AC_PROG_SED])
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+  ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$3"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       $2=yes
+     fi
+   fi
+   $rm conftest*
+])
+
+if test x"[$]$2" = xyes; then
+    ifelse([$5], , :, [$5])
+else
+    ifelse([$6], , :, [$6])
+fi
+])# AC_LIBTOOL_COMPILER_OPTION
+
+
+# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#                          [ACTION-SUCCESS], [ACTION-FAILURE])
+# ------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $3"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&AS_MESSAGE_LOG_FD
+       $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         $2=yes
+       fi
+     else
+       $2=yes
+     fi
+   fi
+   $rm conftest*
+   LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+    ifelse([$4], , :, [$4])
+else
+    ifelse([$5], , :, [$5])
+fi
+])# AC_LIBTOOL_LINKER_OPTION
+
+
+# AC_LIBTOOL_SYS_MAX_CMD_LEN
+# --------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN],
+[# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+  i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536      # usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[       ]]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \
+              = "XX$teststring") >/dev/null 2>&1 &&
+             new_result=`expr "X$teststring" : ".*" 2>&1` &&
+             lt_cv_sys_max_cmd_len=$new_result &&
+             test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on massive
+      # amounts of additional arguments before passing them to the linker.
+      # It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+  AC_MSG_RESULT(none)
+fi
+])# AC_LIBTOOL_SYS_MAX_CMD_LEN
+
+
+# _LT_AC_CHECK_DLFCN
+# ------------------
+AC_DEFUN([_LT_AC_CHECK_DLFCN],
+[AC_CHECK_HEADERS(dlfcn.h)dnl
+])# _LT_AC_CHECK_DLFCN
+
+
+# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                           ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ---------------------------------------------------------------------
+AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+  [$4]
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+    exit (status);
+}]
+EOF
+  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) $1 ;;
+      x$lt_dlneed_uscore) $2 ;;
+      x$lt_dlunknown|x*) $3 ;;
+    esac
+  else :
+    # compilation failed
+    $3
+  fi
+fi
+rm -fr conftest*
+])# _LT_AC_TRY_DLOPEN_SELF
+
+
+# AC_LIBTOOL_DLOPEN_SELF
+# ----------------------
+AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+   ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+   ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    AC_CHECK_LIB([dl], [dlopen],
+               [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ])
+   ;;
+
+  *)
+    AC_CHECK_FUNC([shl_load],
+         [lt_cv_dlopen="shl_load"],
+      [AC_CHECK_LIB([dld], [shl_load],
+           [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
+       [AC_CHECK_FUNC([dlopen],
+             [lt_cv_dlopen="dlopen"],
+         [AC_CHECK_LIB([dl], [dlopen],
+               [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+           [AC_CHECK_LIB([svld], [dlopen],
+                 [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+             [AC_CHECK_LIB([dld], [dld_link],
+                   [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
+             ])
+           ])
+         ])
+       ])
+      ])
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    AC_CACHE_CHECK([whether a program can dlopen itself],
+         lt_cv_dlopen_self, [dnl
+         _LT_AC_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+           lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+    ])
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+         lt_cv_dlopen_self_static, [dnl
+         _LT_AC_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+           lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+      ])
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+])# AC_LIBTOOL_DLOPEN_SELF
+
+
+# AC_LIBTOOL_PROG_CC_C_O([TAGNAME])
+# ---------------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler
+AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+  [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+  [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+   $rm -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+     fi
+   fi
+   chmod u+w . 2>&AS_MESSAGE_LOG_FD
+   $rm conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+   $rm out/* && rmdir out
+   cd ..
+   rmdir conftest
+   $rm conftest*
+])
+])# AC_LIBTOOL_PROG_CC_C_O
+
+
+# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME])
+# -----------------------------------------
+# Check to see if we can do hard links to lock some files if needed
+AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS],
+[AC_REQUIRE([_LT_AC_LOCK])dnl
+
+hard_links="nottested"
+if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test "$hard_links" = no; then
+    AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS
+
+
+# AC_LIBTOOL_OBJDIR
+# -----------------
+AC_DEFUN([AC_LIBTOOL_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+])# AC_LIBTOOL_OBJDIR
+
+
+# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME])
+# ----------------------------------------------
+# Check hardcoding attributes.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_AC_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \
+   test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \
+   test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+  # We can hardcode non-existant directories.
+  if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+     test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then
+    # Linking always hardcodes the temporary library directory.
+    _LT_AC_TAGVAR(hardcode_action, $1)=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    _LT_AC_TAGVAR(hardcode_action, $1)=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  _LT_AC_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH
+
+
+# AC_LIBTOOL_SYS_LIB_STRIP
+# ------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP],
+[striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+   darwin*)
+       if test -n "$STRIP" ; then
+         striplib="$STRIP -x"
+         old_striplib="$STRIP -S"
+         AC_MSG_RESULT([yes])
+       else
+  AC_MSG_RESULT([no])
+fi
+       ;;
+   *)
+  AC_MSG_RESULT([no])
+    ;;
+  esac
+fi
+])# AC_LIBTOOL_SYS_LIB_STRIP
+
+
+# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+m4_if($1,[],[
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+  if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'`
+  else
+    lt_search_path_spec=`echo "$lt_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+  fi
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+  sys_lib_search_path_spec=`echo $lt_search_path_spec`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[[45]]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+  m4_if([$1], [],[
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) 
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[[123]]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+   hppa*64*)
+     shrext_cmds='.sl'
+     hardcode_into_libs=yes
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+     library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[[3-9]]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[         ]*hwcap[        ]/d;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+nto-qnx*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[[89]] | openbsd2.[[89]].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+    shlibpath_overrides_runpath=no
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    shlibpath_overrides_runpath=yes
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+])# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+
+
+# _LT_AC_TAGCONFIG
+# ----------------
+AC_DEFUN([_LT_AC_TAGCONFIG],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_ARG_WITH([tags],
+    [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@],
+        [include additional configurations @<:@automatic@:>@])],
+    [tagnames="$withval"])
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+  if test ! -f "${ofile}"; then
+    AC_MSG_WARN([output file `$ofile' does not exist])
+  fi
+
+  if test -z "$LTCC"; then
+    eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+    if test -z "$LTCC"; then
+      AC_MSG_WARN([output file `$ofile' does not look like a libtool script])
+    else
+      AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile'])
+    fi
+  fi
+  if test -z "$LTCFLAGS"; then
+    eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
+  fi
+
+  # Extract list of available tagged configurations in $ofile.
+  # Note that this assumes the entire list is on one line.
+  available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+  lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+  for tagname in $tagnames; do
+    IFS="$lt_save_ifs"
+    # Check whether tagname contains only valid characters
+    case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in
+    "") ;;
+    *)  AC_MSG_ERROR([invalid tag name: $tagname])
+       ;;
+    esac
+
+    if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+    then
+      AC_MSG_ERROR([tag name \"$tagname\" already exists])
+    fi
+
+    # Update the list of available tags.
+    if test -n "$tagname"; then
+      echo appending configuration tag \"$tagname\" to $ofile
+
+      case $tagname in
+      CXX)
+       if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+           ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+           (test "X$CXX" != "Xg++"))) ; then
+         AC_LIBTOOL_LANG_CXX_CONFIG
+       else
+         tagname=""
+       fi
+       ;;
+
+      F77)
+       if test -n "$F77" && test "X$F77" != "Xno"; then
+         AC_LIBTOOL_LANG_F77_CONFIG
+       else
+         tagname=""
+       fi
+       ;;
+
+      GCJ)
+       if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+         AC_LIBTOOL_LANG_GCJ_CONFIG
+       else
+         tagname=""
+       fi
+       ;;
+
+      RC)
+       AC_LIBTOOL_LANG_RC_CONFIG
+       ;;
+
+      *)
+       AC_MSG_ERROR([Unsupported tag name: $tagname])
+       ;;
+      esac
+
+      # Append the new tag name to the list of available tags.
+      if test -n "$tagname" ; then
+      available_tags="$available_tags $tagname"
+    fi
+    fi
+  done
+  IFS="$lt_save_ifs"
+
+  # Now substitute the updated list of available tags.
+  if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+    mv "${ofile}T" "$ofile"
+    chmod +x "$ofile"
+  else
+    rm -f "${ofile}T"
+    AC_MSG_ERROR([unable to update list of available tagged configurations.])
+  fi
+fi
+])# _LT_AC_TAGCONFIG
+
+
+# AC_LIBTOOL_DLOPEN
+# -----------------
+# enable checks for dlopen support
+AC_DEFUN([AC_LIBTOOL_DLOPEN],
+ [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_DLOPEN
+
+
+# AC_LIBTOOL_WIN32_DLL
+# --------------------
+# declare package support for building win32 DLLs
+AC_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_BEFORE([$0], [AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_WIN32_DLL
+
+
+# AC_ENABLE_SHARED([DEFAULT])
+# ---------------------------
+# implement the --enable-shared flag
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_SHARED],
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([shared],
+    [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+       [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_shared=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_shared=]AC_ENABLE_SHARED_DEFAULT)
+])# AC_ENABLE_SHARED
+
+
+# AC_DISABLE_SHARED
+# -----------------
+# set the default shared flag to --disable-shared
+AC_DEFUN([AC_DISABLE_SHARED],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)
+])# AC_DISABLE_SHARED
+
+
+# AC_ENABLE_STATIC([DEFAULT])
+# ---------------------------
+# implement the --enable-static flag
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_STATIC],
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([static],
+    [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+       [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_static=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_static=]AC_ENABLE_STATIC_DEFAULT)
+])# AC_ENABLE_STATIC
+
+
+# AC_DISABLE_STATIC
+# -----------------
+# set the default static flag to --disable-static
+AC_DEFUN([AC_DISABLE_STATIC],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)
+])# AC_DISABLE_STATIC
+
+
+# AC_ENABLE_FAST_INSTALL([DEFAULT])
+# ---------------------------------
+# implement the --enable-fast-install flag
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_FAST_INSTALL],
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([fast-install],
+    [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+    [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_fast_install=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT)
+])# AC_ENABLE_FAST_INSTALL
+
+
+# AC_DISABLE_FAST_INSTALL
+# -----------------------
+# set the default to --disable-fast-install
+AC_DEFUN([AC_DISABLE_FAST_INSTALL],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)
+])# AC_DISABLE_FAST_INSTALL
+
+
+# AC_LIBTOOL_PICMODE([MODE])
+# --------------------------
+# implement the --with-pic flag
+# MODE is either `yes' or `no'.  If omitted, it defaults to `both'.
+AC_DEFUN([AC_LIBTOOL_PICMODE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+pic_mode=ifelse($#,1,$1,default)
+])# AC_LIBTOOL_PICMODE
+
+
+# AC_PROG_EGREP
+# -------------
+# This is predefined starting with Autoconf 2.54, so this conditional
+# definition can be removed once we require Autoconf 2.54 or later.
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP],
+[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
+   [if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi])
+ EGREP=$ac_cv_prog_egrep
+ AC_SUBST([EGREP])
+])])
+
+
+# AC_PATH_TOOL_PREFIX
+# -------------------
+# find a file program which can recognize shared library
+AC_DEFUN([AC_PATH_TOOL_PREFIX],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] |  ?:[\\/]*])
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="ifelse([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$1; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+])# AC_PATH_TOOL_PREFIX
+
+
+# AC_PATH_MAGIC
+# -------------
+# find a file program which can recognize a shared library
+AC_DEFUN([AC_PATH_MAGIC],
+[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])# AC_PATH_MAGIC
+
+
+# AC_PROG_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([AC_PROG_LD],
+[AC_ARG_WITH([gnu-ld],
+    [AC_HELP_STRING([--with-gnu-ld],
+       [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+    [test "$withval" = no || with_gnu_ld=yes],
+    [with_gnu_ld=no])
+AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by $CC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | ?:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+       test "$with_gnu_ld" != no && break
+       ;;
+      *)
+       test "$with_gnu_ld" != yes && break
+       ;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])# AC_PROG_LD
+
+
+# AC_PROG_LD_GNU
+# --------------
+AC_DEFUN([AC_PROG_LD_GNU],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# AC_PROG_LD_GNU
+
+
+# AC_PROG_LD_RELOAD_FLAG
+# ----------------------
+# find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+  lt_cv_ld_reload_flag,
+  [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+])# AC_PROG_LD_RELOAD_FLAG
+
+
+# AC_DEPLIBS_CHECK_METHOD
+# -----------------------
+# how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+[AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[[45]]*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  if ( file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[[3-9]]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd* | netbsdelf*-gnu)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+nto-qnx*)
+  lt_cv_deplibs_check_method=unknown
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+])# AC_DEPLIBS_CHECK_METHOD
+
+
+# AC_PROG_NM
+# ----------
+# find the pathname to a BSD-compatible name lister
+AC_DEFUN([AC_PROG_NM],
+[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+       # Check to see if the nm accepts a BSD-compat flag.
+       # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+       #   nm: unknown option "B" ignored
+       # Tru64's nm complains that /dev/null is an invalid object file
+       case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+       */dev/null* | *'Invalid file or object type'*)
+         lt_cv_path_NM="$tmp_nm -B"
+         break
+         ;;
+       *)
+         case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+         */dev/null*)
+           lt_cv_path_NM="$tmp_nm -p"
+           break
+           ;;
+         *)
+           lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+           continue # so that we can try to find one that supports BSD flags
+           ;;
+         esac
+         ;;
+       esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi])
+NM="$lt_cv_path_NM"
+])# AC_PROG_NM
+
+
+# AC_CHECK_LIBM
+# -------------
+# check for math library
+AC_DEFUN([AC_CHECK_LIBM],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+  # These system don't have libm, or don't need it
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, cos, LIBM="-lm")
+  ;;
+esac
+])# AC_CHECK_LIBM
+
+
+# AC_LIBLTDL_CONVENIENCE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl convenience library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-convenience to the configure arguments.  Note that
+# AC_CONFIG_SUBDIRS is not called here.  If DIRECTORY is not provided,
+# it is assumed to be `libltdl'.  LIBLTDL will be prefixed with
+# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/'
+# (note the single quotes!).  If your package is not flat and you're not
+# using automake, define top_builddir and top_srcdir appropriately in
+# the Makefiles.
+AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  case $enable_ltdl_convenience in
+  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+  "") enable_ltdl_convenience=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+  esac
+  LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+  LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+  # For backwards non-gettext consistent compatibility...
+  INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_CONVENIENCE
+
+
+# AC_LIBLTDL_INSTALLABLE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl installable library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-install to the configure arguments.  Note that
+# AC_CONFIG_SUBDIRS is not called here.  If DIRECTORY is not provided,
+# and an installed libltdl is not found, it is assumed to be `libltdl'.
+# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with
+# '${top_srcdir}/' (note the single quotes!).  If your package is not
+# flat and you're not using automake, define top_builddir and top_srcdir
+# appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  AC_CHECK_LIB(ltdl, lt_dlinit,
+  [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+  [if test x"$enable_ltdl_install" = xno; then
+     AC_MSG_WARN([libltdl not installed, but installation disabled])
+   else
+     enable_ltdl_install=yes
+   fi
+  ])
+  if test x"$enable_ltdl_install" = x"yes"; then
+    ac_configure_args="$ac_configure_args --enable-ltdl-install"
+    LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+    LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+  else
+    ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+    LIBLTDL="-lltdl"
+    LTDLINCL=
+  fi
+  # For backwards non-gettext consistent compatibility...
+  INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_INSTALLABLE
+
+
+# AC_LIBTOOL_CXX
+# --------------
+# enable support for C++ libraries
+AC_DEFUN([AC_LIBTOOL_CXX],
+[AC_REQUIRE([_LT_AC_LANG_CXX])
+])# AC_LIBTOOL_CXX
+
+
+# _LT_AC_LANG_CXX
+# ---------------
+AC_DEFUN([_LT_AC_LANG_CXX],
+[AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX])
+])# _LT_AC_LANG_CXX
+
+# _LT_AC_PROG_CXXCPP
+# ------------------
+AC_DEFUN([_LT_AC_PROG_CXXCPP],
+[
+AC_REQUIRE([AC_PROG_CXX])
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+    (test "X$CXX" != "Xg++"))) ; then
+  AC_PROG_CXXCPP
+fi
+])# _LT_AC_PROG_CXXCPP
+
+# AC_LIBTOOL_F77
+# --------------
+# enable support for Fortran 77 libraries
+AC_DEFUN([AC_LIBTOOL_F77],
+[AC_REQUIRE([_LT_AC_LANG_F77])
+])# AC_LIBTOOL_F77
+
+
+# _LT_AC_LANG_F77
+# ---------------
+AC_DEFUN([_LT_AC_LANG_F77],
+[AC_REQUIRE([AC_PROG_F77])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77])
+])# _LT_AC_LANG_F77
+
+
+# AC_LIBTOOL_GCJ
+# --------------
+# enable support for GCJ libraries
+AC_DEFUN([AC_LIBTOOL_GCJ],
+[AC_REQUIRE([_LT_AC_LANG_GCJ])
+])# AC_LIBTOOL_GCJ
+
+
+# _LT_AC_LANG_GCJ
+# ---------------
+AC_DEFUN([_LT_AC_LANG_GCJ],
+[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[],
+  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[],
+    [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[],
+      [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])],
+        [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])],
+          [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ])
+])# _LT_AC_LANG_GCJ
+
+
+# AC_LIBTOOL_RC
+# -------------
+# enable support for Windows resource files
+AC_DEFUN([AC_LIBTOOL_RC],
+[AC_REQUIRE([LT_AC_PROG_RC])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC])
+])# AC_LIBTOOL_RC
+
+
+# AC_LIBTOOL_LANG_C_CONFIG
+# ------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG])
+AC_DEFUN([_LT_AC_LANG_C_CONFIG],
+[lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF
+
+# Report which library types will actually be built
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+
+aix4* | aix5*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
+    ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_C_CONFIG
+
+
+# AC_LIBTOOL_LANG_CXX_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)])
+AC_DEFUN([_LT_AC_LANG_CXX_CONFIG],
+[AC_LANG_PUSH(C++)
+AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Dependencies to place before and after the object being linked:
+_LT_AC_TAGVAR(predep_objects, $1)=
+_LT_AC_TAGVAR(postdep_objects, $1)=
+_LT_AC_TAGVAR(predeps, $1)=
+_LT_AC_TAGVAR(postdeps, $1)=
+_LT_AC_TAGVAR(compiler_lib_search_path, $1)=
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+  lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+  $as_unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+  lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+  $as_unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+  _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+else
+  _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+fi
+
+if test "$GXX" = yes; then
+  # Set up default GNU C++ configuration
+
+  AC_PROG_LD
+
+  # Check if GNU C++ uses GNU ld as the underlying linker, since the
+  # archiving commands below assume that GNU ld is being used.
+  if test "$with_gnu_ld" = yes; then
+    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+    #     investigate it a little bit more. (MM)
+    wlarc='${wl}'
+
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+       grep 'no-whole-archive' > /dev/null; then
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+  else
+    with_gnu_ld=no
+    wlarc=
+
+    # A generic and very simple default shared library creation
+    # command for GNU C++ for the case where it uses the native
+    # linker, instead of GNU ld.  If possible, this setting should
+    # overridden to take advantage of the native linker features on
+    # the platform it is being used on.
+    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+  fi
+
+  # Commands to make compiler produce verbose output that lists
+  # what "hidden" libraries, object files and flags are used when
+  # linking a shared library.
+  output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+  GXX=no
+  with_gnu_ld=no
+  wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+_LT_AC_TAGVAR(ld_shlibs, $1)=yes
+case $host_os in
+  aix3*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  aix4* | aix5*)
+    if test "$host_cpu" = ia64; then
+      # On IA64, the linker does run time linking by default, so we don't
+      # have to do anything special.
+      aix_use_runtimelinking=no
+      exp_sym_flag='-Bexport'
+      no_entry_flag=""
+    else
+      aix_use_runtimelinking=no
+
+      # Test if we are trying to use run time linking or normal
+      # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+      # need to do runtime linking.
+      case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+       for ld_flag in $LDFLAGS; do
+         case $ld_flag in
+         *-brtl*)
+           aix_use_runtimelinking=yes
+           break
+           ;;
+         esac
+       done
+       ;;
+      esac
+
+      exp_sym_flag='-bexport'
+      no_entry_flag='-bnoentry'
+    fi
+
+    # When large executables or shared objects are built, AIX ld can
+    # have problems creating the table of contents.  If linking a library
+    # or program results in "error TOC overflow" add -mminimal-toc to
+    # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+    # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+    _LT_AC_TAGVAR(archive_cmds, $1)=''
+    _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+    _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+    if test "$GXX" = yes; then
+      case $host_os in aix4.[[012]]|aix4.[[012]].*)
+      # We only want to do this on AIX 4.2 and lower, the check
+      # below for broken collect2 doesn't work under 4.3+
+       collect2name=`${CC} -print-prog-name=collect2`
+       if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+       then
+         # We have reworked collect2
+         :
+       else
+         # We have old collect2
+         _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+       fi
+       ;;
+      esac
+      shared_flag='-shared'
+      if test "$aix_use_runtimelinking" = yes; then
+       shared_flag="$shared_flag "'${wl}-G'
+      fi
+    else
+      # not using gcc
+      if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+       shared_flag='-G'
+      else
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag='${wl}-G'
+       else
+         shared_flag='${wl}-bM:SRE'
+       fi
+      fi
+    fi
+
+    # It seems that -bexpall does not export symbols beginning with
+    # underscore (_), so it is better to generate a list of symbols to export.
+    _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+    if test "$aix_use_runtimelinking" = yes; then
+      # Warning - without using the other runtime loading flags (-brtl),
+      # -berok will link without error, but may produce a broken library.
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+      # Determine the default libpath from the value encoded in an empty executable.
+      _LT_AC_SYS_LIBPATH_AIX
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+     else
+      if test "$host_cpu" = ia64; then
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+      else
+       # Determine the default libpath from the value encoded in an empty executable.
+       _LT_AC_SYS_LIBPATH_AIX
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+       # Warning - without using the other run time loading flags,
+       # -berok will link without error, but may produce a broken library.
+       _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+       # Exported symbols can be pulled into shared objects from archives
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+       _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+       # This is similar to how AIX traditionally builds its shared libraries.
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+      fi
+    fi
+    ;;
+
+  beos*)
+    if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+      # support --undefined.  This deserves some investigation.  FIXME
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    else
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    fi
+    ;;
+
+  chorus*)
+    case $cc_basename in
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+    # as there is no search path for DLLs.
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+    _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+    _LT_AC_TAGVAR(always_export_symbols, $1)=no
+    _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+    if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      # If the export-symbols file already is a .def file (1st line
+      # is EXPORTS), use it as is; otherwise, prepend...
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+       cp $export_symbols $output_objdir/$soname.def;
+      else
+       echo EXPORTS > $output_objdir/$soname.def;
+       cat $export_symbols >> $output_objdir/$soname.def;
+      fi~
+      $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+    else
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    fi
+  ;;
+      darwin* | rhapsody*)
+        case $host_os in
+        rhapsody* | darwin1.[[012]])
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[[012]])
+               _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+        esac
+      _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+    if test "$GXX" = yes ; then
+      lt_int_apple_cc_single_mod=no
+      output_verbose_link_cmd='echo'
+      if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+       lt_int_apple_cc_single_mod=yes
+      fi
+      if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      else
+          _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+        fi
+        _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+        # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+          if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+            _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          else
+            _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          fi
+            _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      else
+      case $cc_basename in
+        xlc*)
+         output_verbose_link_cmd='echo'
+          _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+          _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+          _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+          ;;
+      esac
+      fi
+        ;;
+
+  dgux*)
+    case $cc_basename in
+      ec++*)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      ghcx*)
+       # Green Hills C++ Compiler
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+  freebsd[[12]]*)
+    # C++ shared libraries reported to be fairly broken before switch to ELF
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  freebsd-elf*)
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+    ;;
+  freebsd* | dragonfly*)
+    # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+    # conventions
+    _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+    ;;
+  gnu*)
+    ;;
+  hpux9*)
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+    _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+    _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+                               # but as the default
+                               # location of the library.
+
+    case $cc_basename in
+    CC*)
+      # FIXME: insert proper C++ library support
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    aCC*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      #
+      # There doesn't appear to be a way to prevent this compiler from
+      # explicitly linking system object files so we need to strip them
+      # from the output so that they don't get included in the library
+      # dependencies.
+      output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+      ;;
+    *)
+      if test "$GXX" = yes; then
+        _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+        # FIXME: insert proper C++ library support
+        _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+    ;;
+  hpux10*|hpux11*)
+    if test $with_gnu_ld = no; then
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+      case $host_cpu in
+      hppa*64*|ia64*) ;;
+      *)
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+        ;;
+      esac
+    fi
+    case $host_cpu in
+    hppa*64*|ia64*)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+    *)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+                                             # but as the default
+                                             # location of the library.
+      ;;
+    esac
+
+    case $cc_basename in
+      CC*)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      aCC*)
+       case $host_cpu in
+       hppa*64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         ;;
+       ia64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         ;;
+       *)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         ;;
+       esac
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes; then
+         if test $with_gnu_ld = no; then
+           case $host_cpu in
+           hppa*64*)
+             _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             ;;
+           ia64*)
+             _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             ;;
+           *)
+             _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             ;;
+           esac
+         fi
+       else
+         # FIXME: insert proper C++ library support
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+    esac
+    ;;
+  interix[[3-9]]*)
+    _LT_AC_TAGVAR(hardcode_direct, $1)=no
+    _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+    # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+    # Instead, shared libraries are loaded at an image base (0x10000000 by
+    # default) and relocated if they conflict, which is a slow very memory
+    # consuming and fragmenting process.  To avoid this, we pick a random,
+    # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+    # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+    ;;
+  irix5* | irix6*)
+    case $cc_basename in
+      CC*)
+       # SGI C++
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+       # Archives containing C++ object files must be created using
+       # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+       # necessary to make sure instantiated templates are included
+       # in the archive.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+       ;;
+      *)
+       if test "$GXX" = yes; then
+         if test "$with_gnu_ld" = no; then
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+         else
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+         fi
+       fi
+       _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+       ;;
+    esac
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+    ;;
+  linux* | k*bsd*-gnu)
+    case $cc_basename in
+      KCC*)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir'
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+       # Archives containing C++ object files must be created using
+       # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+       ;;
+      icpc*)
+       # Intel C++
+       with_gnu_ld=yes
+       # version 8.0 and above of icpc choke on multiply defined symbols
+       # if we add $predep_objects and $postdep_objects, however 7.1 and
+       # earlier do not add the objects themselves.
+       case `$CC -V 2>&1` in
+       *"Version 7."*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+         ;;
+       *)  # Version 8.0 or newer
+         tmp_idyn=
+         case $host_cpu in
+           ia64*) tmp_idyn=' -i_dynamic';;
+         esac
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+         ;;
+       esac
+       _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+       ;;
+      pgCC*)
+        # Portland Group C++ compiler
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+        ;;
+      cxx*)
+       # Compaq C++
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+       runpath_var=LD_RUN_PATH
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)
+         # Sun C++ 5.9
+         _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+
+         # Not sure whether something based on
+         # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+         # would be better.
+         output_verbose_link_cmd='echo'
+
+         # Archives containing C++ object files must be created using
+         # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+         # necessary to make sure instantiated templates are included
+         # in the archive.
+         _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+         ;;
+       esac
+       ;;
+    esac
+    ;;
+  lynxos*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  m88k*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  mvs*)
+    case $cc_basename in
+      cxx*)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+  netbsd* | netbsdelf*-gnu)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+      wlarc=
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+    fi
+    # Workaround some broken pre-1.5 toolchains
+    output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+    ;;
+  openbsd2*)
+    # C++ shared libraries are fairly broken
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  openbsd*)
+    if test -f /usr/libexec/ld.so; then
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+      if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      fi
+      output_verbose_link_cmd='echo'
+    else
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    fi
+    ;;
+  osf3*)
+    case $cc_basename in
+      KCC*)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Archives containing C++ object files must be created using
+       # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+
+       ;;
+      RCC*)
+       # Rational C++ 2.4.1
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      cxx*)
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+         # Commands to make compiler produce verbose output that lists
+         # what "hidden" libraries, object files and flags are used when
+         # linking a shared library.
+         output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+       else
+         # FIXME: insert proper C++ library support
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+    esac
+    ;;
+  osf4* | osf5*)
+    case $cc_basename in
+      KCC*)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Archives containing C++ object files must be created using
+       # the KAI C++ compiler.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs'
+       ;;
+      RCC*)
+       # Rational C++ 2.4.1
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      cxx*)
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+         echo "-hidden">> $lib.exp~
+         $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp  `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
+         $rm $lib.exp'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+        _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+         # Commands to make compiler produce verbose output that lists
+         # what "hidden" libraries, object files and flags are used when
+         # linking a shared library.
+         output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+       else
+         # FIXME: insert proper C++ library support
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+    esac
+    ;;
+  psos*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  sunos4*)
+    case $cc_basename in
+      CC*)
+       # Sun C++ 4.x
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      lcc*)
+       # Lucid
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+  solaris*)
+    case $cc_basename in
+      CC*)
+       # Sun C++ 4.2, 5.x and Centerline C++
+        _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes
+       _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $CC -G${allow_undefined_flag}  ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+       _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+       case $host_os in
+         solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+         *)
+           # The compiler driver will combine and reorder linker options,
+           # but understands `-z linker_flag'.
+           # Supported since Solaris 2.6 (maybe 2.5.1?)
+           _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+           ;;
+       esac
+       _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+       output_verbose_link_cmd='echo'
+
+       # Archives containing C++ object files must be created using
+       # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+       # necessary to make sure instantiated templates are included
+       # in the archive.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+       ;;
+      gcx*)
+       # Green Hills C++ Compiler
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+       # The C++ compiler must be used to create the archive.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+       ;;
+      *)
+       # GNU C++ compiler with Solaris linker
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+         if $CC --version | grep -v '^2\.7' > /dev/null; then
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+           _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+         else
+           # g++ 2.7 appears to require `-G' NOT `-shared' on this
+           # platform.
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+           _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+         fi
+
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+         case $host_os in
+         solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+         *)
+           _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+           ;;
+         esac
+       fi
+       ;;
+    esac
+    ;;
+  sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+    _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+    _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+    runpath_var='LD_RUN_PATH'
+
+    case $cc_basename in
+      CC*)
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+      *)
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+    esac
+    ;;
+  sysv5* | sco3.2v5* | sco5v6*)
+    # Note: We can NOT use -z defs as we might desire, because we do not
+    # link with -lc, and that would cause any symbols used from libc to
+    # always be unresolved, which means just about no library would
+    # ever link correctly.  If we're not using GNU ld we use -z text
+    # though, which does catch some bad symbols but isn't as heavy-handed
+    # as -z defs.
+    # For security reasons, it is highly recommended that you always
+    # use absolute paths for naming shared libraries, and exclude the
+    # DT_RUNPATH tag from executables and libraries.  But doing so
+    # requires that you compile everything twice, which is a pain.
+    # So that behaviour is only enabled if SCOABSPATH is set to a
+    # non-empty value in the environment.  Most likely only useful for
+    # creating official distributions of packages.
+    # This is a hack until libtool officially supports absolute path
+    # names for shared libraries.
+    _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+    _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+    _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+    _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+    runpath_var='LD_RUN_PATH'
+
+    case $cc_basename in
+      CC*)
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+      *)
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+    esac
+    ;;
+  tandem*)
+    case $cc_basename in
+      NCC*)
+       # NonStop-UX NCC 3.20
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+  vxworks*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  *)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+esac
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_AC_TAGVAR(GCC, $1)="$GXX"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_POSTDEP_PREDEP($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+])# AC_LIBTOOL_LANG_CXX_CONFIG
+
+# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME])
+# ------------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library.  It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+ifelse([$1],[],[cat > conftest.$ac_ext <<EOF
+int a;
+void foo (void) { a = 0; }
+EOF
+],[$1],[CXX],[cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+EOF
+],[$1],[F77],[cat > conftest.$ac_ext <<EOF
+      subroutine foo
+      implicit none
+      integer*4 a
+      a=0
+      return
+      end
+EOF
+],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF
+public class foo {
+  private int a;
+  public void bar (void) {
+    a = 0;
+  }
+};
+EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  # The `*' in the case matches for architectures that use `case' in
+  # $output_verbose_cmd can trigger glob expansion during the loop
+  # eval without this substitution.
+  output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
+
+  for p in `eval $output_verbose_link_cmd`; do
+    case $p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test $p = "-L" \
+         || test $p = "-R"; then
+        prev=$p
+        continue
+       else
+        prev=
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+        case $p in
+        -L* | -R*)
+          # Internal compiler library paths should come after those
+          # provided the user.  The postdeps already come after the
+          # user supplied libs so there is no need to process them.
+          if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then
+            _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+          else
+            _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+          fi
+          ;;
+        # The "-l" case would never come before the object being
+        # linked, so don't bother handling this case.
+        esac
+       else
+        if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then
+          _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}"
+        else
+          _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}"
+        fi
+       fi
+       ;;
+
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+        pre_test_object_deps_done=yes
+        continue
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+        if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then
+          _LT_AC_TAGVAR(predep_objects, $1)="$p"
+        else
+          _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p"
+        fi
+       else
+        if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then
+          _LT_AC_TAGVAR(postdep_objects, $1)="$p"
+        else
+          _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p"
+        fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$rm -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+ifelse([$1],[CXX],
+[case $host_os in
+interix[[3-9]]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  _LT_AC_TAGVAR(predep_objects,$1)=
+  _LT_AC_TAGVAR(postdep_objects,$1)=
+  _LT_AC_TAGVAR(postdeps,$1)=
+  ;;
+
+linux*)
+  case `$CC -V 2>&1 | sed 5q` in
+  *Sun\ C*)
+    # Sun C++ 5.9
+    #
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+
+solaris*)
+  case $cc_basename in
+  CC*)
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+esac
+])
+
+case " $_LT_AC_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+])# AC_LIBTOOL_POSTDEP_PREDEP
+
+# AC_LIBTOOL_LANG_F77_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)])
+AC_DEFUN([_LT_AC_LANG_F77_CONFIG],
+[AC_REQUIRE([AC_PROG_F77])
+AC_LANG_PUSH(Fortran 77)
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="\
+      program t
+      end
+"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+aix4* | aix5*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
+  ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+_LT_AC_TAGVAR(GCC, $1)="$G77"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_F77_CONFIG
+
+
+# AC_LIBTOOL_LANG_GCJ_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)])
+AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_GCJ_CONFIG
+
+
+# AC_LIBTOOL_LANG_RC_CONFIG
+# -------------------------
+# Ensure that the configuration vars for the Windows resource compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)])
+AC_DEFUN([_LT_AC_LANG_RC_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_RC_CONFIG
+
+
+# AC_LIBTOOL_CONFIG([TAGNAME])
+# ----------------------------
+# If TAGNAME is not passed, then create an initial libtool script
+# with a default configuration from the untagged config vars.  Otherwise
+# add code to config.status for appending the configuration named by
+# TAGNAME from the matching tagged config vars.
+AC_DEFUN([AC_LIBTOOL_CONFIG],
+[# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    old_postinstall_cmds old_postuninstall_cmds \
+    _LT_AC_TAGVAR(compiler, $1) \
+    _LT_AC_TAGVAR(CC, $1) \
+    _LT_AC_TAGVAR(LD, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \
+    _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \
+    _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \
+    _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \
+    _LT_AC_TAGVAR(old_archive_cmds, $1) \
+    _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \
+    _LT_AC_TAGVAR(predep_objects, $1) \
+    _LT_AC_TAGVAR(postdep_objects, $1) \
+    _LT_AC_TAGVAR(predeps, $1) \
+    _LT_AC_TAGVAR(postdeps, $1) \
+    _LT_AC_TAGVAR(compiler_lib_search_path, $1) \
+    _LT_AC_TAGVAR(archive_cmds, $1) \
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1) \
+    _LT_AC_TAGVAR(postinstall_cmds, $1) \
+    _LT_AC_TAGVAR(postuninstall_cmds, $1) \
+    _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \
+    _LT_AC_TAGVAR(allow_undefined_flag, $1) \
+    _LT_AC_TAGVAR(no_undefined_flag, $1) \
+    _LT_AC_TAGVAR(export_symbols_cmds, $1) \
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \
+    _LT_AC_TAGVAR(hardcode_automatic, $1) \
+    _LT_AC_TAGVAR(module_cmds, $1) \
+    _LT_AC_TAGVAR(module_expsym_cmds, $1) \
+    _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \
+    _LT_AC_TAGVAR(fix_srcfile_path, $1) \
+    _LT_AC_TAGVAR(exclude_expsyms, $1) \
+    _LT_AC_TAGVAR(include_expsyms, $1); do
+
+    case $var in
+    _LT_AC_TAGVAR(old_archive_cmds, $1) | \
+    _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \
+    _LT_AC_TAGVAR(archive_cmds, $1) | \
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \
+    _LT_AC_TAGVAR(module_cmds, $1) | \
+    _LT_AC_TAGVAR(module_expsym_cmds, $1) | \
+    _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \
+    _LT_AC_TAGVAR(export_symbols_cmds, $1) | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case $lt_echo in
+  *'\[$]0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'`
+    ;;
+  esac
+
+ifelse([$1], [],
+  [cfgfile="${ofile}T"
+  trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+  $rm -f "$cfgfile"
+  AC_MSG_NOTICE([creating $ofile])],
+  [cfgfile="$ofile"])
+
+  cat <<__EOF__ >> "$cfgfile"
+ifelse([$1], [],
+[#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 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 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.
+#
+# 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.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e 1s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG],
+[# ### BEGIN LIBTOOL TAG CONFIG: $tagname])
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_[]_LT_AC_TAGVAR(compiler, $1)
+
+# Is the compiler the GNU C compiler?
+with_gcc=$_LT_AC_TAGVAR(GCC, $1)
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_[]_LT_AC_TAGVAR(LD, $1)
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1)
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1)
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1)
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1)
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1)
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1)
+archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1)
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1)
+module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1)
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1)
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1)
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1)
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1)
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1)
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1)
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1)
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1)
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1)
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1)
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1)
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1)
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1)
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1)
+
+# Symbols that must always be exported.
+include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1)
+
+ifelse([$1],[],
+[# ### END LIBTOOL CONFIG],
+[# ### END LIBTOOL TAG CONFIG: $tagname])
+
+__EOF__
+
+ifelse([$1],[], [
+  case $host_os in
+  aix3*)
+    cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+EOF
+    ;;
+  esac
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" || \
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+])
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+])# AC_LIBTOOL_CONFIG
+
+
+# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+
+_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+  _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+  AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+    lt_cv_prog_compiler_rtti_exceptions,
+    [-fno-rtti -fno-exceptions], [],
+    [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI
+
+
+# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+# ---------------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([LT_AC_PROG_SED])
+AC_REQUIRE([AC_PROG_NM])
+AC_REQUIRE([AC_OBJEXT])
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*) # Its linker distinguishes data from code symbols
+  if test "$host_cpu" = ia64; then
+    symcode='[[ABCDEGRST]]'
+  fi
+  lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+  lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  ;;
+linux* | k*bsd*-gnu)
+  if test "$host_cpu" = ia64; then
+    symcode='[[ABCDGIRSTW]]'
+    lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+    lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+osf*)
+  symcode='[[BCDEGQRST]]'
+  ;;
+solaris*)
+  symcode='[[BDRT]]'
+  ;;
+sco3.2v5*)
+  symcode='[[DT]]'
+  ;;
+sysv4.2uw2*)
+  symcode='[[DT]]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[[ABDT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[     ]]\($symcode$symcode*\)[[       ]][[    ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if grep ' nm_test_var$' "$nlist" >/dev/null; then
+       if grep ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+         # Now generate the symbol file.
+         eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+         cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr_t address;
+}
+lt_preloaded_symbols[[]] =
+{
+EOF
+         $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+         cat <<\EOF >> conftest.$ac_ext
+  {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftstm.$ac_objext
+         lt_save_LIBS="$LIBS"
+         lt_save_CFLAGS="$CFLAGS"
+         LIBS="conftstm.$ac_objext"
+         CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+         if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+           pipe_works=yes
+         fi
+         LIBS="$lt_save_LIBS"
+         CFLAGS="$lt_save_CFLAGS"
+       else
+         echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.$ac_ext >&5
+  fi
+  rm -f conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+
+
+# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME])
+# ---------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC],
+[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+ ifelse([$1],[CXX],[
+  # C++ specific cases for pic, static, wl, etc.
+  if test "$GXX" = yes; then
+    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+      ;;
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+      ;;
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       ;;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       ;;
+      esac
+      ;;
+    *)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix4* | aix5*)
+       # All AIX code is PIC.
+       if test "$host_cpu" = ia64; then
+         # AIX 5 now supports IA64 processor
+         _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+       else
+         _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+       fi
+       ;;
+      chorus*)
+       case $cc_basename in
+       cxch68*)
+         # Green Hills C++ Compiler
+         # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+         ;;
+       esac
+       ;;
+       darwin*)
+         # PIC is the default on this platform
+         # Common symbols not allowed in MH_DYLIB files
+         case $cc_basename in
+           xlc*)
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           ;;
+         esac
+       ;;
+      dgux*)
+       case $cc_basename in
+         ec++*)
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           ;;
+         ghcx*)
+           # Green Hills C++ Compiler
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      freebsd* | dragonfly*)
+       # FreeBSD uses GNU C++
+       ;;
+      hpux9* | hpux10* | hpux11*)
+       case $cc_basename in
+         CC*)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+           if test "$host_cpu" != ia64; then
+             _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+           fi
+           ;;
+         aCC*)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+           case $host_cpu in
+           hppa*64*|ia64*)
+             # +Z the default
+             ;;
+           *)
+             _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+             ;;
+           esac
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      interix*)
+       # This is c89, which is MS Visual C++ (no shared libs)
+       # Anyone wants to do a port?
+       ;;
+      irix5* | irix6* | nonstopux*)
+       case $cc_basename in
+         CC*)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           # CC pic flag -KPIC is the default.
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      linux* | k*bsd*-gnu)
+       case $cc_basename in
+         KCC*)
+           # KAI C++ Compiler
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+           ;;
+         icpc* | ecpc*)
+           # Intel C++
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+           ;;
+         pgCC*)
+           # Portland Group C++ compiler.
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+         cxx*)
+           # Compaq C++
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           ;;
+         *)
+           case `$CC -V 2>&1 | sed 5q` in
+           *Sun\ C*)
+             # Sun C++ 5.9
+             _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+             _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+             _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+             ;;
+           esac
+           ;;
+       esac
+       ;;
+      lynxos*)
+       ;;
+      m88k*)
+       ;;
+      mvs*)
+       case $cc_basename in
+         cxx*)
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      netbsd* | netbsdelf*-gnu)
+       ;;
+      osf3* | osf4* | osf5*)
+       case $cc_basename in
+         KCC*)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+           ;;
+         RCC*)
+           # Rational C++ 2.4.1
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         cxx*)
+           # Digital/Compaq C++
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      psos*)
+       ;;
+      solaris*)
+       case $cc_basename in
+         CC*)
+           # Sun C++ 4.2, 5.x and Centerline C++
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+           ;;
+         gcx*)
+           # Green Hills C++ Compiler
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sunos4*)
+       case $cc_basename in
+         CC*)
+           # Sun C++ 4.x
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+         lcc*)
+           # Lucid
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      tandem*)
+       case $cc_basename in
+         NCC*)
+           # NonStop-UX NCC 3.20
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+       case $cc_basename in
+         CC*)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+       esac
+       ;;
+      vxworks*)
+       ;;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+       ;;
+    esac
+  fi
+],
+[
+  if test "$GCC" = yes; then
+    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      enable_shared=no
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       ;;
+      esac
+      ;;
+
+    *)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      else
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+      darwin*)
+        # PIC is the default on this platform
+        # Common symbols not allowed in MH_DYLIB files
+       case $cc_basename in
+         xlc*)
+         _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+         _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         ;;
+       esac
+       ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC (with -KPIC) is the default.
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    newsos6)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    linux* | k*bsd*-gnu)
+      case $cc_basename in
+      icc* | ecc*)
+       _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      pgcc* | pgf77* | pgf90* | pgf95*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+       # which looks to be a dead project)
+       _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+        ;;
+      ccc*)
+        _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+        # All Alpha code is PIC.
+        _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+        ;;
+      *)
+        case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)
+         # Sun C 5.9
+         _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+         _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         ;;
+       *Sun\ F*)
+         # Sun Fortran 8.3 passes all unrecognized flags to the linker
+         _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+         _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=''
+         ;;
+       esac
+       ;;
+      esac
+      ;;
+
+    osf3* | osf4* | osf5*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # All OSF/1 code is PIC.
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    rdos*)
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    solaris*)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+       _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    unicos*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+
+    uts4*)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *)
+      _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+    esac
+  fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then
+  AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works],
+    _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1),
+    [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [],
+    [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in
+     "" | " "*) ;;
+     *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+     esac],
+    [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+     _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+    ;;
+  *)
+    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])"
+    ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\"
+AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+  _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1),
+  $lt_tmp_static_flag,
+  [],
+  [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=])
+])
+
+
+# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME])
+# ------------------------------------
+# See if the linker supports building shared libraries.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ifelse([$1],[CXX],[
+  _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  case $host_os in
+  aix4* | aix5*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+      _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+    else
+      _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+  ;;
+  cygwin* | mingw*)
+    _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+  ;;
+  linux* | k*bsd*-gnu)
+    _LT_AC_TAGVAR(link_all_deplibs, $1)=no
+  ;;
+  *)
+    _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  esac
+],[
+  runpath_var=
+  _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+  _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+  _LT_AC_TAGVAR(archive_cmds, $1)=
+  _LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+  _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)=
+  _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+  _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+  _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+  _LT_AC_TAGVAR(thread_safe_flag_spec, $1)=
+  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+  _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+  _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+  _LT_AC_TAGVAR(hardcode_direct, $1)=no
+  _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+  _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+  _LT_AC_TAGVAR(hardcode_automatic, $1)=no
+  _LT_AC_TAGVAR(module_cmds, $1)=
+  _LT_AC_TAGVAR(module_expsym_cmds, $1)=
+  _LT_AC_TAGVAR(always_export_symbols, $1)=no
+  _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  _LT_AC_TAGVAR(include_expsyms, $1)=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_"
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  extract_expsyms_cmds=
+  # Just being paranoid about ensuring that cc_basename is set.
+  _LT_CC_BASENAME([$compiler])
+  case $host_os in
+  cygwin* | mingw* | pw32*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>/dev/null` in
+      *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+      fi
+      ;;
+
+    amigaos*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+
+      # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+      # that the semantics of dynamic libraries on AmigaOS, at least up
+      # to version 4, is to share data among multiple programs linked
+      # with the same dynamic library.  Since this doesn't match the
+      # behavior of shared libraries on other platforms, we can't use
+      # them.
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+      # as there is no search path for DLLs.
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_AC_TAGVAR(always_export_symbols, $1)=no
+      _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+        _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       # If the export-symbols file already is a .def file (1st line
+       # is EXPORTS), use it as is; otherwise, prepend...
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+         cp $export_symbols $output_objdir/$soname.def;
+       else
+         echo EXPORTS > $output_objdir/$soname.def;
+         cat $export_symbols >> $output_objdir/$soname.def;
+       fi~
+       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    interix[[3-9]]*)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | k*bsd*-gnu)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       tmp_addflag=
+       case $cc_basename,$host_cpu in
+       pgcc*)                          # Portland Group C compiler
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
+         ;;
+       pgf77* | pgf90* | pgf95*)       # Portland Group f77 and f90 compilers
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
+       ecc*,ia64* | icc*,ia64*)                # Intel C compiler on ia64
+         tmp_addflag=' -i_dynamic' ;;
+       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
+         tmp_addflag=' -i_dynamic -nofor_main' ;;
+       ifc* | ifort*)                  # Intel Fortran compiler
+         tmp_addflag=' -nofor_main' ;;
+       esac
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)                       # Sun C 5.9
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_sharedflag='-G' ;;
+       *Sun\ F*)                       # Sun Fortran 8.3
+         tmp_sharedflag='-G' ;;
+       *)
+         tmp_sharedflag='-shared' ;;
+       esac
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+       if test $supports_anon_versioning = yes; then
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~
+  cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+  $echo "local: *; };" >> $output_objdir/$libname.ver~
+         $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+       fi
+       _LT_AC_TAGVAR(link_all_deplibs, $1)=no
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+      elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+       ;;
+       *)
+         if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+           _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+           _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+         else
+           _LT_AC_TAGVAR(ld_shlibs, $1)=no
+         fi
+       ;;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+
+    if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then
+      runpath_var=
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+      fi
+      ;;
+
+    aix4* | aix5*)
+      if test "$host_cpu" = ia64; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=""
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to AIX nm, but means don't demangle with GNU nm
+       if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+         _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+       else
+         _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # need to do runtime linking.
+       case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+         for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+         ;;
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      _LT_AC_TAGVAR(archive_cmds, $1)=''
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+      if test "$GCC" = yes; then
+       case $host_os in aix4.[[012]]|aix4.[[012]].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         :
+         else
+         # We have old collect2
+         _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+         fi
+         ;;
+       esac
+       shared_flag='-shared'
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag="$shared_flag "'${wl}-G'
+       fi
+      else
+       # not using gcc
+       if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag='${wl}-G'
+         else
+           shared_flag='${wl}-bM:SRE'
+         fi
+       fi
+      fi
+
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+      if test "$aix_use_runtimelinking" = yes; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+       # Determine the default libpath from the value encoded in an empty executable.
+       _LT_AC_SYS_LIBPATH_AIX
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+       else
+       if test "$host_cpu" = ia64; then
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an empty executable.
+        _LT_AC_SYS_LIBPATH_AIX
+        _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+         # Exported symbols can be pulled into shared objects from archives
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+         _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+         # This is similar to how AIX traditionally builds its shared libraries.
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      # see comment about different semantics on the GNU ld section
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+
+    bsdi[[45]]*)
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true'
+      # FIXME: Should let the user specify the lib program.
+      _LT_AC_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
+      _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      ;;
+
+    darwin* | rhapsody*)
+      case $host_os in
+        rhapsody* | darwin1.[[012]])
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[[012]])
+               _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+      esac
+      _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+    if test "$GCC" = yes ; then
+       output_verbose_link_cmd='echo'
+        _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    else
+      case $cc_basename in
+        xlc*)
+         output_verbose_link_cmd='echo'
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+         _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+          ;;
+      esac
+    fi
+      ;;
+
+    dgux*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    freebsd1*)
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       case $host_cpu in
+       hppa*64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case $host_cpu in
+       hppa*64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      fi
+      if test "$with_gnu_ld" = no; then
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       case $host_cpu in
+       hppa*64*|ia64*)
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+         _LT_AC_TAGVAR(hardcode_direct, $1)=no
+         _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+         ;;
+       *)
+         _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+         _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    newsos6)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+       _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+       _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+       if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+         _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+       else
+         case $host_os in
+          openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+            _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+            _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+            ;;
+          *)
+            _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+            _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+            ;;
+         esac
+        fi
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    os2*)
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      else
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+       $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    solaris*)
+      _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
+      if test "$GCC" = yes; then
+       wlarc='${wl}'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+         $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+      else
+       wlarc=''
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      case $host_os in
+      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+      *)
+       # The compiler driver will combine and reorder linker options,
+       # but understands `-z linker_flag'.  GCC discards it without `$wl',
+       # but is careful enough not to reorder.
+       # Supported since Solaris 2.6 (maybe 2.5.1?)
+       if test "$GCC" = yes; then
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+       else
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+       fi
+       ;;
+      esac
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+         _LT_AC_TAGVAR(hardcode_direct, $1)=no
+        ;;
+       motorola)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4.3*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+      _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    esac
+  fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+  # Assume -lc should be added
+  _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $_LT_AC_TAGVAR(archive_cmds, $1) in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+      $rm conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+       pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1)
+        _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+        if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
+        then
+         _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+        else
+         _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+        fi
+        _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $rm conftest*
+      AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)])
+      ;;
+    esac
+  fi
+  ;;
+esac
+])# AC_LIBTOOL_PROG_LD_SHLIBS
+
+
+# _LT_AC_FILE_LTDLL_C
+# -------------------
+# Be careful that the start marker always follows a newline.
+AC_DEFUN([_LT_AC_FILE_LTDLL_C], [
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# #  ifdef __CYGWIN32__
+# #    define __CYGWIN__ __CYGWIN32__
+# #  endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+#   __hDllInstance_base = hInst;
+#   return TRUE;
+# }
+# /* ltdll.c ends here */
+])# _LT_AC_FILE_LTDLL_C
+
+
+# _LT_AC_TAGVAR(VARNAME, [TAGNAME])
+# ---------------------------------
+AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])])
+
+
+# old names
+AC_DEFUN([AM_PROG_LIBTOOL],   [AC_PROG_LIBTOOL])
+AC_DEFUN([AM_ENABLE_SHARED],  [AC_ENABLE_SHARED($@)])
+AC_DEFUN([AM_ENABLE_STATIC],  [AC_ENABLE_STATIC($@)])
+AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+AC_DEFUN([AM_PROG_LD],        [AC_PROG_LD])
+AC_DEFUN([AM_PROG_NM],        [AC_PROG_NM])
+
+# This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])
+
+AC_DEFUN([LT_AC_PROG_GCJ],
+[AC_CHECK_TOOL(GCJ, gcj, no)
+  test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+  AC_SUBST(GCJFLAGS)
+])
+
+AC_DEFUN([LT_AC_PROG_RC],
+[AC_CHECK_TOOL(RC, windres, no)
+])
+
+
+# Cheap backport of AS_EXECUTABLE_P and required macros
+# from Autoconf 2.59; we should not use $as_executable_p directly.
+
+# _AS_TEST_PREPARE
+# ----------------
+m4_ifndef([_AS_TEST_PREPARE],
+[m4_defun([_AS_TEST_PREPARE],
+[if test -x / >/dev/null 2>&1; then
+  as_executable_p='test -x'
+else
+  as_executable_p='test -f'
+fi
+])])# _AS_TEST_PREPARE
+
+# AS_EXECUTABLE_P
+# ---------------
+# Check whether a file is executable.
+m4_ifndef([AS_EXECUTABLE_P],
+[m4_defun([AS_EXECUTABLE_P],
+[AS_REQUIRE([_AS_TEST_PREPARE])dnl
+$as_executable_p $1[]dnl
+])])# AS_EXECUTABLE_P
+
+############################################################
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+############################################################
+# LT_AC_PROG_SED
+# --------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible.  Prefer GNU sed if found.
+AC_DEFUN([LT_AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if AS_EXECUTABLE_P(["$as_dir/$lt_ac_prog$ac_exec_ext"]); then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f $lt_ac_sed && continue
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test $lt_ac_count -gt 10 && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test $lt_ac_count -gt $lt_ac_max; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])
+## ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*-
+## Copyright (C) 1999-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 AC_LIB_LTDL
+
+# AC_WITH_LTDL
+# ------------
+# Clients of libltdl can use this macro to allow the installer to
+# choose between a shipped copy of the ltdl sources or a preinstalled
+# version of the library.
+AC_DEFUN([AC_WITH_LTDL],
+[AC_REQUIRE([AC_LIB_LTDL])
+AC_SUBST([LIBLTDL])
+AC_SUBST([INCLTDL])
+
+# Unless the user asks us to check, assume no installed ltdl exists.
+use_installed_libltdl=no
+
+AC_ARG_WITH([included_ltdl],
+    [  --with-included-ltdl    use the GNU ltdl sources included here])
+
+if test "x$with_included_ltdl" != xyes; then
+  # We are not being forced to use the included libltdl sources, so
+  # decide whether there is a useful installed version we can use.
+  AC_CHECK_HEADER([ltdl.h],
+      [AC_CHECK_LIB([ltdl], [lt_dlcaller_register],
+          [with_included_ltdl=no],
+          [with_included_ltdl=yes])
+  ])
+fi
+
+if test "x$enable_ltdl_install" != xyes; then
+  # If the user did not specify an installable libltdl, then default
+  # to a convenience lib.
+  AC_LIBLTDL_CONVENIENCE
+fi
+
+if test "x$with_included_ltdl" = xno; then
+  # If the included ltdl is not to be used. then Use the
+  # preinstalled libltdl we found.
+  AC_DEFINE([HAVE_LTDL], [1],
+    [Define this if a modern libltdl is already installed])
+  LIBLTDL=-lltdl
+fi
+
+# Report our decision...
+AC_MSG_CHECKING([whether to use included libltdl])
+AC_MSG_RESULT([$with_included_ltdl])
+
+AC_CONFIG_SUBDIRS([libltdl])
+])# AC_WITH_LTDL
+
+
+# AC_LIB_LTDL
+# -----------
+# Perform all the checks necessary for compilation of the ltdl objects
+#  -- including compiler checks and header checks.
+AC_DEFUN([AC_LIB_LTDL],
+[AC_PREREQ(2.50)
+AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AC_C_CONST])
+AC_REQUIRE([AC_HEADER_STDC])
+AC_REQUIRE([AC_HEADER_DIRENT])
+AC_REQUIRE([_LT_AC_CHECK_DLFCN])
+AC_REQUIRE([AC_LTDL_ENABLE_INSTALL])
+AC_REQUIRE([AC_LTDL_SHLIBEXT])
+AC_REQUIRE([AC_LTDL_SHLIBPATH])
+AC_REQUIRE([AC_LTDL_SYSSEARCHPATH])
+AC_REQUIRE([AC_LTDL_OBJDIR])
+AC_REQUIRE([AC_LTDL_DLPREOPEN])
+AC_REQUIRE([AC_LTDL_DLLIB])
+AC_REQUIRE([AC_LTDL_SYMBOL_USCORE])
+AC_REQUIRE([AC_LTDL_DLSYM_USCORE])
+AC_REQUIRE([AC_LTDL_SYS_DLOPEN_DEPLIBS])
+AC_REQUIRE([AC_LTDL_FUNC_ARGZ])
+
+AC_CHECK_HEADERS([assert.h ctype.h errno.h malloc.h memory.h stdlib.h \
+                 stdio.h unistd.h])
+AC_CHECK_HEADERS([dl.h sys/dl.h dld.h mach-o/dyld.h])
+AC_CHECK_HEADERS([string.h strings.h], [break])
+
+AC_CHECK_FUNCS([strchr index], [break])
+AC_CHECK_FUNCS([strrchr rindex], [break])
+AC_CHECK_FUNCS([memcpy bcopy], [break])
+AC_CHECK_FUNCS([memmove strcmp])
+AC_CHECK_FUNCS([closedir opendir readdir])
+])# AC_LIB_LTDL
+
+
+# AC_LTDL_ENABLE_INSTALL
+# ----------------------
+AC_DEFUN([AC_LTDL_ENABLE_INSTALL],
+[AC_ARG_ENABLE([ltdl-install],
+    [AC_HELP_STRING([--enable-ltdl-install], [install libltdl])])
+
+AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno)
+AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno)
+])# AC_LTDL_ENABLE_INSTALL
+
+
+# AC_LTDL_SYS_DLOPEN_DEPLIBS
+# --------------------------
+AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_CACHE_CHECK([whether deplibs are loaded by dlopen],
+  [libltdl_cv_sys_dlopen_deplibs],
+  [# PORTME does your system automatically load deplibs for dlopen?
+  # or its logical equivalent (e.g. shl_load for HP-UX < 11)
+  # For now, we just catch OSes we know something about -- in the
+  # future, we'll try test this programmatically.
+  libltdl_cv_sys_dlopen_deplibs=unknown
+  case "$host_os" in
+  aix3*|aix4.1.*|aix4.2.*)
+    # Unknown whether this is true for these versions of AIX, but
+    # we want this `case' here to explicitly catch those versions.
+    libltdl_cv_sys_dlopen_deplibs=unknown
+    ;;
+  aix[[45]]*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  darwin*)
+    # Assuming the user has installed a libdl from somewhere, this is true
+    # If you are looking for one http://www.opendarwin.org/projects/dlcompat
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  freebsd* | dragonfly*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  gnu* | linux* | k*bsd*-gnu)
+    # GNU and its variants, using gnu ld.so (Glibc)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  hpux10*|hpux11*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  interix*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  irix[[12345]]*|irix6.[[01]]*)
+    # Catch all versions of IRIX before 6.2, and indicate that we don't
+    # know how it worked for any of those versions.
+    libltdl_cv_sys_dlopen_deplibs=unknown
+    ;;
+  irix*)
+    # The case above catches anything before 6.2, and it's known that
+    # at 6.2 and later dlopen does load deplibs.
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  netbsd* | netbsdelf*-gnu)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  openbsd*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  osf[[1234]]*)
+    # dlopen did load deplibs (at least at 4.x), but until the 5.x series,
+    # it did *not* use an RPATH in a shared library to find objects the
+    # library depends on, so we explictly say `no'.
+    libltdl_cv_sys_dlopen_deplibs=no
+    ;;
+  osf5.0|osf5.0a|osf5.1)
+    # dlopen *does* load deplibs and with the right loader patch applied
+    # it even uses RPATH in a shared library to search for shared objects
+    # that the library depends on, but there's no easy way to know if that
+    # patch is installed.  Since this is the case, all we can really
+    # say is unknown -- it depends on the patch being installed.  If
+    # it is, this changes to `yes'.  Without it, it would be `no'.
+    libltdl_cv_sys_dlopen_deplibs=unknown
+    ;;
+  osf*)
+    # the two cases above should catch all versions of osf <= 5.1.  Read
+    # the comments above for what we know about them.
+    # At > 5.1, deplibs are loaded *and* any RPATH in a shared library
+    # is used to find them so we can finally say `yes'.
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  solaris*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  esac
+  ])
+if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then
+ AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1],
+    [Define if the OS needs help to load dependent libraries for dlopen().])
+fi
+])# AC_LTDL_SYS_DLOPEN_DEPLIBS
+
+
+# AC_LTDL_SHLIBEXT
+# ----------------
+AC_DEFUN([AC_LTDL_SHLIBEXT],
+[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER])
+AC_CACHE_CHECK([which extension is used for loadable modules],
+  [libltdl_cv_shlibext],
+[
+module=yes
+eval libltdl_cv_shlibext=$shrext_cmds
+  ])
+if test -n "$libltdl_cv_shlibext"; then
+  AC_DEFINE_UNQUOTED([LTDL_SHLIB_EXT], ["$libltdl_cv_shlibext"],
+    [Define to the extension used for shared libraries, say, ".so".])
+fi
+])# AC_LTDL_SHLIBEXT
+
+
+# AC_LTDL_SHLIBPATH
+# -----------------
+AC_DEFUN([AC_LTDL_SHLIBPATH],
+[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER])
+AC_CACHE_CHECK([which variable specifies run-time library path],
+  [libltdl_cv_shlibpath_var], [libltdl_cv_shlibpath_var="$shlibpath_var"])
+if test -n "$libltdl_cv_shlibpath_var"; then
+  AC_DEFINE_UNQUOTED([LTDL_SHLIBPATH_VAR], ["$libltdl_cv_shlibpath_var"],
+    [Define to the name of the environment variable that determines the dynamic library search path.])
+fi
+])# AC_LTDL_SHLIBPATH
+
+
+# AC_LTDL_SYSSEARCHPATH
+# ---------------------
+AC_DEFUN([AC_LTDL_SYSSEARCHPATH],
+[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER])
+AC_CACHE_CHECK([for the default library search path],
+  [libltdl_cv_sys_search_path],
+  [libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec"])
+if test -n "$libltdl_cv_sys_search_path"; then
+  sys_search_path=
+  for dir in $libltdl_cv_sys_search_path; do
+    if test -z "$sys_search_path"; then
+      sys_search_path="$dir"
+    else
+      sys_search_path="$sys_search_path$PATH_SEPARATOR$dir"
+    fi
+  done
+  AC_DEFINE_UNQUOTED([LTDL_SYSSEARCHPATH], ["$sys_search_path"],
+    [Define to the system default library search path.])
+fi
+])# AC_LTDL_SYSSEARCHPATH
+
+
+# AC_LTDL_OBJDIR
+# --------------
+AC_DEFUN([AC_LTDL_OBJDIR],
+[AC_CACHE_CHECK([for objdir],
+  [libltdl_cv_objdir],
+  [libltdl_cv_objdir="$objdir"
+  if test -n "$objdir"; then
+    :
+  else
+    rm -f .libs 2>/dev/null
+    mkdir .libs 2>/dev/null
+    if test -d .libs; then
+      libltdl_cv_objdir=.libs
+    else
+      # MS-DOS does not allow filenames that begin with a dot.
+      libltdl_cv_objdir=_libs
+    fi
+  rmdir .libs 2>/dev/null
+  fi
+  ])
+AC_DEFINE_UNQUOTED([LTDL_OBJDIR], ["$libltdl_cv_objdir/"],
+  [Define to the sub-directory in which libtool stores uninstalled libraries.])
+])# AC_LTDL_OBJDIR
+
+
+# AC_LTDL_DLPREOPEN
+# -----------------
+AC_DEFUN([AC_LTDL_DLPREOPEN],
+[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])
+AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen],
+  [libltdl_cv_preloaded_symbols],
+  [if test -n "$lt_cv_sys_global_symbol_pipe"; then
+    libltdl_cv_preloaded_symbols=yes
+  else
+    libltdl_cv_preloaded_symbols=no
+  fi
+  ])
+if test x"$libltdl_cv_preloaded_symbols" = xyes; then
+  AC_DEFINE([HAVE_PRELOADED_SYMBOLS], [1],
+    [Define if libtool can extract symbol lists from object files.])
+fi
+])# AC_LTDL_DLPREOPEN
+
+
+# AC_LTDL_DLLIB
+# -------------
+AC_DEFUN([AC_LTDL_DLLIB],
+[LIBADD_DL=
+AC_SUBST(LIBADD_DL)
+AC_LANG_PUSH([C])
+
+AC_CHECK_FUNC([shl_load],
+      [AC_DEFINE([HAVE_SHL_LOAD], [1],
+                [Define if you have the shl_load function.])],
+  [AC_CHECK_LIB([dld], [shl_load],
+       [AC_DEFINE([HAVE_SHL_LOAD], [1],
+                  [Define if you have the shl_load function.])
+       LIBADD_DL="$LIBADD_DL -ldld"],
+    [AC_CHECK_LIB([dl], [dlopen],
+         [AC_DEFINE([HAVE_LIBDL], [1],
+                    [Define if you have the libdl library or equivalent.])
+               LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes"],
+      [AC_TRY_LINK([#if HAVE_DLFCN_H
+#  include <dlfcn.h>
+#endif
+      ],
+       [dlopen(0, 0);],
+           [AC_DEFINE([HAVE_LIBDL], [1],
+                            [Define if you have the libdl library or equivalent.]) libltdl_cv_func_dlopen="yes"],
+       [AC_CHECK_LIB([svld], [dlopen],
+             [AC_DEFINE([HAVE_LIBDL], [1],
+                        [Define if you have the libdl library or equivalent.])
+                   LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes"],
+         [AC_CHECK_LIB([dld], [dld_link],
+               [AC_DEFINE([HAVE_DLD], [1],
+                          [Define if you have the GNU dld library.])
+               LIBADD_DL="$LIBADD_DL -ldld"],
+               [AC_CHECK_FUNC([_dyld_func_lookup],
+                      [AC_DEFINE([HAVE_DYLD], [1],
+                         [Define if you have the _dyld_func_lookup function.])])
+          ])
+        ])
+      ])
+    ])
+  ])
+])
+
+if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes
+then
+  lt_save_LIBS="$LIBS"
+  LIBS="$LIBS $LIBADD_DL"
+  AC_CHECK_FUNCS([dlerror])
+  LIBS="$lt_save_LIBS"
+fi
+AC_LANG_POP
+])# AC_LTDL_DLLIB
+
+
+# AC_LTDL_SYMBOL_USCORE
+# ---------------------
+# does the compiler prefix global symbols with an underscore?
+AC_DEFUN([AC_LTDL_SYMBOL_USCORE],
+[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])
+AC_CACHE_CHECK([for _ prefix in compiled symbols],
+  [ac_cv_sys_symbol_underscore],
+  [ac_cv_sys_symbol_underscore=no
+  cat > conftest.$ac_ext <<EOF
+void nm_test_func(){}
+int main(){nm_test_func;return 0;}
+EOF
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    ac_nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then
+      # See whether the symbols have a leading underscore.
+      if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then
+        ac_cv_sys_symbol_underscore=yes
+      else
+        if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then
+         :
+        else
+         echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC
+        fi
+      fi
+    else
+      echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC
+    fi
+  else
+    echo "configure: failed program was:" >&AC_FD_CC
+    cat conftest.c >&AC_FD_CC
+  fi
+  rm -rf conftest*
+  ])
+])# AC_LTDL_SYMBOL_USCORE
+
+
+# AC_LTDL_DLSYM_USCORE
+# --------------------
+AC_DEFUN([AC_LTDL_DLSYM_USCORE],
+[AC_REQUIRE([AC_LTDL_SYMBOL_USCORE])
+if test x"$ac_cv_sys_symbol_underscore" = xyes; then
+  if test x"$libltdl_cv_func_dlopen" = xyes ||
+     test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then
+       AC_CACHE_CHECK([whether we have to add an underscore for dlsym],
+         [libltdl_cv_need_uscore],
+         [libltdl_cv_need_uscore=unknown
+          save_LIBS="$LIBS"
+          LIBS="$LIBS $LIBADD_DL"
+         _LT_AC_TRY_DLOPEN_SELF(
+           [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes],
+           [],                          [libltdl_cv_need_uscore=cross])
+         LIBS="$save_LIBS"
+       ])
+  fi
+fi
+
+if test x"$libltdl_cv_need_uscore" = xyes; then
+  AC_DEFINE([NEED_USCORE], [1],
+    [Define if dlsym() requires a leading underscore in symbol names.])
+fi
+])# AC_LTDL_DLSYM_USCORE
+
+# AC_LTDL_FUNC_ARGZ
+# -----------------
+AC_DEFUN([AC_LTDL_FUNC_ARGZ],
+[AC_CHECK_HEADERS([argz.h])
+
+AC_CHECK_TYPES([error_t],
+  [],
+  [AC_DEFINE([error_t], [int],
+    [Define to a type to use for `error_t' if it is not otherwise available.])],
+  [#if HAVE_ARGZ_H
+#  include <argz.h>
+#endif])
+
+AC_CHECK_FUNCS([argz_append argz_create_sep argz_insert argz_next argz_stringify])
+])# AC_LTDL_FUNC_ARGZ
diff --git a/libltdl/aclocal.m4 b/libltdl/aclocal.m4
new file mode 100644 (file)
index 0000000..fcc414d
--- /dev/null
@@ -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])
diff --git a/libltdl/config-h.in b/libltdl/config-h.in
new file mode 100644 (file)
index 0000000..b864071
--- /dev/null
@@ -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
diff --git a/libltdl/config.guess b/libltdl/config.guess
new file mode 100755 (executable)
index 0000000..0f0fe71
--- /dev/null
@@ -0,0 +1,1516 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+#   Inc.
+
+timestamp='2007-03-06'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# 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.
+#
+# 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.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+       for c in cc gcc c89 c99 ; do
+         if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+            CC_FOR_BUILD="$c"; break ;
+         fi ;
+       done ;
+       if test x"$CC_FOR_BUILD" = x ; then
+         CC_FOR_BUILD=no_compiler_found ;
+       fi
+       ;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+       PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+       # NetBSD (nbsd) targets should (where applicable) match one or
+       # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+       # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+       # switched to ELF, *-*-netbsd* would select the old
+       # object file format.  This provides both forward
+       # compatibility and a consistent mechanism for selecting the
+       # object file format.
+       #
+       # Note: NetBSD doesn't particularly care about the vendor
+       # portion of the name.  We always set it to "unknown".
+       sysctl="sysctl -n hw.machine_arch"
+       UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+           /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+       case "${UNAME_MACHINE_ARCH}" in
+           armeb) machine=armeb-unknown ;;
+           arm*) machine=arm-unknown ;;
+           sh3el) machine=shl-unknown ;;
+           sh3eb) machine=sh-unknown ;;
+           sh5el) machine=sh5le-unknown ;;
+           *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+       esac
+       # The Operating System including object format, if it has switched
+       # to ELF recently, or will in the future.
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+               eval $set_cc_for_build
+               if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+                       | grep __ELF__ >/dev/null
+               then
+                   # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+                   # Return netbsd for either.  FIX?
+                   os=netbsd
+               else
+                   os=netbsdelf
+               fi
+               ;;
+           *)
+               os=netbsd
+               ;;
+       esac
+       # The OS release
+       # Debian GNU/NetBSD machines have a different userland, and
+       # thus, need a distinct triplet. However, they do not need
+       # kernel version information, so it can be replaced with a
+       # suitable tag, in the style of linux-gnu.
+       case "${UNAME_VERSION}" in
+           Debian*)
+               release='-gnu'
+               ;;
+           *)
+               release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+               ;;
+       esac
+       # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+       # contains redundant information, the shorter form:
+       # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+       echo "${machine}-${os}${release}"
+       exit ;;
+    *:OpenBSD:*:*)
+       UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+       echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+       exit ;;
+    *:ekkoBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+       exit ;;
+    *:SolidBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+       exit ;;
+    macppc:MirBSD:*:*)
+       echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    *:MirBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    alpha:OSF1:*:*)
+       case $UNAME_RELEASE in
+       *4.0)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+               ;;
+       *5.*)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+               ;;
+       esac
+       # According to Compaq, /usr/sbin/psrinfo has been available on
+       # OSF/1 and Tru64 systems produced since 1995.  I hope that
+       # covers most systems running today.  This code pipes the CPU
+       # types through head -n 1, so we only detect the type of CPU 0.
+       ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+       case "$ALPHA_CPU_TYPE" in
+           "EV4 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "EV4.5 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "LCA4 (21066/21068)")
+               UNAME_MACHINE="alpha" ;;
+           "EV5 (21164)")
+               UNAME_MACHINE="alphaev5" ;;
+           "EV5.6 (21164A)")
+               UNAME_MACHINE="alphaev56" ;;
+           "EV5.6 (21164PC)")
+               UNAME_MACHINE="alphapca56" ;;
+           "EV5.7 (21164PC)")
+               UNAME_MACHINE="alphapca57" ;;
+           "EV6 (21264)")
+               UNAME_MACHINE="alphaev6" ;;
+           "EV6.7 (21264A)")
+               UNAME_MACHINE="alphaev67" ;;
+           "EV6.8CB (21264C)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8AL (21264B)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8CX (21264D)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.9A (21264/EV69A)")
+               UNAME_MACHINE="alphaev69" ;;
+           "EV7 (21364)")
+               UNAME_MACHINE="alphaev7" ;;
+           "EV7.9 (21364A)")
+               UNAME_MACHINE="alphaev79" ;;
+       esac
+       # A Pn.n version is a patched version.
+       # A Vn.n version is a released version.
+       # A Tn.n version is a released field test version.
+       # A Xn.n version is an unreleased experimental baselevel.
+       # 1.2 uses "1.2" for uname -r.
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       exit ;;
+    Alpha\ *:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # Should we change UNAME_MACHINE based on the output of uname instead
+       # of the specific Alpha model?
+       echo alpha-pc-interix
+       exit ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-unknown-sysv4
+       exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-amigaos
+       exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-morphos
+       exit ;;
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
+       exit ;;
+    *:z/VM:*:*)
+       echo s390-ibm-zvmoe
+       exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+       exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+       echo arm-unknown-riscos
+       exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+       if test "`(/bin/universe) 2>/dev/null`" = att ; then
+               echo pyramid-pyramid-sysv3
+       else
+               echo pyramid-pyramid-bsd
+       fi
+       exit ;;
+    NILE*:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit ;;
+    DRS?6000:unix:4.0:6*)
+       echo sparc-icl-nx6
+       exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+       case `/usr/bin/uname -p` in
+           sparc) echo sparc-icl-nx7; exit ;;
+       esac ;;
+    sun4H:SunOS:5.*:*)
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    i86pc:SunOS:5.*:*)
+       echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:6*:*)
+       # According to config.sub, this is the proper way to canonicalize
+       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+       # it's likely to be more like Solaris than SunOS4.
+       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:*:*)
+       case "`/usr/bin/arch -k`" in
+           Series*|S4*)
+               UNAME_RELEASE=`uname -v`
+               ;;
+       esac
+       # Japanese Language versions have a version number like `4.1.3-JL'.
+       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+       exit ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit ;;
+    sun*:*:4.2BSD:*)
+       UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+       test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+       case "`/bin/arch`" in
+           sun3)
+               echo m68k-sun-sunos${UNAME_RELEASE}
+               ;;
+           sun4)
+               echo sparc-sun-sunos${UNAME_RELEASE}
+               ;;
+       esac
+       exit ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+       echo m68k-apple-machten${UNAME_RELEASE}
+       exit ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+       int main (int argc, char *argv[]) {
+#else
+       int main (argc, argv) int argc; char *argv[]; {
+#endif
+       #if defined (host_mips) && defined (MIPSEB)
+       #if defined (SYSTYPE_SYSV)
+         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_SVR4)
+         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+       #endif
+       #endif
+         exit (-1);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c &&
+         dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+         SYSTEM_NAME=`$dummy $dummyarg` &&
+           { echo "$SYSTEM_NAME"; exit; }
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit ;;
+    Motorola:*:4.3:PL8-*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+       if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+       then
+           if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+              [ ${TARGET_BINARY_INTERFACE}x = x ]
+           then
+               echo m88k-dg-dgux${UNAME_RELEASE}
+           else
+               echo m88k-dg-dguxbcs${UNAME_RELEASE}
+           fi
+       else
+           echo i586-dg-dgux${UNAME_RELEASE}
+       fi
+       exit ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+       echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+       exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+       echo i386-ibm-aix
+       exit ;;
+    ia64:AIX:*:*)
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               eval $set_cc_for_build
+               sed 's/^                //' << EOF >$dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+               then
+                       echo "$SYSTEM_NAME"
+               else
+                       echo rs6000-ibm-aix3.2.5
+               fi
+       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+               echo rs6000-ibm-aix3.2.4
+       else
+               echo rs6000-ibm-aix3.2
+       fi
+       exit ;;
+    *:AIX:*:[45])
+       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+       if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+               IBM_ARCH=rs6000
+       else
+               IBM_ARCH=powerpc
+       fi
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit ;;
+    9000/[34678]??:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/[678][0-9][0-9])
+               if [ -x /usr/bin/getconf ]; then
+                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+               fi
+               if [ "${HP_ARCH}" = "" ]; then
+                   eval $set_cc_for_build
+                   sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+               {
+               case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+               case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+               case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+                   switch (bits)
+                       {
+                       case 64: puts ("hppa2.0w"); break;
+                       case 32: puts ("hppa2.0n"); break;
+                       default: puts ("hppa2.0"); break;
+                       } break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+                   puts ("hppa2.0"); break;
+              #endif
+               default: puts ("hppa1.0"); break;
+               }
+                  exit (0);
+              }
+EOF
+                   (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+                   test -z "$HP_ARCH" && HP_ARCH=hppa
+               fi ;;
+       esac
+       if [ ${HP_ARCH} = "hppa2.0w" ]
+       then
+           eval $set_cc_for_build
+
+           # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+           # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+           # generating 64-bit code.  GNU and HP use different nomenclature:
+           #
+           # $ CC_FOR_BUILD=cc ./config.guess
+           # => hppa2.0w-hp-hpux11.23
+           # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+           # => hppa64-hp-hpux11.23
+
+           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+               grep __LP64__ >/dev/null
+           then
+               HP_ARCH="hppa2.0w"
+           else
+               HP_ARCH="hppa64"
+           fi
+       fi
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit ;;
+    3050*:HI-UX:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+            results, however.  */
+         if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+               { echo "$SYSTEM_NAME"; exit; }
+       echo unknown-hitachi-hiuxwe2
+       exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit ;;
+    i*86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*[A-Z]90:*:*:*)
+       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+             -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    *:UNICOS/mp:*:*)
+       echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+       FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+       exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit ;;
+    sparc*:BSD/OS:*:*)
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:FreeBSD:*:*)
+       case ${UNAME_MACHINE} in
+           pc98)
+               echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           amd64)
+               echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           *)
+               echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+       esac
+       exit ;;
+    i*:CYGWIN*:*)
+       echo ${UNAME_MACHINE}-pc-cygwin
+       exit ;;
+    *:MINGW*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit ;;
+    i*:windows32*:*)
+       # uname -m includes "-pc" on this system.
+       echo ${UNAME_MACHINE}-mingw32
+       exit ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit ;;
+    *:Interix*:[3456]*)
+       case ${UNAME_MACHINE} in
+           x86) 
+               echo i586-pc-interix${UNAME_RELEASE}
+               exit ;;
+           EM64T | authenticamd)
+               echo x86_64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+       esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+       echo i${UNAME_MACHINE}-pc-mks
+       exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+       # UNAME_MACHINE based on the output of uname instead of i386?
+       echo i586-pc-interix
+       exit ;;
+    i*:UWIN*:*)
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+       echo x86_64-unknown-cygwin
+       exit ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin
+       exit ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    *:GNU:*:*)
+       # the GNU system
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit ;;
+    *:GNU/*:*:*)
+       # other systems with GNU libc and userland
+       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+       exit ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit ;;
+    arm*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    avr32*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    cris:Linux:*:*)
+       echo cris-axis-linux-gnu
+       exit ;;
+    crisv32:Linux:*:*)
+       echo crisv32-axis-linux-gnu
+       exit ;;
+    frv:Linux:*:*)
+       echo frv-unknown-linux-gnu
+       exit ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m32r*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    mips:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef mips
+       #undef mipsel
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=mipsel
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=mips
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^CPU/{
+               s: ::g
+               p
+           }'`"
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       ;;
+    mips64:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef mips64
+       #undef mips64el
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=mips64el
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=mips64
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^CPU/{
+               s: ::g
+               p
+           }'`"
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       ;;
+    or32:Linux:*:*)
+       echo or32-unknown-linux-gnu
+       exit ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-gnu
+       exit ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-gnu
+       exit ;;
+    alpha:Linux:*:*)
+       case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+         EV5)   UNAME_MACHINE=alphaev5 ;;
+         EV56)  UNAME_MACHINE=alphaev56 ;;
+         PCA56) UNAME_MACHINE=alphapca56 ;;
+         PCA57) UNAME_MACHINE=alphapca56 ;;
+         EV6)   UNAME_MACHINE=alphaev6 ;;
+         EV67)  UNAME_MACHINE=alphaev67 ;;
+         EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+       objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+       if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+       exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+       # Look for CPU level
+       case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+         PA7*) echo hppa1.1-unknown-linux-gnu ;;
+         PA8*) echo hppa2.0-unknown-linux-gnu ;;
+         *)    echo hppa-unknown-linux-gnu ;;
+       esac
+       exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-gnu
+       exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux
+       exit ;;
+    sh64*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    vax:Linux:*:*)
+       echo ${UNAME_MACHINE}-dec-linux-gnu
+       exit ;;
+    x86_64:Linux:*:*)
+       echo x86_64-unknown-linux-gnu
+       exit ;;
+    xtensa:Linux:*:*)
+       echo xtensa-unknown-linux-gnu
+       exit ;;
+    i*86:Linux:*:*)
+       # The BFD linker knows what the default object file format is, so
+       # first see if it will tell us. cd to the root directory to prevent
+       # problems with other programs or directories called `ld' in the path.
+       # Set LC_ALL=C to ensure ld outputs messages in English.
+       ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+                        | sed -ne '/supported targets:/!d
+                                   s/[         ][      ]*/ /g
+                                   s/.*supported targets: *//
+                                   s/ .*//
+                                   p'`
+        case "$ld_supported_targets" in
+         elf32-i386)
+               TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+               ;;
+         a.out-i386-linux)
+               echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+               exit ;;
+         coff-i386)
+               echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+               exit ;;
+         "")
+               # Either a pre-BFD a.out linker (linux-gnuoldld) or
+               # one that does not give us useful --help.
+               echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+               exit ;;
+       esac
+       # Determine whether the default compiler is a.out or elf
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <features.h>
+       #ifdef __ELF__
+       # ifdef __GLIBC__
+       #  if __GLIBC__ >= 2
+       LIBC=gnu
+       #  else
+       LIBC=gnulibc1
+       #  endif
+       # else
+       LIBC=gnulibc1
+       # endif
+       #else
+       #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+       LIBC=gnu
+       #else
+       LIBC=gnuaout
+       #endif
+       #endif
+       #ifdef __dietlibc__
+       LIBC=dietlibc
+       #endif
+EOF
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^LIBC/{
+               s: ::g
+               p
+           }'`"
+       test x"${LIBC}" != x && {
+               echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+               exit
+       }
+       test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+       ;;
+    i*86:DYNIX/ptx:4*:*)
+       # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+       # earlier versions are messed up and put the nodename in both
+       # sysname and nodename.
+       echo i386-sequent-sysv4
+       exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+       # I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+       echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+       exit ;;
+    i*86:OS/2:*:*)
+       # If we were able to find `uname', then EMX Unix compatibility
+       # is probably installed.
+       echo ${UNAME_MACHINE}-pc-os2-emx
+       exit ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit ;;
+    i*86:syllable:*:*)
+       echo ${UNAME_MACHINE}-pc-syllable
+       exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+       UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+       else
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+       fi
+       exit ;;
+    i*86:*:5:[678]*)
+       # UnixWare 7.x, OpenUNIX and OpenServer 6.
+       case `/bin/uname -X | grep "^Machine"` in
+           *486*)           UNAME_MACHINE=i486 ;;
+           *Pentium)        UNAME_MACHINE=i586 ;;
+           *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+       esac
+       echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+       exit ;;
+    i*86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit ;;
+    pc:*:*:*)
+       # Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+       echo i386-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit ;;
+    i860:*:4.*:*) # i860-SVR4
+       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+       else # Add other i860-SVR4 vendors below as they are discovered.
+         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+       fi
+       exit ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+       echo m68k-convergent-sysv
+       exit ;;
+    M680?0:D-NIX:5.3:*)
+       echo m68k-diab-dnix
+       exit ;;
+    M68*:*:R3V[5678]*:*)
+       test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+       OS_REL=''
+       test -r /etc/.relid \
+       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    rs6000:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    *:SINIX-*:*:*)
+       if uname -p 2>/dev/null >/dev/null ; then
+               UNAME_MACHINE=`(uname -p) 2>/dev/null`
+               echo ${UNAME_MACHINE}-sni-sysv4
+       else
+               echo ns32k-sni-sysv
+       fi
+       exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit ;;
+    i*86:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo ${UNAME_MACHINE}-stratus-vos
+       exit ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit ;;
+    news*:NEWS-OS:6*:*)
+       echo mips-sony-newsos6
+       exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+       if [ -d /usr/nec ]; then
+               echo mips-nec-sysv${UNAME_RELEASE}
+       else
+               echo mips-unknown-sysv${UNAME_RELEASE}
+       fi
+        exit ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
+       exit ;;
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
+       echo powerpc-apple-beos
+       exit ;;
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
+       echo i586-pc-beos
+       exit ;;
+    SX-4:SUPER-UX:*:*)
+       echo sx4-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-5:SUPER-UX:*:*)
+       echo sx5-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-6:SUPER-UX:*:*)
+       echo sx6-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-7:SUPER-UX:*:*)
+       echo sx7-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8:SUPER-UX:*:*)
+       echo sx8-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8R:SUPER-UX:*:*)
+       echo sx8r-nec-superux${UNAME_RELEASE}
+       exit ;;
+    Power*:Rhapsody:*:*)
+       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Rhapsody:*:*)
+       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Darwin:*:*)
+       UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+       case $UNAME_PROCESSOR in
+           unknown) UNAME_PROCESSOR=powerpc ;;
+       esac
+       echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+       exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+       UNAME_PROCESSOR=`uname -p`
+       if test "$UNAME_PROCESSOR" = "x86"; then
+               UNAME_PROCESSOR=i386
+               UNAME_MACHINE=pc
+       fi
+       echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+       exit ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+       echo nse-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit ;;
+    *:Plan9:*:*)
+       # "uname -m" is not consistent, so use $cputype instead. 386
+       # is converted to i386 for consistency with other x86
+       # operating systems.
+       if test "$cputype" = "386"; then
+           UNAME_MACHINE=i386
+       else
+           UNAME_MACHINE="$cputype"
+       fi
+       echo ${UNAME_MACHINE}-unknown-plan9
+       exit ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+       exit ;;
+    *:DragonFly:*:*)
+       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit ;;
+    *:*VMS:*:*)
+       UNAME_MACHINE=`(uname -p) 2>/dev/null`
+       case "${UNAME_MACHINE}" in
+           A*) echo alpha-dec-vms ; exit ;;
+           I*) echo ia64-dec-vms ; exit ;;
+           V*) echo vax-dec-vms ; exit ;;
+       esac ;;
+    *:XENIX:*:SysV)
+       echo i386-pc-xenix
+       exit ;;
+    i*86:skyos:*:*)
+       echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+       exit ;;
+    i*86:rdos:*:*)
+       echo ${UNAME_MACHINE}-pc-rdos
+       exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+         ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+       printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+       printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+       { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+       echo c1-convex-bsd
+       exit ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit ;;
+    c34*)
+       echo c34-convex-bsd
+       exit ;;
+    c38*)
+       echo c38-convex-bsd
+       exit ;;
+    c4*)
+       echo c4-convex-bsd
+       exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/libltdl/config.h b/libltdl/config.h
new file mode 100644 (file)
index 0000000..a04820a
--- /dev/null
@@ -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
diff --git a/libltdl/config.sub b/libltdl/config.sub
new file mode 100755 (executable)
index 0000000..5defff6
--- /dev/null
@@ -0,0 +1,1622 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+#   Inc.
+
+timestamp='2007-01-18'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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.
+#
+# 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.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+       -sun*os*)
+               # Prevent following clause from handling this invalid input.
+               ;;
+       -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+       -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+       -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+       -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+       -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+       -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+       -apple | -axis | -knuth | -cray)
+               os=
+               basic_machine=$1
+               ;;
+       -sim | -cisco | -oki | -wec | -winbond)
+               os=
+               basic_machine=$1
+               ;;
+       -scout)
+               ;;
+       -wrs)
+               os=-vxworks
+               basic_machine=$1
+               ;;
+       -chorusos*)
+               os=-chorusos
+               basic_machine=$1
+               ;;
+       -chorusrdb)
+               os=-chorusrdb
+               basic_machine=$1
+               ;;
+       -hiux*)
+               os=-hiuxwe2
+               ;;
+       -sco6)
+               os=-sco5v6
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5)
+               os=-sco3.2v5
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco4)
+               os=-sco3.2v4
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2.[4-9]*)
+               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2v[4-9]*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5v6*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco*)
+               os=-sco3.2v2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -udk*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -isc)
+               os=-isc2.2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -clix*)
+               basic_machine=clipper-intergraph
+               ;;
+       -isc*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -lynx*)
+               os=-lynxos
+               ;;
+       -ptx*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+               ;;
+       -windowsnt*)
+               os=`echo $os | sed -e 's/windowsnt/winnt/'`
+               ;;
+       -psos*)
+               os=-psos
+               ;;
+       -mint | -mint[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+       # Recognize the basic CPU types without company name.
+       # Some are omitted here because they have special meanings below.
+       1750a | 580 \
+       | a29k \
+       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+       | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | am33_2.0 \
+       | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+       | bfin \
+       | c4x | clipper \
+       | d10v | d30v | dlx | dsp16xx \
+       | fido | fr30 | frv \
+       | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+       | i370 | i860 | i960 | ia64 \
+       | ip2k | iq2000 \
+       | m32c | m32r | m32rle | m68000 | m68k | m88k \
+       | maxq | mb | microblaze | mcore | mep \
+       | mips | mipsbe | mipseb | mipsel | mipsle \
+       | mips16 \
+       | mips64 | mips64el \
+       | mips64vr | mips64vrel \
+       | mips64orion | mips64orionel \
+       | mips64vr4100 | mips64vr4100el \
+       | mips64vr4300 | mips64vr4300el \
+       | mips64vr5000 | mips64vr5000el \
+       | mips64vr5900 | mips64vr5900el \
+       | mipsisa32 | mipsisa32el \
+       | mipsisa32r2 | mipsisa32r2el \
+       | mipsisa64 | mipsisa64el \
+       | mipsisa64r2 | mipsisa64r2el \
+       | mipsisa64sb1 | mipsisa64sb1el \
+       | mipsisa64sr71k | mipsisa64sr71kel \
+       | mipstx39 | mipstx39el \
+       | mn10200 | mn10300 \
+       | mt \
+       | msp430 \
+       | nios | nios2 \
+       | ns16k | ns32k \
+       | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+       | pyramid \
+       | score \
+       | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+       | sh64 | sh64le \
+       | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+       | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+       | spu | strongarm \
+       | tahoe | thumb | tic4x | tic80 | tron \
+       | v850 | v850e \
+       | we32k \
+       | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+       | z8k)
+               basic_machine=$basic_machine-unknown
+               ;;
+       m6811 | m68hc11 | m6812 | m68hc12)
+               # Motorola 68HC11/12.
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+               ;;
+       ms1)
+               basic_machine=mt-unknown
+               ;;
+
+       # We use `pc' rather than `unknown'
+       # because (1) that's what they normally are, and
+       # (2) the word "unknown" tends to confuse beginning users.
+       i*86 | x86_64)
+         basic_machine=$basic_machine-pc
+         ;;
+       # Object if more than one company name word.
+       *-*-*)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+       # Recognize the basic CPU types with company name.
+       580-* \
+       | a29k-* \
+       | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+       | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+       | arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+       | avr-* | avr32-* \
+       | bfin-* | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+       | clipper-* | craynv-* | cydra-* \
+       | d10v-* | d30v-* | dlx-* \
+       | elxsi-* \
+       | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+       | h8300-* | h8500-* \
+       | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+       | i*86-* | i860-* | i960-* | ia64-* \
+       | ip2k-* | iq2000-* \
+       | m32c-* | m32r-* | m32rle-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | maxq-* | mcore-* \
+       | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+       | mips16-* \
+       | mips64-* | mips64el-* \
+       | mips64vr-* | mips64vrel-* \
+       | mips64orion-* | mips64orionel-* \
+       | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* \
+       | mips64vr5000-* | mips64vr5000el-* \
+       | mips64vr5900-* | mips64vr5900el-* \
+       | mipsisa32-* | mipsisa32el-* \
+       | mipsisa32r2-* | mipsisa32r2el-* \
+       | mipsisa64-* | mipsisa64el-* \
+       | mipsisa64r2-* | mipsisa64r2el-* \
+       | mipsisa64sb1-* | mipsisa64sb1el-* \
+       | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+       | mipstx39-* | mipstx39el-* \
+       | mmix-* \
+       | mt-* \
+       | msp430-* \
+       | nios-* | nios2-* \
+       | none-* | np1-* | ns16k-* | ns32k-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+       | pyramid-* \
+       | romp-* | rs6000-* \
+       | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+       | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+       | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+       | sparclite-* \
+       | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+       | tahoe-* | thumb-* \
+       | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+       | tron-* \
+       | v850-* | v850e-* | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+       | xstormy16-* | xtensa-* \
+       | ymp-* \
+       | z8k-*)
+               ;;
+       # Recognize the various machine names and aliases which stand
+       # for a CPU type and a company and sometimes even an OS.
+       386bsd)
+               basic_machine=i386-unknown
+               os=-bsd
+               ;;
+       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+               basic_machine=m68000-att
+               ;;
+       3b*)
+               basic_machine=we32k-att
+               ;;
+       a29khif)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       abacus)
+               basic_machine=abacus-unknown
+               ;;
+       adobe68k)
+               basic_machine=m68010-adobe
+               os=-scout
+               ;;
+       alliant | fx80)
+               basic_machine=fx80-alliant
+               ;;
+       altos | altos3068)
+               basic_machine=m68k-altos
+               ;;
+       am29k)
+               basic_machine=a29k-none
+               os=-bsd
+               ;;
+       amd64)
+               basic_machine=x86_64-pc
+               ;;
+       amd64-*)
+               basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       amdahl)
+               basic_machine=580-amdahl
+               os=-sysv
+               ;;
+       amiga | amiga-*)
+               basic_machine=m68k-unknown
+               ;;
+       amigaos | amigados)
+               basic_machine=m68k-unknown
+               os=-amigaos
+               ;;
+       amigaunix | amix)
+               basic_machine=m68k-unknown
+               os=-sysv4
+               ;;
+       apollo68)
+               basic_machine=m68k-apollo
+               os=-sysv
+               ;;
+       apollo68bsd)
+               basic_machine=m68k-apollo
+               os=-bsd
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       c90)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+       convex-c1)
+               basic_machine=c1-convex
+               os=-bsd
+               ;;
+       convex-c2)
+               basic_machine=c2-convex
+               os=-bsd
+               ;;
+       convex-c32)
+               basic_machine=c32-convex
+               os=-bsd
+               ;;
+       convex-c34)
+               basic_machine=c34-convex
+               os=-bsd
+               ;;
+       convex-c38)
+               basic_machine=c38-convex
+               os=-bsd
+               ;;
+       cray | j90)
+               basic_machine=j90-cray
+               os=-unicos
+               ;;
+       craynv)
+               basic_machine=craynv-cray
+               os=-unicosmp
+               ;;
+       cr16c)
+               basic_machine=cr16c-unknown
+               os=-elf
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       crisv32 | crisv32-* | etraxfs*)
+               basic_machine=crisv32-axis
+               ;;
+       cris | cris-* | etrax*)
+               basic_machine=cris-axis
+               ;;
+       crx)
+               basic_machine=crx-unknown
+               os=-elf
+               ;;
+       da30 | da30-*)
+               basic_machine=m68k-da30
+               ;;
+       decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+               basic_machine=mips-dec
+               ;;
+       decsystem10* | dec10*)
+               basic_machine=pdp10-dec
+               os=-tops10
+               ;;
+       decsystem20* | dec20*)
+               basic_machine=pdp10-dec
+               os=-tops20
+               ;;
+       delta | 3300 | motorola-3300 | motorola-delta \
+             | 3300-motorola | delta-motorola)
+               basic_machine=m68k-motorola
+               ;;
+       delta88)
+               basic_machine=m88k-motorola
+               os=-sysv3
+               ;;
+       djgpp)
+               basic_machine=i586-pc
+               os=-msdosdjgpp
+               ;;
+       dpx20 | dpx20-*)
+               basic_machine=rs6000-bull
+               os=-bosx
+               ;;
+       dpx2* | dpx2*-bull)
+               basic_machine=m68k-bull
+               os=-sysv3
+               ;;
+       ebmon29k)
+               basic_machine=a29k-amd
+               os=-ebmon
+               ;;
+       elxsi)
+               basic_machine=elxsi-elxsi
+               os=-bsd
+               ;;
+       encore | umax | mmax)
+               basic_machine=ns32k-encore
+               ;;
+       es1800 | OSE68k | ose68k | ose | OSE)
+               basic_machine=m68k-ericsson
+               os=-ose
+               ;;
+       fx2800)
+               basic_machine=i860-alliant
+               ;;
+       genix)
+               basic_machine=ns32k-ns
+               ;;
+       gmicro)
+               basic_machine=tron-gmicro
+               os=-sysv
+               ;;
+       go32)
+               basic_machine=i386-pc
+               os=-go32
+               ;;
+       h3050r* | hiux*)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       h8300hms)
+               basic_machine=h8300-hitachi
+               os=-hms
+               ;;
+       h8300xray)
+               basic_machine=h8300-hitachi
+               os=-xray
+               ;;
+       h8500hms)
+               basic_machine=h8500-hitachi
+               os=-hms
+               ;;
+       harris)
+               basic_machine=m88k-harris
+               os=-sysv3
+               ;;
+       hp300-*)
+               basic_machine=m68k-hp
+               ;;
+       hp300bsd)
+               basic_machine=m68k-hp
+               os=-bsd
+               ;;
+       hp300hpux)
+               basic_machine=m68k-hp
+               os=-hpux
+               ;;
+       hp3k9[0-9][0-9] | hp9[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k2[0-9][0-9] | hp9k31[0-9])
+               basic_machine=m68000-hp
+               ;;
+       hp9k3[2-9][0-9])
+               basic_machine=m68k-hp
+               ;;
+       hp9k6[0-9][0-9] | hp6[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k7[0-79][0-9] | hp7[0-79][0-9])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k78[0-9] | hp78[0-9])
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][13679] | hp8[0-9][13679])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][0-9] | hp8[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hppa-next)
+               os=-nextstep3
+               ;;
+       hppaosf)
+               basic_machine=hppa1.1-hp
+               os=-osf
+               ;;
+       hppro)
+               basic_machine=hppa1.1-hp
+               os=-proelf
+               ;;
+       i370-ibm* | ibm*)
+               basic_machine=i370-ibm
+               ;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+       i*86v32)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv32
+               ;;
+       i*86v4*)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv4
+               ;;
+       i*86v)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv
+               ;;
+       i*86sol2)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-solaris2
+               ;;
+       i386mach)
+               basic_machine=i386-mach
+               os=-mach
+               ;;
+       i386-vsta | vsta)
+               basic_machine=i386-unknown
+               os=-vsta
+               ;;
+       iris | iris4d)
+               basic_machine=mips-sgi
+               case $os in
+                   -irix*)
+                       ;;
+                   *)
+                       os=-irix4
+                       ;;
+               esac
+               ;;
+       isi68 | isi)
+               basic_machine=m68k-isi
+               os=-sysv
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+       mingw32)
+               basic_machine=i386-pc
+               os=-mingw32
+               ;;
+       miniframe)
+               basic_machine=m68000-convergent
+               ;;
+       *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+       mips3*-*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+               ;;
+       mips3*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+               ;;
+       monitor)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
+       msdos)
+               basic_machine=i386-pc
+               os=-msdos
+               ;;
+       ms1-*)
+               basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+               ;;
+       mvs)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+       ncr3000)
+               basic_machine=i486-ncr
+               os=-sysv4
+               ;;
+       netbsd386)
+               basic_machine=i386-unknown
+               os=-netbsd
+               ;;
+       netwinder)
+               basic_machine=armv4l-rebel
+               os=-linux
+               ;;
+       news | news700 | news800 | news900)
+               basic_machine=m68k-sony
+               os=-newsos
+               ;;
+       news1000)
+               basic_machine=m68030-sony
+               os=-newsos
+               ;;
+       news-3600 | risc-news)
+               basic_machine=mips-sony
+               os=-newsos
+               ;;
+       necv70)
+               basic_machine=v70-nec
+               os=-sysv
+               ;;
+       next | m*-next )
+               basic_machine=m68k-next
+               case $os in
+                   -nextstep* )
+                       ;;
+                   -ns2*)
+                     os=-nextstep2
+                       ;;
+                   *)
+                     os=-nextstep3
+                       ;;
+               esac
+               ;;
+       nh3000)
+               basic_machine=m68k-harris
+               os=-cxux
+               ;;
+       nh[45]000)
+               basic_machine=m88k-harris
+               os=-cxux
+               ;;
+       nindy960)
+               basic_machine=i960-intel
+               os=-nindy
+               ;;
+       mon960)
+               basic_machine=i960-intel
+               os=-mon960
+               ;;
+       nonstopux)
+               basic_machine=mips-compaq
+               os=-nonstopux
+               ;;
+       np1)
+               basic_machine=np1-gould
+               ;;
+       nsr-tandem)
+               basic_machine=nsr-tandem
+               ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       openrisc | openrisc-*)
+               basic_machine=or32-unknown
+               ;;
+       os400)
+               basic_machine=powerpc-ibm
+               os=-os400
+               ;;
+       OSE68000 | ose68000)
+               basic_machine=m68000-ericsson
+               os=-ose
+               ;;
+       os68k)
+               basic_machine=m68k-none
+               os=-os68k
+               ;;
+       pa-hitachi)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       paragon)
+               basic_machine=i860-intel
+               os=-osf
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+       pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pc98)
+               basic_machine=i386-pc
+               ;;
+       pc98-*)
+               basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium | p5 | k5 | k6 | nexgen | viac3)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86 | athlon | athlon_*)
+               basic_machine=i686-pc
+               ;;
+       pentiumii | pentium2 | pentiumiii | pentium3)
+               basic_machine=i686-pc
+               ;;
+       pentium4)
+               basic_machine=i786-pc
+               ;;
+       pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumpro-* | p6-* | 6x86-* | athlon-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium4-*)
+               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=power-ibm
+               ;;
+       ppc)    basic_machine=powerpc-unknown
+               ;;
+       ppc-*)  basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppcle | powerpclittle | ppc-le | powerpc-little)
+               basic_machine=powerpcle-unknown
+               ;;
+       ppcle-* | powerpclittle-*)
+               basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64)  basic_machine=powerpc64-unknown
+               ;;
+       ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+               basic_machine=powerpc64le-unknown
+               ;;
+       ppc64le-* | powerpc64little-*)
+               basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ps2)
+               basic_machine=i386-ibm
+               ;;
+       pw32)
+               basic_machine=i586-unknown
+               os=-pw32
+               ;;
+       rdos)
+               basic_machine=i386-pc
+               os=-rdos
+               ;;
+       rom68k)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       rm[46]00)
+               basic_machine=mips-siemens
+               ;;
+       rtpc | rtpc-*)
+               basic_machine=romp-ibm
+               ;;
+       s390 | s390-*)
+               basic_machine=s390-ibm
+               ;;
+       s390x | s390x-*)
+               basic_machine=s390x-ibm
+               ;;
+       sa29200)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       sb1)
+               basic_machine=mipsisa64sb1-unknown
+               ;;
+       sb1el)
+               basic_machine=mipsisa64sb1el-unknown
+               ;;
+       sde)
+               basic_machine=mipsisa32-sde
+               os=-elf
+               ;;
+       sei)
+               basic_machine=mips-sei
+               os=-seiux
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       sh5el)
+               basic_machine=sh5le-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparclite-wrs | simso-wrs)
+               basic_machine=sparclite-wrs
+               os=-vxworks
+               ;;
+       sps7)
+               basic_machine=m68k-bull
+               os=-sysv2
+               ;;
+       spur)
+               basic_machine=spur-unknown
+               ;;
+       st2000)
+               basic_machine=m68k-tandem
+               ;;
+       stratus)
+               basic_machine=i860-stratus
+               os=-sysv4
+               ;;
+       sun2)
+               basic_machine=m68000-sun
+               ;;
+       sun2os3)
+               basic_machine=m68000-sun
+               os=-sunos3
+               ;;
+       sun2os4)
+               basic_machine=m68000-sun
+               os=-sunos4
+               ;;
+       sun3os3)
+               basic_machine=m68k-sun
+               os=-sunos3
+               ;;
+       sun3os4)
+               basic_machine=m68k-sun
+               os=-sunos4
+               ;;
+       sun4os3)
+               basic_machine=sparc-sun
+               os=-sunos3
+               ;;
+       sun4os4)
+               basic_machine=sparc-sun
+               os=-sunos4
+               ;;
+       sun4sol2)
+               basic_machine=sparc-sun
+               os=-solaris2
+               ;;
+       sun3 | sun3-*)
+               basic_machine=m68k-sun
+               ;;
+       sun4)
+               basic_machine=sparc-sun
+               ;;
+       sun386 | sun386i | roadrunner)
+               basic_machine=i386-sun
+               ;;
+       sv1)
+               basic_machine=sv1-cray
+               os=-unicos
+               ;;
+       symmetry)
+               basic_machine=i386-sequent
+               os=-dynix
+               ;;
+       t3e)
+               basic_machine=alphaev5-cray
+               os=-unicos
+               ;;
+       t90)
+               basic_machine=t90-cray
+               os=-unicos
+               ;;
+       tic54x | c54x*)
+               basic_machine=tic54x-unknown
+               os=-coff
+               ;;
+       tic55x | c55x*)
+               basic_machine=tic55x-unknown
+               os=-coff
+               ;;
+       tic6x | c6x*)
+               basic_machine=tic6x-unknown
+               os=-coff
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       toad1)
+               basic_machine=pdp10-xkl
+               os=-tops20
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       tpf)
+               basic_machine=s390x-ibm
+               os=-tpf
+               ;;
+       udi29k)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       ultra3)
+               basic_machine=a29k-nyu
+               os=-sym1
+               ;;
+       v810 | necv810)
+               basic_machine=v810-nec
+               os=-none
+               ;;
+       vaxv)
+               basic_machine=vax-dec
+               os=-sysv
+               ;;
+       vms)
+               basic_machine=vax-dec
+               os=-vms
+               ;;
+       vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+       vxworks960)
+               basic_machine=i960-wrs
+               os=-vxworks
+               ;;
+       vxworks68)
+               basic_machine=m68k-wrs
+               os=-vxworks
+               ;;
+       vxworks29k)
+               basic_machine=a29k-wrs
+               os=-vxworks
+               ;;
+       w65*)
+               basic_machine=w65-wdc
+               os=-none
+               ;;
+       w89k-*)
+               basic_machine=hppa1.1-winbond
+               os=-proelf
+               ;;
+       xbox)
+               basic_machine=i686-pc
+               os=-mingw32
+               ;;
+       xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       z8k-*-coff)
+               basic_machine=z8k-unknown
+               os=-sim
+               ;;
+       none)
+               basic_machine=none-none
+               os=-none
+               ;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+       w89k)
+               basic_machine=hppa1.1-winbond
+               ;;
+       op50n)
+               basic_machine=hppa1.1-oki
+               ;;
+       op60c)
+               basic_machine=hppa1.1-oki
+               ;;
+       romp)
+               basic_machine=romp-ibm
+               ;;
+       mmix)
+               basic_machine=mmix-knuth
+               ;;
+       rs6000)
+               basic_machine=rs6000-ibm
+               ;;
+       vax)
+               basic_machine=vax-dec
+               ;;
+       pdp10)
+               # there are many clones, so DEC is not a safe bet
+               basic_machine=pdp10-unknown
+               ;;
+       pdp11)
+               basic_machine=pdp11-dec
+               ;;
+       we32k)
+               basic_machine=we32k-att
+               ;;
+       sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+               basic_machine=sh-unknown
+               ;;
+       sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+               basic_machine=sparc-sun
+               ;;
+       cydra)
+               basic_machine=cydra-cydrome
+               ;;
+       orion)
+               basic_machine=orion-highlevel
+               ;;
+       orion105)
+               basic_machine=clipper-highlevel
+               ;;
+       mac | mpw | mac-mpw)
+               basic_machine=m68k-apple
+               ;;
+       pmac | pmac-mpw)
+               basic_machine=powerpc-apple
+               ;;
+       *-unknown)
+               # Make sure to match an already-canonicalized machine name.
+               ;;
+       *)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+       *-digital*)
+               basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+               ;;
+       *-commodore*)
+               basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+               ;;
+       *)
+               ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+       # -solaris* is a basic system type, with this one exception.
+       -solaris1 | -solaris1.*)
+               os=`echo $os | sed -e 's|solaris1|sunos4|'`
+               ;;
+       -solaris)
+               os=-solaris2
+               ;;
+       -svr4*)
+               os=-sysv4
+               ;;
+       -unixware*)
+               os=-sysv4.2uw
+               ;;
+       -gnu/linux*)
+               os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+               ;;
+       # First accept the basic system types.
+       # The portable systems comes first.
+       # Each alternative MUST END IN A *, to match a version number.
+       # -sysv* is not here because it comes later, after sysvr4.
+       -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+             | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+             | -aos* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+             | -openbsd* | -solidbsd* \
+             | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+             | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -chorusos* | -chorusrdb* \
+             | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+             | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+             | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+             | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+             | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+             | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+             | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+             | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       -qnx*)
+               case $basic_machine in
+                   x86-* | i*86-*)
+                       ;;
+                   *)
+                       os=-nto$os
+                       ;;
+               esac
+               ;;
+       -nto-qnx*)
+               ;;
+       -nto*)
+               os=`echo $os | sed -e 's|nto|nto-qnx|'`
+               ;;
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
+       -linux-dietlibc)
+               os=-linux-dietlibc
+               ;;
+       -linux*)
+               os=`echo $os | sed -e 's|linux|linux-gnu|'`
+               ;;
+       -sunos5*)
+               os=`echo $os | sed -e 's|sunos5|solaris2|'`
+               ;;
+       -sunos6*)
+               os=`echo $os | sed -e 's|sunos6|solaris3|'`
+               ;;
+       -opened*)
+               os=-openedition
+               ;;
+        -os400*)
+               os=-os400
+               ;;
+       -wince*)
+               os=-wince
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -atheos*)
+               os=-atheos
+               ;;
+       -syllable*)
+               os=-syllable
+               ;;
+       -386bsd)
+               os=-bsd
+               ;;
+       -ctix* | -uts*)
+               os=-sysv
+               ;;
+       -nova*)
+               os=-rtmk-nova
+               ;;
+       -ns2 )
+               os=-nextstep2
+               ;;
+       -nsk*)
+               os=-nsk
+               ;;
+       # Preserve the version number of sinix5.
+       -sinix5.*)
+               os=`echo $os | sed -e 's|sinix|sysv|'`
+               ;;
+       -sinix*)
+               os=-sysv4
+               ;;
+        -tpf*)
+               os=-tpf
+               ;;
+       -triton*)
+               os=-sysv3
+               ;;
+       -oss*)
+               os=-sysv3
+               ;;
+       -svr4)
+               os=-sysv4
+               ;;
+       -svr3)
+               os=-sysv3
+               ;;
+       -sysvr4)
+               os=-sysv4
+               ;;
+       # This must come after -sysvr4.
+       -sysv*)
+               ;;
+       -ose*)
+               os=-ose
+               ;;
+       -es1800*)
+               os=-ose
+               ;;
+       -xenix)
+               os=-xenix
+               ;;
+       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+               os=-mint
+               ;;
+       -aros*)
+               os=-aros
+               ;;
+       -kaos*)
+               os=-kaos
+               ;;
+       -zvmoe)
+               os=-zvmoe
+               ;;
+       -none)
+               ;;
+       *)
+               # Get rid of the `-' at the beginning of $os.
+               os=`echo $os | sed 's/[^-]*-//'`
+               echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        score-*)
+               os=-elf
+               ;;
+        spu-*)
+               os=-elf
+               ;;
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-rebel)
+               os=-linux
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+        c4x-* | tic4x-*)
+               os=-coff
+               ;;
+       # This must come before the *-dec entry.
+       pdp10-*)
+               os=-tops20
+               ;;
+       pdp11-*)
+               os=-none
+               ;;
+       *-dec | vax-*)
+               os=-ultrix4.2
+               ;;
+       m68*-apollo)
+               os=-domain
+               ;;
+       i386-sun)
+               os=-sunos4.0.2
+               ;;
+       m68000-sun)
+               os=-sunos3
+               # This also exists in the configure program, but was not the
+               # default.
+               # os=-sunos4
+               ;;
+       m68*-cisco)
+               os=-aout
+               ;;
+        mep-*)
+               os=-elf
+               ;;
+       mips*-cisco)
+               os=-elf
+               ;;
+       mips*-*)
+               os=-elf
+               ;;
+       or32-*)
+               os=-coff
+               ;;
+       *-tti)  # must be before sparc entry or we get the wrong os.
+               os=-sysv3
+               ;;
+       sparc-* | *-sun)
+               os=-sunos4.1.1
+               ;;
+       *-be)
+               os=-beos
+               ;;
+       *-haiku)
+               os=-haiku
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-knuth)
+               os=-mmixware
+               ;;
+       *-wec)
+               os=-proelf
+               ;;
+       *-winbond)
+               os=-proelf
+               ;;
+       *-oki)
+               os=-proelf
+               ;;
+       *-hp)
+               os=-hpux
+               ;;
+       *-hitachi)
+               os=-hiux
+               ;;
+       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+               os=-sysv
+               ;;
+       *-cbm)
+               os=-amigaos
+               ;;
+       *-dg)
+               os=-dgux
+               ;;
+       *-dolphin)
+               os=-sysv3
+               ;;
+       m68k-ccur)
+               os=-rtu
+               ;;
+       m88k-omron*)
+               os=-luna
+               ;;
+       *-next )
+               os=-nextstep
+               ;;
+       *-sequent)
+               os=-ptx
+               ;;
+       *-crds)
+               os=-unos
+               ;;
+       *-ns)
+               os=-genix
+               ;;
+       i370-*)
+               os=-mvs
+               ;;
+       *-next)
+               os=-nextstep3
+               ;;
+       *-gould)
+               os=-sysv
+               ;;
+       *-highlevel)
+               os=-bsd
+               ;;
+       *-encore)
+               os=-bsd
+               ;;
+       *-sgi)
+               os=-irix
+               ;;
+       *-siemens)
+               os=-sysv4
+               ;;
+       *-masscomp)
+               os=-rtu
+               ;;
+       f30[01]-fujitsu | f700-fujitsu)
+               os=-uxpv
+               ;;
+       *-rom68k)
+               os=-coff
+               ;;
+       *-*bug)
+               os=-coff
+               ;;
+       *-apple)
+               os=-macos
+               ;;
+       *-atari*)
+               os=-mint
+               ;;
+       *)
+               os=-none
+               ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+       *-unknown)
+               case $os in
+                       -riscix*)
+                               vendor=acorn
+                               ;;
+                       -sunos*)
+                               vendor=sun
+                               ;;
+                       -aix*)
+                               vendor=ibm
+                               ;;
+                       -beos*)
+                               vendor=be
+                               ;;
+                       -hpux*)
+                               vendor=hp
+                               ;;
+                       -mpeix*)
+                               vendor=hp
+                               ;;
+                       -hiux*)
+                               vendor=hitachi
+                               ;;
+                       -unos*)
+                               vendor=crds
+                               ;;
+                       -dgux*)
+                               vendor=dg
+                               ;;
+                       -luna*)
+                               vendor=omron
+                               ;;
+                       -genix*)
+                               vendor=ns
+                               ;;
+                       -mvs* | -opened*)
+                               vendor=ibm
+                               ;;
+                       -os400*)
+                               vendor=ibm
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -tpf*)
+                               vendor=ibm
+                               ;;
+                       -vxsim* | -vxworks* | -windiss*)
+                               vendor=wrs
+                               ;;
+                       -aux*)
+                               vendor=apple
+                               ;;
+                       -hms*)
+                               vendor=hitachi
+                               ;;
+                       -mpw* | -macos*)
+                               vendor=apple
+                               ;;
+                       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+                               vendor=atari
+                               ;;
+                       -vos*)
+                               vendor=stratus
+                               ;;
+               esac
+               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+               ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/libltdl/configure b/libltdl/configure
new file mode 100755 (executable)
index 0000000..aa2994e
--- /dev/null
@@ -0,0 +1,23853 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61 for libltdl 1.2.
+#
+# Report bugs to <bug-libtool@gnu.org>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+  if (eval ":") 2>/dev/null; then
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+
+  if test $as_have_required = yes &&    (eval ":
+(as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=\$LINENO
+  as_lineno_2=\$LINENO
+  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+  :
+else
+  as_candidate_shells=
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  case $as_dir in
+        /*)
+          for as_base in sh bash ksh sh5; do
+            as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+          done;;
+       esac
+done
+IFS=$as_save_IFS
+
+
+      for as_shell in $as_candidate_shells $SHELL; do
+        # Try only shells that exist, to save several forks.
+        if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+               { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+  CONFIG_SHELL=$as_shell
+              as_have_required=yes
+              if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+  (exit $1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+  break
+fi
+
+fi
+
+      done
+
+      if test "x$CONFIG_SHELL" != x; then
+  for as_var in BASH_ENV ENV
+        do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+        done
+        export CONFIG_SHELL
+        exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+    if test $as_have_required = no; then
+  echo This script requires a shell more modern than all the
+      echo shells that I found on your system.  Please install a
+      echo modern shell, or manually run the script under such a
+      echo shell if you do have one.
+      { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+  echo No shell found that supports shell functions.
+  echo Please tell autoconf@gnu.org about your system,
+  echo including any error possibly output before this
+  echo message
+}
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+        test -d "$1/.";
+      else
+       case $1 in
+        -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','`
+  ;;
+esac
+
+echo=${ECHO-echo}
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+  for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+    if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+       echo_test_string=`eval $cmd` &&
+       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+    then
+      break
+    fi
+  done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+   echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+   test "X$echo_testing_string" = "X$echo_test_string"; then
+  :
+else
+  # The Solaris, AIX, and Digital Unix default echo programs unquote
+  # backslashes.  This makes it impossible to quote backslashes using
+  #   echo "$something" | sed 's/\\/\\\\/g'
+  #
+  # So, first we look for a working echo in the user's PATH.
+
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for dir in $PATH /usr/ucb; do
+    IFS="$lt_save_ifs"
+    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      echo="$dir/echo"
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+
+  if test "X$echo" = Xecho; then
+    # We didn't find a better echo, so look for alternatives.
+    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      # This shell has a builtin print -r that does the trick.
+      echo='print -r'
+    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+        test "X$CONFIG_SHELL" != X/bin/ksh; then
+      # If we have ksh, try running configure again with it.
+      ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+      export ORIGINAL_CONFIG_SHELL
+      CONFIG_SHELL=/bin/ksh
+      export CONFIG_SHELL
+      exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+    else
+      # Try using printf.
+      echo='printf %s\n'
+      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+        echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+        test "X$echo_testing_string" = "X$echo_test_string"; then
+       # Cool, printf works
+       :
+      elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+       export CONFIG_SHELL
+       SHELL="$CONFIG_SHELL"
+       export SHELL
+       echo="$CONFIG_SHELL $0 --fallback-echo"
+      elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       echo="$CONFIG_SHELL $0 --fallback-echo"
+      else
+       # maybe with a smaller string...
+       prev=:
+
+       for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+         if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+         then
+           break
+         fi
+         prev="$cmd"
+       done
+
+       if test "$prev" != 'sed 50q "$0"'; then
+         echo_test_string=`eval $prev`
+         export echo_test_string
+         exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+       else
+         # Oops.  We lost completely, so just stick with echo.
+         echo=echo
+       fi
+      fi
+    fi
+  fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+   ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+fi
+
+
+
+
+tagnames=${tagnames+${tagnames},}CXX
+
+tagnames=${tagnames+${tagnames},}F77
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='libltdl'
+PACKAGE_TARNAME='libltdl'
+PACKAGE_VERSION='1.2'
+PACKAGE_STRING='libltdl 1.2'
+PACKAGE_BUGREPORT='bug-libtool@gnu.org'
+
+ac_unique_file="ltdl.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+am__isrc
+CYGPATH_W
+PACKAGE
+VERSION
+ACLOCAL
+AUTOCONF
+AUTOMAKE
+AUTOHEADER
+MAKEINFO
+install_sh
+STRIP
+INSTALL_STRIP_PROGRAM
+mkdir_p
+AWK
+SET_MAKE
+am__leading_dot
+AMTAR
+am__tar
+am__untar
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+DEPDIR
+am__include
+am__quote
+AMDEP_TRUE
+AMDEP_FALSE
+AMDEPBACKSLASH
+CCDEPMODE
+am__fastdepCC_TRUE
+am__fastdepCC_FALSE
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+SED
+GREP
+EGREP
+LN_S
+ECHO
+AR
+RANLIB
+DLLTOOL
+AS
+OBJDUMP
+CPP
+CXX
+CXXFLAGS
+ac_ct_CXX
+CXXDEPMODE
+am__fastdepCXX_TRUE
+am__fastdepCXX_FALSE
+CXXCPP
+F77
+FFLAGS
+ac_ct_F77
+LIBTOOL
+LIBTOOL_DEPS
+INSTALL_LTDL_TRUE
+INSTALL_LTDL_FALSE
+CONVENIENCE_LTDL_TRUE
+CONVENIENCE_LTDL_FALSE
+LIBADD_DL
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+CXX
+CXXFLAGS
+CCC
+CXXCPP
+F77
+FFLAGS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)   ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+    eval enable_$ac_feature=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+    eval enable_$ac_feature=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+    eval with_$ac_package=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+    eval with_$ac_package=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
+               datadir sysconfdir sharedstatedir localstatedir includedir \
+               oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+               libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  { echo "$as_me: error: Working directory cannot be determined" >&2
+   { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  { echo "$as_me: error: pwd does not report name of working directory" >&2
+   { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$0" : 'X\(//\)[^/]' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+       cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+   { (exit 1); exit 1; }; }
+       pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures libltdl 1.2 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                         [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                         [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --datarootdir=DIR      read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR          read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR          info documentation [DATAROOTDIR/info]
+  --localedir=DIR        locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR           man documentation [DATAROOTDIR/man]
+  --docdir=DIR           documentation root [DATAROOTDIR/doc/libltdl]
+  --htmldir=DIR          html documentation [DOCDIR]
+  --dvidir=DIR           dvi documentation [DOCDIR]
+  --pdfdir=DIR           pdf documentation [DOCDIR]
+  --psdir=DIR            ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of libltdl 1.2:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors
+  --enable-shared[=PKGS]  build shared libraries [default=yes]
+  --enable-static[=PKGS]  build static libraries [default=yes]
+  --enable-fast-install[=PKGS]
+                          optimize for fast installation [default=yes]
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --enable-ltdl-install   install libltdl
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+  --with-pic              try to use only PIC/non-PIC objects [default=use
+                          both]
+  --with-tags[=TAGS]      include additional configurations [automatic]
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  CXXCPP      C++ preprocessor
+  F77         Fortran 77 compiler command
+  FFLAGS      Fortran 77 compiler flags
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <bug-libtool@gnu.org>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" || continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+libltdl configure 1.2
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by libltdl $as_me 1.2, which was
+generated by GNU Autoconf 2.61.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      ac_configure_args="$ac_configure_args '$ac_arg'"
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+       "s/'\''/'\''\\\\'\'''\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=\$$ac_var
+       case $ac_val in
+       *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+       esac
+       echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+  set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+  set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+  set x "$ac_default_prefix/share/config.site" \
+       "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+       { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+       { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+       ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+## ------------------------------- ##
+## Libltdl specific configuration. ##
+## ------------------------------- ##
+
+ac_aux_dir=
+for ac_dir in . "$srcdir"/.; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in . \"$srcdir\"/." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in . \"$srcdir\"/." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+
+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
+    { echo "$as_me:$LINENO: WARNING: *** The top-level configure must select either" >&5
+echo "$as_me: WARNING: *** The top-level configure must select either" >&2;}
+    { echo "$as_me:$LINENO: WARNING: *** A\"\"C_LIBLTDL_INSTALLABLE or A\"\"C_LIBLTDL_CONVENIENCE." >&5
+echo "$as_me: WARNING: *** A\"\"C_LIBLTDL_INSTALLABLE or A\"\"C_LIBLTDL_CONVENIENCE." >&2;}
+    { { echo "$as_me:$LINENO: error: *** Maybe you want to --enable-ltdl-install?" >&5
+echo "$as_me: error: *** Maybe you want to --enable-ltdl-install?" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+fi
+
+
+## ------------------------ ##
+## Automake Initialisation. ##
+## ------------------------ ##
+am__api_version='1.10'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+           break 3
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; }
+# 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".
+      { { echo "$as_me:$LINENO: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&2;}
+   { (exit 1); exit 1; }; }
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.  echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm -f conftest.sed
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+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=
+  { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+{ echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5
+echo $ECHO_N "checking for a thread-safe mkdir -p... $ECHO_C" >&6; }
+if test -z "$MKDIR_P"; then
+  if test "${ac_cv_path_mkdir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in mkdir gmkdir; do
+        for ac_exec_ext in '' $ac_executable_extensions; do
+          { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+          case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+            'mkdir (GNU coreutils) '* | \
+            'mkdir (coreutils) '* | \
+            'mkdir (fileutils) '4.1*)
+              ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+              break 3;;
+          esac
+        done
+       done
+done
+IFS=$as_save_IFS
+
+fi
+
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    test -d ./--version && rmdir ./--version
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $MKDIR_P" >&5
+echo "${ECHO_T}$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+  [\\/$]* | ?:[\\/]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+       @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+  SET_MAKE=
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+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
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+   { (exit 1); exit 1; }; }
+  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
+
+
+# Define the identity of the package.
+ PACKAGE=libltdl
+ VERSION=1.2
+
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+
+# 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.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+ac_config_headers="$ac_config_headers config.h:config-h.in"
+
+
+
+## ------------------ ##
+## C compiler checks. ##
+## ------------------ ##
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort.  b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions.  Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+        if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+       then :; else
+          ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       fi
+       # We set ac_cv_exeext here because the later test for it is not
+       # safe: cross compilers may not add the suffix if given an `-o'
+       # argument, so we may need to know it at that point already.
+       # Even if this section looks crufty: it has the advantage of
+       # actually working.
+       break;;
+    * )
+       break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  xno)
+    { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+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.
+{ echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; }
+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
+
+
+{ echo "$as_me:$LINENO: result: $_am_result" >&5
+echo "${ECHO_T}$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+
+depcc="$CC"   am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  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_CC_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_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+
+{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
+if test "${ac_cv_c_const+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset cs;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *pcpcc;
+  char **ppc;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  pcpcc = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++pcpcc;
+  ppc = (char**) pcpcc;
+  pcpcc = (char const *const *) ppc;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+    if (s) return 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+    if (!foo) return 0;
+  }
+  return !cs[0] && !zero.x;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_const=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_c_const=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for inline" >&5
+echo $ECHO_N "checking for inline... $ECHO_C" >&6; }
+if test "${ac_cv_c_inline+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_inline=$ac_kw
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+echo "${ECHO_T}$ac_cv_c_inline" >&6; }
+
+
+case $ac_cv_c_inline in
+  inline | yes) ;;
+  *)
+    case $ac_cv_c_inline in
+      no) ac_val=;;
+      *) ac_val=$ac_cv_c_inline;;
+    esac
+    cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+    ;;
+esac
+
+
+
+## ----------------------- ##
+## Libtool initialisation. ##
+## ----------------------- ##
+
+
+# Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then
+  enableval=$enable_shared; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_shared=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_shared=yes
+fi
+
+
+# Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then
+  enableval=$enable_static; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_static=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_static=yes
+fi
+
+
+# Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+  enableval=$enable_fast_install; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_fast_install=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_fast_install=yes
+fi
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
+echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6; }
+if test "${lt_cv_path_SED+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if { test -f "$as_dir/$lt_ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$lt_ac_prog$ac_exec_ext"; }; then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f $lt_ac_sed && continue
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test $lt_ac_count -gt 10 && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test $lt_ac_count -gt $lt_ac_max; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+
+fi
+
+SED=$lt_cv_path_SED
+
+{ echo "$as_me:$LINENO: result: $SED" >&5
+echo "${ECHO_T}$SED" >&6; }
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in grep ggrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+    # Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_GREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in egrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+    # Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_EGREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+
+   fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; }
+else
+  { echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+       test "$with_gnu_ld" != no && break
+       ;;
+      *)
+       test "$with_gnu_ld" != yes && break
+       ;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  { echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+{ echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
+echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6; }
+if test "${lt_cv_ld_reload_flag+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
+echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
+echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; }
+if test "${lt_cv_path_NM+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+       # Check to see if the nm accepts a BSD-compat flag.
+       # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+       #   nm: unknown option "B" ignored
+       # Tru64's nm complains that /dev/null is an invalid object file
+       case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+       */dev/null* | *'Invalid file or object type'*)
+         lt_cv_path_NM="$tmp_nm -B"
+         break
+         ;;
+       *)
+         case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+         */dev/null*)
+           lt_cv_path_NM="$tmp_nm -p"
+           break
+           ;;
+         *)
+           lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+           continue # so that we can try to find one that supports BSD flags
+           ;;
+         esac
+         ;;
+       esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5
+echo "${ECHO_T}$lt_cv_path_NM" >&6; }
+NM="$lt_cv_path_NM"
+
+{ echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6; }
+fi
+
+{ echo "$as_me:$LINENO: checking how to recognize dependent libraries" >&5
+echo $ECHO_N "checking how to recognize dependent libraries... $ECHO_C" >&6; }
+if test "${lt_cv_deplibs_check_method+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[45]*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  if ( file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[3-9]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd* | netbsdelf*-gnu)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+nto-qnx*)
+  lt_cv_deplibs_check_method=unknown
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
+echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6; }
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+  enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *ELF-32*)
+      HPUX_IA64_MODE="32"
+      ;;
+    *ELF-64*)
+      HPUX_IA64_MODE="64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line 4531 "configure"' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+   if test "$lt_cv_prog_gnu_ld" = yes; then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -melf32bsmip"
+      ;;
+    *N32*)
+      LD="${LD-ld} -melf32bmipn32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -melf64bmip"
+      ;;
+    esac
+   else
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+   fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case `/usr/bin/file conftest.o` in
+    *32-bit*)
+      case $host in
+        x86_64-*kfreebsd*-gnu)
+          LD="${LD-ld} -m elf_i386_fbsd"
+          ;;
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_i386"
+          ;;
+        ppc64-*linux*|powerpc64-*linux*)
+          LD="${LD-ld} -m elf32ppclinux"
+          ;;
+        s390x-*linux*)
+          LD="${LD-ld} -m elf_s390"
+          ;;
+        sparc64-*linux*)
+          LD="${LD-ld} -m elf32_sparc"
+          ;;
+      esac
+      ;;
+    *64-bit*)
+      case $host in
+        x86_64-*kfreebsd*-gnu)
+          LD="${LD-ld} -m elf_x86_64_fbsd"
+          ;;
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        ppc*-*linux*|powerpc*-*linux*)
+          LD="${LD-ld} -m elf64ppc"
+          ;;
+        s390*-*linux*)
+          LD="${LD-ld} -m elf64_s390"
+          ;;
+        sparc*-*linux*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  { echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6; }
+if test "${lt_cv_cc_needs_belf+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  lt_cv_cc_needs_belf=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       lt_cv_cc_needs_belf=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6; }
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+sparc*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+      *)    LD="${LD-ld} -64" ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_DLLTOOL+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$DLLTOOL"; then
+  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+  { echo "$as_me:$LINENO: result: $DLLTOOL" >&5
+echo "${ECHO_T}$DLLTOOL" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+  ac_ct_DLLTOOL=$DLLTOOL
+  # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_DLLTOOL+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_DLLTOOL"; then
+  ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_DLLTOOL" >&5
+echo "${ECHO_T}$ac_ct_DLLTOOL" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_DLLTOOL" = x; then
+    DLLTOOL="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    DLLTOOL=$ac_ct_DLLTOOL
+  fi
+else
+  DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
+set dummy ${ac_tool_prefix}as; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AS+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AS"; then
+  ac_cv_prog_AS="$AS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AS="${ac_tool_prefix}as"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AS=$ac_cv_prog_AS
+if test -n "$AS"; then
+  { echo "$as_me:$LINENO: result: $AS" >&5
+echo "${ECHO_T}$AS" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AS"; then
+  ac_ct_AS=$AS
+  # Extract the first word of "as", so it can be a program name with args.
+set dummy as; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_AS+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_AS"; then
+  ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_AS="as"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AS=$ac_cv_prog_ac_ct_AS
+if test -n "$ac_ct_AS"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_AS" >&5
+echo "${ECHO_T}$ac_ct_AS" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_AS" = x; then
+    AS="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    AS=$ac_ct_AS
+  fi
+else
+  AS="$ac_cv_prog_AS"
+fi
+
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_OBJDUMP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$OBJDUMP"; then
+  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+  { echo "$as_me:$LINENO: result: $OBJDUMP" >&5
+echo "${ECHO_T}$OBJDUMP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+  ac_ct_OBJDUMP=$OBJDUMP
+  # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_OBJDUMP"; then
+  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OBJDUMP="objdump"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_OBJDUMP" >&5
+echo "${ECHO_T}$ac_ct_OBJDUMP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJDUMP" = x; then
+    OBJDUMP="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJDUMP=$ac_ct_OBJDUMP
+  fi
+else
+  OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+  ;;
+
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in dlfcn.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ---------------------------------- ##
+## Report this to bug-libtool@gnu.org ##
+## ---------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cxx_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       CXXFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+        CXXFLAGS="-g"
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cxx_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+depcc="$CXX"  am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  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_CXX_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_CXX_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+  am__fastdepCXX_TRUE=
+  am__fastdepCXX_FALSE='#'
+else
+  am__fastdepCXX_TRUE='#'
+  am__fastdepCXX_FALSE=
+fi
+
+
+
+
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+    (test "X$CXX" != "Xg++"))) ; then
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; }
+if test -z "$CXXCPP"; then
+  if test "${ac_cv_prog_CXXCPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CXXCPP needs to be expanded
+    for CXXCPP in "$CXX -E" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+  CXXCPP=$ac_cv_prog_CXXCPP
+else
+  ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ echo "$as_me:$LINENO: result: $CXXCPP" >&5
+echo "${ECHO_T}$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+fi
+
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_F77+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$F77"; then
+  ac_cv_prog_F77="$F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_F77="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+F77=$ac_cv_prog_F77
+if test -n "$F77"; then
+  { echo "$as_me:$LINENO: result: $F77" >&5
+echo "${ECHO_T}$F77" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$F77" && break
+  done
+fi
+if test -z "$F77"; then
+  ac_ct_F77=$F77
+  for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_F77+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_F77"; then
+  ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_F77="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_F77=$ac_cv_prog_ac_ct_F77
+if test -n "$ac_ct_F77"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_F77" >&5
+echo "${ECHO_T}$ac_ct_F77" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_F77" && break
+done
+
+  if test "x$ac_ct_F77" = x; then
+    F77=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    F77=$ac_ct_F77
+  fi
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+rm -f a.out
+
+# If we don't use `.F' as extension, the preprocessor is not run on the
+# input file.  (Note that this only needs to work for GNU compilers.)
+ac_save_ext=$ac_ext
+ac_ext=F
+{ echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6; }
+if test "${ac_cv_f77_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+      program main
+#ifndef __GNUC__
+       choke me
+#endif
+
+      end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_f77_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_f77_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6; }
+ac_ext=$ac_save_ext
+ac_test_FFLAGS=${FFLAGS+set}
+ac_save_FFLAGS=$FFLAGS
+FFLAGS=
+{ echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5
+echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_f77_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  FFLAGS=-g
+cat >conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_f77_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_f77_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_prog_f77_g=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5
+echo "${ECHO_T}$ac_cv_prog_f77_g" >&6; }
+if test "$ac_test_FFLAGS" = set; then
+  FFLAGS=$ac_save_FFLAGS
+elif test $ac_cv_prog_f77_g = yes; then
+  if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+    FFLAGS="-g -O2"
+  else
+    FFLAGS="-g"
+  fi
+else
+  if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+    FFLAGS="-O2"
+  else
+    FFLAGS=
+  fi
+fi
+
+G77=`test $ac_compiler_gnu = yes && echo yes`
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+
+# find the maximum length of command line arguments
+{ echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5
+echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6; }
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+    i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536      # usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[        ]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \
+              = "XX$teststring") >/dev/null 2>&1 &&
+             new_result=`expr "X$teststring" : ".*" 2>&1` &&
+             lt_cv_sys_max_cmd_len=$new_result &&
+             test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on massive
+      # amounts of additional arguments before passing them to the linker.
+      # It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+  { echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5
+echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6; }
+else
+  { echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6; }
+fi
+
+
+
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5
+echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; }
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*) # Its linker distinguishes data from code symbols
+  if test "$host_cpu" = ia64; then
+    symcode='[ABCDEGRST]'
+  fi
+  lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+  lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  ;;
+linux* | k*bsd*-gnu)
+  if test "$host_cpu" = ia64; then
+    symcode='[ABCDGIRSTW]'
+    lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+    lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+osf*)
+  symcode='[BCDEGQRST]'
+  ;;
+solaris*)
+  symcode='[BDRT]'
+  ;;
+sco3.2v5*)
+  symcode='[DT]'
+  ;;
+sysv4.2uw2*)
+  symcode='[DT]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[ABDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[      ]\($symcode$symcode*\)[         ][      ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5
+  (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if grep ' nm_test_var$' "$nlist" >/dev/null; then
+       if grep ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+         # Now generate the symbol file.
+         eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+         cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+         $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+         cat <<\EOF >> conftest.$ac_ext
+  {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftstm.$ac_objext
+         lt_save_LIBS="$LIBS"
+         lt_save_CFLAGS="$CFLAGS"
+         LIBS="conftstm.$ac_objext"
+         CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+         if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest${ac_exeext}; then
+           pipe_works=yes
+         fi
+         LIBS="$lt_save_LIBS"
+         CFLAGS="$lt_save_CFLAGS"
+       else
+         echo "cannot find nm_test_func in $nlist" >&5
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -f conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  { echo "$as_me:$LINENO: result: failed" >&5
+echo "${ECHO_T}failed" >&6; }
+else
+  { echo "$as_me:$LINENO: result: ok" >&5
+echo "${ECHO_T}ok" >&6; }
+fi
+
+{ echo "$as_me:$LINENO: checking for objdir" >&5
+echo $ECHO_N "checking for objdir... $ECHO_C" >&6; }
+if test "${lt_cv_objdir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5
+echo "${ECHO_T}$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AR+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AR="${ac_tool_prefix}ar"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+  ac_ct_AR=$AR
+  # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_AR="ar"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+echo "${ECHO_T}$ac_ct_AR" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+else
+  AR="$ac_cv_prog_AR"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    { echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
+echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/${ac_tool_prefix}file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    { echo "$as_me:$LINENO: checking for file" >&5
+echo $ECHO_N "checking for file... $ECHO_C" >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+enable_dlopen=no
+enable_win32_dll=yes
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+  enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then
+  withval=$with_pic; pic_mode="$withval"
+else
+  pic_mode=default
+fi
+
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+  lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+  ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:7567: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:7571: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl='-Wl,'
+    lt_prog_compiler_static='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared=no
+      enable_shared=no
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       lt_prog_compiler_pic=-Kconform_pic
+      fi
+      ;;
+
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic='-fPIC'
+       ;;
+      esac
+      ;;
+
+    *)
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl='-Wl,'
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static='-Bstatic'
+      else
+       lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+      darwin*)
+        # PIC is the default on this platform
+        # Common symbols not allowed in MH_DYLIB files
+       case $cc_basename in
+         xlc*)
+         lt_prog_compiler_pic='-qnocommon'
+         lt_prog_compiler_wl='-Wl,'
+         ;;
+       esac
+       ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    linux* | k*bsd*-gnu)
+      case $cc_basename in
+      icc* | ecc*)
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='-KPIC'
+       lt_prog_compiler_static='-static'
+        ;;
+      pgcc* | pgf77* | pgf90* | pgf95*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+       # which looks to be a dead project)
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='-fpic'
+       lt_prog_compiler_static='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static='-non_shared'
+        ;;
+      *)
+        case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)
+         # Sun C 5.9
+         lt_prog_compiler_pic='-KPIC'
+         lt_prog_compiler_static='-Bstatic'
+         lt_prog_compiler_wl='-Wl,'
+         ;;
+       *Sun\ F*)
+         # Sun Fortran 8.3 passes all unrecognized flags to the linker
+         lt_prog_compiler_pic='-KPIC'
+         lt_prog_compiler_static='-Bstatic'
+         lt_prog_compiler_wl=''
+         ;;
+       esac
+       ;;
+      esac
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+       lt_prog_compiler_wl='-Qoption ld ';;
+      *)
+       lt_prog_compiler_wl='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl='-Qoption ld '
+      lt_prog_compiler_pic='-PIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       lt_prog_compiler_pic='-Kconform_pic'
+       lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_can_build_shared=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic='-pic'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared=no
+      ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_pic_works=no
+  ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:7857: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:7861: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_prog_compiler_pic_works=yes
+     fi
+   fi
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_prog_compiler_pic_works" = xyes; then
+    case $lt_prog_compiler_pic in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+     esac
+else
+    lt_prog_compiler_pic=
+     lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic=
+    ;;
+  *)
+    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+    ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_static_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_static_works=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_prog_compiler_static_works=yes
+       fi
+     else
+       lt_prog_compiler_static_works=yes
+     fi
+   fi
+   $rm conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works" >&6; }
+
+if test x"$lt_prog_compiler_static_works" = xyes; then
+    :
+else
+    lt_prog_compiler_static=
+fi
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $rm -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:7961: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:7965: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $rm conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+   $rm out/* && rmdir out
+   cd ..
+   rmdir conftest
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+  runpath_var=
+  allow_undefined_flag=
+  enable_shared_with_static_runtimes=no
+  archive_cmds=
+  archive_expsym_cmds=
+  old_archive_From_new_cmds=
+  old_archive_from_expsyms_cmds=
+  export_dynamic_flag_spec=
+  whole_archive_flag_spec=
+  thread_safe_flag_spec=
+  hardcode_libdir_flag_spec=
+  hardcode_libdir_flag_spec_ld=
+  hardcode_libdir_separator=
+  hardcode_direct=no
+  hardcode_minus_L=no
+  hardcode_shlibpath_var=unsupported
+  link_all_deplibs=unknown
+  hardcode_automatic=no
+  module_cmds=
+  module_expsym_cmds=
+  always_export_symbols=no
+  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  extract_expsyms_cmds=
+  # Just being paranoid about ensuring that cc_basename is set.
+  for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+  case $host_os in
+  cygwin* | mingw* | pw32*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  ld_shlibs=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+       whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+       whole_archive_flag_spec=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>/dev/null` in
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+       ld_shlibs=no
+       cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+      fi
+      ;;
+
+    amigaos*)
+      archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+
+      # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+      # that the semantics of dynamic libraries on AmigaOS, at least up
+      # to version 4, is to share data among multiple programs linked
+      # with the same dynamic library.  Since this doesn't match the
+      # behavior of shared libraries on other platforms, we can't use
+      # them.
+      ld_shlibs=no
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       allow_undefined_flag=unsupported
+       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      allow_undefined_flag=unsupported
+      always_export_symbols=no
+      enable_shared_with_static_runtimes=yes
+      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       # If the export-symbols file already is a .def file (1st line
+       # is EXPORTS), use it as is; otherwise, prepend...
+       archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+         cp $export_symbols $output_objdir/$soname.def;
+       else
+         echo EXPORTS > $output_objdir/$soname.def;
+         cat $export_symbols >> $output_objdir/$soname.def;
+       fi~
+       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | k*bsd*-gnu)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       tmp_addflag=
+       case $cc_basename,$host_cpu in
+       pgcc*)                          # Portland Group C compiler
+         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
+         ;;
+       pgf77* | pgf90* | pgf95*)       # Portland Group f77 and f90 compilers
+         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
+       ecc*,ia64* | icc*,ia64*)                # Intel C compiler on ia64
+         tmp_addflag=' -i_dynamic' ;;
+       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
+         tmp_addflag=' -i_dynamic -nofor_main' ;;
+       ifc* | ifort*)                  # Intel Fortran compiler
+         tmp_addflag=' -nofor_main' ;;
+       esac
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)                       # Sun C 5.9
+         whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_sharedflag='-G' ;;
+       *Sun\ F*)                       # Sun Fortran 8.3
+         tmp_sharedflag='-G' ;;
+       *)
+         tmp_sharedflag='-shared' ;;
+       esac
+       archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+       if test $supports_anon_versioning = yes; then
+         archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~
+  cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+  $echo "local: *; };" >> $output_objdir/$libname.ver~
+         $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+       fi
+       link_all_deplibs=no
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+       ld_shlibs=no
+       cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+      elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+       ld_shlibs=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+       ;;
+       *)
+         if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+           hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+           archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+           archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+         else
+           ld_shlibs=no
+         fi
+       ;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec=
+      export_dynamic_flag_spec=
+      whole_archive_flag_spec=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag=unsupported
+      always_export_symbols=yes
+      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       hardcode_direct=unsupported
+      fi
+      ;;
+
+    aix4* | aix5*)
+      if test "$host_cpu" = ia64; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=""
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to AIX nm, but means don't demangle with GNU nm
+       if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+         export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+       else
+         export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # need to do runtime linking.
+       case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+         for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+         ;;
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds=''
+      hardcode_direct=yes
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+
+      if test "$GCC" = yes; then
+       case $host_os in aix4.[012]|aix4.[012].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         :
+         else
+         # We have old collect2
+         hardcode_direct=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         hardcode_minus_L=yes
+         hardcode_libdir_flag_spec='-L$libdir'
+         hardcode_libdir_separator=
+         fi
+         ;;
+       esac
+       shared_flag='-shared'
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag="$shared_flag "'${wl}-G'
+       fi
+      else
+       # not using gcc
+       if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag='${wl}-G'
+         else
+           shared_flag='${wl}-bM:SRE'
+         fi
+       fi
+      fi
+
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols=yes
+      if test "$aix_use_runtimelinking" = yes; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       allow_undefined_flag='-berok'
+       # Determine the default libpath from the value encoded in an empty executable.
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+       hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+       archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+       else
+       if test "$host_cpu" = ia64; then
+         hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+         allow_undefined_flag="-z nodefs"
+         archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an empty executable.
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         no_undefined_flag=' ${wl}-bernotok'
+         allow_undefined_flag=' ${wl}-berok'
+         # Exported symbols can be pulled into shared objects from archives
+         whole_archive_flag_spec='$convenience'
+         archive_cmds_need_lc=yes
+         # This is similar to how AIX traditionally builds its shared libraries.
+         archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      # see comment about different semantics on the GNU ld section
+      ld_shlibs=no
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec=' '
+      allow_undefined_flag=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      old_archive_From_new_cmds='true'
+      # FIXME: Should let the user specify the lib program.
+      old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path='`cygpath -w "$srcfile"`'
+      enable_shared_with_static_runtimes=yes
+      ;;
+
+    darwin* | rhapsody*)
+      case $host_os in
+        rhapsody* | darwin1.[012])
+         allow_undefined_flag='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[012])
+               allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+      esac
+      archive_cmds_need_lc=no
+      hardcode_direct=no
+      hardcode_automatic=yes
+      hardcode_shlibpath_var=unsupported
+      whole_archive_flag_spec=''
+      link_all_deplibs=yes
+    if test "$GCC" = yes ; then
+       output_verbose_link_cmd='echo'
+        archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+      archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      module_expsym_cmds='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    else
+      case $cc_basename in
+        xlc*)
+         output_verbose_link_cmd='echo'
+         archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+         module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+         archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          module_expsym_cmds='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         ld_shlibs=no
+          ;;
+      esac
+    fi
+      ;;
+
+    dgux*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    freebsd1*)
+      ld_shlibs=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+       archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+       archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L=yes
+      export_dynamic_flag_spec='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator=:
+
+       hardcode_direct=yes
+       export_dynamic_flag_spec='${wl}-E'
+
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       hardcode_minus_L=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator=:
+
+       case $host_cpu in
+       hppa*64*|ia64*)
+         hardcode_libdir_flag_spec_ld='+b $libdir'
+         hardcode_direct=no
+         hardcode_shlibpath_var=no
+         ;;
+       *)
+         hardcode_direct=yes
+         export_dynamic_flag_spec='${wl}-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         hardcode_minus_L=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+       archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec_ld='-rpath $libdir'
+      fi
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      link_all_deplibs=yes
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    newsos6)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_shlibpath_var=no
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+       hardcode_direct=yes
+       hardcode_shlibpath_var=no
+       if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+         archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+         hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+         export_dynamic_flag_spec='${wl}-E'
+       else
+         case $host_os in
+          openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+            archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+            hardcode_libdir_flag_spec='-R$libdir'
+            ;;
+          *)
+            archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+            hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+            ;;
+         esac
+        fi
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+       allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       allow_undefined_flag=' -expect_unresolved \*'
+       archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+       allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      else
+       allow_undefined_flag=' -expect_unresolved \*'
+       archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+       $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      hardcode_libdir_separator=:
+      ;;
+
+    solaris*)
+      no_undefined_flag=' -z text'
+      if test "$GCC" = yes; then
+       wlarc='${wl}'
+       archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+         $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+      else
+       wlarc=''
+       archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_shlibpath_var=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+       # The compiler driver will combine and reorder linker options,
+       # but understands `-z linker_flag'.  GCC discards it without `$wl',
+       # but is careful enough not to reorder.
+       # Supported since Solaris 2.6 (maybe 2.5.1?)
+       if test "$GCC" = yes; then
+         whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+       else
+         whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+       fi
+       ;;
+      esac
+      link_all_deplibs=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         reload_cmds='$CC -r -o $output$reload_objs'
+         hardcode_direct=no
+        ;;
+       motorola)
+         archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      export_dynamic_flag_spec='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       hardcode_shlibpath_var=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       ld_shlibs=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag='${wl}-z,text'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag='${wl}-z,text'
+      allow_undefined_flag='${wl}-z,nodefs'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      export_dynamic_flag_spec='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      ld_shlibs=no
+      ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs" >&5
+echo "${ECHO_T}$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+      $rm conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$lt_prog_compiler_wl
+       pic_flag=$lt_prog_compiler_pic
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$allow_undefined_flag
+        allow_undefined_flag=
+        if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+  (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+        then
+         archive_cmds_need_lc=no
+        else
+         archive_cmds_need_lc=yes
+        fi
+        allow_undefined_flag=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $rm conftest*
+      { echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5
+echo "${ECHO_T}$archive_cmds_need_lc" >&6; }
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+  if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'`
+  else
+    lt_search_path_spec=`echo "$lt_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+  fi
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[lt_foo]++; }
+  if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+  sys_lib_search_path_spec=`echo $lt_search_path_spec`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+   hppa*64*)
+     shrext_cmds='.sl'
+     hardcode_into_libs=yes
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+     library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[     ]*hwcap[        ]/d;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+nto-qnx*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+    shlibpath_overrides_runpath=no
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    shlibpath_overrides_runpath=yes
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+   test -n "$runpath_var" || \
+   test "X$hardcode_automatic" = "Xyes" ; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action" >&5
+echo "${ECHO_T}$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+striplib=
+old_striplib=
+{ echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+   darwin*)
+       if test -n "$STRIP" ; then
+         striplib="$STRIP -x"
+         old_striplib="$STRIP -S"
+         { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+       else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+       ;;
+   *)
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+    ;;
+  esac
+fi
+
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+   ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+   ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dl_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+
+fi
+
+   ;;
+
+  *)
+    { echo "$as_me:$LINENO: checking for shl_load" >&5
+echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; }
+if test "${ac_cv_func_shl_load+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define shl_load innocuous_shl_load
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char shl_load (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef shl_load
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_shl_load || defined __stub___shl_load
+choke me
+#endif
+
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_shl_load=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_func_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+echo "${ECHO_T}$ac_cv_func_shl_load" >&6; }
+if test $ac_cv_func_shl_load = yes; then
+  lt_cv_dlopen="shl_load"
+else
+  { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dld_shl_load=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_dld_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; }
+if test $ac_cv_lib_dld_shl_load = yes; then
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
+else
+  { echo "$as_me:$LINENO: checking for dlopen" >&5
+echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; }
+if test "${ac_cv_func_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define dlopen innocuous_dlopen
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char dlopen (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef dlopen
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_dlopen || defined __stub___dlopen
+choke me
+#endif
+
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_func_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
+echo "${ECHO_T}$ac_cv_func_dlopen" >&6; }
+if test $ac_cv_func_dlopen = yes; then
+  lt_cv_dlopen="dlopen"
+else
+  { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dl_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_svld_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_svld_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; }
+if test $ac_cv_lib_svld_dlopen = yes; then
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+  { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dld_dld_link=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_dld_dld_link=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; }
+if test $ac_cv_lib_dld_dld_link = yes; then
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
+echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; }
+if test "${lt_cv_dlopen_self+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+         if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+#line 10323 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+    exit (status);
+}
+EOF
+  if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self" >&6; }
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
+echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; }
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+         if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self_static=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+#line 10423 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+    exit (status);
+}
+EOF
+  if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; }
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+# Report which library types will actually be built
+{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; }
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+
+aix4* | aix5*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
+    ;;
+esac
+{ echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; }
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+{ echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6; }
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    old_postinstall_cmds old_postuninstall_cmds \
+    compiler \
+    CC \
+    LD \
+    lt_prog_compiler_wl \
+    lt_prog_compiler_pic \
+    lt_prog_compiler_static \
+    lt_prog_compiler_no_builtin_flag \
+    export_dynamic_flag_spec \
+    thread_safe_flag_spec \
+    whole_archive_flag_spec \
+    enable_shared_with_static_runtimes \
+    old_archive_cmds \
+    old_archive_from_new_cmds \
+    predep_objects \
+    postdep_objects \
+    predeps \
+    postdeps \
+    compiler_lib_search_path \
+    archive_cmds \
+    archive_expsym_cmds \
+    postinstall_cmds \
+    postuninstall_cmds \
+    old_archive_from_expsyms_cmds \
+    allow_undefined_flag \
+    no_undefined_flag \
+    export_symbols_cmds \
+    hardcode_libdir_flag_spec \
+    hardcode_libdir_flag_spec_ld \
+    hardcode_libdir_separator \
+    hardcode_automatic \
+    module_cmds \
+    module_expsym_cmds \
+    lt_cv_prog_compiler_c_o \
+    fix_srcfile_path \
+    exclude_expsyms \
+    include_expsyms; do
+
+    case $var in
+    old_archive_cmds | \
+    old_archive_from_new_cmds | \
+    archive_cmds | \
+    archive_expsym_cmds | \
+    module_cmds | \
+    module_expsym_cmds | \
+    old_archive_from_expsyms_cmds | \
+    export_symbols_cmds | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case $lt_echo in
+  *'\$0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+    ;;
+  esac
+
+cfgfile="${ofile}T"
+  trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+  $rm -f "$cfgfile"
+  { echo "$as_me:$LINENO: creating $ofile" >&5
+echo "$as_me: creating $ofile" >&6;}
+
+  cat <<__EOF__ >> "$cfgfile"
+#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 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 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.
+#
+# 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.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e 1s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# ### END LIBTOOL CONFIG
+
+__EOF__
+
+
+  case $host_os in
+  aix3*)
+    cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+EOF
+    ;;
+  esac
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" || \
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+# Check whether --with-tags was given.
+if test "${with_tags+set}" = set; then
+  withval=$with_tags; tagnames="$withval"
+fi
+
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+  if test ! -f "${ofile}"; then
+    { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;}
+  fi
+
+  if test -z "$LTCC"; then
+    eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+    if test -z "$LTCC"; then
+      { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;}
+    else
+      { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5
+echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;}
+    fi
+  fi
+  if test -z "$LTCFLAGS"; then
+    eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
+  fi
+
+  # Extract list of available tagged configurations in $ofile.
+  # Note that this assumes the entire list is on one line.
+  available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+  lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+  for tagname in $tagnames; do
+    IFS="$lt_save_ifs"
+    # Check whether tagname contains only valid characters
+    case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in
+    "") ;;
+    *)  { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5
+echo "$as_me: error: invalid tag name: $tagname" >&2;}
+   { (exit 1); exit 1; }; }
+       ;;
+    esac
+
+    if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+    then
+      { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5
+echo "$as_me: error: tag name \"$tagname\" already exists" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+    # Update the list of available tags.
+    if test -n "$tagname"; then
+      echo appending configuration tag \"$tagname\" to $ofile
+
+      case $tagname in
+      CXX)
+       if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+           ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+           (test "X$CXX" != "Xg++"))) ; then
+         ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+
+archive_cmds_need_lc_CXX=no
+allow_undefined_flag_CXX=
+always_export_symbols_CXX=no
+archive_expsym_cmds_CXX=
+export_dynamic_flag_spec_CXX=
+hardcode_direct_CXX=no
+hardcode_libdir_flag_spec_CXX=
+hardcode_libdir_flag_spec_ld_CXX=
+hardcode_libdir_separator_CXX=
+hardcode_minus_L_CXX=no
+hardcode_shlibpath_var_CXX=unsupported
+hardcode_automatic_CXX=no
+module_cmds_CXX=
+module_expsym_cmds_CXX=
+link_all_deplibs_CXX=unknown
+old_archive_cmds_CXX=$old_archive_cmds
+no_undefined_flag_CXX=
+whole_archive_flag_spec_CXX=
+enable_shared_with_static_runtimes_CXX=no
+
+# Dependencies to place before and after the object being linked:
+predep_objects_CXX=
+postdep_objects_CXX=
+predeps_CXX=
+postdeps_CXX=
+compiler_lib_search_path_CXX=
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+objext_CXX=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[]) { return(0); }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+  lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+  $as_unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+  lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+  $as_unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+compiler_CXX=$CC
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+  lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+else
+  lt_prog_compiler_no_builtin_flag_CXX=
+fi
+
+if test "$GXX" = yes; then
+  # Set up default GNU C++ configuration
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; }
+else
+  { echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+       test "$with_gnu_ld" != no && break
+       ;;
+      *)
+       test "$with_gnu_ld" != yes && break
+       ;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  { echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+  # Check if GNU C++ uses GNU ld as the underlying linker, since the
+  # archiving commands below assume that GNU ld is being used.
+  if test "$with_gnu_ld" = yes; then
+    archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+    hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+    #     investigate it a little bit more. (MM)
+    wlarc='${wl}'
+
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+       grep 'no-whole-archive' > /dev/null; then
+      whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      whole_archive_flag_spec_CXX=
+    fi
+  else
+    with_gnu_ld=no
+    wlarc=
+
+    # A generic and very simple default shared library creation
+    # command for GNU C++ for the case where it uses the native
+    # linker, instead of GNU ld.  If possible, this setting should
+    # overridden to take advantage of the native linker features on
+    # the platform it is being used on.
+    archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+  fi
+
+  # Commands to make compiler produce verbose output that lists
+  # what "hidden" libraries, object files and flags are used when
+  # linking a shared library.
+  output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+  GXX=no
+  with_gnu_ld=no
+  wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+ld_shlibs_CXX=yes
+case $host_os in
+  aix3*)
+    # FIXME: insert proper C++ library support
+    ld_shlibs_CXX=no
+    ;;
+  aix4* | aix5*)
+    if test "$host_cpu" = ia64; then
+      # On IA64, the linker does run time linking by default, so we don't
+      # have to do anything special.
+      aix_use_runtimelinking=no
+      exp_sym_flag='-Bexport'
+      no_entry_flag=""
+    else
+      aix_use_runtimelinking=no
+
+      # Test if we are trying to use run time linking or normal
+      # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+      # need to do runtime linking.
+      case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+       for ld_flag in $LDFLAGS; do
+         case $ld_flag in
+         *-brtl*)
+           aix_use_runtimelinking=yes
+           break
+           ;;
+         esac
+       done
+       ;;
+      esac
+
+      exp_sym_flag='-bexport'
+      no_entry_flag='-bnoentry'
+    fi
+
+    # When large executables or shared objects are built, AIX ld can
+    # have problems creating the table of contents.  If linking a library
+    # or program results in "error TOC overflow" add -mminimal-toc to
+    # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+    # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+    archive_cmds_CXX=''
+    hardcode_direct_CXX=yes
+    hardcode_libdir_separator_CXX=':'
+    link_all_deplibs_CXX=yes
+
+    if test "$GXX" = yes; then
+      case $host_os in aix4.[012]|aix4.[012].*)
+      # We only want to do this on AIX 4.2 and lower, the check
+      # below for broken collect2 doesn't work under 4.3+
+       collect2name=`${CC} -print-prog-name=collect2`
+       if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+       then
+         # We have reworked collect2
+         :
+       else
+         # We have old collect2
+         hardcode_direct_CXX=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         hardcode_minus_L_CXX=yes
+         hardcode_libdir_flag_spec_CXX='-L$libdir'
+         hardcode_libdir_separator_CXX=
+       fi
+       ;;
+      esac
+      shared_flag='-shared'
+      if test "$aix_use_runtimelinking" = yes; then
+       shared_flag="$shared_flag "'${wl}-G'
+      fi
+    else
+      # not using gcc
+      if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+       shared_flag='-G'
+      else
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag='${wl}-G'
+       else
+         shared_flag='${wl}-bM:SRE'
+       fi
+      fi
+    fi
+
+    # It seems that -bexpall does not export symbols beginning with
+    # underscore (_), so it is better to generate a list of symbols to export.
+    always_export_symbols_CXX=yes
+    if test "$aix_use_runtimelinking" = yes; then
+      # Warning - without using the other runtime loading flags (-brtl),
+      # -berok will link without error, but may produce a broken library.
+      allow_undefined_flag_CXX='-berok'
+      # Determine the default libpath from the value encoded in an empty executable.
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+      hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+      archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+     else
+      if test "$host_cpu" = ia64; then
+       hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib'
+       allow_undefined_flag_CXX="-z nodefs"
+       archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+      else
+       # Determine the default libpath from the value encoded in an empty executable.
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+       hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+       # Warning - without using the other run time loading flags,
+       # -berok will link without error, but may produce a broken library.
+       no_undefined_flag_CXX=' ${wl}-bernotok'
+       allow_undefined_flag_CXX=' ${wl}-berok'
+       # Exported symbols can be pulled into shared objects from archives
+       whole_archive_flag_spec_CXX='$convenience'
+       archive_cmds_need_lc_CXX=yes
+       # This is similar to how AIX traditionally builds its shared libraries.
+       archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+      fi
+    fi
+    ;;
+
+  beos*)
+    if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+      allow_undefined_flag_CXX=unsupported
+      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+      # support --undefined.  This deserves some investigation.  FIXME
+      archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    else
+      ld_shlibs_CXX=no
+    fi
+    ;;
+
+  chorus*)
+    case $cc_basename in
+      *)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+    esac
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
+    # as there is no search path for DLLs.
+    hardcode_libdir_flag_spec_CXX='-L$libdir'
+    allow_undefined_flag_CXX=unsupported
+    always_export_symbols_CXX=no
+    enable_shared_with_static_runtimes_CXX=yes
+
+    if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+      archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      # If the export-symbols file already is a .def file (1st line
+      # is EXPORTS), use it as is; otherwise, prepend...
+      archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+       cp $export_symbols $output_objdir/$soname.def;
+      else
+       echo EXPORTS > $output_objdir/$soname.def;
+       cat $export_symbols >> $output_objdir/$soname.def;
+      fi~
+      $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+    else
+      ld_shlibs_CXX=no
+    fi
+  ;;
+      darwin* | rhapsody*)
+        case $host_os in
+        rhapsody* | darwin1.[012])
+         allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[012])
+               allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+        esac
+      archive_cmds_need_lc_CXX=no
+      hardcode_direct_CXX=no
+      hardcode_automatic_CXX=yes
+      hardcode_shlibpath_var_CXX=unsupported
+      whole_archive_flag_spec_CXX=''
+      link_all_deplibs_CXX=yes
+
+    if test "$GXX" = yes ; then
+      lt_int_apple_cc_single_mod=no
+      output_verbose_link_cmd='echo'
+      if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+       lt_int_apple_cc_single_mod=yes
+      fi
+      if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+       archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      else
+          archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+        fi
+        module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+        # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+          if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+            archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          else
+            archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          fi
+            module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      else
+      case $cc_basename in
+        xlc*)
+         output_verbose_link_cmd='echo'
+          archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+          module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+          archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         ld_shlibs_CXX=no
+          ;;
+      esac
+      fi
+        ;;
+
+  dgux*)
+    case $cc_basename in
+      ec++*)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      ghcx*)
+       # Green Hills C++ Compiler
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+    esac
+    ;;
+  freebsd[12]*)
+    # C++ shared libraries reported to be fairly broken before switch to ELF
+    ld_shlibs_CXX=no
+    ;;
+  freebsd-elf*)
+    archive_cmds_need_lc_CXX=no
+    ;;
+  freebsd* | dragonfly*)
+    # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+    # conventions
+    ld_shlibs_CXX=yes
+    ;;
+  gnu*)
+    ;;
+  hpux9*)
+    hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+    hardcode_libdir_separator_CXX=:
+    export_dynamic_flag_spec_CXX='${wl}-E'
+    hardcode_direct_CXX=yes
+    hardcode_minus_L_CXX=yes # Not in the search PATH,
+                               # but as the default
+                               # location of the library.
+
+    case $cc_basename in
+    CC*)
+      # FIXME: insert proper C++ library support
+      ld_shlibs_CXX=no
+      ;;
+    aCC*)
+      archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      #
+      # There doesn't appear to be a way to prevent this compiler from
+      # explicitly linking system object files so we need to strip them
+      # from the output so that they don't get included in the library
+      # dependencies.
+      output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+      ;;
+    *)
+      if test "$GXX" = yes; then
+        archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+        # FIXME: insert proper C++ library support
+        ld_shlibs_CXX=no
+      fi
+      ;;
+    esac
+    ;;
+  hpux10*|hpux11*)
+    if test $with_gnu_ld = no; then
+      hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator_CXX=:
+
+      case $host_cpu in
+      hppa*64*|ia64*) ;;
+      *)
+       export_dynamic_flag_spec_CXX='${wl}-E'
+        ;;
+      esac
+    fi
+    case $host_cpu in
+    hppa*64*|ia64*)
+      hardcode_direct_CXX=no
+      hardcode_shlibpath_var_CXX=no
+      ;;
+    *)
+      hardcode_direct_CXX=yes
+      hardcode_minus_L_CXX=yes # Not in the search PATH,
+                                             # but as the default
+                                             # location of the library.
+      ;;
+    esac
+
+    case $cc_basename in
+      CC*)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      aCC*)
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         ;;
+       *)
+         archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         ;;
+       esac
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes; then
+         if test $with_gnu_ld = no; then
+           case $host_cpu in
+           hppa*64*)
+             archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             ;;
+           ia64*)
+             archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             ;;
+           *)
+             archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             ;;
+           esac
+         fi
+       else
+         # FIXME: insert proper C++ library support
+         ld_shlibs_CXX=no
+       fi
+       ;;
+    esac
+    ;;
+  interix[3-9]*)
+    hardcode_direct_CXX=no
+    hardcode_shlibpath_var_CXX=no
+    hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+    export_dynamic_flag_spec_CXX='${wl}-E'
+    # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+    # Instead, shared libraries are loaded at an image base (0x10000000 by
+    # default) and relocated if they conflict, which is a slow very memory
+    # consuming and fragmenting process.  To avoid this, we pick a random,
+    # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+    # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+    archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+    archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+    ;;
+  irix5* | irix6*)
+    case $cc_basename in
+      CC*)
+       # SGI C++
+       archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+       # Archives containing C++ object files must be created using
+       # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+       # necessary to make sure instantiated templates are included
+       # in the archive.
+       old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
+       ;;
+      *)
+       if test "$GXX" = yes; then
+         if test "$with_gnu_ld" = no; then
+           archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+         else
+           archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+         fi
+       fi
+       link_all_deplibs_CXX=yes
+       ;;
+    esac
+    hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator_CXX=:
+    ;;
+  linux* | k*bsd*-gnu)
+    case $cc_basename in
+      KCC*)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+       archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+       hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir'
+       export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+       # Archives containing C++ object files must be created using
+       # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+       old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+       ;;
+      icpc*)
+       # Intel C++
+       with_gnu_ld=yes
+       # version 8.0 and above of icpc choke on multiply defined symbols
+       # if we add $predep_objects and $postdep_objects, however 7.1 and
+       # earlier do not add the objects themselves.
+       case `$CC -V 2>&1` in
+       *"Version 7."*)
+         archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+         archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+         ;;
+       *)  # Version 8.0 or newer
+         tmp_idyn=
+         case $host_cpu in
+           ia64*) tmp_idyn=' -i_dynamic';;
+         esac
+         archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+         archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+         ;;
+       esac
+       archive_cmds_need_lc_CXX=no
+       hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+       export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+       whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+       ;;
+      pgCC*)
+        # Portland Group C++ compiler
+       archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+       archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+
+       hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+       export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+       whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+        ;;
+      cxx*)
+       # Compaq C++
+       archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+       runpath_var=LD_RUN_PATH
+       hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+       hardcode_libdir_separator_CXX=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)
+         # Sun C++ 5.9
+         no_undefined_flag_CXX=' -zdefs'
+         archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+         hardcode_libdir_flag_spec_CXX='-R$libdir'
+         whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+
+         # Not sure whether something based on
+         # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+         # would be better.
+         output_verbose_link_cmd='echo'
+
+         # Archives containing C++ object files must be created using
+         # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+         # necessary to make sure instantiated templates are included
+         # in the archive.
+         old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+         ;;
+       esac
+       ;;
+    esac
+    ;;
+  lynxos*)
+    # FIXME: insert proper C++ library support
+    ld_shlibs_CXX=no
+    ;;
+  m88k*)
+    # FIXME: insert proper C++ library support
+    ld_shlibs_CXX=no
+    ;;
+  mvs*)
+    case $cc_basename in
+      cxx*)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+    esac
+    ;;
+  netbsd* | netbsdelf*-gnu)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      archive_cmds_CXX='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+      wlarc=
+      hardcode_libdir_flag_spec_CXX='-R$libdir'
+      hardcode_direct_CXX=yes
+      hardcode_shlibpath_var_CXX=no
+    fi
+    # Workaround some broken pre-1.5 toolchains
+    output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+    ;;
+  openbsd2*)
+    # C++ shared libraries are fairly broken
+    ld_shlibs_CXX=no
+    ;;
+  openbsd*)
+    if test -f /usr/libexec/ld.so; then
+      hardcode_direct_CXX=yes
+      hardcode_shlibpath_var_CXX=no
+      archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+      hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+      if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+       archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+       export_dynamic_flag_spec_CXX='${wl}-E'
+       whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      fi
+      output_verbose_link_cmd='echo'
+    else
+      ld_shlibs_CXX=no
+    fi
+    ;;
+  osf3*)
+    case $cc_basename in
+      KCC*)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+       hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+       hardcode_libdir_separator_CXX=:
+
+       # Archives containing C++ object files must be created using
+       # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+       old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+
+       ;;
+      RCC*)
+       # Rational C++ 2.4.1
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      cxx*)
+       allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+       hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+       hardcode_libdir_separator_CXX=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+         archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+         hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+         hardcode_libdir_separator_CXX=:
+
+         # Commands to make compiler produce verbose output that lists
+         # what "hidden" libraries, object files and flags are used when
+         # linking a shared library.
+         output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+       else
+         # FIXME: insert proper C++ library support
+         ld_shlibs_CXX=no
+       fi
+       ;;
+    esac
+    ;;
+  osf4* | osf5*)
+    case $cc_basename in
+      KCC*)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+       hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+       hardcode_libdir_separator_CXX=:
+
+       # Archives containing C++ object files must be created using
+       # the KAI C++ compiler.
+       old_archive_cmds_CXX='$CC -o $oldlib $oldobjs'
+       ;;
+      RCC*)
+       # Rational C++ 2.4.1
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      cxx*)
+       allow_undefined_flag_CXX=' -expect_unresolved \*'
+       archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+         echo "-hidden">> $lib.exp~
+         $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp  `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
+         $rm $lib.exp'
+
+       hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+       hardcode_libdir_separator_CXX=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+        archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+         hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+         hardcode_libdir_separator_CXX=:
+
+         # Commands to make compiler produce verbose output that lists
+         # what "hidden" libraries, object files and flags are used when
+         # linking a shared library.
+         output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+       else
+         # FIXME: insert proper C++ library support
+         ld_shlibs_CXX=no
+       fi
+       ;;
+    esac
+    ;;
+  psos*)
+    # FIXME: insert proper C++ library support
+    ld_shlibs_CXX=no
+    ;;
+  sunos4*)
+    case $cc_basename in
+      CC*)
+       # Sun C++ 4.x
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      lcc*)
+       # Lucid
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+    esac
+    ;;
+  solaris*)
+    case $cc_basename in
+      CC*)
+       # Sun C++ 4.2, 5.x and Centerline C++
+        archive_cmds_need_lc_CXX=yes
+       no_undefined_flag_CXX=' -zdefs'
+       archive_cmds_CXX='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+       archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $CC -G${allow_undefined_flag}  ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+       hardcode_libdir_flag_spec_CXX='-R$libdir'
+       hardcode_shlibpath_var_CXX=no
+       case $host_os in
+         solaris2.[0-5] | solaris2.[0-5].*) ;;
+         *)
+           # The compiler driver will combine and reorder linker options,
+           # but understands `-z linker_flag'.
+           # Supported since Solaris 2.6 (maybe 2.5.1?)
+           whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract'
+           ;;
+       esac
+       link_all_deplibs_CXX=yes
+
+       output_verbose_link_cmd='echo'
+
+       # Archives containing C++ object files must be created using
+       # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+       # necessary to make sure instantiated templates are included
+       # in the archive.
+       old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+       ;;
+      gcx*)
+       # Green Hills C++ Compiler
+       archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+       # The C++ compiler must be used to create the archive.
+       old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+       ;;
+      *)
+       # GNU C++ compiler with Solaris linker
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
+         if $CC --version | grep -v '^2\.7' > /dev/null; then
+           archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+           archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+         else
+           # g++ 2.7 appears to require `-G' NOT `-shared' on this
+           # platform.
+           archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+           archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+         fi
+
+         hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir'
+         case $host_os in
+         solaris2.[0-5] | solaris2.[0-5].*) ;;
+         *)
+           whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+           ;;
+         esac
+       fi
+       ;;
+    esac
+    ;;
+  sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+    no_undefined_flag_CXX='${wl}-z,text'
+    archive_cmds_need_lc_CXX=no
+    hardcode_shlibpath_var_CXX=no
+    runpath_var='LD_RUN_PATH'
+
+    case $cc_basename in
+      CC*)
+       archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+      *)
+       archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+    esac
+    ;;
+  sysv5* | sco3.2v5* | sco5v6*)
+    # Note: We can NOT use -z defs as we might desire, because we do not
+    # link with -lc, and that would cause any symbols used from libc to
+    # always be unresolved, which means just about no library would
+    # ever link correctly.  If we're not using GNU ld we use -z text
+    # though, which does catch some bad symbols but isn't as heavy-handed
+    # as -z defs.
+    # For security reasons, it is highly recommended that you always
+    # use absolute paths for naming shared libraries, and exclude the
+    # DT_RUNPATH tag from executables and libraries.  But doing so
+    # requires that you compile everything twice, which is a pain.
+    # So that behaviour is only enabled if SCOABSPATH is set to a
+    # non-empty value in the environment.  Most likely only useful for
+    # creating official distributions of packages.
+    # This is a hack until libtool officially supports absolute path
+    # names for shared libraries.
+    no_undefined_flag_CXX='${wl}-z,text'
+    allow_undefined_flag_CXX='${wl}-z,nodefs'
+    archive_cmds_need_lc_CXX=no
+    hardcode_shlibpath_var_CXX=no
+    hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+    hardcode_libdir_separator_CXX=':'
+    link_all_deplibs_CXX=yes
+    export_dynamic_flag_spec_CXX='${wl}-Bexport'
+    runpath_var='LD_RUN_PATH'
+
+    case $cc_basename in
+      CC*)
+       archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+      *)
+       archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+    esac
+    ;;
+  tandem*)
+    case $cc_basename in
+      NCC*)
+       # NonStop-UX NCC 3.20
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       ld_shlibs_CXX=no
+       ;;
+    esac
+    ;;
+  vxworks*)
+    # FIXME: insert proper C++ library support
+    ld_shlibs_CXX=no
+    ;;
+  *)
+    # FIXME: insert proper C++ library support
+    ld_shlibs_CXX=no
+    ;;
+esac
+{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6; }
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+GCC_CXX="$GXX"
+LD_CXX="$LD"
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+
+cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+EOF
+
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  # The `*' in the case matches for architectures that use `case' in
+  # $output_verbose_cmd can trigger glob expansion during the loop
+  # eval without this substitution.
+  output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
+
+  for p in `eval $output_verbose_link_cmd`; do
+    case $p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test $p = "-L" \
+         || test $p = "-R"; then
+        prev=$p
+        continue
+       else
+        prev=
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+        case $p in
+        -L* | -R*)
+          # Internal compiler library paths should come after those
+          # provided the user.  The postdeps already come after the
+          # user supplied libs so there is no need to process them.
+          if test -z "$compiler_lib_search_path_CXX"; then
+            compiler_lib_search_path_CXX="${prev}${p}"
+          else
+            compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}"
+          fi
+          ;;
+        # The "-l" case would never come before the object being
+        # linked, so don't bother handling this case.
+        esac
+       else
+        if test -z "$postdeps_CXX"; then
+          postdeps_CXX="${prev}${p}"
+        else
+          postdeps_CXX="${postdeps_CXX} ${prev}${p}"
+        fi
+       fi
+       ;;
+
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+        pre_test_object_deps_done=yes
+        continue
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+        if test -z "$predep_objects_CXX"; then
+          predep_objects_CXX="$p"
+        else
+          predep_objects_CXX="$predep_objects_CXX $p"
+        fi
+       else
+        if test -z "$postdep_objects_CXX"; then
+          postdep_objects_CXX="$p"
+        else
+          postdep_objects_CXX="$postdep_objects_CXX $p"
+        fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling CXX test program"
+fi
+
+$rm -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+case $host_os in
+interix[3-9]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  predep_objects_CXX=
+  postdep_objects_CXX=
+  postdeps_CXX=
+  ;;
+
+linux*)
+  case `$CC -V 2>&1 | sed 5q` in
+  *Sun\ C*)
+    # Sun C++ 5.9
+    #
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+    if test "$solaris_use_stlport4" != yes; then
+      postdeps_CXX='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+
+solaris*)
+  case $cc_basename in
+  CC*)
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    if test "$solaris_use_stlport4" != yes; then
+      postdeps_CXX='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+esac
+
+
+case " $postdeps_CXX " in
+*" -lc "*) archive_cmds_need_lc_CXX=no ;;
+esac
+
+lt_prog_compiler_wl_CXX=
+lt_prog_compiler_pic_CXX=
+lt_prog_compiler_static_CXX=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+  # C++ specific cases for pic, static, wl, etc.
+  if test "$GXX" = yes; then
+    lt_prog_compiler_wl_CXX='-Wl,'
+    lt_prog_compiler_static_CXX='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static_CXX='-Bstatic'
+      fi
+      ;;
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
+      ;;
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic_CXX='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      lt_prog_compiler_pic_CXX=
+      ;;
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       lt_prog_compiler_pic_CXX=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       ;;
+      *)
+       lt_prog_compiler_pic_CXX='-fPIC'
+       ;;
+      esac
+      ;;
+    *)
+      lt_prog_compiler_pic_CXX='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix4* | aix5*)
+       # All AIX code is PIC.
+       if test "$host_cpu" = ia64; then
+         # AIX 5 now supports IA64 processor
+         lt_prog_compiler_static_CXX='-Bstatic'
+       else
+         lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
+       fi
+       ;;
+      chorus*)
+       case $cc_basename in
+       cxch68*)
+         # Green Hills C++ Compiler
+         # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+         ;;
+       esac
+       ;;
+       darwin*)
+         # PIC is the default on this platform
+         # Common symbols not allowed in MH_DYLIB files
+         case $cc_basename in
+           xlc*)
+           lt_prog_compiler_pic_CXX='-qnocommon'
+           lt_prog_compiler_wl_CXX='-Wl,'
+           ;;
+         esac
+       ;;
+      dgux*)
+       case $cc_basename in
+         ec++*)
+           lt_prog_compiler_pic_CXX='-KPIC'
+           ;;
+         ghcx*)
+           # Green Hills C++ Compiler
+           lt_prog_compiler_pic_CXX='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      freebsd* | dragonfly*)
+       # FreeBSD uses GNU C++
+       ;;
+      hpux9* | hpux10* | hpux11*)
+       case $cc_basename in
+         CC*)
+           lt_prog_compiler_wl_CXX='-Wl,'
+           lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+           if test "$host_cpu" != ia64; then
+             lt_prog_compiler_pic_CXX='+Z'
+           fi
+           ;;
+         aCC*)
+           lt_prog_compiler_wl_CXX='-Wl,'
+           lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+           case $host_cpu in
+           hppa*64*|ia64*)
+             # +Z the default
+             ;;
+           *)
+             lt_prog_compiler_pic_CXX='+Z'
+             ;;
+           esac
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      interix*)
+       # This is c89, which is MS Visual C++ (no shared libs)
+       # Anyone wants to do a port?
+       ;;
+      irix5* | irix6* | nonstopux*)
+       case $cc_basename in
+         CC*)
+           lt_prog_compiler_wl_CXX='-Wl,'
+           lt_prog_compiler_static_CXX='-non_shared'
+           # CC pic flag -KPIC is the default.
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      linux* | k*bsd*-gnu)
+       case $cc_basename in
+         KCC*)
+           # KAI C++ Compiler
+           lt_prog_compiler_wl_CXX='--backend -Wl,'
+           lt_prog_compiler_pic_CXX='-fPIC'
+           ;;
+         icpc* | ecpc*)
+           # Intel C++
+           lt_prog_compiler_wl_CXX='-Wl,'
+           lt_prog_compiler_pic_CXX='-KPIC'
+           lt_prog_compiler_static_CXX='-static'
+           ;;
+         pgCC*)
+           # Portland Group C++ compiler.
+           lt_prog_compiler_wl_CXX='-Wl,'
+           lt_prog_compiler_pic_CXX='-fpic'
+           lt_prog_compiler_static_CXX='-Bstatic'
+           ;;
+         cxx*)
+           # Compaq C++
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           lt_prog_compiler_pic_CXX=
+           lt_prog_compiler_static_CXX='-non_shared'
+           ;;
+         *)
+           case `$CC -V 2>&1 | sed 5q` in
+           *Sun\ C*)
+             # Sun C++ 5.9
+             lt_prog_compiler_pic_CXX='-KPIC'
+             lt_prog_compiler_static_CXX='-Bstatic'
+             lt_prog_compiler_wl_CXX='-Qoption ld '
+             ;;
+           esac
+           ;;
+       esac
+       ;;
+      lynxos*)
+       ;;
+      m88k*)
+       ;;
+      mvs*)
+       case $cc_basename in
+         cxx*)
+           lt_prog_compiler_pic_CXX='-W c,exportall'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      netbsd* | netbsdelf*-gnu)
+       ;;
+      osf3* | osf4* | osf5*)
+       case $cc_basename in
+         KCC*)
+           lt_prog_compiler_wl_CXX='--backend -Wl,'
+           ;;
+         RCC*)
+           # Rational C++ 2.4.1
+           lt_prog_compiler_pic_CXX='-pic'
+           ;;
+         cxx*)
+           # Digital/Compaq C++
+           lt_prog_compiler_wl_CXX='-Wl,'
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           lt_prog_compiler_pic_CXX=
+           lt_prog_compiler_static_CXX='-non_shared'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      psos*)
+       ;;
+      solaris*)
+       case $cc_basename in
+         CC*)
+           # Sun C++ 4.2, 5.x and Centerline C++
+           lt_prog_compiler_pic_CXX='-KPIC'
+           lt_prog_compiler_static_CXX='-Bstatic'
+           lt_prog_compiler_wl_CXX='-Qoption ld '
+           ;;
+         gcx*)
+           # Green Hills C++ Compiler
+           lt_prog_compiler_pic_CXX='-PIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sunos4*)
+       case $cc_basename in
+         CC*)
+           # Sun C++ 4.x
+           lt_prog_compiler_pic_CXX='-pic'
+           lt_prog_compiler_static_CXX='-Bstatic'
+           ;;
+         lcc*)
+           # Lucid
+           lt_prog_compiler_pic_CXX='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      tandem*)
+       case $cc_basename in
+         NCC*)
+           # NonStop-UX NCC 3.20
+           lt_prog_compiler_pic_CXX='-KPIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+       case $cc_basename in
+         CC*)
+           lt_prog_compiler_wl_CXX='-Wl,'
+           lt_prog_compiler_pic_CXX='-KPIC'
+           lt_prog_compiler_static_CXX='-Bstatic'
+           ;;
+       esac
+       ;;
+      vxworks*)
+       ;;
+      *)
+       lt_prog_compiler_can_build_shared_CXX=no
+       ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_CXX"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_pic_works_CXX=no
+  ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:12847: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:12851: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_prog_compiler_pic_works_CXX=yes
+     fi
+   fi
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6; }
+
+if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then
+    case $lt_prog_compiler_pic_CXX in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
+     esac
+else
+    lt_prog_compiler_pic_CXX=
+     lt_prog_compiler_can_build_shared_CXX=no
+fi
+
+fi
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic_CXX=
+    ;;
+  *)
+    lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
+    ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
+{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_static_works_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_static_works_CXX=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_prog_compiler_static_works_CXX=yes
+       fi
+     else
+       lt_prog_compiler_static_works_CXX=yes
+     fi
+   fi
+   $rm conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6; }
+
+if test x"$lt_prog_compiler_static_works_CXX" = xyes; then
+    :
+else
+    lt_prog_compiler_static_CXX=
+fi
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_prog_compiler_c_o_CXX=no
+   $rm -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:12951: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:12955: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o_CXX=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $rm conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+   $rm out/* && rmdir out
+   cd ..
+   rmdir conftest
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+  export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  case $host_os in
+  aix4* | aix5*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+      export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+    else
+      export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    export_symbols_cmds_CXX="$ltdll_cmds"
+  ;;
+  cygwin* | mingw*)
+    export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+  ;;
+  linux* | k*bsd*-gnu)
+    link_all_deplibs_CXX=no
+  ;;
+  *)
+    export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  esac
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6; }
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_CXX" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc_CXX=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds_CXX in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+      $rm conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$lt_prog_compiler_wl_CXX
+       pic_flag=$lt_prog_compiler_pic_CXX
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
+        allow_undefined_flag_CXX=
+        if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+  (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+        then
+         archive_cmds_need_lc_CXX=no
+        else
+         archive_cmds_need_lc_CXX=yes
+        fi
+        allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $rm conftest*
+      { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6; }
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+   hppa*64*)
+     shrext_cmds='.sl'
+     hardcode_into_libs=yes
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+     library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[     ]*hwcap[        ]/d;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+nto-qnx*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+    shlibpath_overrides_runpath=no
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    shlibpath_overrides_runpath=yes
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action_CXX=
+if test -n "$hardcode_libdir_flag_spec_CXX" || \
+   test -n "$runpath_var_CXX" || \
+   test "X$hardcode_automatic_CXX" = "Xyes" ; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct_CXX" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no &&
+     test "$hardcode_minus_L_CXX" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action_CXX=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action_CXX=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action_CXX=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5
+echo "${ECHO_T}$hardcode_action_CXX" >&6; }
+
+if test "$hardcode_action_CXX" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    old_postinstall_cmds old_postuninstall_cmds \
+    compiler_CXX \
+    CC_CXX \
+    LD_CXX \
+    lt_prog_compiler_wl_CXX \
+    lt_prog_compiler_pic_CXX \
+    lt_prog_compiler_static_CXX \
+    lt_prog_compiler_no_builtin_flag_CXX \
+    export_dynamic_flag_spec_CXX \
+    thread_safe_flag_spec_CXX \
+    whole_archive_flag_spec_CXX \
+    enable_shared_with_static_runtimes_CXX \
+    old_archive_cmds_CXX \
+    old_archive_from_new_cmds_CXX \
+    predep_objects_CXX \
+    postdep_objects_CXX \
+    predeps_CXX \
+    postdeps_CXX \
+    compiler_lib_search_path_CXX \
+    archive_cmds_CXX \
+    archive_expsym_cmds_CXX \
+    postinstall_cmds_CXX \
+    postuninstall_cmds_CXX \
+    old_archive_from_expsyms_cmds_CXX \
+    allow_undefined_flag_CXX \
+    no_undefined_flag_CXX \
+    export_symbols_cmds_CXX \
+    hardcode_libdir_flag_spec_CXX \
+    hardcode_libdir_flag_spec_ld_CXX \
+    hardcode_libdir_separator_CXX \
+    hardcode_automatic_CXX \
+    module_cmds_CXX \
+    module_expsym_cmds_CXX \
+    lt_cv_prog_compiler_c_o_CXX \
+    fix_srcfile_path_CXX \
+    exclude_expsyms_CXX \
+    include_expsyms_CXX; do
+
+    case $var in
+    old_archive_cmds_CXX | \
+    old_archive_from_new_cmds_CXX | \
+    archive_cmds_CXX | \
+    archive_expsym_cmds_CXX | \
+    module_cmds_CXX | \
+    module_expsym_cmds_CXX | \
+    old_archive_from_expsyms_cmds_CXX | \
+    export_symbols_cmds_CXX | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case $lt_echo in
+  *'\$0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+    ;;
+  esac
+
+cfgfile="$ofile"
+
+  cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_CXX
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_CXX
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_CXX
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_CXX
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_CXX
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_CXX
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_CXX
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_CXX
+archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_CXX
+module_expsym_cmds=$lt_module_expsym_cmds_CXX
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_CXX
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_CXX
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_CXX
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_CXX
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_CXX
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_CXX
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_CXX
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_CXX
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_CXX
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_CXX
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_CXX
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_CXX
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_CXX
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_CXX
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_CXX
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+
+       else
+         tagname=""
+       fi
+       ;;
+
+      F77)
+       if test -n "$F77" && test "X$F77" != "Xno"; then
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+archive_cmds_need_lc_F77=no
+allow_undefined_flag_F77=
+always_export_symbols_F77=no
+archive_expsym_cmds_F77=
+export_dynamic_flag_spec_F77=
+hardcode_direct_F77=no
+hardcode_libdir_flag_spec_F77=
+hardcode_libdir_flag_spec_ld_F77=
+hardcode_libdir_separator_F77=
+hardcode_minus_L_F77=no
+hardcode_automatic_F77=no
+module_cmds_F77=
+module_expsym_cmds_F77=
+link_all_deplibs_F77=unknown
+old_archive_cmds_F77=$old_archive_cmds
+no_undefined_flag_F77=
+whole_archive_flag_spec_F77=
+enable_shared_with_static_runtimes_F77=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+objext_F77=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="\
+      program t
+      end
+"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+compiler_F77=$CC
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; }
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+aix4* | aix5*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
+  ;;
+esac
+{ echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; }
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+{ echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6; }
+
+GCC_F77="$G77"
+LD_F77="$LD"
+
+lt_prog_compiler_wl_F77=
+lt_prog_compiler_pic_F77=
+lt_prog_compiler_static_F77=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl_F77='-Wl,'
+    lt_prog_compiler_static_F77='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static_F77='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4'
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic_F77='-fno-common'
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared_F77=no
+      enable_shared=no
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       lt_prog_compiler_pic_F77=-Kconform_pic
+      fi
+      ;;
+
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic_F77='-fPIC'
+       ;;
+      esac
+      ;;
+
+    *)
+      lt_prog_compiler_pic_F77='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static_F77='-Bstatic'
+      else
+       lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+      darwin*)
+        # PIC is the default on this platform
+        # Common symbols not allowed in MH_DYLIB files
+       case $cc_basename in
+         xlc*)
+         lt_prog_compiler_pic_F77='-qnocommon'
+         lt_prog_compiler_wl_F77='-Wl,'
+         ;;
+       esac
+       ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic_F77='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static_F77='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static_F77='-non_shared'
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic_F77='-KPIC'
+      lt_prog_compiler_static_F77='-Bstatic'
+      ;;
+
+    linux* | k*bsd*-gnu)
+      case $cc_basename in
+      icc* | ecc*)
+       lt_prog_compiler_wl_F77='-Wl,'
+       lt_prog_compiler_pic_F77='-KPIC'
+       lt_prog_compiler_static_F77='-static'
+        ;;
+      pgcc* | pgf77* | pgf90* | pgf95*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+       # which looks to be a dead project)
+       lt_prog_compiler_wl_F77='-Wl,'
+       lt_prog_compiler_pic_F77='-fpic'
+       lt_prog_compiler_static_F77='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl_F77='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static_F77='-non_shared'
+        ;;
+      *)
+        case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)
+         # Sun C 5.9
+         lt_prog_compiler_pic_F77='-KPIC'
+         lt_prog_compiler_static_F77='-Bstatic'
+         lt_prog_compiler_wl_F77='-Wl,'
+         ;;
+       *Sun\ F*)
+         # Sun Fortran 8.3 passes all unrecognized flags to the linker
+         lt_prog_compiler_pic_F77='-KPIC'
+         lt_prog_compiler_static_F77='-Bstatic'
+         lt_prog_compiler_wl_F77=''
+         ;;
+       esac
+       ;;
+      esac
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static_F77='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static_F77='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic_F77='-KPIC'
+      lt_prog_compiler_static_F77='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+       lt_prog_compiler_wl_F77='-Qoption ld ';;
+      *)
+       lt_prog_compiler_wl_F77='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl_F77='-Qoption ld '
+      lt_prog_compiler_pic_F77='-PIC'
+      lt_prog_compiler_static_F77='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      lt_prog_compiler_pic_F77='-KPIC'
+      lt_prog_compiler_static_F77='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       lt_prog_compiler_pic_F77='-Kconform_pic'
+       lt_prog_compiler_static_F77='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      lt_prog_compiler_pic_F77='-KPIC'
+      lt_prog_compiler_static_F77='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl_F77='-Wl,'
+      lt_prog_compiler_can_build_shared_F77=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic_F77='-pic'
+      lt_prog_compiler_static_F77='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared_F77=no
+      ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_F77"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works_F77+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_pic_works_F77=no
+  ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic_F77"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:14528: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:14532: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_prog_compiler_pic_works_F77=yes
+     fi
+   fi
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6; }
+
+if test x"$lt_prog_compiler_pic_works_F77" = xyes; then
+    case $lt_prog_compiler_pic_F77 in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;;
+     esac
+else
+    lt_prog_compiler_pic_F77=
+     lt_prog_compiler_can_build_shared_F77=no
+fi
+
+fi
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic_F77=
+    ;;
+  *)
+    lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77"
+    ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\"
+{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_static_works_F77+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_static_works_F77=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_prog_compiler_static_works_F77=yes
+       fi
+     else
+       lt_prog_compiler_static_works_F77=yes
+     fi
+   fi
+   $rm conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6; }
+
+if test x"$lt_prog_compiler_static_works_F77" = xyes; then
+    :
+else
+    lt_prog_compiler_static_F77=
+fi
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_prog_compiler_c_o_F77=no
+   $rm -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:14632: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:14636: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o_F77=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $rm conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+   $rm out/* && rmdir out
+   cd ..
+   rmdir conftest
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+  runpath_var=
+  allow_undefined_flag_F77=
+  enable_shared_with_static_runtimes_F77=no
+  archive_cmds_F77=
+  archive_expsym_cmds_F77=
+  old_archive_From_new_cmds_F77=
+  old_archive_from_expsyms_cmds_F77=
+  export_dynamic_flag_spec_F77=
+  whole_archive_flag_spec_F77=
+  thread_safe_flag_spec_F77=
+  hardcode_libdir_flag_spec_F77=
+  hardcode_libdir_flag_spec_ld_F77=
+  hardcode_libdir_separator_F77=
+  hardcode_direct_F77=no
+  hardcode_minus_L_F77=no
+  hardcode_shlibpath_var_F77=unsupported
+  link_all_deplibs_F77=unknown
+  hardcode_automatic_F77=no
+  module_cmds_F77=
+  module_expsym_cmds_F77=
+  always_export_symbols_F77=no
+  export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms_F77=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_"
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  extract_expsyms_cmds=
+  # Just being paranoid about ensuring that cc_basename is set.
+  for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+  case $host_os in
+  cygwin* | mingw* | pw32*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  ld_shlibs_F77=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec_F77='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+       whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+       whole_archive_flag_spec_F77=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>/dev/null` in
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+       ld_shlibs_F77=no
+       cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+      fi
+      ;;
+
+    amigaos*)
+      archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      hardcode_minus_L_F77=yes
+
+      # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+      # that the semantics of dynamic libraries on AmigaOS, at least up
+      # to version 4, is to share data among multiple programs linked
+      # with the same dynamic library.  Since this doesn't match the
+      # behavior of shared libraries on other platforms, we can't use
+      # them.
+      ld_shlibs_F77=no
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       allow_undefined_flag_F77=unsupported
+       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+       ld_shlibs_F77=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      allow_undefined_flag_F77=unsupported
+      always_export_symbols_F77=no
+      enable_shared_with_static_runtimes_F77=yes
+      export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+        archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       # If the export-symbols file already is a .def file (1st line
+       # is EXPORTS), use it as is; otherwise, prepend...
+       archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+         cp $export_symbols $output_objdir/$soname.def;
+       else
+         echo EXPORTS > $output_objdir/$soname.def;
+         cat $export_symbols >> $output_objdir/$soname.def;
+       fi~
+       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+       ld_shlibs_F77=no
+      fi
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct_F77=no
+      hardcode_shlibpath_var_F77=no
+      hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec_F77='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | k*bsd*-gnu)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       tmp_addflag=
+       case $cc_basename,$host_cpu in
+       pgcc*)                          # Portland Group C compiler
+         whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
+         ;;
+       pgf77* | pgf90* | pgf95*)       # Portland Group f77 and f90 compilers
+         whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
+       ecc*,ia64* | icc*,ia64*)                # Intel C compiler on ia64
+         tmp_addflag=' -i_dynamic' ;;
+       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
+         tmp_addflag=' -i_dynamic -nofor_main' ;;
+       ifc* | ifort*)                  # Intel Fortran compiler
+         tmp_addflag=' -nofor_main' ;;
+       esac
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)                       # Sun C 5.9
+         whole_archive_flag_spec_F77='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_sharedflag='-G' ;;
+       *Sun\ F*)                       # Sun Fortran 8.3
+         tmp_sharedflag='-G' ;;
+       *)
+         tmp_sharedflag='-shared' ;;
+       esac
+       archive_cmds_F77='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+       if test $supports_anon_versioning = yes; then
+         archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~
+  cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+  $echo "local: *; };" >> $output_objdir/$libname.ver~
+         $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+       fi
+       link_all_deplibs_F77=no
+      else
+       ld_shlibs_F77=no
+      fi
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+       ld_shlibs_F77=no
+       cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+      elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs_F77=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+       ld_shlibs_F77=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+       ;;
+       *)
+         if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+           hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+           archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+           archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+         else
+           ld_shlibs_F77=no
+         fi
+       ;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct_F77=yes
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs_F77=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs_F77" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec_F77=
+      export_dynamic_flag_spec_F77=
+      whole_archive_flag_spec_F77=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag_F77=unsupported
+      always_export_symbols_F77=yes
+      archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L_F77=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       hardcode_direct_F77=unsupported
+      fi
+      ;;
+
+    aix4* | aix5*)
+      if test "$host_cpu" = ia64; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=""
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to AIX nm, but means don't demangle with GNU nm
+       if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+         export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+       else
+         export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # need to do runtime linking.
+       case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+         for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+         ;;
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds_F77=''
+      hardcode_direct_F77=yes
+      hardcode_libdir_separator_F77=':'
+      link_all_deplibs_F77=yes
+
+      if test "$GCC" = yes; then
+       case $host_os in aix4.[012]|aix4.[012].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         :
+         else
+         # We have old collect2
+         hardcode_direct_F77=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         hardcode_minus_L_F77=yes
+         hardcode_libdir_flag_spec_F77='-L$libdir'
+         hardcode_libdir_separator_F77=
+         fi
+         ;;
+       esac
+       shared_flag='-shared'
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag="$shared_flag "'${wl}-G'
+       fi
+      else
+       # not using gcc
+       if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag='${wl}-G'
+         else
+           shared_flag='${wl}-bM:SRE'
+         fi
+       fi
+      fi
+
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols_F77=yes
+      if test "$aix_use_runtimelinking" = yes; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       allow_undefined_flag_F77='-berok'
+       # Determine the default libpath from the value encoded in an empty executable.
+       cat >conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_f77_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+       hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+       archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+       else
+       if test "$host_cpu" = ia64; then
+         hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib'
+         allow_undefined_flag_F77="-z nodefs"
+         archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an empty executable.
+        cat >conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_f77_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+        hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         no_undefined_flag_F77=' ${wl}-bernotok'
+         allow_undefined_flag_F77=' ${wl}-berok'
+         # Exported symbols can be pulled into shared objects from archives
+         whole_archive_flag_spec_F77='$convenience'
+         archive_cmds_need_lc_F77=yes
+         # This is similar to how AIX traditionally builds its shared libraries.
+         archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      hardcode_minus_L_F77=yes
+      # see comment about different semantics on the GNU ld section
+      ld_shlibs_F77=no
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec_F77=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec_F77=' '
+      allow_undefined_flag_F77=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      old_archive_From_new_cmds_F77='true'
+      # FIXME: Should let the user specify the lib program.
+      old_archive_cmds_F77='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path_F77='`cygpath -w "$srcfile"`'
+      enable_shared_with_static_runtimes_F77=yes
+      ;;
+
+    darwin* | rhapsody*)
+      case $host_os in
+        rhapsody* | darwin1.[012])
+         allow_undefined_flag_F77='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[012])
+               allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+      esac
+      archive_cmds_need_lc_F77=no
+      hardcode_direct_F77=no
+      hardcode_automatic_F77=yes
+      hardcode_shlibpath_var_F77=unsupported
+      whole_archive_flag_spec_F77=''
+      link_all_deplibs_F77=yes
+    if test "$GCC" = yes ; then
+       output_verbose_link_cmd='echo'
+        archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+      archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    else
+      case $cc_basename in
+        xlc*)
+         output_verbose_link_cmd='echo'
+         archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+         module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+         archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         ld_shlibs_F77=no
+          ;;
+      esac
+    fi
+      ;;
+
+    dgux*)
+      archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    freebsd1*)
+      ld_shlibs_F77=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec_F77='-R$libdir'
+      hardcode_direct_F77=yes
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct_F77=yes
+      hardcode_minus_L_F77=yes
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec_F77='-R$libdir'
+      hardcode_direct_F77=yes
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+       archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+       archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator_F77=:
+      hardcode_direct_F77=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L_F77=yes
+      export_dynamic_flag_spec_F77='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator_F77=:
+
+       hardcode_direct_F77=yes
+       export_dynamic_flag_spec_F77='${wl}-E'
+
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       hardcode_minus_L_F77=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator_F77=:
+
+       case $host_cpu in
+       hppa*64*|ia64*)
+         hardcode_libdir_flag_spec_ld_F77='+b $libdir'
+         hardcode_direct_F77=no
+         hardcode_shlibpath_var_F77=no
+         ;;
+       *)
+         hardcode_direct_F77=yes
+         export_dynamic_flag_spec_F77='${wl}-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         hardcode_minus_L_F77=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+       archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec_ld_F77='-rpath $libdir'
+      fi
+      hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_F77=:
+      link_all_deplibs_F77=yes
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec_F77='-R$libdir'
+      hardcode_direct_F77=yes
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    newsos6)
+      archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct_F77=yes
+      hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_F77=:
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+       hardcode_direct_F77=yes
+       hardcode_shlibpath_var_F77=no
+       if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+         archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+         hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+         export_dynamic_flag_spec_F77='${wl}-E'
+       else
+         case $host_os in
+          openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+            archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+            hardcode_libdir_flag_spec_F77='-R$libdir'
+            ;;
+          *)
+            archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+            hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+            ;;
+         esac
+        fi
+      else
+       ld_shlibs_F77=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      hardcode_minus_L_F77=yes
+      allow_undefined_flag_F77=unsupported
+      archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+       allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       allow_undefined_flag_F77=' -expect_unresolved \*'
+       archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_F77=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+       allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+      else
+       allow_undefined_flag_F77=' -expect_unresolved \*'
+       archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+       $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       hardcode_libdir_flag_spec_F77='-rpath $libdir'
+      fi
+      hardcode_libdir_separator_F77=:
+      ;;
+
+    solaris*)
+      no_undefined_flag_F77=' -z text'
+      if test "$GCC" = yes; then
+       wlarc='${wl}'
+       archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+         $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+      else
+       wlarc=''
+       archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+      fi
+      hardcode_libdir_flag_spec_F77='-R$libdir'
+      hardcode_shlibpath_var_F77=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+       # The compiler driver will combine and reorder linker options,
+       # but understands `-z linker_flag'.  GCC discards it without `$wl',
+       # but is careful enough not to reorder.
+       # Supported since Solaris 2.6 (maybe 2.5.1?)
+       if test "$GCC" = yes; then
+         whole_archive_flag_spec_F77='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+       else
+         whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract'
+       fi
+       ;;
+      esac
+      link_all_deplibs_F77=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      hardcode_direct_F77=yes
+      hardcode_minus_L_F77=yes
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct_F77=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         reload_cmds_F77='$CC -r -o $output$reload_objs'
+         hardcode_direct_F77=no
+        ;;
+       motorola)
+         archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var_F77=no
+      export_dynamic_flag_spec_F77='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       hardcode_shlibpath_var_F77=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       ld_shlibs_F77=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag_F77='${wl}-z,text'
+      archive_cmds_need_lc_F77=no
+      hardcode_shlibpath_var_F77=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag_F77='${wl}-z,text'
+      allow_undefined_flag_F77='${wl}-z,nodefs'
+      archive_cmds_need_lc_F77=no
+      hardcode_shlibpath_var_F77=no
+      hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+      hardcode_libdir_separator_F77=':'
+      link_all_deplibs_F77=yes
+      export_dynamic_flag_spec_F77='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec_F77='-L$libdir'
+      hardcode_shlibpath_var_F77=no
+      ;;
+
+    *)
+      ld_shlibs_F77=no
+      ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5
+echo "${ECHO_T}$ld_shlibs_F77" >&6; }
+test "$ld_shlibs_F77" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_F77" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc_F77=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds_F77 in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+      $rm conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$lt_prog_compiler_wl_F77
+       pic_flag=$lt_prog_compiler_pic_F77
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$allow_undefined_flag_F77
+        allow_undefined_flag_F77=
+        if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+  (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+        then
+         archive_cmds_need_lc_F77=no
+        else
+         archive_cmds_need_lc_F77=yes
+        fi
+        allow_undefined_flag_F77=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $rm conftest*
+      { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6; }
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+   hppa*64*)
+     shrext_cmds='.sl'
+     hardcode_into_libs=yes
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+     library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[     ]*hwcap[        ]/d;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+nto-qnx*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+    shlibpath_overrides_runpath=no
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    shlibpath_overrides_runpath=yes
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action_F77=
+if test -n "$hardcode_libdir_flag_spec_F77" || \
+   test -n "$runpath_var_F77" || \
+   test "X$hardcode_automatic_F77" = "Xyes" ; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct_F77" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no &&
+     test "$hardcode_minus_L_F77" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action_F77=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action_F77=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action_F77=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5
+echo "${ECHO_T}$hardcode_action_F77" >&6; }
+
+if test "$hardcode_action_F77" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    old_postinstall_cmds old_postuninstall_cmds \
+    compiler_F77 \
+    CC_F77 \
+    LD_F77 \
+    lt_prog_compiler_wl_F77 \
+    lt_prog_compiler_pic_F77 \
+    lt_prog_compiler_static_F77 \
+    lt_prog_compiler_no_builtin_flag_F77 \
+    export_dynamic_flag_spec_F77 \
+    thread_safe_flag_spec_F77 \
+    whole_archive_flag_spec_F77 \
+    enable_shared_with_static_runtimes_F77 \
+    old_archive_cmds_F77 \
+    old_archive_from_new_cmds_F77 \
+    predep_objects_F77 \
+    postdep_objects_F77 \
+    predeps_F77 \
+    postdeps_F77 \
+    compiler_lib_search_path_F77 \
+    archive_cmds_F77 \
+    archive_expsym_cmds_F77 \
+    postinstall_cmds_F77 \
+    postuninstall_cmds_F77 \
+    old_archive_from_expsyms_cmds_F77 \
+    allow_undefined_flag_F77 \
+    no_undefined_flag_F77 \
+    export_symbols_cmds_F77 \
+    hardcode_libdir_flag_spec_F77 \
+    hardcode_libdir_flag_spec_ld_F77 \
+    hardcode_libdir_separator_F77 \
+    hardcode_automatic_F77 \
+    module_cmds_F77 \
+    module_expsym_cmds_F77 \
+    lt_cv_prog_compiler_c_o_F77 \
+    fix_srcfile_path_F77 \
+    exclude_expsyms_F77 \
+    include_expsyms_F77; do
+
+    case $var in
+    old_archive_cmds_F77 | \
+    old_archive_from_new_cmds_F77 | \
+    archive_cmds_F77 | \
+    archive_expsym_cmds_F77 | \
+    module_cmds_F77 | \
+    module_expsym_cmds_F77 | \
+    old_archive_from_expsyms_cmds_F77 | \
+    export_symbols_cmds_F77 | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case $lt_echo in
+  *'\$0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+    ;;
+  esac
+
+cfgfile="$ofile"
+
+  cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_F77
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_F77
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_F77
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_F77
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_F77
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_F77
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_F77
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_F77
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_F77
+archive_expsym_cmds=$lt_archive_expsym_cmds_F77
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_F77
+module_expsym_cmds=$lt_module_expsym_cmds_F77
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_F77
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_F77
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_F77
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_F77
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_F77
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_F77
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_F77
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_F77
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_F77
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_F77
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_F77
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_F77
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_F77
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_F77
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_F77
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_F77
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_F77
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+       else
+         tagname=""
+       fi
+       ;;
+
+      GCJ)
+       if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+objext_GCJ=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+compiler_GCJ=$CC
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+archive_cmds_need_lc_GCJ=no
+
+old_archive_cmds_GCJ=$old_archive_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+
+lt_prog_compiler_no_builtin_flag_GCJ=
+
+if test "$GCC" = yes; then
+  lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin'
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+  ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:16836: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:16840: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+    lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+lt_prog_compiler_wl_GCJ=
+lt_prog_compiler_pic_GCJ=
+lt_prog_compiler_static_GCJ=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl_GCJ='-Wl,'
+    lt_prog_compiler_static_GCJ='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static_GCJ='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4'
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic_GCJ='-fno-common'
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared_GCJ=no
+      enable_shared=no
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       lt_prog_compiler_pic_GCJ=-Kconform_pic
+      fi
+      ;;
+
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic_GCJ='-fPIC'
+       ;;
+      esac
+      ;;
+
+    *)
+      lt_prog_compiler_pic_GCJ='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static_GCJ='-Bstatic'
+      else
+       lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+      darwin*)
+        # PIC is the default on this platform
+        # Common symbols not allowed in MH_DYLIB files
+       case $cc_basename in
+         xlc*)
+         lt_prog_compiler_pic_GCJ='-qnocommon'
+         lt_prog_compiler_wl_GCJ='-Wl,'
+         ;;
+       esac
+       ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic_GCJ='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static_GCJ='-non_shared'
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic_GCJ='-KPIC'
+      lt_prog_compiler_static_GCJ='-Bstatic'
+      ;;
+
+    linux* | k*bsd*-gnu)
+      case $cc_basename in
+      icc* | ecc*)
+       lt_prog_compiler_wl_GCJ='-Wl,'
+       lt_prog_compiler_pic_GCJ='-KPIC'
+       lt_prog_compiler_static_GCJ='-static'
+        ;;
+      pgcc* | pgf77* | pgf90* | pgf95*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+       # which looks to be a dead project)
+       lt_prog_compiler_wl_GCJ='-Wl,'
+       lt_prog_compiler_pic_GCJ='-fpic'
+       lt_prog_compiler_static_GCJ='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl_GCJ='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static_GCJ='-non_shared'
+        ;;
+      *)
+        case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)
+         # Sun C 5.9
+         lt_prog_compiler_pic_GCJ='-KPIC'
+         lt_prog_compiler_static_GCJ='-Bstatic'
+         lt_prog_compiler_wl_GCJ='-Wl,'
+         ;;
+       *Sun\ F*)
+         # Sun Fortran 8.3 passes all unrecognized flags to the linker
+         lt_prog_compiler_pic_GCJ='-KPIC'
+         lt_prog_compiler_static_GCJ='-Bstatic'
+         lt_prog_compiler_wl_GCJ=''
+         ;;
+       esac
+       ;;
+      esac
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static_GCJ='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static_GCJ='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic_GCJ='-KPIC'
+      lt_prog_compiler_static_GCJ='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+       lt_prog_compiler_wl_GCJ='-Qoption ld ';;
+      *)
+       lt_prog_compiler_wl_GCJ='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl_GCJ='-Qoption ld '
+      lt_prog_compiler_pic_GCJ='-PIC'
+      lt_prog_compiler_static_GCJ='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      lt_prog_compiler_pic_GCJ='-KPIC'
+      lt_prog_compiler_static_GCJ='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       lt_prog_compiler_pic_GCJ='-Kconform_pic'
+       lt_prog_compiler_static_GCJ='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      lt_prog_compiler_pic_GCJ='-KPIC'
+      lt_prog_compiler_static_GCJ='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl_GCJ='-Wl,'
+      lt_prog_compiler_can_build_shared_GCJ=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic_GCJ='-pic'
+      lt_prog_compiler_static_GCJ='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared_GCJ=no
+      ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_GCJ"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_pic_works_GCJ=no
+  ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic_GCJ"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:17126: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:17130: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_prog_compiler_pic_works_GCJ=yes
+     fi
+   fi
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6; }
+
+if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then
+    case $lt_prog_compiler_pic_GCJ in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;;
+     esac
+else
+    lt_prog_compiler_pic_GCJ=
+     lt_prog_compiler_can_build_shared_GCJ=no
+fi
+
+fi
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic_GCJ=
+    ;;
+  *)
+    lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ"
+    ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\"
+{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_prog_compiler_static_works_GCJ=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_prog_compiler_static_works_GCJ=yes
+       fi
+     else
+       lt_prog_compiler_static_works_GCJ=yes
+     fi
+   fi
+   $rm conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6; }
+
+if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then
+    :
+else
+    lt_prog_compiler_static_GCJ=
+fi
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_prog_compiler_c_o_GCJ=no
+   $rm -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:17230: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:17234: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o_GCJ=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $rm conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+   $rm out/* && rmdir out
+   cd ..
+   rmdir conftest
+   $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+  runpath_var=
+  allow_undefined_flag_GCJ=
+  enable_shared_with_static_runtimes_GCJ=no
+  archive_cmds_GCJ=
+  archive_expsym_cmds_GCJ=
+  old_archive_From_new_cmds_GCJ=
+  old_archive_from_expsyms_cmds_GCJ=
+  export_dynamic_flag_spec_GCJ=
+  whole_archive_flag_spec_GCJ=
+  thread_safe_flag_spec_GCJ=
+  hardcode_libdir_flag_spec_GCJ=
+  hardcode_libdir_flag_spec_ld_GCJ=
+  hardcode_libdir_separator_GCJ=
+  hardcode_direct_GCJ=no
+  hardcode_minus_L_GCJ=no
+  hardcode_shlibpath_var_GCJ=unsupported
+  link_all_deplibs_GCJ=unknown
+  hardcode_automatic_GCJ=no
+  module_cmds_GCJ=
+  module_expsym_cmds_GCJ=
+  always_export_symbols_GCJ=no
+  export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms_GCJ=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_"
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  extract_expsyms_cmds=
+  # Just being paranoid about ensuring that cc_basename is set.
+  for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+  case $host_os in
+  cygwin* | mingw* | pw32*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  ld_shlibs_GCJ=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec_GCJ='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+       whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+       whole_archive_flag_spec_GCJ=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>/dev/null` in
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+       ld_shlibs_GCJ=no
+       cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+      fi
+      ;;
+
+    amigaos*)
+      archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      hardcode_minus_L_GCJ=yes
+
+      # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+      # that the semantics of dynamic libraries on AmigaOS, at least up
+      # to version 4, is to share data among multiple programs linked
+      # with the same dynamic library.  Since this doesn't match the
+      # behavior of shared libraries on other platforms, we can't use
+      # them.
+      ld_shlibs_GCJ=no
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       allow_undefined_flag_GCJ=unsupported
+       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+       ld_shlibs_GCJ=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      allow_undefined_flag_GCJ=unsupported
+      always_export_symbols_GCJ=no
+      enable_shared_with_static_runtimes_GCJ=yes
+      export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+        archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       # If the export-symbols file already is a .def file (1st line
+       # is EXPORTS), use it as is; otherwise, prepend...
+       archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+         cp $export_symbols $output_objdir/$soname.def;
+       else
+         echo EXPORTS > $output_objdir/$soname.def;
+         cat $export_symbols >> $output_objdir/$soname.def;
+       fi~
+       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+       ld_shlibs_GCJ=no
+      fi
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct_GCJ=no
+      hardcode_shlibpath_var_GCJ=no
+      hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec_GCJ='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | k*bsd*-gnu)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       tmp_addflag=
+       case $cc_basename,$host_cpu in
+       pgcc*)                          # Portland Group C compiler
+         whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
+         ;;
+       pgf77* | pgf90* | pgf95*)       # Portland Group f77 and f90 compilers
+         whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
+       ecc*,ia64* | icc*,ia64*)                # Intel C compiler on ia64
+         tmp_addflag=' -i_dynamic' ;;
+       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
+         tmp_addflag=' -i_dynamic -nofor_main' ;;
+       ifc* | ifort*)                  # Intel Fortran compiler
+         tmp_addflag=' -nofor_main' ;;
+       esac
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)                       # Sun C 5.9
+         whole_archive_flag_spec_GCJ='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_sharedflag='-G' ;;
+       *Sun\ F*)                       # Sun Fortran 8.3
+         tmp_sharedflag='-G' ;;
+       *)
+         tmp_sharedflag='-shared' ;;
+       esac
+       archive_cmds_GCJ='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+       if test $supports_anon_versioning = yes; then
+         archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~
+  cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+  $echo "local: *; };" >> $output_objdir/$libname.ver~
+         $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+       fi
+       link_all_deplibs_GCJ=no
+      else
+       ld_shlibs_GCJ=no
+      fi
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+       ld_shlibs_GCJ=no
+       cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+      elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs_GCJ=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+       ld_shlibs_GCJ=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+       ;;
+       *)
+         if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+           hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+           archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+           archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+         else
+           ld_shlibs_GCJ=no
+         fi
+       ;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct_GCJ=yes
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs_GCJ=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs_GCJ" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec_GCJ=
+      export_dynamic_flag_spec_GCJ=
+      whole_archive_flag_spec_GCJ=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag_GCJ=unsupported
+      always_export_symbols_GCJ=yes
+      archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L_GCJ=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       hardcode_direct_GCJ=unsupported
+      fi
+      ;;
+
+    aix4* | aix5*)
+      if test "$host_cpu" = ia64; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=""
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to AIX nm, but means don't demangle with GNU nm
+       if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+         export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+       else
+         export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # need to do runtime linking.
+       case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+         for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+         ;;
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds_GCJ=''
+      hardcode_direct_GCJ=yes
+      hardcode_libdir_separator_GCJ=':'
+      link_all_deplibs_GCJ=yes
+
+      if test "$GCC" = yes; then
+       case $host_os in aix4.[012]|aix4.[012].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         :
+         else
+         # We have old collect2
+         hardcode_direct_GCJ=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         hardcode_minus_L_GCJ=yes
+         hardcode_libdir_flag_spec_GCJ='-L$libdir'
+         hardcode_libdir_separator_GCJ=
+         fi
+         ;;
+       esac
+       shared_flag='-shared'
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag="$shared_flag "'${wl}-G'
+       fi
+      else
+       # not using gcc
+       if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag='${wl}-G'
+         else
+           shared_flag='${wl}-bM:SRE'
+         fi
+       fi
+      fi
+
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols_GCJ=yes
+      if test "$aix_use_runtimelinking" = yes; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       allow_undefined_flag_GCJ='-berok'
+       # Determine the default libpath from the value encoded in an empty executable.
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+       hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+       archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+       else
+       if test "$host_cpu" = ia64; then
+         hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib'
+         allow_undefined_flag_GCJ="-z nodefs"
+         archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an empty executable.
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+       /^0/ {
+           s/^0  *\(.*\)$/\1/
+           p
+       }
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+        hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         no_undefined_flag_GCJ=' ${wl}-bernotok'
+         allow_undefined_flag_GCJ=' ${wl}-berok'
+         # Exported symbols can be pulled into shared objects from archives
+         whole_archive_flag_spec_GCJ='$convenience'
+         archive_cmds_need_lc_GCJ=yes
+         # This is similar to how AIX traditionally builds its shared libraries.
+         archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      hardcode_minus_L_GCJ=yes
+      # see comment about different semantics on the GNU ld section
+      ld_shlibs_GCJ=no
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec_GCJ=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec_GCJ=' '
+      allow_undefined_flag_GCJ=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      old_archive_From_new_cmds_GCJ='true'
+      # FIXME: Should let the user specify the lib program.
+      old_archive_cmds_GCJ='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`'
+      enable_shared_with_static_runtimes_GCJ=yes
+      ;;
+
+    darwin* | rhapsody*)
+      case $host_os in
+        rhapsody* | darwin1.[012])
+         allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress'
+         ;;
+       *) # Darwin 1.3 on
+         if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+           allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+         else
+           case ${MACOSX_DEPLOYMENT_TARGET} in
+             10.[012])
+               allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+               ;;
+             10.*)
+               allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup'
+               ;;
+           esac
+         fi
+         ;;
+      esac
+      archive_cmds_need_lc_GCJ=no
+      hardcode_direct_GCJ=no
+      hardcode_automatic_GCJ=yes
+      hardcode_shlibpath_var_GCJ=unsupported
+      whole_archive_flag_spec_GCJ=''
+      link_all_deplibs_GCJ=yes
+    if test "$GCC" = yes ; then
+       output_verbose_link_cmd='echo'
+        archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+      archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    else
+      case $cc_basename in
+        xlc*)
+         output_verbose_link_cmd='echo'
+         archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+         module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+          # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+         archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+          ;;
+       *)
+         ld_shlibs_GCJ=no
+          ;;
+      esac
+    fi
+      ;;
+
+    dgux*)
+      archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    freebsd1*)
+      ld_shlibs_GCJ=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec_GCJ='-R$libdir'
+      hardcode_direct_GCJ=yes
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct_GCJ=yes
+      hardcode_minus_L_GCJ=yes
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec_GCJ='-R$libdir'
+      hardcode_direct_GCJ=yes
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+       archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+       archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator_GCJ=:
+      hardcode_direct_GCJ=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L_GCJ=yes
+      export_dynamic_flag_spec_GCJ='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator_GCJ=:
+
+       hardcode_direct_GCJ=yes
+       export_dynamic_flag_spec_GCJ='${wl}-E'
+
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       hardcode_minus_L_GCJ=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator_GCJ=:
+
+       case $host_cpu in
+       hppa*64*|ia64*)
+         hardcode_libdir_flag_spec_ld_GCJ='+b $libdir'
+         hardcode_direct_GCJ=no
+         hardcode_shlibpath_var_GCJ=no
+         ;;
+       *)
+         hardcode_direct_GCJ=yes
+         export_dynamic_flag_spec_GCJ='${wl}-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         hardcode_minus_L_GCJ=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+       archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir'
+      fi
+      hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_GCJ=:
+      link_all_deplibs_GCJ=yes
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec_GCJ='-R$libdir'
+      hardcode_direct_GCJ=yes
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    newsos6)
+      archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct_GCJ=yes
+      hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_GCJ=:
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+       hardcode_direct_GCJ=yes
+       hardcode_shlibpath_var_GCJ=no
+       if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+         archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+         hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+         export_dynamic_flag_spec_GCJ='${wl}-E'
+       else
+         case $host_os in
+          openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+            archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+            hardcode_libdir_flag_spec_GCJ='-R$libdir'
+            ;;
+          *)
+            archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+            hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+            ;;
+         esac
+        fi
+      else
+       ld_shlibs_GCJ=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      hardcode_minus_L_GCJ=yes
+      allow_undefined_flag_GCJ=unsupported
+      archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+       allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       allow_undefined_flag_GCJ=' -expect_unresolved \*'
+       archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator_GCJ=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+       allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+      else
+       allow_undefined_flag_GCJ=' -expect_unresolved \*'
+       archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+       $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       hardcode_libdir_flag_spec_GCJ='-rpath $libdir'
+      fi
+      hardcode_libdir_separator_GCJ=:
+      ;;
+
+    solaris*)
+      no_undefined_flag_GCJ=' -z text'
+      if test "$GCC" = yes; then
+       wlarc='${wl}'
+       archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+         $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+      else
+       wlarc=''
+       archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+      fi
+      hardcode_libdir_flag_spec_GCJ='-R$libdir'
+      hardcode_shlibpath_var_GCJ=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+       # The compiler driver will combine and reorder linker options,
+       # but understands `-z linker_flag'.  GCC discards it without `$wl',
+       # but is careful enough not to reorder.
+       # Supported since Solaris 2.6 (maybe 2.5.1?)
+       if test "$GCC" = yes; then
+         whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+       else
+         whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract'
+       fi
+       ;;
+      esac
+      link_all_deplibs_GCJ=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      hardcode_direct_GCJ=yes
+      hardcode_minus_L_GCJ=yes
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct_GCJ=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         reload_cmds_GCJ='$CC -r -o $output$reload_objs'
+         hardcode_direct_GCJ=no
+        ;;
+       motorola)
+         archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var_GCJ=no
+      export_dynamic_flag_spec_GCJ='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       hardcode_shlibpath_var_GCJ=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       ld_shlibs_GCJ=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag_GCJ='${wl}-z,text'
+      archive_cmds_need_lc_GCJ=no
+      hardcode_shlibpath_var_GCJ=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag_GCJ='${wl}-z,text'
+      allow_undefined_flag_GCJ='${wl}-z,nodefs'
+      archive_cmds_need_lc_GCJ=no
+      hardcode_shlibpath_var_GCJ=no
+      hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+      hardcode_libdir_separator_GCJ=':'
+      link_all_deplibs_GCJ=yes
+      export_dynamic_flag_spec_GCJ='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec_GCJ='-L$libdir'
+      hardcode_shlibpath_var_GCJ=no
+      ;;
+
+    *)
+      ld_shlibs_GCJ=no
+      ;;
+    esac
+  fi
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5
+echo "${ECHO_T}$ld_shlibs_GCJ" >&6; }
+test "$ld_shlibs_GCJ" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_GCJ" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc_GCJ=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds_GCJ in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+      $rm conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$lt_prog_compiler_wl_GCJ
+       pic_flag=$lt_prog_compiler_pic_GCJ
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ
+        allow_undefined_flag_GCJ=
+        if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+  (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+        then
+         archive_cmds_need_lc_GCJ=no
+        else
+         archive_cmds_need_lc_GCJ=yes
+        fi
+        allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $rm conftest*
+      { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6; }
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+   hppa*64*)
+     shrext_cmds='.sl'
+     hardcode_into_libs=yes
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+     library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[     ]*hwcap[        ]/d;s/[:,       ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+nto-qnx*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+    shlibpath_overrides_runpath=no
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    shlibpath_overrides_runpath=yes
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action_GCJ=
+if test -n "$hardcode_libdir_flag_spec_GCJ" || \
+   test -n "$runpath_var_GCJ" || \
+   test "X$hardcode_automatic_GCJ" = "Xyes" ; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct_GCJ" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no &&
+     test "$hardcode_minus_L_GCJ" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action_GCJ=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action_GCJ=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action_GCJ=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5
+echo "${ECHO_T}$hardcode_action_GCJ" >&6; }
+
+if test "$hardcode_action_GCJ" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    old_postinstall_cmds old_postuninstall_cmds \
+    compiler_GCJ \
+    CC_GCJ \
+    LD_GCJ \
+    lt_prog_compiler_wl_GCJ \
+    lt_prog_compiler_pic_GCJ \
+    lt_prog_compiler_static_GCJ \
+    lt_prog_compiler_no_builtin_flag_GCJ \
+    export_dynamic_flag_spec_GCJ \
+    thread_safe_flag_spec_GCJ \
+    whole_archive_flag_spec_GCJ \
+    enable_shared_with_static_runtimes_GCJ \
+    old_archive_cmds_GCJ \
+    old_archive_from_new_cmds_GCJ \
+    predep_objects_GCJ \
+    postdep_objects_GCJ \
+    predeps_GCJ \
+    postdeps_GCJ \
+    compiler_lib_search_path_GCJ \
+    archive_cmds_GCJ \
+    archive_expsym_cmds_GCJ \
+    postinstall_cmds_GCJ \
+    postuninstall_cmds_GCJ \
+    old_archive_from_expsyms_cmds_GCJ \
+    allow_undefined_flag_GCJ \
+    no_undefined_flag_GCJ \
+    export_symbols_cmds_GCJ \
+    hardcode_libdir_flag_spec_GCJ \
+    hardcode_libdir_flag_spec_ld_GCJ \
+    hardcode_libdir_separator_GCJ \
+    hardcode_automatic_GCJ \
+    module_cmds_GCJ \
+    module_expsym_cmds_GCJ \
+    lt_cv_prog_compiler_c_o_GCJ \
+    fix_srcfile_path_GCJ \
+    exclude_expsyms_GCJ \
+    include_expsyms_GCJ; do
+
+    case $var in
+    old_archive_cmds_GCJ | \
+    old_archive_from_new_cmds_GCJ | \
+    archive_cmds_GCJ | \
+    archive_expsym_cmds_GCJ | \
+    module_cmds_GCJ | \
+    module_expsym_cmds_GCJ | \
+    old_archive_from_expsyms_cmds_GCJ | \
+    export_symbols_cmds_GCJ | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case $lt_echo in
+  *'\$0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+    ;;
+  esac
+
+cfgfile="$ofile"
+
+  cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_GCJ
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_GCJ
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_GCJ
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_GCJ
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_GCJ
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_GCJ
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_GCJ
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_GCJ
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_GCJ
+archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_GCJ
+module_expsym_cmds=$lt_module_expsym_cmds_GCJ
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_GCJ
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_GCJ
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_GCJ
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_GCJ
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_GCJ
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_GCJ
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_GCJ
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_GCJ
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_GCJ
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_GCJ
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_GCJ
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_GCJ
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_GCJ
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_GCJ
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_GCJ
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+       else
+         tagname=""
+       fi
+       ;;
+
+      RC)
+
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+objext_RC=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+compiler_RC=$CC
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+lt_cv_prog_compiler_c_o_RC=yes
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    old_postinstall_cmds old_postuninstall_cmds \
+    compiler_RC \
+    CC_RC \
+    LD_RC \
+    lt_prog_compiler_wl_RC \
+    lt_prog_compiler_pic_RC \
+    lt_prog_compiler_static_RC \
+    lt_prog_compiler_no_builtin_flag_RC \
+    export_dynamic_flag_spec_RC \
+    thread_safe_flag_spec_RC \
+    whole_archive_flag_spec_RC \
+    enable_shared_with_static_runtimes_RC \
+    old_archive_cmds_RC \
+    old_archive_from_new_cmds_RC \
+    predep_objects_RC \
+    postdep_objects_RC \
+    predeps_RC \
+    postdeps_RC \
+    compiler_lib_search_path_RC \
+    archive_cmds_RC \
+    archive_expsym_cmds_RC \
+    postinstall_cmds_RC \
+    postuninstall_cmds_RC \
+    old_archive_from_expsyms_cmds_RC \
+    allow_undefined_flag_RC \
+    no_undefined_flag_RC \
+    export_symbols_cmds_RC \
+    hardcode_libdir_flag_spec_RC \
+    hardcode_libdir_flag_spec_ld_RC \
+    hardcode_libdir_separator_RC \
+    hardcode_automatic_RC \
+    module_cmds_RC \
+    module_expsym_cmds_RC \
+    lt_cv_prog_compiler_c_o_RC \
+    fix_srcfile_path_RC \
+    exclude_expsyms_RC \
+    include_expsyms_RC; do
+
+    case $var in
+    old_archive_cmds_RC | \
+    old_archive_from_new_cmds_RC | \
+    archive_cmds_RC | \
+    archive_expsym_cmds_RC | \
+    module_cmds_RC | \
+    module_expsym_cmds_RC | \
+    old_archive_from_expsyms_cmds_RC | \
+    export_symbols_cmds_RC | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case $lt_echo in
+  *'\$0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+    ;;
+  esac
+
+cfgfile="$ofile"
+
+  cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_RC
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_RC
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_RC
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_RC
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_RC
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_RC
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_RC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_RC
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_RC
+archive_expsym_cmds=$lt_archive_expsym_cmds_RC
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_RC
+module_expsym_cmds=$lt_module_expsym_cmds_RC
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_RC
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_RC
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_RC
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_RC
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_RC
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_RC
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_RC
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_RC
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_RC
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_RC
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_RC
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_RC
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_RC
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_RC
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_RC
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_RC
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_RC
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+       ;;
+
+      *)
+       { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5
+echo "$as_me: error: Unsupported tag name: $tagname" >&2;}
+   { (exit 1); exit 1; }; }
+       ;;
+      esac
+
+      # Append the new tag name to the list of available tags.
+      if test -n "$tagname" ; then
+      available_tags="$available_tags $tagname"
+    fi
+    fi
+  done
+  IFS="$lt_save_ifs"
+
+  # Now substitute the updated list of available tags.
+  if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+    mv "${ofile}T" "$ofile"
+    chmod +x "$ofile"
+  else
+    rm -f "${ofile}T"
+    { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5
+echo "$as_me: error: unable to update list of available tagged configurations." >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+fi
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Prevent multiple expansion
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+  as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
+echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+  { echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; }
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir ();
+int
+main ()
+{
+return opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dir; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_search_opendir=$ac_res
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_opendir+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_opendir+set}" = set; then
+  :
+else
+  ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+else
+  { echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; }
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir ();
+int
+main ()
+{
+return opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' x; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_search_opendir=$ac_res
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_opendir+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_opendir+set}" = set; then
+  :
+else
+  ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+fi
+
+# Check whether --enable-ltdl-install was given.
+if test "${enable_ltdl_install+set}" = set; then
+  enableval=$enable_ltdl_install;
+fi
+
+
+ if test x"${enable_ltdl_install-no}" != xno; then
+  INSTALL_LTDL_TRUE=
+  INSTALL_LTDL_FALSE='#'
+else
+  INSTALL_LTDL_TRUE='#'
+  INSTALL_LTDL_FALSE=
+fi
+
+ if test x"${enable_ltdl_convenience-no}" != xno; then
+  CONVENIENCE_LTDL_TRUE=
+  CONVENIENCE_LTDL_FALSE='#'
+else
+  CONVENIENCE_LTDL_TRUE='#'
+  CONVENIENCE_LTDL_FALSE=
+fi
+
+
+
+{ echo "$as_me:$LINENO: checking which extension is used for loadable modules" >&5
+echo $ECHO_N "checking which extension is used for loadable modules... $ECHO_C" >&6; }
+if test "${libltdl_cv_shlibext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+module=yes
+eval libltdl_cv_shlibext=$shrext_cmds
+
+fi
+{ echo "$as_me:$LINENO: result: $libltdl_cv_shlibext" >&5
+echo "${ECHO_T}$libltdl_cv_shlibext" >&6; }
+if test -n "$libltdl_cv_shlibext"; then
+
+cat >>confdefs.h <<_ACEOF
+#define LTDL_SHLIB_EXT "$libltdl_cv_shlibext"
+_ACEOF
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking which variable specifies run-time library path" >&5
+echo $ECHO_N "checking which variable specifies run-time library path... $ECHO_C" >&6; }
+if test "${libltdl_cv_shlibpath_var+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  libltdl_cv_shlibpath_var="$shlibpath_var"
+fi
+{ echo "$as_me:$LINENO: result: $libltdl_cv_shlibpath_var" >&5
+echo "${ECHO_T}$libltdl_cv_shlibpath_var" >&6; }
+if test -n "$libltdl_cv_shlibpath_var"; then
+
+cat >>confdefs.h <<_ACEOF
+#define LTDL_SHLIBPATH_VAR "$libltdl_cv_shlibpath_var"
+_ACEOF
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for the default library search path" >&5
+echo $ECHO_N "checking for the default library search path... $ECHO_C" >&6; }
+if test "${libltdl_cv_sys_search_path+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec"
+fi
+{ echo "$as_me:$LINENO: result: $libltdl_cv_sys_search_path" >&5
+echo "${ECHO_T}$libltdl_cv_sys_search_path" >&6; }
+if test -n "$libltdl_cv_sys_search_path"; then
+  sys_search_path=
+  for dir in $libltdl_cv_sys_search_path; do
+    if test -z "$sys_search_path"; then
+      sys_search_path="$dir"
+    else
+      sys_search_path="$sys_search_path$PATH_SEPARATOR$dir"
+    fi
+  done
+
+cat >>confdefs.h <<_ACEOF
+#define LTDL_SYSSEARCHPATH "$sys_search_path"
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for objdir" >&5
+echo $ECHO_N "checking for objdir... $ECHO_C" >&6; }
+if test "${libltdl_cv_objdir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  libltdl_cv_objdir="$objdir"
+  if test -n "$objdir"; then
+    :
+  else
+    rm -f .libs 2>/dev/null
+    mkdir .libs 2>/dev/null
+    if test -d .libs; then
+      libltdl_cv_objdir=.libs
+    else
+      # MS-DOS does not allow filenames that begin with a dot.
+      libltdl_cv_objdir=_libs
+    fi
+  rmdir .libs 2>/dev/null
+  fi
+
+fi
+{ echo "$as_me:$LINENO: result: $libltdl_cv_objdir" >&5
+echo "${ECHO_T}$libltdl_cv_objdir" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define LTDL_OBJDIR "$libltdl_cv_objdir/"
+_ACEOF
+
+
+
+{ echo "$as_me:$LINENO: checking whether libtool supports -dlopen/-dlpreopen" >&5
+echo $ECHO_N "checking whether libtool supports -dlopen/-dlpreopen... $ECHO_C" >&6; }
+if test "${libltdl_cv_preloaded_symbols+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$lt_cv_sys_global_symbol_pipe"; then
+    libltdl_cv_preloaded_symbols=yes
+  else
+    libltdl_cv_preloaded_symbols=no
+  fi
+
+fi
+{ echo "$as_me:$LINENO: result: $libltdl_cv_preloaded_symbols" >&5
+echo "${ECHO_T}$libltdl_cv_preloaded_symbols" >&6; }
+if test x"$libltdl_cv_preloaded_symbols" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PRELOADED_SYMBOLS 1
+_ACEOF
+
+fi
+
+LIBADD_DL=
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for shl_load" >&5
+echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; }
+if test "${ac_cv_func_shl_load+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define shl_load innocuous_shl_load
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char shl_load (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef shl_load
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_shl_load || defined __stub___shl_load
+choke me
+#endif
+
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_shl_load=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_func_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+echo "${ECHO_T}$ac_cv_func_shl_load" >&6; }
+if test $ac_cv_func_shl_load = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SHL_LOAD 1
+_ACEOF
+
+else
+  { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dld_shl_load=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_dld_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; }
+if test $ac_cv_lib_dld_shl_load = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SHL_LOAD 1
+_ACEOF
+
+       LIBADD_DL="$LIBADD_DL -ldld"
+else
+  { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dl_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+
+               LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes"
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if HAVE_DLFCN_H
+#  include <dlfcn.h>
+#endif
+
+int
+main ()
+{
+dlopen(0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+ libltdl_cv_func_dlopen="yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_svld_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_svld_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; }
+if test $ac_cv_lib_svld_dlopen = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+
+                   LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes"
+else
+  { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dld_dld_link=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_dld_dld_link=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; }
+if test $ac_cv_lib_dld_dld_link = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DLD 1
+_ACEOF
+
+               LIBADD_DL="$LIBADD_DL -ldld"
+else
+  { echo "$as_me:$LINENO: checking for _dyld_func_lookup" >&5
+echo $ECHO_N "checking for _dyld_func_lookup... $ECHO_C" >&6; }
+if test "${ac_cv_func__dyld_func_lookup+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define _dyld_func_lookup to an innocuous variant, in case <limits.h> declares _dyld_func_lookup.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define _dyld_func_lookup innocuous__dyld_func_lookup
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char _dyld_func_lookup (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef _dyld_func_lookup
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char _dyld_func_lookup ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub__dyld_func_lookup || defined __stub____dyld_func_lookup
+choke me
+#endif
+
+int
+main ()
+{
+return _dyld_func_lookup ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func__dyld_func_lookup=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_func__dyld_func_lookup=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func__dyld_func_lookup" >&5
+echo "${ECHO_T}$ac_cv_func__dyld_func_lookup" >&6; }
+if test $ac_cv_func__dyld_func_lookup = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DYLD 1
+_ACEOF
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+
+fi
+
+
+fi
+
+
+fi
+
+
+if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes
+then
+  lt_save_LIBS="$LIBS"
+  LIBS="$LIBS $LIBADD_DL"
+
+for ac_func in dlerror
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+  LIBS="$lt_save_LIBS"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+{ echo "$as_me:$LINENO: checking for _ prefix in compiled symbols" >&5
+echo $ECHO_N "checking for _ prefix in compiled symbols... $ECHO_C" >&6; }
+if test "${ac_cv_sys_symbol_underscore+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_sys_symbol_underscore=no
+  cat > conftest.$ac_ext <<EOF
+void nm_test_func(){}
+int main(){nm_test_func;return 0;}
+EOF
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    # Now try to grab the symbols.
+    ac_nlist=conftest.nm
+    if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist\"") >&5
+  (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s "$ac_nlist"; then
+      # See whether the symbols have a leading underscore.
+      if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then
+        ac_cv_sys_symbol_underscore=yes
+      else
+        if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then
+         :
+        else
+         echo "configure: cannot find nm_test_func in $ac_nlist" >&5
+        fi
+      fi
+    else
+      echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "configure: failed program was:" >&5
+    cat conftest.c >&5
+  fi
+  rm -rf conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_symbol_underscore" >&5
+echo "${ECHO_T}$ac_cv_sys_symbol_underscore" >&6; }
+
+
+if test x"$ac_cv_sys_symbol_underscore" = xyes; then
+  if test x"$libltdl_cv_func_dlopen" = xyes ||
+     test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then
+       { echo "$as_me:$LINENO: checking whether we have to add an underscore for dlsym" >&5
+echo $ECHO_N "checking whether we have to add an underscore for dlsym... $ECHO_C" >&6; }
+if test "${libltdl_cv_need_uscore+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  libltdl_cv_need_uscore=unknown
+          save_LIBS="$LIBS"
+          LIBS="$LIBS $LIBADD_DL"
+         if test "$cross_compiling" = yes; then :
+  libltdl_cv_need_uscore=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+#line 20977 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+    exit (status);
+}
+EOF
+  if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) libltdl_cv_need_uscore=no ;;
+      x$lt_dlneed_uscore) libltdl_cv_need_uscore=yes ;;
+      x$lt_dlunknown|x*)  ;;
+    esac
+  else :
+    # compilation failed
+
+  fi
+fi
+rm -fr conftest*
+
+         LIBS="$save_LIBS"
+
+fi
+{ echo "$as_me:$LINENO: result: $libltdl_cv_need_uscore" >&5
+echo "${ECHO_T}$libltdl_cv_need_uscore" >&6; }
+  fi
+fi
+
+if test x"$libltdl_cv_need_uscore" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define NEED_USCORE 1
+_ACEOF
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking whether deplibs are loaded by dlopen" >&5
+echo $ECHO_N "checking whether deplibs are loaded by dlopen... $ECHO_C" >&6; }
+if test "${libltdl_cv_sys_dlopen_deplibs+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # PORTME does your system automatically load deplibs for dlopen?
+  # or its logical equivalent (e.g. shl_load for HP-UX < 11)
+  # For now, we just catch OSes we know something about -- in the
+  # future, we'll try test this programmatically.
+  libltdl_cv_sys_dlopen_deplibs=unknown
+  case "$host_os" in
+  aix3*|aix4.1.*|aix4.2.*)
+    # Unknown whether this is true for these versions of AIX, but
+    # we want this `case' here to explicitly catch those versions.
+    libltdl_cv_sys_dlopen_deplibs=unknown
+    ;;
+  aix[45]*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  darwin*)
+    # Assuming the user has installed a libdl from somewhere, this is true
+    # If you are looking for one http://www.opendarwin.org/projects/dlcompat
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  freebsd* | dragonfly*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  gnu* | linux* | k*bsd*-gnu)
+    # GNU and its variants, using gnu ld.so (Glibc)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  hpux10*|hpux11*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  interix*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  irix[12345]*|irix6.[01]*)
+    # Catch all versions of IRIX before 6.2, and indicate that we don't
+    # know how it worked for any of those versions.
+    libltdl_cv_sys_dlopen_deplibs=unknown
+    ;;
+  irix*)
+    # The case above catches anything before 6.2, and it's known that
+    # at 6.2 and later dlopen does load deplibs.
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  netbsd* | netbsdelf*-gnu)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  openbsd*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  osf[1234]*)
+    # dlopen did load deplibs (at least at 4.x), but until the 5.x series,
+    # it did *not* use an RPATH in a shared library to find objects the
+    # library depends on, so we explictly say `no'.
+    libltdl_cv_sys_dlopen_deplibs=no
+    ;;
+  osf5.0|osf5.0a|osf5.1)
+    # dlopen *does* load deplibs and with the right loader patch applied
+    # it even uses RPATH in a shared library to search for shared objects
+    # that the library depends on, but there's no easy way to know if that
+    # patch is installed.  Since this is the case, all we can really
+    # say is unknown -- it depends on the patch being installed.  If
+    # it is, this changes to `yes'.  Without it, it would be `no'.
+    libltdl_cv_sys_dlopen_deplibs=unknown
+    ;;
+  osf*)
+    # the two cases above should catch all versions of osf <= 5.1.  Read
+    # the comments above for what we know about them.
+    # At > 5.1, deplibs are loaded *and* any RPATH in a shared library
+    # is used to find them so we can finally say `yes'.
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  solaris*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  esac
+
+fi
+{ echo "$as_me:$LINENO: result: $libltdl_cv_sys_dlopen_deplibs" >&5
+echo "${ECHO_T}$libltdl_cv_sys_dlopen_deplibs" >&6; }
+if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define LTDL_DLOPEN_DEPLIBS 1
+_ACEOF
+
+fi
+
+
+for ac_header in argz.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ---------------------------------- ##
+## Report this to bug-libtool@gnu.org ##
+## ---------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ echo "$as_me:$LINENO: checking for error_t" >&5
+echo $ECHO_N "checking for error_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_error_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if HAVE_ARGZ_H
+#  include <argz.h>
+#endif
+
+typedef error_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_error_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_type_error_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_error_t" >&5
+echo "${ECHO_T}$ac_cv_type_error_t" >&6; }
+if test $ac_cv_type_error_t = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ERROR_T 1
+_ACEOF
+
+
+else
+
+cat >>confdefs.h <<\_ACEOF
+#define error_t int
+_ACEOF
+
+fi
+
+
+
+
+
+
+
+for ac_func in argz_append argz_create_sep argz_insert argz_next argz_stringify
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in assert.h ctype.h errno.h malloc.h memory.h stdlib.h \
+                 stdio.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ---------------------------------- ##
+## Report this to bug-libtool@gnu.org ##
+## ---------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+for ac_header in dl.h sys/dl.h dld.h mach-o/dyld.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ---------------------------------- ##
+## Report this to bug-libtool@gnu.org ##
+## ---------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in string.h strings.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ---------------------------------- ##
+## Report this to bug-libtool@gnu.org ##
+## ---------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ break
+fi
+
+done
+
+
+
+
+for ac_func in strchr index
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+ break
+fi
+done
+
+
+
+for ac_func in strrchr rindex
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+ break
+fi
+done
+
+
+
+for ac_func in memcpy bcopy
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+ break
+fi
+done
+
+
+
+for ac_func in memmove strcmp
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+for ac_func in closedir opendir readdir
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+## -------- ##
+## Outputs. ##
+## -------- ##
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${INSTALL_LTDL_TRUE}" && test -z "${INSTALL_LTDL_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"INSTALL_LTDL\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"INSTALL_LTDL\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${CONVENIENCE_LTDL_TRUE}" && test -z "${CONVENIENCE_LTDL_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"CONVENIENCE_LTDL\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"CONVENIENCE_LTDL\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+        test -d "$1/.";
+      else
+       case $1 in
+        -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by libltdl $as_me 1.2, which was
+generated by GNU Autoconf 2.61.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+                  instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+                  instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+libltdl config.status 1.2
+configured by $0, generated by GNU Autoconf 2.61,
+  with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  CONFIG_SHELL=$SHELL
+  export CONFIG_SHELL
+  exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:config-h.in" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+am__isrc!$am__isrc$ac_delim
+CYGPATH_W!$CYGPATH_W$ac_delim
+PACKAGE!$PACKAGE$ac_delim
+VERSION!$VERSION$ac_delim
+ACLOCAL!$ACLOCAL$ac_delim
+AUTOCONF!$AUTOCONF$ac_delim
+AUTOMAKE!$AUTOMAKE$ac_delim
+AUTOHEADER!$AUTOHEADER$ac_delim
+MAKEINFO!$MAKEINFO$ac_delim
+install_sh!$install_sh$ac_delim
+STRIP!$STRIP$ac_delim
+INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim
+mkdir_p!$mkdir_p$ac_delim
+AWK!$AWK$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+am__leading_dot!$am__leading_dot$ac_delim
+AMTAR!$AMTAR$ac_delim
+am__tar!$am__tar$ac_delim
+am__untar!$am__untar$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+DEPDIR!$DEPDIR$ac_delim
+am__include!$am__include$ac_delim
+am__quote!$am__quote$ac_delim
+AMDEP_TRUE!$AMDEP_TRUE$ac_delim
+AMDEP_FALSE!$AMDEP_FALSE$ac_delim
+AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim
+CCDEPMODE!$CCDEPMODE$ac_delim
+am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim
+am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+SED!$SED$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+LN_S!$LN_S$ac_delim
+ECHO!$ECHO$ac_delim
+AR!$AR$ac_delim
+RANLIB!$RANLIB$ac_delim
+DLLTOOL!$DLLTOOL$ac_delim
+AS!$AS$ac_delim
+OBJDUMP!$OBJDUMP$ac_delim
+CPP!$CPP$ac_delim
+CXX!$CXX$ac_delim
+CXXFLAGS!$CXXFLAGS$ac_delim
+ac_ct_CXX!$ac_ct_CXX$ac_delim
+_ACEOF
+
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
+    break
+  elif $ac_last_try; then
+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+  ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+CEOF$ac_eof
+_ACEOF
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
+CXXDEPMODE!$CXXDEPMODE$ac_delim
+am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim
+am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim
+CXXCPP!$CXXCPP$ac_delim
+F77!$F77$ac_delim
+FFLAGS!$FFLAGS$ac_delim
+ac_ct_F77!$ac_ct_F77$ac_delim
+LIBTOOL!$LIBTOOL$ac_delim
+LIBTOOL_DEPS!$LIBTOOL_DEPS$ac_delim
+INSTALL_LTDL_TRUE!$INSTALL_LTDL_TRUE$ac_delim
+INSTALL_LTDL_FALSE!$INSTALL_LTDL_FALSE$ac_delim
+CONVENIENCE_LTDL_TRUE!$CONVENIENCE_LTDL_TRUE$ac_delim
+CONVENIENCE_LTDL_FALSE!$CONVENIENCE_LTDL_FALSE$ac_delim
+LIBADD_DL!$LIBADD_DL$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 16; then
+    break
+  elif $ac_last_try; then
+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+  ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[    ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[      ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+   { (exit 1); exit 1; }; };;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+        # (if the path is not absolute).  The absolute path cannot be DOS-style,
+        # because $ac_f cannot contain `:'.
+        test -f "$ac_f" ||
+          case $ac_f in
+          [\\/$]*) false;;
+          *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+          esac ||
+          { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+   { (exit 1); exit 1; }; };;
+      esac
+      ac_file_inputs="$ac_file_inputs $ac_f"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input="Generated from "`IFS=:
+         echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    fi
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin";;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  { as_dir="$ac_dir"
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+    s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[         ]*datarootdir[  ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out"; rm -f "$tmp/out";;
+  *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+  esac
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status.  If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless.  But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([  #]*\\)[^        ]*\\([  ]*'
+ac_dB='\\)[     (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+  sed -n '
+       t rset
+       :rset
+       s/^[     ]*#[    ]*define[       ][      ]*//
+       t ok
+       d
+       :ok
+       s/[\\&,]/\\&/g
+       s/^\('"$ac_word_re"'\)\(([^()]*)\)[      ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+       s/^\('"$ac_word_re"'\)[  ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+  ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[    #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is:         sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is:        sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be:    sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+  # Write a here document:
+    cat >>$CONFIG_STATUS <<_ACEOF
+    # First, check the format of the line:
+    cat >"\$tmp/defines.sed" <<\\CEOF
+/^[     ]*#[    ]*undef[        ][      ]*$ac_word_re[  ]*\$/b def
+/^[     ]*#[    ]*define[       ][      ]*$ac_word_re[(         ]/b def
+b
+:def
+_ACEOF
+  sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+    sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+  ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+  sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+  grep . conftest.tail >/dev/null || break
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+  if test x"$ac_file" != x-; then
+    echo "/* $configure_input  */" >"$tmp/config.h"
+    cat "$ac_result" >>"$tmp/config.h"
+    if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f $ac_file
+      mv "$tmp/config.h" $ac_file
+    fi
+  else
+    echo "/* $configure_input  */"
+    cat "$ac_result"
+  fi
+  rm -f "$tmp/out12"
+# Compute $ac_file's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $ac_file | $ac_file:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $ac_file" >`$as_dirname -- $ac_file ||
+$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X$ac_file : 'X\(//\)[^/]' \| \
+        X$ac_file : 'X\(//\)$' \| \
+        X$ac_file : 'X\(/\)' \| . 2>/dev/null ||
+echo X$ac_file |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { echo "$as_me:$LINENO: executing $ac_file commands" >&5
+echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || 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" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$mf" : 'X\(//\)[^/]' \| \
+        X"$mf" : 'X\(//\)$' \| \
+        X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  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_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$file" : 'X\(//\)[^/]' \| \
+        X"$file" : 'X\(//\)$' \| \
+        X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+    { as_dir=$dirpart/$fdir
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+ ;;
+
+  esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
diff --git a/libltdl/configure.ac b/libltdl/configure.ac
new file mode 100644 (file)
index 0000000..1446efb
--- /dev/null
@@ -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
diff --git a/libltdl/install-sh b/libltdl/install-sh
new file mode 100755 (executable)
index 0000000..a5897de
--- /dev/null
@@ -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:
diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c
new file mode 100644 (file)
index 0000000..3a76ff1
--- /dev/null
@@ -0,0 +1,4530 @@
+/* ltdl.c -- system independent dlopen wrapper
+   Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006, 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
+
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#if HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+#if HAVE_STDIO_H
+#  include <stdio.h>
+#endif
+
+/* Include the header defining malloc.  On K&R C compilers,
+   that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>.  */
+#if HAVE_STDLIB_H
+#  include <stdlib.h>
+#else
+#  if HAVE_MALLOC_H
+#    include <malloc.h>
+#  endif
+#endif
+
+#if HAVE_STRING_H
+#  include <string.h>
+#else
+#  if HAVE_STRINGS_H
+#    include <strings.h>
+#  endif
+#endif
+
+#if HAVE_CTYPE_H
+#  include <ctype.h>
+#endif
+
+#if HAVE_MEMORY_H
+#  include <memory.h>
+#endif
+
+#if HAVE_ERRNO_H
+#  include <errno.h>
+#endif
+
+
+#ifndef __WINDOWS__
+#  ifdef __WIN32__
+#    define __WINDOWS__
+#  endif
+#endif
+
+
+#undef LT_USE_POSIX_DIRENT
+#ifdef HAVE_CLOSEDIR
+#  ifdef HAVE_OPENDIR
+#    ifdef HAVE_READDIR
+#      ifdef HAVE_DIRENT_H
+#        define LT_USE_POSIX_DIRENT
+#      endif /* HAVE_DIRENT_H */
+#    endif /* HAVE_READDIR */
+#  endif /* HAVE_OPENDIR */
+#endif /* HAVE_CLOSEDIR */
+
+
+#undef LT_USE_WINDOWS_DIRENT_EMULATION
+#ifndef LT_USE_POSIX_DIRENT
+#  ifdef __WINDOWS__
+#    define LT_USE_WINDOWS_DIRENT_EMULATION
+#  endif /* __WINDOWS__ */
+#endif /* LT_USE_POSIX_DIRENT */
+
+
+#ifdef LT_USE_POSIX_DIRENT
+#  include <dirent.h>
+#  define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
+#else
+#  ifdef LT_USE_WINDOWS_DIRENT_EMULATION
+#    define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
+#  else
+#    define dirent direct
+#    define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
+#    if HAVE_SYS_NDIR_H
+#      include <sys/ndir.h>
+#    endif
+#    if HAVE_SYS_DIR_H
+#      include <sys/dir.h>
+#    endif
+#    if HAVE_NDIR_H
+#      include <ndir.h>
+#    endif
+#  endif
+#endif
+
+#if HAVE_ARGZ_H
+#  include <argz.h>
+#endif
+
+#if HAVE_ASSERT_H
+#  include <assert.h>
+#else
+#  define assert(arg)  ((void) 0)
+#endif
+
+#include "ltdl.h"
+
+#if WITH_DMALLOC
+#  include <dmalloc.h>
+#endif
+
+
+
+
+/* --- WINDOWS SUPPORT --- */
+
+/* DLL building support on win32 hosts;  mostly to workaround their
+   ridiculous implementation of data symbol exporting. */
+#ifndef LT_GLOBAL_DATA
+#  if defined(__WINDOWS__) || defined(__CYGWIN__)
+#    ifdef DLL_EXPORT           /* defined by libtool (if required) */
+#      define LT_GLOBAL_DATA __declspec(dllexport)
+#    endif
+#  endif
+#  ifndef LT_GLOBAL_DATA        /* static linking or !__WINDOWS__ */
+#    define LT_GLOBAL_DATA
+#  endif
+#endif
+
+/* fopen() mode flags for reading a text file */
+#undef LT_READTEXT_MODE
+#if defined(__WINDOWS__) || defined(__CYGWIN__)
+#  define LT_READTEXT_MODE "rt"
+#else
+#  define LT_READTEXT_MODE "r"
+#endif
+
+#ifdef LT_USE_WINDOWS_DIRENT_EMULATION
+
+#include <windows.h>
+
+#define dirent lt_dirent
+#define DIR lt_DIR
+
+struct dirent
+{
+  char d_name[2048];
+  int  d_namlen;
+};
+
+typedef struct _DIR
+{
+  HANDLE hSearch;
+  WIN32_FIND_DATA Win32FindData;
+  BOOL firsttime;
+  struct dirent file_info;
+} DIR;
+
+#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
+
+
+/* --- MANIFEST CONSTANTS --- */
+
+
+/* Standard libltdl search path environment variable name  */
+#undef  LTDL_SEARCHPATH_VAR
+#define LTDL_SEARCHPATH_VAR    "LTDL_LIBRARY_PATH"
+
+/* Standard libtool archive file extension.  */
+#undef  LTDL_ARCHIVE_EXT
+#define LTDL_ARCHIVE_EXT       ".la"
+
+/* max. filename length */
+#ifndef LT_FILENAME_MAX
+#  define LT_FILENAME_MAX      1024
+#endif
+
+/* This is the maximum symbol size that won't require malloc/free */
+#undef LT_SYMBOL_LENGTH
+#define LT_SYMBOL_LENGTH       128
+
+/* This accounts for the _LTX_ separator */
+#undef LT_SYMBOL_OVERHEAD
+#define LT_SYMBOL_OVERHEAD     5
+
+
+
+
+/* --- MEMORY HANDLING --- */
+
+
+/* These are the functions used internally.  In addition to making
+   use of the associated function pointers above, they also perform
+   error handling.  */
+static char   *lt_estrdup      LT_PARAMS((const char *str));
+static lt_ptr lt_emalloc       LT_PARAMS((size_t size));
+static lt_ptr lt_erealloc      LT_PARAMS((lt_ptr addr, size_t size));
+
+/* static lt_ptr rpl_realloc   LT_PARAMS((lt_ptr ptr, size_t size)); */
+#define rpl_realloc realloc
+
+/* These are the pointers that can be changed by the caller:  */
+LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc)   LT_PARAMS((size_t size))
+                       = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
+LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc)  LT_PARAMS((lt_ptr ptr, size_t size))
+                       = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
+LT_GLOBAL_DATA void   (*lt_dlfree)     LT_PARAMS((lt_ptr ptr))
+                       = (void (*) LT_PARAMS((lt_ptr))) free;
+
+/* The following macros reduce the amount of typing needed to cast
+   assigned memory.  */
+#if WITH_DMALLOC
+
+#define LT_DLMALLOC(tp, n)     ((tp *) xmalloc ((n) * sizeof(tp)))
+#define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
+#define LT_DLFREE(p)                                           \
+       LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
+
+#define LT_EMALLOC(tp, n)      ((tp *) xmalloc ((n) * sizeof(tp)))
+#define LT_EREALLOC(tp, p, n)  ((tp *) xrealloc ((p), (n) * sizeof(tp)))
+
+#else
+
+#define LT_DLMALLOC(tp, n)     ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
+#define LT_DLREALLOC(tp, p, n) ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp)))
+#define LT_DLFREE(p)                                           \
+       LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
+
+#define LT_EMALLOC(tp, n)      ((tp *) lt_emalloc ((n) * sizeof(tp)))
+#define LT_EREALLOC(tp, p, n)  ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
+
+#endif
+
+#define LT_DLMEM_REASSIGN(p, q)                        LT_STMT_START { \
+       if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; }   \
+                                               } LT_STMT_END
+
+
+/* --- REPLACEMENT FUNCTIONS --- */
+
+
+#undef strdup
+#define strdup rpl_strdup
+
+static char *strdup LT_PARAMS((const char *str));
+
+static char *
+strdup(str)
+     const char *str;
+{
+  char *tmp = 0;
+
+  if (str)
+    {
+      tmp = LT_DLMALLOC (char, 1+ strlen (str));
+      if (tmp)
+       {
+         strcpy(tmp, str);
+       }
+    }
+
+  return tmp;
+}
+
+
+#if ! HAVE_STRCMP
+
+#undef strcmp
+#define strcmp rpl_strcmp
+
+static int strcmp LT_PARAMS((const char *str1, const char *str2));
+
+static int
+strcmp (str1, str2)
+     const char *str1;
+     const char *str2;
+{
+  if (str1 == str2)
+    return 0;
+  if (str1 == 0)
+    return -1;
+  if (str2 == 0)
+    return 1;
+
+  for (;*str1 && *str2; ++str1, ++str2)
+    {
+      if (*str1 != *str2)
+       break;
+    }
+
+  return (int)(*str1 - *str2);
+}
+#endif
+
+
+#if ! HAVE_STRCHR
+
+#  if HAVE_INDEX
+#    define strchr index
+#  else
+#    define strchr rpl_strchr
+
+static const char *strchr LT_PARAMS((const char *str, int ch));
+
+static const char*
+strchr(str, ch)
+     const char *str;
+     int ch;
+{
+  const char *p;
+
+  for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
+    /*NOWORK*/;
+
+  return (*p == (char)ch) ? p : 0;
+}
+
+#  endif
+#endif /* !HAVE_STRCHR */
+
+
+#if ! HAVE_STRRCHR
+
+#  if HAVE_RINDEX
+#    define strrchr rindex
+#  else
+#    define strrchr rpl_strrchr
+
+static const char *strrchr LT_PARAMS((const char *str, int ch));
+
+static const char*
+strrchr(str, ch)
+     const char *str;
+     int ch;
+{
+  const char *p, *q = 0;
+
+  for (p = str; *p != LT_EOS_CHAR; ++p)
+    {
+      if (*p == (char) ch)
+       {
+         q = p;
+       }
+    }
+
+  return q;
+}
+
+# endif
+#endif
+
+/* NOTE:  Neither bcopy nor the memcpy implementation below can
+          reliably handle copying in overlapping areas of memory.  Use
+          memmove (for which there is a fallback implmentation below)
+         if you need that behaviour.  */
+#if ! HAVE_MEMCPY
+
+#  if HAVE_BCOPY
+#    define memcpy(dest, src, size)    bcopy (src, dest, size)
+#  else
+#    define memcpy rpl_memcpy
+
+static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
+
+static lt_ptr
+memcpy (dest, src, size)
+     lt_ptr dest;
+     const lt_ptr src;
+     size_t size;
+{
+  const char * s = src;
+  char *       d = dest;
+  size_t       i = 0;
+
+  for (i = 0; i < size; ++i)
+    {
+      d[i] = s[i];
+    }
+
+  return dest;
+}
+
+#  endif /* !HAVE_BCOPY */
+#endif   /* !HAVE_MEMCPY */
+
+#if ! HAVE_MEMMOVE
+#  define memmove rpl_memmove
+
+static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
+
+static lt_ptr
+memmove (dest, src, size)
+     lt_ptr dest;
+     const lt_ptr src;
+     size_t size;
+{
+  const char * s = src;
+  char *       d = dest;
+  size_t       i;
+
+  if (d < s)
+    for (i = 0; i < size; ++i)
+      {
+       d[i] = s[i];
+      }
+  else if (d > s && size > 0)
+    for (i = size -1; ; --i)
+      {
+       d[i] = s[i];
+       if (i == 0)
+         break;
+      }
+
+  return dest;
+}
+
+#endif /* !HAVE_MEMMOVE */
+
+#ifdef LT_USE_WINDOWS_DIRENT_EMULATION
+
+static void closedir LT_PARAMS((DIR *entry));
+
+static void
+closedir(entry)
+  DIR *entry;
+{
+  assert(entry != (DIR *) NULL);
+  FindClose(entry->hSearch);
+  lt_dlfree((lt_ptr)entry);
+}
+
+
+static DIR * opendir LT_PARAMS((const char *path));
+
+static DIR*
+opendir (path)
+  const char *path;
+{
+  char file_specification[LT_FILENAME_MAX];
+  DIR *entry;
+
+  assert(path != (char *) NULL);
+  /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */
+  (void) strncpy (file_specification, path, LT_FILENAME_MAX-6);
+  file_specification[LT_FILENAME_MAX-6] = LT_EOS_CHAR;
+  (void) strcat(file_specification,"\\");
+  entry = LT_DLMALLOC (DIR,sizeof(DIR));
+  if (entry != (DIR *) 0)
+    {
+      entry->firsttime = TRUE;
+      entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
+    }
+  if (entry->hSearch == INVALID_HANDLE_VALUE)
+    {
+      (void) strcat(file_specification,"\\*.*");
+      entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
+      if (entry->hSearch == INVALID_HANDLE_VALUE)
+        {
+          LT_DLFREE (entry);
+          return (DIR *) 0;
+        }
+    }
+  return(entry);
+}
+
+
+static struct dirent *readdir LT_PARAMS((DIR *entry));
+
+static struct dirent *readdir(entry)
+  DIR *entry;
+{
+  int
+    status;
+
+  if (entry == (DIR *) 0)
+    return((struct dirent *) 0);
+  if (!entry->firsttime)
+    {
+      status = FindNextFile(entry->hSearch,&entry->Win32FindData);
+      if (status == 0)
+        return((struct dirent *) 0);
+    }
+  entry->firsttime = FALSE;
+  (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
+    LT_FILENAME_MAX-1);
+  entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR;
+  entry->file_info.d_namlen = strlen(entry->file_info.d_name);
+  return(&entry->file_info);
+}
+
+#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
+
+/* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
+    ``realloc is not entirely portable''
+   In any case we want to use the allocator supplied by the user without
+   burdening them with an lt_dlrealloc function pointer to maintain.
+   Instead implement our own version (with known boundary conditions)
+   using lt_dlmalloc and lt_dlfree. */
+
+/* #undef realloc
+   #define realloc rpl_realloc
+*/
+#if 0
+  /* You can't (re)define realloc unless you also (re)define malloc.
+     Right now, this code uses the size of the *destination* to decide
+     how much to copy.  That's not right, but you can't know the size
+     of the source unless you know enough about, or wrote malloc.  So
+     this code is disabled... */
+
+static lt_ptr
+realloc (ptr, size)
+     lt_ptr ptr;
+     size_t size;
+{
+  if (size == 0)
+    {
+      /* For zero or less bytes, free the original memory */
+      if (ptr != 0)
+       {
+         lt_dlfree (ptr);
+       }
+
+      return (lt_ptr) 0;
+    }
+  else if (ptr == 0)
+    {
+      /* Allow reallocation of a NULL pointer.  */
+      return lt_dlmalloc (size);
+    }
+  else
+    {
+      /* Allocate a new block, copy and free the old block.  */
+      lt_ptr mem = lt_dlmalloc (size);
+
+      if (mem)
+       {
+         memcpy (mem, ptr, size);
+         lt_dlfree (ptr);
+       }
+
+      /* Note that the contents of PTR are not damaged if there is
+        insufficient memory to realloc.  */
+      return mem;
+    }
+}
+#endif
+
+
+#if ! HAVE_ARGZ_APPEND
+#  define argz_append rpl_argz_append
+
+static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
+                                       const char *buf, size_t buf_len));
+
+static error_t
+argz_append (pargz, pargz_len, buf, buf_len)
+     char **pargz;
+     size_t *pargz_len;
+     const char *buf;
+     size_t buf_len;
+{
+  size_t argz_len;
+  char  *argz;
+
+  assert (pargz);
+  assert (pargz_len);
+  assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
+
+  /* If nothing needs to be appended, no more work is required.  */
+  if (buf_len == 0)
+    return 0;
+
+  /* Ensure there is enough room to append BUF_LEN.  */
+  argz_len = *pargz_len + buf_len;
+  argz = LT_DLREALLOC (char, *pargz, argz_len);
+  if (!argz)
+    return ENOMEM;
+
+  /* Copy characters from BUF after terminating '\0' in ARGZ.  */
+  memcpy (argz + *pargz_len, buf, buf_len);
+
+  /* Assign new values.  */
+  *pargz = argz;
+  *pargz_len = argz_len;
+
+  return 0;
+}
+#endif /* !HAVE_ARGZ_APPEND */
+
+
+#if ! HAVE_ARGZ_CREATE_SEP
+#  define argz_create_sep rpl_argz_create_sep
+
+static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
+                                           char **pargz, size_t *pargz_len));
+
+static error_t
+argz_create_sep (str, delim, pargz, pargz_len)
+     const char *str;
+     int delim;
+     char **pargz;
+     size_t *pargz_len;
+{
+  size_t argz_len;
+  char *argz = 0;
+
+  assert (str);
+  assert (pargz);
+  assert (pargz_len);
+
+  /* Make a copy of STR, but replacing each occurrence of
+     DELIM with '\0'.  */
+  argz_len = 1+ LT_STRLEN (str);
+  if (argz_len)
+    {
+      const char *p;
+      char *q;
+
+      argz = LT_DLMALLOC (char, argz_len);
+      if (!argz)
+       return ENOMEM;
+
+      for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
+       {
+         if (*p == delim)
+           {
+             /* Ignore leading delimiters, and fold consecutive
+                delimiters in STR into a single '\0' in ARGZ.  */
+             if ((q > argz) && (q[-1] != LT_EOS_CHAR))
+               *q++ = LT_EOS_CHAR;
+             else
+               --argz_len;
+           }
+         else
+           *q++ = *p;
+       }
+      /* Copy terminating LT_EOS_CHAR.  */
+      *q = *p;
+    }
+
+  /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory.  */
+  if (!argz_len)
+    LT_DLFREE (argz);
+
+  /* Assign new values.  */
+  *pargz = argz;
+  *pargz_len = argz_len;
+
+  return 0;
+}
+#endif /* !HAVE_ARGZ_CREATE_SEP */
+
+
+#if ! HAVE_ARGZ_INSERT
+#  define argz_insert rpl_argz_insert
+
+static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
+                                       char *before, const char *entry));
+
+static error_t
+argz_insert (pargz, pargz_len, before, entry)
+     char **pargz;
+     size_t *pargz_len;
+     char *before;
+     const char *entry;
+{
+  assert (pargz);
+  assert (pargz_len);
+  assert (entry && *entry);
+
+  /* No BEFORE address indicates ENTRY should be inserted after the
+     current last element.  */
+  if (!before)
+    return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
+
+  /* This probably indicates a programmer error, but to preserve
+     semantics, scan back to the start of an entry if BEFORE points
+     into the middle of it.  */
+  while ((before > *pargz) && (before[-1] != LT_EOS_CHAR))
+    --before;
+
+  {
+    size_t entry_len   = 1+ LT_STRLEN (entry);
+    size_t argz_len    = *pargz_len + entry_len;
+    size_t offset      = before - *pargz;
+    char   *argz       = LT_DLREALLOC (char, *pargz, argz_len);
+
+    if (!argz)
+      return ENOMEM;
+
+    /* Make BEFORE point to the equivalent offset in ARGZ that it
+       used to have in *PARGZ incase realloc() moved the block.  */
+    before = argz + offset;
+
+    /* Move the ARGZ entries starting at BEFORE up into the new
+       space at the end -- making room to copy ENTRY into the
+       resulting gap.  */
+    memmove (before + entry_len, before, *pargz_len - offset);
+    memcpy  (before, entry, entry_len);
+
+    /* Assign new values.  */
+    *pargz = argz;
+    *pargz_len = argz_len;
+  }
+
+  return 0;
+}
+#endif /* !HAVE_ARGZ_INSERT */
+
+
+#if ! HAVE_ARGZ_NEXT
+#  define argz_next rpl_argz_next
+
+static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
+                                   const char *entry));
+
+static char *
+argz_next (argz, argz_len, entry)
+     char *argz;
+     size_t argz_len;
+     const char *entry;
+{
+  assert ((argz && argz_len) || (!argz && !argz_len));
+
+  if (entry)
+    {
+      /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
+        within the ARGZ vector.  */
+      assert ((!argz && !argz_len)
+             || ((argz <= entry) && (entry < (argz + argz_len))));
+
+      /* Move to the char immediately after the terminating
+        '\0' of ENTRY.  */
+      entry = 1+ strchr (entry, LT_EOS_CHAR);
+
+      /* Return either the new ENTRY, or else NULL if ARGZ is
+        exhausted.  */
+      return (entry >= argz + argz_len) ? 0 : (char *) entry;
+    }
+  else
+    {
+      /* This should probably be flagged as a programmer error,
+        since starting an argz_next loop with the iterator set
+        to ARGZ is safer.  To preserve semantics, handle the NULL
+        case by returning the start of ARGZ (if any).  */
+      if (argz_len > 0)
+       return argz;
+      else
+       return 0;
+    }
+}
+#endif /* !HAVE_ARGZ_NEXT */
+
+
+
+#if ! HAVE_ARGZ_STRINGIFY
+#  define argz_stringify rpl_argz_stringify
+
+static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
+                                      int sep));
+
+static void
+argz_stringify (argz, argz_len, sep)
+     char *argz;
+     size_t argz_len;
+     int sep;
+{
+  assert ((argz && argz_len) || (!argz && !argz_len));
+
+  if (sep)
+    {
+      --argz_len;              /* don't stringify the terminating EOS */
+      while (--argz_len > 0)
+       {
+         if (argz[argz_len] == LT_EOS_CHAR)
+           argz[argz_len] = sep;
+       }
+    }
+}
+#endif /* !HAVE_ARGZ_STRINGIFY */
+
+
+
+
+/* --- TYPE DEFINITIONS -- */
+
+
+/* This type is used for the array of caller data sets in each handler. */
+typedef struct {
+  lt_dlcaller_id       key;
+  lt_ptr               data;
+} lt_caller_data;
+
+
+
+
+/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
+
+
+/* Extract the diagnostic strings from the error table macro in the same
+   order as the enumerated indices in ltdl.h. */
+
+static const char *lt_dlerror_strings[] =
+  {
+#define LT_ERROR(name, diagnostic)     (diagnostic),
+    lt_dlerror_table
+#undef LT_ERROR
+
+    0
+  };
+
+/* This structure is used for the list of registered loaders. */
+struct lt_dlloader {
+  struct lt_dlloader   *next;
+  const char          *loader_name;    /* identifying name for each loader */
+  const char          *sym_prefix;     /* prefix for symbols */
+  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;
+};
+
+struct lt_dlhandle_struct {
+  struct lt_dlhandle_struct   *next;
+  lt_dlloader         *loader;         /* dlopening interface */
+  lt_dlinfo            info;
+  int                  depcount;       /* number of dependencies */
+  lt_dlhandle         *deplibs;        /* dependencies */
+  lt_module            module;         /* system module handle */
+  lt_ptr               system;         /* system specific data */
+  lt_caller_data       *caller_data;   /* per caller associated data */
+  int                  flags;          /* various boolean stats */
+};
+
+/* Various boolean flags can be stored in the flags field of an
+   lt_dlhandle_struct... */
+#define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
+#define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
+
+#define LT_DLRESIDENT_FLAG         (0x01 << 0)
+/* ...add more flags here... */
+
+#define LT_DLIS_RESIDENT(handle)    LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
+
+
+#define LT_DLSTRERROR(name)    lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
+
+static const char      objdir[]                = LTDL_OBJDIR;
+static const char      archive_ext[]           = LTDL_ARCHIVE_EXT;
+#ifdef LTDL_SHLIB_EXT
+static const char      shlib_ext[]             = LTDL_SHLIB_EXT;
+#endif
+#ifdef LTDL_SYSSEARCHPATH
+static const char      sys_search_path[]       = LTDL_SYSSEARCHPATH;
+#endif
+
+
+
+
+/* --- MUTEX LOCKING --- */
+
+
+/* Macros to make it easier to run the lock functions only if they have
+   been registered.  The reason for the complicated lock macro is to
+   ensure that the stored error message from the last error is not
+   accidentally erased if the current function doesn't generate an
+   error of its own.  */
+#define LT_DLMUTEX_LOCK()                      LT_STMT_START { \
+       if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)();    \
+                                               } LT_STMT_END
+#define LT_DLMUTEX_UNLOCK()                    LT_STMT_START { \
+       if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
+                                               } LT_STMT_END
+#define LT_DLMUTEX_SETERROR(errormsg)          LT_STMT_START { \
+       if (lt_dlmutex_seterror_func)                           \
+               (*lt_dlmutex_seterror_func) (errormsg);         \
+       else    lt_dllast_error = (errormsg);   } LT_STMT_END
+#define LT_DLMUTEX_GETERROR(errormsg)          LT_STMT_START { \
+       if (lt_dlmutex_geterror_func)                           \
+               (errormsg) = (*lt_dlmutex_geterror_func) ();    \
+       else    (errormsg) = lt_dllast_error;   } LT_STMT_END
+
+/* The mutex functions stored here are global, and are necessarily the
+   same for all threads that wish to share access to libltdl.  */
+static lt_dlmutex_lock     *lt_dlmutex_lock_func     = 0;
+static lt_dlmutex_unlock   *lt_dlmutex_unlock_func   = 0;
+static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
+static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
+static const char          *lt_dllast_error          = 0;
+
+
+/* Either set or reset the mutex functions.  Either all the arguments must
+   be valid functions, or else all can be NULL to turn off locking entirely.
+   The registered functions should be manipulating a static global lock
+   from the lock() and unlock() callbacks, which needs to be reentrant.  */
+int
+lt_dlmutex_register (lock, unlock, seterror, geterror)
+     lt_dlmutex_lock *lock;
+     lt_dlmutex_unlock *unlock;
+     lt_dlmutex_seterror *seterror;
+     lt_dlmutex_geterror *geterror;
+{
+  lt_dlmutex_unlock *old_unlock = lt_dlmutex_unlock_func;
+  int               errors     = 0;
+
+  /* Lock using the old lock() callback, if any.  */
+  LT_DLMUTEX_LOCK ();
+
+  if ((lock && unlock && seterror && geterror)
+      || !(lock || unlock || seterror || geterror))
+    {
+      lt_dlmutex_lock_func     = lock;
+      lt_dlmutex_unlock_func   = unlock;
+      lt_dlmutex_seterror_func = seterror;
+      lt_dlmutex_geterror_func = geterror;
+    }
+  else
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
+      ++errors;
+    }
+
+  /* Use the old unlock() callback we saved earlier, if any.  Otherwise
+     record any errors using internal storage.  */
+  if (old_unlock)
+    (*old_unlock) ();
+
+  /* Return the number of errors encountered during the execution of
+     this function.  */
+  return errors;
+}
+
+
+
+
+/* --- ERROR HANDLING --- */
+
+
+static const char    **user_error_strings      = 0;
+static int             errorcount              = LT_ERROR_MAX;
+
+int
+lt_dladderror (diagnostic)
+     const char *diagnostic;
+{
+  int          errindex = 0;
+  int          result   = -1;
+  const char  **temp     = (const char **) 0;
+
+  assert (diagnostic);
+
+  LT_DLMUTEX_LOCK ();
+
+  errindex = errorcount - LT_ERROR_MAX;
+  temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
+  if (temp)
+    {
+      user_error_strings               = temp;
+      user_error_strings[errindex]     = diagnostic;
+      result                           = errorcount++;
+    }
+
+  LT_DLMUTEX_UNLOCK ();
+
+  return result;
+}
+
+int
+lt_dlseterror (errindex)
+     int errindex;
+{
+  int          errors   = 0;
+
+  LT_DLMUTEX_LOCK ();
+
+  if (errindex >= errorcount || errindex < 0)
+    {
+      /* Ack!  Error setting the error message! */
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
+      ++errors;
+    }
+  else if (errindex < LT_ERROR_MAX)
+    {
+      /* No error setting the error message! */
+      LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
+    }
+  else
+    {
+      /* No error setting the error message! */
+      LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
+    }
+
+  LT_DLMUTEX_UNLOCK ();
+
+  return errors;
+}
+
+static lt_ptr
+lt_emalloc (size)
+     size_t size;
+{
+  lt_ptr mem = lt_dlmalloc (size);
+  if (size && !mem)
+    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
+  return mem;
+}
+
+static lt_ptr
+lt_erealloc (addr, size)
+     lt_ptr addr;
+     size_t size;
+{
+  lt_ptr mem = lt_dlrealloc (addr, size);
+  if (size && !mem)
+    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
+  return mem;
+}
+
+static char *
+lt_estrdup (str)
+     const char *str;
+{
+  char *copy = strdup (str);
+  if (LT_STRLEN (str) && !copy)
+    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
+  return copy;
+}
+
+
+
+
+/* --- DLOPEN() INTERFACE LOADER --- */
+
+
+#if HAVE_LIBDL
+
+/* dynamic linking with dlopen/dlsym */
+
+#if HAVE_DLFCN_H
+#  include <dlfcn.h>
+#endif
+
+#if HAVE_SYS_DL_H
+#  include <sys/dl.h>
+#endif
+
+/* We may have to define LT_LAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_LAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_LAZY_OR_NOW     RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_LAZY_OR_NOW   DL_LAZY
+#    endif
+#  endif /* !RTLD_LAZY */
+#endif
+#ifndef LT_LAZY_OR_NOW
+#  ifdef RTLD_NOW
+#    define LT_LAZY_OR_NOW     RTLD_NOW
+#  else
+#    ifdef DL_NOW
+#      define LT_LAZY_OR_NOW   DL_NOW
+#    endif
+#  endif /* !RTLD_NOW */
+#endif
+#ifndef LT_LAZY_OR_NOW
+#  define LT_LAZY_OR_NOW       0
+#endif /* !LT_LAZY_OR_NOW */
+
+#if HAVE_DLERROR
+#  define DLERROR(arg) dlerror ()
+#else
+#  define DLERROR(arg) LT_DLSTRERROR (arg)
+#endif
+
+static lt_module
+sys_dl_open (loader_data, filename)
+     lt_user_data loader_data;
+     const char *filename;
+{
+  lt_module   module   = dlopen (filename, LT_LAZY_OR_NOW);
+
+  if (!module)
+    {
+      LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
+    }
+
+  return module;
+}
+
+static int
+sys_dl_close (loader_data, module)
+     lt_user_data loader_data;
+     lt_module module;
+{
+  int errors = 0;
+
+  if (dlclose (module) != 0)
+    {
+      LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
+      ++errors;
+    }
+
+  return errors;
+}
+
+static lt_ptr
+sys_dl_sym (loader_data, module, symbol)
+     lt_user_data loader_data;
+     lt_module module;
+     const char *symbol;
+{
+  lt_ptr address = dlsym (module, symbol);
+
+  if (!address)
+    {
+      LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
+    }
+
+  return address;
+}
+
+static struct lt_user_dlloader sys_dl =
+  {
+#  ifdef NEED_USCORE
+    "_",
+#  else
+    0,
+#  endif
+    sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
+
+
+#endif /* HAVE_LIBDL */
+
+
+
+/* --- SHL_LOAD() INTERFACE LOADER --- */
+
+#if HAVE_SHL_LOAD
+
+/* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
+
+#ifdef HAVE_DL_H
+#  include <dl.h>
+#endif
+
+/* some flags are missing on some systems, so we provide
+ * harmless defaults.
+ *
+ * Mandatory:
+ * BIND_IMMEDIATE  - Resolve symbol references when the library is loaded.
+ * BIND_DEFERRED   - Delay code symbol resolution until actual reference.
+ *
+ * Optionally:
+ * BIND_FIRST     - Place the library at the head of the symbol search
+ *                  order.
+ * BIND_NONFATAL   - The default BIND_IMMEDIATE behavior is to treat all
+ *                  unsatisfied symbols as fatal.  This flag allows
+ *                  binding of unsatisfied code symbols to be deferred
+ *                  until use.
+ *                  [Perl: For certain libraries, like DCE, deferred
+ *                  binding often causes run time problems. Adding
+ *                  BIND_NONFATAL to BIND_IMMEDIATE still allows
+ *                  unresolved references in situations like this.]
+ * BIND_NOSTART           - Do not call the initializer for the shared library
+ *                  when the library is loaded, nor on a future call to
+ *                  shl_unload().
+ * BIND_VERBOSE           - Print verbose messages concerning possible
+ *                  unsatisfied symbols.
+ *
+ * hp9000s700/hp9000s800:
+ * BIND_RESTRICTED - Restrict symbols visible by the library to those
+ *                  present at library load time.
+ * DYNAMIC_PATH           - Allow the loader to dynamically search for the
+ *                  library specified by the path argument.
+ */
+
+#ifndef        DYNAMIC_PATH
+#  define DYNAMIC_PATH         0
+#endif
+#ifndef        BIND_RESTRICTED
+#  define BIND_RESTRICTED      0
+#endif
+
+#define        LT_BIND_FLAGS   (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
+
+static lt_module
+sys_shl_open (loader_data, filename)
+     lt_user_data loader_data;
+     const char *filename;
+{
+  static shl_t self = (shl_t) 0;
+  lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
+
+  /* Since searching for a symbol against a NULL module handle will also
+     look in everything else that was already loaded and exported with
+     the -E compiler flag, we always cache a handle saved before any
+     modules are loaded.  */
+  if (!self)
+    {
+      lt_ptr address;
+      shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
+    }
+
+  if (!filename)
+    {
+      module = self;
+    }
+  else
+    {
+      module = shl_load (filename, LT_BIND_FLAGS, 0L);
+
+      if (!module)
+       {
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
+       }
+    }
+
+  return module;
+}
+
+static int
+sys_shl_close (loader_data, module)
+     lt_user_data loader_data;
+     lt_module module;
+{
+  int errors = 0;
+
+  if (module && (shl_unload ((shl_t) (module)) != 0))
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
+      ++errors;
+    }
+
+  return errors;
+}
+
+static lt_ptr
+sys_shl_sym (loader_data, module, symbol)
+     lt_user_data loader_data;
+     lt_module module;
+     const char *symbol;
+{
+  lt_ptr address = 0;
+
+  /* sys_shl_open should never return a NULL module handle */
+  if (module == (lt_module) 0)
+  {
+    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
+  }
+  else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
+    {
+      if (!address)
+       {
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
+       }
+    }
+
+  return address;
+}
+
+static struct lt_user_dlloader sys_shl = {
+  0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
+};
+
+#endif /* HAVE_SHL_LOAD */
+
+
+
+
+/* --- LOADLIBRARY() INTERFACE LOADER --- */
+
+#ifdef __WINDOWS__
+
+/* dynamic linking for Win32 */
+
+#include <windows.h>
+
+/* Forward declaration; required to implement handle search below. */
+static lt_dlhandle handles;
+
+static lt_module
+sys_wll_open (loader_data, filename)
+     lt_user_data loader_data;
+     const char *filename;
+{
+  lt_dlhandle  cur;
+  lt_module    module     = 0;
+  const char   *errormsg   = 0;
+  char        *searchname = 0;
+  char        *ext;
+  char         self_name_buf[MAX_PATH];
+
+  if (!filename)
+    {
+      /* Get the name of main module */
+      *self_name_buf = 0;
+      GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
+      filename = ext = self_name_buf;
+    }
+  else
+    {
+      ext = strrchr (filename, '.');
+    }
+
+  if (ext)
+    {
+      /* FILENAME already has an extension. */
+      searchname = lt_estrdup (filename);
+    }
+  else
+    {
+      /* Append a `.' to stop Windows from adding an
+        implicit `.dll' extension. */
+      searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
+      if (searchname)
+       sprintf (searchname, "%s.", filename);
+    }
+  if (!searchname)
+    return 0;
+
+  {
+    /* Silence dialog from LoadLibrary on some failures.
+       No way to get the error mode, but to set it,
+       so set it twice to preserve any previous flags. */
+    UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
+    SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
+
+#if defined(__CYGWIN__)
+    {
+      char wpath[MAX_PATH];
+      cygwin_conv_to_full_win32_path (searchname, wpath);
+      module = LoadLibrary (wpath);
+    }
+#else
+    module = LoadLibrary (searchname);
+#endif
+
+    /* Restore the error mode. */
+    SetErrorMode(errormode);
+  }
+
+  LT_DLFREE (searchname);
+
+  /* libltdl expects this function to fail if it is unable
+     to physically load the library.  Sadly, LoadLibrary
+     will search the loaded libraries for a match and return
+     one of them if the path search load fails.
+
+     We check whether LoadLibrary is returning a handle to
+     an already loaded module, and simulate failure if we
+     find one. */
+  LT_DLMUTEX_LOCK ();
+  cur = handles;
+  while (cur)
+    {
+      if (!cur->module)
+       {
+         cur = 0;
+         break;
+       }
+
+      if (cur->module == module)
+       {
+         break;
+       }
+
+      cur = cur->next;
+  }
+  LT_DLMUTEX_UNLOCK ();
+
+  if (cur || !module)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
+      module = 0;
+    }
+
+  return module;
+}
+
+static int
+sys_wll_close (loader_data, module)
+     lt_user_data loader_data;
+     lt_module module;
+{
+  int        errors   = 0;
+
+  if (FreeLibrary(module) == 0)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
+      ++errors;
+    }
+
+  return errors;
+}
+
+static lt_ptr
+sys_wll_sym (loader_data, module, symbol)
+     lt_user_data loader_data;
+     lt_module module;
+     const char *symbol;
+{
+  lt_ptr      address  = GetProcAddress (module, symbol);
+
+  if (!address)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
+    }
+
+  return address;
+}
+
+static struct lt_user_dlloader sys_wll = {
+  0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
+};
+
+#endif /* __WINDOWS__ */
+
+
+
+
+/* --- LOAD_ADD_ON() INTERFACE LOADER --- */
+
+
+#ifdef __BEOS__
+
+/* dynamic linking for BeOS */
+
+#include <kernel/image.h>
+
+static lt_module
+sys_bedl_open (loader_data, filename)
+     lt_user_data loader_data;
+     const char *filename;
+{
+  image_id image = 0;
+
+  if (filename)
+    {
+      image = load_add_on (filename);
+    }
+  else
+    {
+      image_info info;
+      int32 cookie = 0;
+      if (get_next_image_info (0, &cookie, &info) == B_OK)
+       image = load_add_on (info.name);
+    }
+
+  if (image <= 0)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
+      image = 0;
+    }
+
+  return (lt_module) image;
+}
+
+static int
+sys_bedl_close (loader_data, module)
+     lt_user_data loader_data;
+     lt_module module;
+{
+  int errors = 0;
+
+  if (unload_add_on ((image_id) module) != B_OK)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
+      ++errors;
+    }
+
+  return errors;
+}
+
+static lt_ptr
+sys_bedl_sym (loader_data, module, symbol)
+     lt_user_data loader_data;
+     lt_module module;
+     const char *symbol;
+{
+  lt_ptr address = 0;
+  image_id image = (image_id) module;
+
+  if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
+      address = 0;
+    }
+
+  return address;
+}
+
+static struct lt_user_dlloader sys_bedl = {
+  0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
+};
+
+#endif /* __BEOS__ */
+
+
+
+
+/* --- DLD_LINK() INTERFACE LOADER --- */
+
+
+#if HAVE_DLD
+
+/* dynamic linking with dld */
+
+#if HAVE_DLD_H
+#include <dld.h>
+#endif
+
+static lt_module
+sys_dld_open (loader_data, filename)
+     lt_user_data loader_data;
+     const char *filename;
+{
+  lt_module module = strdup (filename);
+
+  if (dld_link (filename) != 0)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
+      LT_DLFREE (module);
+      module = 0;
+    }
+
+  return module;
+}
+
+static int
+sys_dld_close (loader_data, module)
+     lt_user_data loader_data;
+     lt_module module;
+{
+  int errors = 0;
+
+  if (dld_unlink_by_file ((char*)(module), 1) != 0)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
+      ++errors;
+    }
+  else
+    {
+      LT_DLFREE (module);
+    }
+
+  return errors;
+}
+
+static lt_ptr
+sys_dld_sym (loader_data, module, symbol)
+     lt_user_data loader_data;
+     lt_module module;
+     const char *symbol;
+{
+  lt_ptr address = dld_get_func (symbol);
+
+  if (!address)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
+    }
+
+  return address;
+}
+
+static struct lt_user_dlloader sys_dld = {
+  0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
+};
+
+#endif /* HAVE_DLD */
+
+/* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
+#if HAVE_DYLD
+
+
+#if HAVE_MACH_O_DYLD_H
+#if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
+/* Is this correct? Does it still function properly? */
+#define __private_extern__ extern
+#endif
+# include <mach-o/dyld.h>
+#endif
+#include <mach-o/getsect.h>
+
+/* We have to put some stuff here that isn't in older dyld.h files */
+#ifndef ENUM_DYLD_BOOL
+# define ENUM_DYLD_BOOL
+# undef FALSE
+# undef TRUE
+ enum DYLD_BOOL {
+    FALSE,
+    TRUE
+ };
+#endif
+#ifndef LC_REQ_DYLD
+# define LC_REQ_DYLD 0x80000000
+#endif
+#ifndef LC_LOAD_WEAK_DYLIB
+# define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
+#endif
+static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
+static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
+static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
+static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
+
+#ifndef NSADDIMAGE_OPTION_NONE
+#define NSADDIMAGE_OPTION_NONE                          0x0
+#endif
+#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
+#define NSADDIMAGE_OPTION_RETURN_ON_ERROR               0x1
+#endif
+#ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
+#define NSADDIMAGE_OPTION_WITH_SEARCHING                0x2
+#endif
+#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
+#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED         0x4
+#endif
+#ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
+#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
+#endif
+#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
+#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND            0x0
+#endif
+#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
+#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW        0x1
+#endif
+#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
+#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY      0x2
+#endif
+#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
+#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
+#endif
+
+
+static const char *
+lt_int_dyld_error(othererror)
+       char* othererror;
+{
+/* return the dyld error string, or the passed in error string if none */
+       NSLinkEditErrors ler;
+       int lerno;
+       const char *errstr;
+       const char *file;
+       NSLinkEditError(&ler,&lerno,&file,&errstr);
+       if (!errstr || !strlen(errstr)) errstr = othererror;
+       return errstr;
+}
+
+static const struct mach_header *
+lt_int_dyld_get_mach_header_from_nsmodule(module)
+       NSModule module;
+{
+/* There should probably be an apple dyld api for this */
+       int i=_dyld_image_count();
+       int j;
+       const char *modname=NSNameOfModule(module);
+       const struct mach_header *mh=NULL;
+       if (!modname) return NULL;
+       for (j = 0; j < i; j++)
+       {
+               if (!strcmp(_dyld_get_image_name(j),modname))
+               {
+                       mh=_dyld_get_image_header(j);
+                       break;
+               }
+       }
+       return mh;
+}
+
+static const char* lt_int_dyld_lib_install_name(mh)
+       const struct mach_header *mh;
+{
+/* NSAddImage is also used to get the loaded image, but it only works if the lib
+   is installed, for uninstalled libs we need to check the install_names against
+   each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
+   different lib was loaded as a result
+*/
+       int j;
+       struct load_command *lc;
+       unsigned long offset = sizeof(struct mach_header);
+       const char* retStr=NULL;
+       for (j = 0; j < mh->ncmds; j++)
+       {
+               lc = (struct load_command*)(((unsigned long)mh) + offset);
+               if (LC_ID_DYLIB == lc->cmd)
+               {
+                       retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
+                                                                       (unsigned long)lc);
+               }
+               offset += lc->cmdsize;
+       }
+       return retStr;
+}
+
+static const struct mach_header *
+lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
+{
+       int i=_dyld_image_count();
+       int j;
+       const struct mach_header *mh=NULL;
+       const char *id=NULL;
+       for (j = 0; j < i; j++)
+       {
+               id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
+               if ((id) && (!strcmp(id,name)))
+               {
+                       mh=_dyld_get_image_header(j);
+                       break;
+               }
+       }
+       return mh;
+}
+
+static NSSymbol
+lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
+       const char *symbol;
+       const struct mach_header *mh;
+{
+       /* Safe to assume our mh is good */
+       int j;
+       struct load_command *lc;
+       unsigned long offset = sizeof(struct mach_header);
+       NSSymbol retSym = 0;
+       const struct mach_header *mh1;
+       if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
+       {
+               for (j = 0; j < mh->ncmds; j++)
+               {
+                       lc = (struct load_command*)(((unsigned long)mh) + offset);
+                       if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
+                       {
+                               mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
+                                                                               (unsigned long)lc));
+                               if (!mh1)
+                               {
+                                       /* Maybe NSAddImage can find it */
+                                       mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
+                                                                               (unsigned long)lc),
+                                                                               NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
+                                                                               NSADDIMAGE_OPTION_WITH_SEARCHING +
+                                                                               NSADDIMAGE_OPTION_RETURN_ON_ERROR );
+                               }
+                               if (mh1)
+                               {
+                                       retSym = ltdl_NSLookupSymbolInImage(mh1,
+                                                                                       symbol,
+                                                                                       NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
+                                                                                       | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
+                                                                                       );
+                                       if (retSym) break;
+                               }
+                       }
+                       offset += lc->cmdsize;
+               }
+       }
+       return retSym;
+}
+
+static int
+sys_dyld_init()
+{
+       int retCode = 0;
+       int err = 0;
+       if (!_dyld_present()) {
+               retCode=1;
+       }
+       else {
+      err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)&ltdl_NSAddImage);
+      err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)&ltdl_NSLookupSymbolInImage);
+      err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)&ltdl_NSIsSymbolNameDefinedInImage);
+      err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)&ltdl_NSMakePrivateModulePublic);
+    }
+ return retCode;
+}
+
+static lt_module
+sys_dyld_open (loader_data, filename)
+     lt_user_data loader_data;
+     const char *filename;
+{
+       lt_module   module   = 0;
+       NSObjectFileImage ofi = 0;
+       NSObjectFileImageReturnCode ofirc;
+
+       if (!filename)
+               return (lt_module)-1;
+       ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
+       switch (ofirc)
+       {
+               case NSObjectFileImageSuccess:
+                       module = NSLinkModule(ofi, filename,
+                                               NSLINKMODULE_OPTION_RETURN_ON_ERROR
+                                                | NSLINKMODULE_OPTION_PRIVATE
+                                                | NSLINKMODULE_OPTION_BINDNOW);
+                       NSDestroyObjectFileImage(ofi);
+                       if (module)
+                               ltdl_NSMakePrivateModulePublic(module);
+                       break;
+               case NSObjectFileImageInappropriateFile:
+                   if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
+                   {
+                               module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+                               break;
+                       }
+               default:
+                       LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
+                       return 0;
+       }
+       if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
+  return module;
+}
+
+static int
+sys_dyld_close (loader_data, module)
+     lt_user_data loader_data;
+     lt_module module;
+{
+       int retCode = 0;
+       int flags = 0;
+       if (module == (lt_module)-1) return 0;
+#ifdef __BIG_ENDIAN__
+       if (((struct mach_header *)module)->magic == MH_MAGIC)
+#else
+    if (((struct mach_header *)module)->magic == MH_CIGAM)
+#endif
+       {
+         LT_DLMUTEX_SETERROR("Can not close a dylib");
+         retCode = 1;
+       }
+       else
+       {
+#if 1
+/* Currently, if a module contains c++ static destructors and it is unloaded, we
+   get a segfault in atexit(), due to compiler and dynamic loader differences of
+   opinion, this works around that.
+*/
+               if ((const struct section *)NULL !=
+                  getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
+                  "__DATA","__mod_term_func"))
+               {
+                       flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
+               }
+#endif
+#ifdef __ppc__
+                       flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
+#endif
+               if (!NSUnLinkModule(module,flags))
+               {
+                       retCode=1;
+                       LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
+               }
+       }
+
+ return retCode;
+}
+
+static lt_ptr
+sys_dyld_sym (loader_data, module, symbol)
+     lt_user_data loader_data;
+     lt_module module;
+     const char *symbol;
+{
+       lt_ptr address = 0;
+       NSSymbol *nssym = 0;
+       void *unused;
+       const struct mach_header *mh=NULL;
+       char saveError[256] = "Symbol not found";
+       if (module == (lt_module)-1)
+       {
+               _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
+               return address;
+       }
+#ifdef __BIG_ENDIAN__
+       if (((struct mach_header *)module)->magic == MH_MAGIC)
+#else
+    if (((struct mach_header *)module)->magic == MH_CIGAM)
+#endif
+       {
+           if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
+           {
+               mh=module;
+                       if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
+                       {
+                               nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
+                                                                                       symbol,
+                                                                                       NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
+                                                                                       | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
+                                                                                       );
+                       }
+           }
+
+       }
+  else {
+       nssym = NSLookupSymbolInModule(module, symbol);
+       }
+       if (!nssym)
+       {
+               strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255);
+               saveError[255] = 0;
+               if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
+               nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
+       }
+       if (!nssym)
+       {
+               LT_DLMUTEX_SETERROR (saveError);
+               return NULL;
+       }
+       return NSAddressOfSymbol(nssym);
+}
+
+static struct lt_user_dlloader sys_dyld =
+  { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
+
+
+#endif /* HAVE_DYLD */
+
+
+/* --- DLPREOPEN() INTERFACE LOADER --- */
+
+
+/* emulate dynamic linking using preloaded_symbols */
+
+typedef struct lt_dlsymlists_t
+{
+  struct lt_dlsymlists_t       *next;
+  const lt_dlsymlist          *syms;
+} lt_dlsymlists_t;
+
+static const lt_dlsymlist     *default_preloaded_symbols       = 0;
+static lt_dlsymlists_t        *preloaded_symbols               = 0;
+
+static int
+presym_init (loader_data)
+     lt_user_data loader_data;
+{
+  int errors = 0;
+
+  LT_DLMUTEX_LOCK ();
+
+  preloaded_symbols = 0;
+  if (default_preloaded_symbols)
+    {
+      errors = lt_dlpreload (default_preloaded_symbols);
+    }
+
+  LT_DLMUTEX_UNLOCK ();
+
+  return errors;
+}
+
+static int
+presym_free_symlists ()
+{
+  lt_dlsymlists_t *lists;
+
+  LT_DLMUTEX_LOCK ();
+
+  lists = preloaded_symbols;
+  while (lists)
+    {
+      lt_dlsymlists_t  *tmp = lists;
+
+      lists = lists->next;
+      LT_DLFREE (tmp);
+    }
+  preloaded_symbols = 0;
+
+  LT_DLMUTEX_UNLOCK ();
+
+  return 0;
+}
+
+static int
+presym_exit (loader_data)
+     lt_user_data loader_data;
+{
+  presym_free_symlists ();
+  return 0;
+}
+
+static int
+presym_add_symlist (preloaded)
+     const lt_dlsymlist *preloaded;
+{
+  lt_dlsymlists_t *tmp;
+  lt_dlsymlists_t *lists;
+  int             errors   = 0;
+
+  LT_DLMUTEX_LOCK ();
+
+  lists = preloaded_symbols;
+  while (lists)
+    {
+      if (lists->syms == preloaded)
+       {
+         goto done;
+       }
+      lists = lists->next;
+    }
+
+  tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
+  if (tmp)
+    {
+      memset (tmp, 0, sizeof(lt_dlsymlists_t));
+      tmp->syms = preloaded;
+      tmp->next = preloaded_symbols;
+      preloaded_symbols = tmp;
+    }
+  else
+    {
+      ++errors;
+    }
+
+ done:
+  LT_DLMUTEX_UNLOCK ();
+  return errors;
+}
+
+static lt_module
+presym_open (loader_data, filename)
+     lt_user_data loader_data;
+     const char *filename;
+{
+  lt_dlsymlists_t *lists;
+  lt_module       module = (lt_module) 0;
+
+  LT_DLMUTEX_LOCK ();
+  lists = preloaded_symbols;
+
+  if (!lists)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
+      goto done;
+    }
+
+  /* Can't use NULL as the reflective symbol header, as NULL is
+     used to mark the end of the entire symbol list.  Self-dlpreopened
+     symbols follow this magic number, chosen to be an unlikely
+     clash with a real module name.  */
+  if (!filename)
+    {
+      filename = "@PROGRAM@";
+    }
+
+  while (lists)
+    {
+      const lt_dlsymlist *syms = lists->syms;
+
+      while (syms->name)
+       {
+         if (!syms->address && strcmp(syms->name, filename) == 0)
+           {
+             module = (lt_module) syms;
+             goto done;
+           }
+         ++syms;
+       }
+
+      lists = lists->next;
+    }
+
+  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
+
+ done:
+  LT_DLMUTEX_UNLOCK ();
+  return module;
+}
+
+static int
+presym_close (loader_data, module)
+     lt_user_data loader_data;
+     lt_module module;
+{
+  /* Just to silence gcc -Wall */
+  module = 0;
+  return 0;
+}
+
+static lt_ptr
+presym_sym (loader_data, module, symbol)
+     lt_user_data loader_data;
+     lt_module module;
+     const char *symbol;
+{
+  lt_dlsymlist *syms = (lt_dlsymlist*) module;
+
+  ++syms;
+  while (syms->address)
+    {
+      if (strcmp(syms->name, symbol) == 0)
+       {
+         return syms->address;
+       }
+
+    ++syms;
+  }
+
+  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
+
+  return 0;
+}
+
+static struct lt_user_dlloader presym = {
+  0, presym_open, presym_close, presym_sym, presym_exit, 0
+};
+
+
+
+
+
+/* --- DYNAMIC MODULE LOADING --- */
+
+
+/* The type of a function used at each iteration of  foreach_dirinpath().  */
+typedef int    foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
+                                                lt_ptr data2));
+
+static int     foreach_dirinpath     LT_PARAMS((const char *search_path,
+                                                const char *base_name,
+                                                foreach_callback_func *func,
+                                                lt_ptr data1, lt_ptr data2));
+
+static int     find_file_callback    LT_PARAMS((char *filename, lt_ptr data,
+                                                lt_ptr ignored));
+static int     find_handle_callback  LT_PARAMS((char *filename, lt_ptr data,
+                                                lt_ptr ignored));
+static int     foreachfile_callback  LT_PARAMS((char *filename, lt_ptr data1,
+                                                lt_ptr data2));
+
+
+static int     canonicalize_path     LT_PARAMS((const char *path,
+                                                char **pcanonical));
+static int     argzize_path          LT_PARAMS((const char *path,
+                                                char **pargz,
+                                                size_t *pargz_len));
+static FILE   *find_file             LT_PARAMS((const char *search_path,
+                                                const char *base_name,
+                                                char **pdir));
+static lt_dlhandle *find_handle      LT_PARAMS((const char *search_path,
+                                                const char *base_name,
+                                                lt_dlhandle *handle));
+static int     find_module           LT_PARAMS((lt_dlhandle *handle,
+                                                const char *dir,
+                                                const char *libdir,
+                                                const char *dlname,
+                                                const char *old_name,
+                                                int installed));
+static int     free_vars             LT_PARAMS((char *dlname, char *oldname,
+                                                char *libdir, char *deplibs));
+static int     load_deplibs          LT_PARAMS((lt_dlhandle handle,
+                                                char *deplibs));
+static int     trim                  LT_PARAMS((char **dest,
+                                                const char *str));
+static int     try_dlopen            LT_PARAMS((lt_dlhandle *handle,
+                                                const char *filename));
+static int     tryall_dlopen         LT_PARAMS((lt_dlhandle *handle,
+                                                const char *filename));
+static int     unload_deplibs        LT_PARAMS((lt_dlhandle handle));
+static int     lt_argz_insert        LT_PARAMS((char **pargz,
+                                                size_t *pargz_len,
+                                                char *before,
+                                                const char *entry));
+static int     lt_argz_insertinorder LT_PARAMS((char **pargz,
+                                                size_t *pargz_len,
+                                                const char *entry));
+static int     lt_argz_insertdir     LT_PARAMS((char **pargz,
+                                                size_t *pargz_len,
+                                                const char *dirnam,
+                                                struct dirent *dp));
+static int     lt_dlpath_insertdir   LT_PARAMS((char **ppath,
+                                                char *before,
+                                                const char *dir));
+static int     list_files_by_dir     LT_PARAMS((const char *dirnam,
+                                                char **pargz,
+                                                size_t *pargz_len));
+static int     file_not_found        LT_PARAMS((void));
+
+static char           *user_search_path= 0;
+static lt_dlloader    *loaders         = 0;
+static lt_dlhandle     handles         = 0;
+static int             initialized     = 0;
+
+/* Initialize libltdl. */
+int
+lt_dlinit ()
+{
+  int        errors   = 0;
+
+  LT_DLMUTEX_LOCK ();
+
+  /* Initialize only at first call. */
+  if (++initialized == 1)
+    {
+      handles = 0;
+      user_search_path = 0; /* empty search path */
+
+#if HAVE_LIBDL
+      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
+#endif
+#if HAVE_SHL_LOAD
+      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
+#endif
+#ifdef __WINDOWS__
+      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
+#endif
+#ifdef __BEOS__
+      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
+#endif
+#if HAVE_DLD
+      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
+#endif
+#if HAVE_DYLD
+       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
+       errors += sys_dyld_init();
+#endif
+      errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
+
+      if (presym_init (presym.dlloader_data))
+       {
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
+         ++errors;
+       }
+      else if (errors != 0)
+       {
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
+         ++errors;
+       }
+    }
+
+  LT_DLMUTEX_UNLOCK ();
+
+  return errors;
+}
+
+int
+lt_dlpreload (preloaded)
+     const lt_dlsymlist *preloaded;
+{
+  int errors = 0;
+
+  if (preloaded)
+    {
+      errors = presym_add_symlist (preloaded);
+    }
+  else
+    {
+      presym_free_symlists();
+
+      LT_DLMUTEX_LOCK ();
+      if (default_preloaded_symbols)
+       {
+         errors = lt_dlpreload (default_preloaded_symbols);
+       }
+      LT_DLMUTEX_UNLOCK ();
+    }
+
+  return errors;
+}
+
+int
+lt_dlpreload_default (preloaded)
+     const lt_dlsymlist *preloaded;
+{
+  LT_DLMUTEX_LOCK ();
+  default_preloaded_symbols = preloaded;
+  LT_DLMUTEX_UNLOCK ();
+  return 0;
+}
+
+int
+lt_dlexit ()
+{
+  /* shut down libltdl */
+  lt_dlloader *loader;
+  int         errors   = 0;
+
+  LT_DLMUTEX_LOCK ();
+  loader = loaders;
+
+  if (!initialized)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
+      ++errors;
+      goto done;
+    }
+
+  /* shut down only at last call. */
+  if (--initialized == 0)
+    {
+      int      level;
+
+      while (handles && LT_DLIS_RESIDENT (handles))
+       {
+         handles = handles->next;
+       }
+
+      /* close all modules */
+      for (level = 1; handles; ++level)
+       {
+         lt_dlhandle cur = handles;
+         int saw_nonresident = 0;
+
+         while (cur)
+           {
+             lt_dlhandle tmp = cur;
+             cur = cur->next;
+             if (!LT_DLIS_RESIDENT (tmp))
+               saw_nonresident = 1;
+             if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
+               {
+                 if (lt_dlclose (tmp))
+                   {
+                     ++errors;
+                   }
+                 /* Make sure that the handle pointed to by 'cur' still exists.
+                    lt_dlclose recursively closes dependent libraries which removes
+                    them from the linked list.  One of these might be the one
+                    pointed to by 'cur'.  */
+                 if (cur)
+                   {
+                     for (tmp = handles; tmp; tmp = tmp->next)
+                       if (tmp == cur)
+                         break;
+                     if (! tmp)
+                       cur = handles;
+                   }
+               }
+           }
+         /* done if only resident modules are left */
+         if (!saw_nonresident)
+           break;
+       }
+
+      /* close all loaders */
+      while (loader)
+       {
+         lt_dlloader *next = loader->next;
+         lt_user_data data = loader->dlloader_data;
+         if (loader->dlloader_exit && loader->dlloader_exit (data))
+           {
+             ++errors;
+           }
+
+         LT_DLMEM_REASSIGN (loader, next);
+       }
+      loaders = 0;
+    }
+
+ done:
+  LT_DLMUTEX_UNLOCK ();
+  return errors;
+}
+
+static int
+tryall_dlopen (handle, filename)
+     lt_dlhandle *handle;
+     const char *filename;
+{
+  lt_dlhandle   cur;
+  lt_dlloader   *loader;
+  const char   *saved_error;
+  int           errors         = 0;
+
+  LT_DLMUTEX_GETERROR (saved_error);
+  LT_DLMUTEX_LOCK ();
+
+  cur   = handles;
+  loader = loaders;
+
+  /* check whether the module was already opened */
+  while (cur)
+    {
+      /* try to dlopen the program itself? */
+      if (!cur->info.filename && !filename)
+       {
+         break;
+       }
+
+      if (cur->info.filename && filename
+         && strcmp (cur->info.filename, filename) == 0)
+       {
+         break;
+       }
+
+      cur = cur->next;
+    }
+
+  if (cur)
+    {
+      ++cur->info.ref_count;
+      *handle = cur;
+      goto done;
+    }
+
+  cur = *handle;
+  if (filename)
+    {
+      /* Comment out the check of file permissions using access.
+        This call seems to always return -1 with error EACCES.
+      */
+      /* We need to catch missing file errors early so that
+        file_not_found() can detect what happened.
+      if (access (filename, R_OK) != 0)
+       {
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
+         ++errors;
+         goto done;
+       } */
+
+      cur->info.filename = lt_estrdup (filename);
+      if (!cur->info.filename)
+       {
+         ++errors;
+         goto done;
+       }
+    }
+  else
+    {
+      cur->info.filename = 0;
+    }
+
+  while (loader)
+    {
+      lt_user_data data = loader->dlloader_data;
+
+      cur->module = loader->module_open (data, filename);
+
+      if (cur->module != 0)
+       {
+         break;
+       }
+      loader = loader->next;
+    }
+
+  if (!loader)
+    {
+      LT_DLFREE (cur->info.filename);
+      ++errors;
+      goto done;
+    }
+
+  cur->loader  = loader;
+  LT_DLMUTEX_SETERROR (saved_error);
+
+ done:
+  LT_DLMUTEX_UNLOCK ();
+
+  return errors;
+}
+
+static int
+tryall_dlopen_module (handle, prefix, dirname, dlname)
+     lt_dlhandle *handle;
+     const char *prefix;
+     const char *dirname;
+     const char *dlname;
+{
+  int      error       = 0;
+  char     *filename   = 0;
+  size_t   filename_len        = 0;
+  size_t   dirname_len = LT_STRLEN (dirname);
+
+  assert (handle);
+  assert (dirname);
+  assert (dlname);
+#ifdef LT_DIRSEP_CHAR
+  /* Only canonicalized names (i.e. with DIRSEP chars already converted)
+     should make it into this function:  */
+  assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
+#endif
+
+  if (dirname_len > 0)
+    if (dirname[dirname_len -1] == '/')
+      --dirname_len;
+  filename_len = dirname_len + 1 + LT_STRLEN (dlname);
+
+  /* Allocate memory, and combine DIRNAME and MODULENAME into it.
+     The PREFIX (if any) is handled below.  */
+  filename  = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
+  if (!filename)
+    return 1;
+
+  sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
+
+  /* Now that we have combined DIRNAME and MODULENAME, if there is
+     also a PREFIX to contend with, simply recurse with the arguments
+     shuffled.  Otherwise, attempt to open FILENAME as a module.  */
+  if (prefix)
+    {
+      error += tryall_dlopen_module (handle,
+                                    (const char *) 0, prefix, filename);
+    }
+  else if (tryall_dlopen (handle, filename) != 0)
+    {
+      ++error;
+    }
+
+  LT_DLFREE (filename);
+  return error;
+}
+
+static int
+find_module (handle, dir, libdir, dlname, old_name, installed)
+     lt_dlhandle *handle;
+     const char *dir;
+     const char *libdir;
+     const char *dlname;
+     const char *old_name;
+     int installed;
+{
+  /* Try to open the old library first; if it was dlpreopened,
+     we want the preopened version of it, even if a dlopenable
+     module is available.  */
+  if (old_name && tryall_dlopen (handle, old_name) == 0)
+    {
+      return 0;
+    }
+
+  /* Try to open the dynamic library.  */
+  if (dlname)
+    {
+      /* try to open the installed module */
+      if (installed && libdir)
+       {
+         if (tryall_dlopen_module (handle,
+                                   (const char *) 0, libdir, dlname) == 0)
+           return 0;
+       }
+
+      /* try to open the not-installed module */
+      if (!installed)
+       {
+         if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
+           return 0;
+       }
+
+      /* maybe it was moved to another directory */
+      {
+         if (dir && (tryall_dlopen_module (handle,
+                                   (const char *) 0, dir, dlname) == 0))
+           return 0;
+      }
+    }
+
+  return 1;
+}
+
+
+static int
+canonicalize_path (path, pcanonical)
+     const char *path;
+     char **pcanonical;
+{
+  char *canonical = 0;
+
+  assert (path && *path);
+  assert (pcanonical);
+
+  canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
+  if (!canonical)
+    return 1;
+
+  {
+    size_t dest = 0;
+    size_t src;
+    for (src = 0; path[src] != LT_EOS_CHAR; ++src)
+      {
+       /* Path separators are not copied to the beginning or end of
+          the destination, or if another separator would follow
+          immediately.  */
+       if (path[src] == LT_PATHSEP_CHAR)
+         {
+           if ((dest == 0)
+               || (path[1+ src] == LT_PATHSEP_CHAR)
+               || (path[1+ src] == LT_EOS_CHAR))
+             continue;
+         }
+
+       /* Anything other than a directory separator is copied verbatim.  */
+       if ((path[src] != '/')
+#ifdef LT_DIRSEP_CHAR
+           && (path[src] != LT_DIRSEP_CHAR)
+#endif
+           )
+         {
+           canonical[dest++] = path[src];
+         }
+       /* Directory separators are converted and copied only if they are
+          not at the end of a path -- i.e. before a path separator or
+          NULL terminator.  */
+       else if ((path[1+ src] != LT_PATHSEP_CHAR)
+                && (path[1+ src] != LT_EOS_CHAR)
+#ifdef LT_DIRSEP_CHAR
+                && (path[1+ src] != LT_DIRSEP_CHAR)
+#endif
+                && (path[1+ src] != '/'))
+         {
+           canonical[dest++] = '/';
+         }
+      }
+
+    /* Add an end-of-string marker at the end.  */
+    canonical[dest] = LT_EOS_CHAR;
+  }
+
+  /* Assign new value.  */
+  *pcanonical = canonical;
+
+  return 0;
+}
+
+static int
+argzize_path (path, pargz, pargz_len)
+     const char *path;
+     char **pargz;
+     size_t *pargz_len;
+{
+  error_t error;
+
+  assert (path);
+  assert (pargz);
+  assert (pargz_len);
+
+  if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
+    {
+      switch (error)
+       {
+       case ENOMEM:
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
+         break;
+       default:
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
+         break;
+       }
+
+      return 1;
+    }
+
+  return 0;
+}
+
+/* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
+   of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
+   non-zero or all elements are exhausted.  If BASE_NAME is non-NULL,
+   it is appended to each SEARCH_PATH element before FUNC is called.  */
+static int
+foreach_dirinpath (search_path, base_name, func, data1, data2)
+     const char *search_path;
+     const char *base_name;
+     foreach_callback_func *func;
+     lt_ptr data1;
+     lt_ptr data2;
+{
+  int   result         = 0;
+  int   filenamesize   = 0;
+  size_t lenbase       = LT_STRLEN (base_name);
+  size_t argz_len      = 0;
+  char *argz           = 0;
+  char *filename       = 0;
+  char *canonical      = 0;
+
+  LT_DLMUTEX_LOCK ();
+
+  if (!search_path || !*search_path)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
+      goto cleanup;
+    }
+
+  if (canonicalize_path (search_path, &canonical) != 0)
+    goto cleanup;
+
+  if (argzize_path (canonical, &argz, &argz_len) != 0)
+    goto cleanup;
+
+  {
+    char *dir_name = 0;
+    while ((dir_name = argz_next (argz, argz_len, dir_name)))
+      {
+       size_t lendir = LT_STRLEN (dir_name);
+
+       if (lendir +1 +lenbase >= filenamesize)
+       {
+         LT_DLFREE (filename);
+         filenamesize  = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
+         filename      = LT_EMALLOC (char, filenamesize);
+         if (!filename)
+           goto cleanup;
+       }
+
+       assert (filenamesize > lendir);
+       strcpy (filename, dir_name);
+
+       if (base_name && *base_name)
+         {
+           if (filename[lendir -1] != '/')
+             filename[lendir++] = '/';
+           strcpy (filename +lendir, base_name);
+         }
+
+       if ((result = (*func) (filename, data1, data2)))
+         {
+           break;
+         }
+      }
+  }
+
+ cleanup:
+  LT_DLFREE (argz);
+  LT_DLFREE (canonical);
+  LT_DLFREE (filename);
+
+  LT_DLMUTEX_UNLOCK ();
+
+  return result;
+}
+
+/* If FILEPATH can be opened, store the name of the directory component
+   in DATA1, and the opened FILE* structure address in DATA2.  Otherwise
+   DATA1 is unchanged, but DATA2 is set to a pointer to NULL.  */
+static int
+find_file_callback (filename, data1, data2)
+     char *filename;
+     lt_ptr data1;
+     lt_ptr data2;
+{
+  char      **pdir     = (char **) data1;
+  FILE      **pfile    = (FILE **) data2;
+  int       is_done    = 0;
+
+  assert (filename && *filename);
+  assert (pdir);
+  assert (pfile);
+
+  if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
+    {
+      char *dirend = strrchr (filename, '/');
+
+      if (dirend > filename)
+       *dirend   = LT_EOS_CHAR;
+
+      LT_DLFREE (*pdir);
+      *pdir   = lt_estrdup (filename);
+      is_done = (*pdir == 0) ? -1 : 1;
+    }
+
+  return is_done;
+}
+
+static FILE *
+find_file (search_path, base_name, pdir)
+     const char *search_path;
+     const char *base_name;
+     char **pdir;
+{
+  FILE *file = 0;
+
+  foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
+
+  return file;
+}
+
+static int
+find_handle_callback (filename, data, ignored)
+     char *filename;
+     lt_ptr data;
+     lt_ptr ignored;
+{
+  lt_dlhandle  *handle         = (lt_dlhandle *) data;
+  int          notfound        = access (filename, R_OK);
+
+  /* Bail out if file cannot be read...  */
+  if (notfound)
+    return 0;
+
+  /* Try to dlopen the file, but do not continue searching in any
+     case.  */
+  if (tryall_dlopen (handle, filename) != 0)
+    *handle = 0;
+
+  return 1;
+}
+
+/* If HANDLE was found return it, otherwise return 0.  If HANDLE was
+   found but could not be opened, *HANDLE will be set to 0.  */
+static lt_dlhandle *
+find_handle (search_path, base_name, handle)
+     const char *search_path;
+     const char *base_name;
+     lt_dlhandle *handle;
+{
+  if (!search_path)
+    return 0;
+
+  if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
+                         handle, 0))
+    return 0;
+
+  return handle;
+}
+
+static int
+load_deplibs (handle, deplibs)
+     lt_dlhandle handle;
+     char *deplibs;
+{
+#if LTDL_DLOPEN_DEPLIBS
+  char *p, *save_search_path = 0;
+  int   depcount = 0;
+  int  i;
+  char **names = 0;
+#endif
+  int  errors = 0;
+
+  handle->depcount = 0;
+
+#if LTDL_DLOPEN_DEPLIBS
+  if (!deplibs)
+    {
+      return errors;
+    }
+  ++errors;
+
+  LT_DLMUTEX_LOCK ();
+  if (user_search_path)
+    {
+      save_search_path = lt_estrdup (user_search_path);
+      if (!save_search_path)
+       goto cleanup;
+    }
+
+  /* extract search paths and count deplibs */
+  p = deplibs;
+  while (*p)
+    {
+      if (!isspace ((int) *p))
+       {
+         char *end = p+1;
+         while (*end && !isspace((int) *end))
+           {
+             ++end;
+           }
+
+         if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
+           {
+             char save = *end;
+             *end = 0; /* set a temporary string terminator */
+             if (lt_dladdsearchdir(p+2))
+               {
+                 goto cleanup;
+               }
+             *end = save;
+           }
+         else
+           {
+             ++depcount;
+           }
+
+         p = end;
+       }
+      else
+       {
+         ++p;
+       }
+    }
+
+  if (!depcount)
+    {
+      errors = 0;
+      goto cleanup;
+    }
+
+  names = LT_EMALLOC (char *, depcount * sizeof (char*));
+  if (!names)
+    goto cleanup;
+
+  /* now only extract the actual deplibs */
+  depcount = 0;
+  p = deplibs;
+  while (*p)
+    {
+      if (isspace ((int) *p))
+       {
+         ++p;
+       }
+      else
+       {
+         char *end = p+1;
+         while (*end && !isspace ((int) *end))
+           {
+             ++end;
+           }
+
+         if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
+           {
+             char *name;
+             char save = *end;
+             *end = 0; /* set a temporary string terminator */
+             if (strncmp(p, "-l", 2) == 0)
+               {
+                 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
+                 name = LT_EMALLOC (char, 1+ name_len);
+                 if (name)
+                   sprintf (name, "lib%s", p+2);
+               }
+             else
+               name = lt_estrdup(p);
+
+             if (!name)
+               goto cleanup_names;
+
+             names[depcount++] = name;
+             *end = save;
+           }
+         p = end;
+       }
+    }
+
+  /* load the deplibs (in reverse order)
+     At this stage, don't worry if the deplibs do not load correctly,
+     they may already be statically linked into the loading application
+     for instance.  There will be a more enlightening error message
+     later on if the loaded module cannot resolve all of its symbols.  */
+  if (depcount)
+    {
+      int      j = 0;
+
+      handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
+      if (!handle->deplibs)
+       goto cleanup_names;
+
+      for (i = 0; i < depcount; ++i)
+       {
+         handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
+         if (handle->deplibs[j])
+           {
+             ++j;
+           }
+       }
+
+      handle->depcount = j;    /* Number of successfully loaded deplibs */
+      errors           = 0;
+    }
+
+ cleanup_names:
+  for (i = 0; i < depcount; ++i)
+    {
+      LT_DLFREE (names[i]);
+    }
+
+ cleanup:
+  LT_DLFREE (names);
+  /* restore the old search path */
+  if (user_search_path) {
+    LT_DLFREE (user_search_path);
+    user_search_path = save_search_path;
+  }
+  LT_DLMUTEX_UNLOCK ();
+
+#endif
+
+  return errors;
+}
+
+static int
+unload_deplibs (handle)
+     lt_dlhandle handle;
+{
+  int i;
+  int errors = 0;
+
+  if (handle->depcount)
+    {
+      for (i = 0; i < handle->depcount; ++i)
+       {
+         if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
+           {
+             errors += lt_dlclose (handle->deplibs[i]);
+           }
+       }
+      LT_DLFREE (handle->deplibs);
+    }
+
+  return errors;
+}
+
+static int
+trim (dest, str)
+     char **dest;
+     const char *str;
+{
+  /* remove the leading and trailing "'" from str
+     and store the result in dest */
+  const char *end   = strrchr (str, '\'');
+  size_t len       = LT_STRLEN (str);
+  char *tmp;
+
+  LT_DLFREE (*dest);
+
+  if (!end)
+    return 1;
+
+  if (len > 3 && str[0] == '\'')
+    {
+      tmp = LT_EMALLOC (char, end - str);
+      if (!tmp)
+       return 1;
+
+      strncpy(tmp, &str[1], (end - str) - 1);
+      tmp[len-3] = LT_EOS_CHAR;
+      *dest = tmp;
+    }
+  else
+    {
+      *dest = 0;
+    }
+
+  return 0;
+}
+
+static int
+free_vars (dlname, oldname, libdir, deplibs)
+     char *dlname;
+     char *oldname;
+     char *libdir;
+     char *deplibs;
+{
+  LT_DLFREE (dlname);
+  LT_DLFREE (oldname);
+  LT_DLFREE (libdir);
+  LT_DLFREE (deplibs);
+
+  return 0;
+}
+
+static int
+try_dlopen (phandle, filename)
+     lt_dlhandle *phandle;
+     const char *filename;
+{
+  const char * ext             = 0;
+  const char * saved_error     = 0;
+  char *       canonical       = 0;
+  char *       base_name       = 0;
+  char *       dir             = 0;
+  char *       name            = 0;
+  int          errors          = 0;
+  lt_dlhandle  newhandle;
+
+  assert (phandle);
+  assert (*phandle == 0);
+
+  LT_DLMUTEX_GETERROR (saved_error);
+
+  /* dlopen self? */
+  if (!filename)
+    {
+      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
+      if (*phandle == 0)
+       return 1;
+
+      memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
+      newhandle        = *phandle;
+
+      /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
+      LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
+
+      if (tryall_dlopen (&newhandle, 0) != 0)
+       {
+         LT_DLFREE (*phandle);
+         return 1;
+       }
+
+      goto register_handle;
+    }
+
+  assert (filename && *filename);
+
+  /* Doing this immediately allows internal functions to safely
+     assume only canonicalized paths are passed.  */
+  if (canonicalize_path (filename, &canonical) != 0)
+    {
+      ++errors;
+      goto cleanup;
+    }
+
+  /* If the canonical module name is a path (relative or absolute)
+     then split it into a directory part and a name part.  */
+  base_name = strrchr (canonical, '/');
+  if (base_name)
+    {
+      size_t dirlen = (1+ base_name) - canonical;
+
+      dir = LT_EMALLOC (char, 1+ dirlen);
+      if (!dir)
+       {
+         ++errors;
+         goto cleanup;
+       }
+
+      strncpy (dir, canonical, dirlen);
+      dir[dirlen] = LT_EOS_CHAR;
+
+      ++base_name;
+    }
+  else
+    base_name = canonical;
+
+  assert (base_name && *base_name);
+
+  /* Check whether we are opening a libtool module (.la extension).  */
+  ext = strrchr (base_name, '.');
+  if (ext && strcmp (ext, archive_ext) == 0)
+    {
+      /* this seems to be a libtool module */
+      FILE *   file     = 0;
+      char *   dlname   = 0;
+      char *   old_name = 0;
+      char *   libdir   = 0;
+      char *   deplibs  = 0;
+      char *    line    = 0;
+      size_t   line_len;
+
+      /* if we can't find the installed flag, it is probably an
+        installed libtool archive, produced with an old version
+        of libtool */
+      int      installed = 1;
+
+      /* extract the module name from the file name */
+      name = LT_EMALLOC (char, ext - base_name + 1);
+      if (!name)
+       {
+         ++errors;
+         goto cleanup;
+       }
+
+      /* canonicalize the module name */
+      {
+        size_t i;
+        for (i = 0; i < ext - base_name; ++i)
+         {
+           if (isalnum ((int)(base_name[i])))
+             {
+               name[i] = base_name[i];
+             }
+           else
+             {
+               name[i] = '_';
+             }
+         }
+        name[ext - base_name] = LT_EOS_CHAR;
+      }
+
+      /* Now try to open the .la file.  If there is no directory name
+         component, try to find it first in user_search_path and then other
+         prescribed paths.  Otherwise (or in any case if the module was not
+         yet found) try opening just the module name as passed.  */
+      if (!dir)
+       {
+         const char *search_path;
+
+         LT_DLMUTEX_LOCK ();
+         search_path = user_search_path;
+         if (search_path)
+           file = find_file (user_search_path, base_name, &dir);
+         LT_DLMUTEX_UNLOCK ();
+
+         if (!file)
+           {
+             search_path = getenv (LTDL_SEARCHPATH_VAR);
+             if (search_path)
+               file = find_file (search_path, base_name, &dir);
+           }
+
+#ifdef LTDL_SHLIBPATH_VAR
+         if (!file)
+           {
+             search_path = getenv (LTDL_SHLIBPATH_VAR);
+             if (search_path)
+               file = find_file (search_path, base_name, &dir);
+           }
+#endif
+#ifdef LTDL_SYSSEARCHPATH
+         if (!file && sys_search_path)
+           {
+             file = find_file (sys_search_path, base_name, &dir);
+           }
+#endif
+       }
+      if (!file)
+       {
+         file = fopen (filename, LT_READTEXT_MODE);
+       }
+
+      /* If we didn't find the file by now, it really isn't there.  Set
+        the status flag, and bail out.  */
+      if (!file)
+       {
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
+         ++errors;
+         goto cleanup;
+       }
+
+      line_len = LT_FILENAME_MAX;
+      line = LT_EMALLOC (char, line_len);
+      if (!line)
+       {
+         fclose (file);
+         ++errors;
+         goto cleanup;
+       }
+
+      /* read the .la file */
+      while (!feof (file))
+       {
+         if (!fgets (line, (int) line_len, file))
+           {
+             break;
+           }
+
+         /* Handle the case where we occasionally need to read a line
+            that is longer than the initial buffer size.  */
+         while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file)))
+           {
+             line = LT_DLREALLOC (char, line, line_len *2);
+             if (!fgets (&line[line_len -1], (int) line_len +1, file))
+               {
+                 break;
+               }
+             line_len *= 2;
+           }
+
+         if (line[0] == '\n' || line[0] == '#')
+           {
+             continue;
+           }
+
+#undef  STR_DLNAME
+#define STR_DLNAME     "dlname="
+         if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
+           {
+             errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
+           }
+
+#undef  STR_OLD_LIBRARY
+#define STR_OLD_LIBRARY        "old_library="
+         else if (strncmp (line, STR_OLD_LIBRARY,
+                           sizeof (STR_OLD_LIBRARY) - 1) == 0)
+           {
+             errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
+           }
+#undef  STR_LIBDIR
+#define STR_LIBDIR     "libdir="
+         else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
+           {
+             errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
+           }
+
+#undef  STR_DL_DEPLIBS
+#define STR_DL_DEPLIBS "dependency_libs="
+         else if (strncmp (line, STR_DL_DEPLIBS,
+                           sizeof (STR_DL_DEPLIBS) - 1) == 0)
+           {
+             errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
+           }
+         else if (strcmp (line, "installed=yes\n") == 0)
+           {
+             installed = 1;
+           }
+         else if (strcmp (line, "installed=no\n") == 0)
+           {
+             installed = 0;
+           }
+
+#undef  STR_LIBRARY_NAMES
+#define STR_LIBRARY_NAMES "library_names="
+         else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
+                                       sizeof (STR_LIBRARY_NAMES) - 1) == 0)
+           {
+             char *last_libname;
+             errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
+             if (!errors
+                 && dlname
+                 && (last_libname = strrchr (dlname, ' ')) != 0)
+               {
+                 last_libname = lt_estrdup (last_libname + 1);
+                 if (!last_libname)
+                   {
+                     ++errors;
+                     goto cleanup;
+                   }
+                 LT_DLMEM_REASSIGN (dlname, last_libname);
+               }
+           }
+
+         if (errors)
+           break;
+       }
+
+      fclose (file);
+      LT_DLFREE (line);
+
+      /* allocate the handle */
+      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
+      if (*phandle == 0)
+       ++errors;
+
+      if (errors)
+       {
+         free_vars (dlname, old_name, libdir, deplibs);
+         LT_DLFREE (*phandle);
+         goto cleanup;
+       }
+
+      assert (*phandle);
+
+      memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
+      if (load_deplibs (*phandle, deplibs) == 0)
+       {
+         newhandle = *phandle;
+         /* find_module may replace newhandle */
+         if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
+           {
+             unload_deplibs (*phandle);
+             ++errors;
+           }
+       }
+      else
+       {
+         ++errors;
+       }
+
+      free_vars (dlname, old_name, libdir, deplibs);
+      if (errors)
+       {
+         LT_DLFREE (*phandle);
+         goto cleanup;
+       }
+
+      if (*phandle != newhandle)
+       {
+         unload_deplibs (*phandle);
+       }
+    }
+  else
+    {
+      /* not a libtool module */
+      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
+      if (*phandle == 0)
+       {
+         ++errors;
+         goto cleanup;
+       }
+
+      memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
+      newhandle = *phandle;
+
+      /* If the module has no directory name component, try to find it
+        first in user_search_path and then other prescribed paths.
+        Otherwise (or in any case if the module was not yet found) try
+        opening just the module name as passed.  */
+      if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
+                  && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
+                                   &newhandle)
+#ifdef LTDL_SHLIBPATH_VAR
+                  && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
+                                   &newhandle)
+#endif
+#ifdef LTDL_SYSSEARCHPATH
+                  && !find_handle (sys_search_path, base_name, &newhandle)
+#endif
+                  )))
+       {
+          if (tryall_dlopen (&newhandle, filename) != 0)
+            {
+              newhandle = NULL;
+            }
+       }
+
+      if (!newhandle)
+       {
+         LT_DLFREE (*phandle);
+         ++errors;
+         goto cleanup;
+       }
+    }
+
+ register_handle:
+  LT_DLMEM_REASSIGN (*phandle, newhandle);
+
+  if ((*phandle)->info.ref_count == 0)
+    {
+      (*phandle)->info.ref_count       = 1;
+      LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
+
+      LT_DLMUTEX_LOCK ();
+      (*phandle)->next         = handles;
+      handles                  = *phandle;
+      LT_DLMUTEX_UNLOCK ();
+    }
+
+  LT_DLMUTEX_SETERROR (saved_error);
+
+ cleanup:
+  LT_DLFREE (dir);
+  LT_DLFREE (name);
+  LT_DLFREE (canonical);
+
+  return errors;
+}
+
+lt_dlhandle
+lt_dlopen (filename)
+     const char *filename;
+{
+  lt_dlhandle handle = 0;
+
+  /* Just incase we missed a code path in try_dlopen() that reports
+     an error, but forgets to reset handle... */
+  if (try_dlopen (&handle, filename) != 0)
+    return 0;
+
+  return handle;
+}
+
+/* If the last error messge store was `FILE_NOT_FOUND', then return
+   non-zero.  */
+static int
+file_not_found ()
+{
+  const char *error = 0;
+
+  LT_DLMUTEX_GETERROR (error);
+  if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
+    return 1;
+
+  return 0;
+}
+
+/* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
+   open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,
+   and if a file is still not found try again with SHLIB_EXT appended
+   instead.  */
+lt_dlhandle
+lt_dlopenext (filename)
+     const char *filename;
+{
+  lt_dlhandle  handle          = 0;
+  char *       tmp             = 0;
+  char *       ext             = 0;
+  size_t       len;
+  int          errors          = 0;
+
+  if (!filename)
+    {
+      return lt_dlopen (filename);
+    }
+
+  assert (filename);
+
+  len = LT_STRLEN (filename);
+  ext = strrchr (filename, '.');
+
+  /* If FILENAME already bears a suitable extension, there is no need
+     to try appending additional extensions.  */
+  if (ext && ((strcmp (ext, archive_ext) == 0)
+#ifdef LTDL_SHLIB_EXT
+             || (strcmp (ext, shlib_ext) == 0)
+#endif
+      ))
+    {
+      return lt_dlopen (filename);
+    }
+
+  /* First try appending ARCHIVE_EXT.  */
+  tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
+  if (!tmp)
+    return 0;
+
+  strcpy (tmp, filename);
+  strcat (tmp, archive_ext);
+  errors = try_dlopen (&handle, tmp);
+
+  /* If we found FILENAME, stop searching -- whether we were able to
+     load the file as a module or not.  If the file exists but loading
+     failed, it is better to return an error message here than to
+     report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
+     in the module search path.  */
+  if (handle || ((errors > 0) && !file_not_found ()))
+    {
+      LT_DLFREE (tmp);
+      return handle;
+    }
+
+#ifdef LTDL_SHLIB_EXT
+  /* Try appending SHLIB_EXT.   */
+  if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
+    {
+      LT_DLFREE (tmp);
+      tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
+      if (!tmp)
+       return 0;
+
+      strcpy (tmp, filename);
+    }
+  else
+    {
+      tmp[len] = LT_EOS_CHAR;
+    }
+
+  strcat(tmp, shlib_ext);
+  errors = try_dlopen (&handle, tmp);
+
+  /* As before, if the file was found but loading failed, return now
+     with the current error message.  */
+  if (handle || ((errors > 0) && !file_not_found ()))
+    {
+      LT_DLFREE (tmp);
+      return handle;
+    }
+#endif
+
+  /* Still here?  Then we really did fail to locate any of the file
+     names we tried.  */
+  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
+  LT_DLFREE (tmp);
+  return 0;
+}
+
+
+static int
+lt_argz_insert (pargz, pargz_len, before, entry)
+     char **pargz;
+     size_t *pargz_len;
+     char *before;
+     const char *entry;
+{
+  error_t error;
+
+  /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
+     pargz_len, NULL, entry) failed with EINVAL.  */
+  if (before)
+    error = argz_insert (pargz, pargz_len, before, entry);
+  else
+    error = argz_append (pargz, pargz_len, entry, 1 + LT_STRLEN (entry));
+
+  if (error)
+    {
+      switch (error)
+       {
+       case ENOMEM:
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
+         break;
+       default:
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
+         break;
+       }
+      return 1;
+    }
+
+  return 0;
+}
+
+static int
+lt_argz_insertinorder (pargz, pargz_len, entry)
+     char **pargz;
+     size_t *pargz_len;
+     const char *entry;
+{
+  char *before = 0;
+
+  assert (pargz);
+  assert (pargz_len);
+  assert (entry && *entry);
+
+  if (*pargz)
+    while ((before = argz_next (*pargz, *pargz_len, before)))
+      {
+       int cmp = strcmp (entry, before);
+
+       if (cmp < 0)  break;
+       if (cmp == 0) return 0; /* No duplicates! */
+      }
+
+  return lt_argz_insert (pargz, pargz_len, before, entry);
+}
+
+static int
+lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
+     char **pargz;
+     size_t *pargz_len;
+     const char *dirnam;
+     struct dirent *dp;
+{
+  char   *buf      = 0;
+  size_t buf_len    = 0;
+  char   *end      = 0;
+  size_t end_offset = 0;
+  size_t dir_len    = 0;
+  int    errors            = 0;
+
+  assert (pargz);
+  assert (pargz_len);
+  assert (dp);
+
+  dir_len = LT_STRLEN (dirnam);
+  end     = dp->d_name + LT_D_NAMLEN(dp);
+
+  /* Ignore version numbers.  */
+  {
+    char *p;
+    for (p = end; p -1 > dp->d_name; --p)
+      if (strchr (".0123456789", p[-1]) == 0)
+       break;
+
+    if (*p == '.')
+      end = p;
+  }
+
+  /* Ignore filename extension.  */
+  {
+    char *p;
+    for (p = end -1; p > dp->d_name; --p)
+      if (*p == '.')
+       {
+         end = p;
+         break;
+       }
+  }
+
+  /* Prepend the directory name.  */
+  end_offset   = end - dp->d_name;
+  buf_len      = dir_len + 1+ end_offset;
+  buf          = LT_EMALLOC (char, 1+ buf_len);
+  if (!buf)
+    return ++errors;
+
+  assert (buf);
+
+  strcpy  (buf, dirnam);
+  strcat  (buf, "/");
+  strncat (buf, dp->d_name, end_offset);
+  buf[buf_len] = LT_EOS_CHAR;
+
+  /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */
+  if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
+    ++errors;
+
+  LT_DLFREE (buf);
+
+  return errors;
+}
+
+static int
+list_files_by_dir (dirnam, pargz, pargz_len)
+     const char *dirnam;
+     char **pargz;
+     size_t *pargz_len;
+{
+  DIR  *dirp     = 0;
+  int    errors          = 0;
+
+  assert (dirnam && *dirnam);
+  assert (pargz);
+  assert (pargz_len);
+  assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
+
+  dirp = opendir (dirnam);
+  if (dirp)
+    {
+      struct dirent *dp        = 0;
+
+      while ((dp = readdir (dirp)))
+       if (dp->d_name[0] != '.')
+         if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
+           {
+             ++errors;
+             break;
+           }
+
+      closedir (dirp);
+    }
+  else
+    ++errors;
+
+  return errors;
+}
+
+
+/* If there are any files in DIRNAME, call the function passed in
+   DATA1 (with the name of each file and DATA2 as arguments).  */
+static int
+foreachfile_callback (dirname, data1, data2)
+     char *dirname;
+     lt_ptr data1;
+     lt_ptr data2;
+{
+  int (*func) LT_PARAMS((const char *filename, lt_ptr data))
+       = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
+
+  int    is_done  = 0;
+  char   *argz     = 0;
+  size_t  argz_len = 0;
+
+  if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
+    goto cleanup;
+  if (!argz)
+    goto cleanup;
+
+  {
+    char *filename = 0;
+    while ((filename = argz_next (argz, argz_len, filename)))
+      if ((is_done = (*func) (filename, data2)))
+       break;
+  }
+
+ cleanup:
+  LT_DLFREE (argz);
+
+  return is_done;
+}
+
+
+/* Call FUNC for each unique extensionless file in SEARCH_PATH, along
+   with DATA.  The filenames passed to FUNC would be suitable for
+   passing to lt_dlopenext.  The extensions are stripped so that
+   individual modules do not generate several entries (e.g. libfoo.la,
+   libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,
+   then the same directories that lt_dlopen would search are examined.  */
+int
+lt_dlforeachfile (search_path, func, data)
+     const char *search_path;
+     int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
+     lt_ptr data;
+{
+  int is_done = 0;
+
+  if (search_path)
+    {
+      /* If a specific path was passed, search only the directories
+        listed in it.  */
+      is_done = foreach_dirinpath (search_path, 0,
+                                  foreachfile_callback, func, data);
+    }
+  else
+    {
+      /* Otherwise search the default paths.  */
+      is_done = foreach_dirinpath (user_search_path, 0,
+                                  foreachfile_callback, func, data);
+      if (!is_done)
+       {
+         is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
+                                      foreachfile_callback, func, data);
+       }
+
+#ifdef LTDL_SHLIBPATH_VAR
+      if (!is_done)
+       {
+         is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
+                                      foreachfile_callback, func, data);
+       }
+#endif
+#ifdef LTDL_SYSSEARCHPATH
+      if (!is_done)
+       {
+         is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
+                                      foreachfile_callback, func, data);
+       }
+#endif
+    }
+
+  return is_done;
+}
+
+int
+lt_dlclose (handle)
+     lt_dlhandle handle;
+{
+  lt_dlhandle cur, last;
+  int errors = 0;
+
+  LT_DLMUTEX_LOCK ();
+
+  /* check whether the handle is valid */
+  last = cur = handles;
+  while (cur && handle != cur)
+    {
+      last = cur;
+      cur = cur->next;
+    }
+
+  if (!cur)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
+      ++errors;
+      goto done;
+    }
+
+  handle->info.ref_count--;
+
+  /* Note that even with resident modules, we must track the ref_count
+     correctly incase the user decides to reset the residency flag
+     later (even though the API makes no provision for that at the
+     moment).  */
+  if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
+    {
+      lt_user_data data = handle->loader->dlloader_data;
+
+      if (handle != handles)
+       {
+         last->next = handle->next;
+       }
+      else
+       {
+         handles = handle->next;
+       }
+
+      errors += handle->loader->module_close (data, handle->module);
+      errors += unload_deplibs(handle);
+
+      /* It is up to the callers to free the data itself.  */
+      LT_DLFREE (handle->caller_data);
+
+      LT_DLFREE (handle->info.filename);
+      LT_DLFREE (handle->info.name);
+      LT_DLFREE (handle);
+
+      goto done;
+    }
+
+  if (LT_DLIS_RESIDENT (handle))
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
+      ++errors;
+    }
+
+ done:
+  LT_DLMUTEX_UNLOCK ();
+
+  return errors;
+}
+
+lt_ptr
+lt_dlsym (handle, symbol)
+     lt_dlhandle handle;
+     const char *symbol;
+{
+  size_t lensym;
+  char lsym[LT_SYMBOL_LENGTH];
+  char *sym;
+  lt_ptr address;
+  lt_user_data data;
+
+  if (!handle)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
+      return 0;
+    }
+
+  if (!symbol)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
+      return 0;
+    }
+
+  lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
+                                       + LT_STRLEN (handle->info.name);
+
+  if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
+    {
+      sym = lsym;
+    }
+  else
+    {
+      sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
+      if (!sym)
+       {
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
+         return 0;
+       }
+    }
+
+  data = handle->loader->dlloader_data;
+  if (handle->info.name)
+    {
+      const char *saved_error;
+
+      LT_DLMUTEX_GETERROR (saved_error);
+
+      /* this is a libtool module */
+      if (handle->loader->sym_prefix)
+       {
+         strcpy(sym, handle->loader->sym_prefix);
+         strcat(sym, handle->info.name);
+       }
+      else
+       {
+         strcpy(sym, handle->info.name);
+       }
+
+      strcat(sym, "_LTX_");
+      strcat(sym, symbol);
+
+      /* try "modulename_LTX_symbol" */
+      address = handle->loader->find_sym (data, handle->module, sym);
+      if (address)
+       {
+         if (sym != lsym)
+           {
+             LT_DLFREE (sym);
+           }
+         return address;
+       }
+      LT_DLMUTEX_SETERROR (saved_error);
+    }
+
+  /* otherwise try "symbol" */
+  if (handle->loader->sym_prefix)
+    {
+      strcpy(sym, handle->loader->sym_prefix);
+      strcat(sym, symbol);
+    }
+  else
+    {
+      strcpy(sym, symbol);
+    }
+
+  address = handle->loader->find_sym (data, handle->module, sym);
+  if (sym != lsym)
+    {
+      LT_DLFREE (sym);
+    }
+
+  return address;
+}
+
+const char *
+lt_dlerror ()
+{
+  const char *error;
+
+  LT_DLMUTEX_GETERROR (error);
+  LT_DLMUTEX_SETERROR (0);
+
+  return error ? error : NULL;
+}
+
+static int
+lt_dlpath_insertdir (ppath, before, dir)
+     char **ppath;
+     char *before;
+     const char *dir;
+{
+  int    errors                = 0;
+  char  *canonical     = 0;
+  char  *argz          = 0;
+  size_t argz_len      = 0;
+
+  assert (ppath);
+  assert (dir && *dir);
+
+  if (canonicalize_path (dir, &canonical) != 0)
+    {
+      ++errors;
+      goto cleanup;
+    }
+
+  assert (canonical && *canonical);
+
+  /* If *PPATH is empty, set it to DIR.  */
+  if (*ppath == 0)
+    {
+      assert (!before);                /* BEFORE cannot be set without PPATH.  */
+      assert (dir);            /* Without DIR, don't call this function!  */
+
+      *ppath = lt_estrdup (dir);
+      if (*ppath == 0)
+       ++errors;
+
+      return errors;
+    }
+
+  assert (ppath && *ppath);
+
+  if (argzize_path (*ppath, &argz, &argz_len) != 0)
+    {
+      ++errors;
+      goto cleanup;
+    }
+
+  /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
+     if *PPATH is already canonicalized, and hence does not change length
+     with respect to ARGZ.  We canonicalize each entry as it is added to
+     the search path, and don't call this function with (uncanonicalized)
+     user paths, so this is a fair assumption.  */
+  if (before)
+    {
+      assert (*ppath <= before);
+      assert (before - *ppath <= strlen (*ppath));
+
+      before = before - *ppath + argz;
+    }
+
+  if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
+    {
+      ++errors;
+      goto cleanup;
+    }
+
+  argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
+  LT_DLMEM_REASSIGN (*ppath,  argz);
+
+ cleanup:
+  LT_DLFREE (canonical);
+  LT_DLFREE (argz);
+
+  return errors;
+}
+
+int
+lt_dladdsearchdir (search_dir)
+     const char *search_dir;
+{
+  int errors = 0;
+
+  if (search_dir && *search_dir)
+    {
+      LT_DLMUTEX_LOCK ();
+      if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
+       ++errors;
+      LT_DLMUTEX_UNLOCK ();
+    }
+
+  return errors;
+}
+
+int
+lt_dlinsertsearchdir (before, search_dir)
+     const char *before;
+     const char *search_dir;
+{
+  int errors = 0;
+
+  if (before)
+    {
+      LT_DLMUTEX_LOCK ();
+      if ((before < user_search_path)
+         || (before >= user_search_path + LT_STRLEN (user_search_path)))
+       {
+         LT_DLMUTEX_UNLOCK ();
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
+         return 1;
+       }
+      LT_DLMUTEX_UNLOCK ();
+    }
+
+  if (search_dir && *search_dir)
+    {
+      LT_DLMUTEX_LOCK ();
+      if (lt_dlpath_insertdir (&user_search_path,
+                              (char *) before, search_dir) != 0)
+       {
+         ++errors;
+       }
+      LT_DLMUTEX_UNLOCK ();
+    }
+
+  return errors;
+}
+
+int
+lt_dlsetsearchpath (search_path)
+     const char *search_path;
+{
+  int   errors     = 0;
+
+  LT_DLMUTEX_LOCK ();
+  LT_DLFREE (user_search_path);
+  LT_DLMUTEX_UNLOCK ();
+
+  if (!search_path || !LT_STRLEN (search_path))
+    {
+      return errors;
+    }
+
+  LT_DLMUTEX_LOCK ();
+  if (canonicalize_path (search_path, &user_search_path) != 0)
+    ++errors;
+  LT_DLMUTEX_UNLOCK ();
+
+  return errors;
+}
+
+const char *
+lt_dlgetsearchpath ()
+{
+  const char *saved_path;
+
+  LT_DLMUTEX_LOCK ();
+  saved_path = user_search_path;
+  LT_DLMUTEX_UNLOCK ();
+
+  return saved_path;
+}
+
+int
+lt_dlmakeresident (handle)
+     lt_dlhandle handle;
+{
+  int errors = 0;
+
+  if (!handle)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
+      ++errors;
+    }
+  else
+    {
+      LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
+    }
+
+  return errors;
+}
+
+int
+lt_dlisresident        (handle)
+     lt_dlhandle handle;
+{
+  if (!handle)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
+      return -1;
+    }
+
+  return LT_DLIS_RESIDENT (handle);
+}
+
+
+
+
+/* --- MODULE INFORMATION --- */
+
+const lt_dlinfo *
+lt_dlgetinfo (handle)
+     lt_dlhandle handle;
+{
+  if (!handle)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
+      return 0;
+    }
+
+  return &(handle->info);
+}
+
+lt_dlhandle
+lt_dlhandle_next (place)
+     lt_dlhandle place;
+{
+  return place ? place->next : handles;
+}
+
+int
+lt_dlforeach (func, data)
+     int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
+     lt_ptr data;
+{
+  int errors = 0;
+  lt_dlhandle cur;
+
+  LT_DLMUTEX_LOCK ();
+
+  cur = handles;
+  while (cur)
+    {
+      lt_dlhandle tmp = cur;
+
+      cur = cur->next;
+      if ((*func) (tmp, data))
+       {
+         ++errors;
+         break;
+       }
+    }
+
+  LT_DLMUTEX_UNLOCK ();
+
+  return errors;
+}
+
+lt_dlcaller_id
+lt_dlcaller_register ()
+{
+  static lt_dlcaller_id last_caller_id = 0;
+  int result;
+
+  LT_DLMUTEX_LOCK ();
+  result = ++last_caller_id;
+  LT_DLMUTEX_UNLOCK ();
+
+  return result;
+}
+
+lt_ptr
+lt_dlcaller_set_data (key, handle, data)
+     lt_dlcaller_id key;
+     lt_dlhandle handle;
+     lt_ptr data;
+{
+  int n_elements = 0;
+  lt_ptr stale = (lt_ptr) 0;
+  int i;
+
+  /* This needs to be locked so that the caller data can be updated
+     simultaneously by different threads.  */
+  LT_DLMUTEX_LOCK ();
+
+  if (handle->caller_data)
+    while (handle->caller_data[n_elements].key)
+      ++n_elements;
+
+  for (i = 0; i < n_elements; ++i)
+    {
+      if (handle->caller_data[i].key == key)
+       {
+         stale = handle->caller_data[i].data;
+         break;
+       }
+    }
+
+  /* Ensure that there is enough room in this handle's caller_data
+     array to accept a new element (and an empty end marker).  */
+  if (i == n_elements)
+    {
+      lt_caller_data *temp
+       = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
+
+      if (!temp)
+       {
+         stale = 0;
+         goto done;
+       }
+
+      handle->caller_data = temp;
+
+      /* We only need this if we needed to allocate a new caller_data.  */
+      handle->caller_data[i].key  = key;
+      handle->caller_data[1+ i].key = 0;
+    }
+
+  handle->caller_data[i].data = data;
+
+ done:
+  LT_DLMUTEX_UNLOCK ();
+
+  return stale;
+}
+
+lt_ptr
+lt_dlcaller_get_data  (key, handle)
+     lt_dlcaller_id key;
+     lt_dlhandle handle;
+{
+  lt_ptr result = (lt_ptr) 0;
+
+  /* This needs to be locked so that the caller data isn't updated by
+     another thread part way through this function.  */
+  LT_DLMUTEX_LOCK ();
+
+  /* Locate the index of the element with a matching KEY.  */
+  {
+    int i;
+    for (i = 0; handle->caller_data[i].key; ++i)
+      {
+       if (handle->caller_data[i].key == key)
+         {
+           result = handle->caller_data[i].data;
+           break;
+         }
+      }
+  }
+
+  LT_DLMUTEX_UNLOCK ();
+
+  return result;
+}
+
+
+
+/* --- USER MODULE LOADER API --- */
+
+
+int
+lt_dlloader_add (place, dlloader, loader_name)
+     lt_dlloader *place;
+     const struct lt_user_dlloader *dlloader;
+     const char *loader_name;
+{
+  int errors = 0;
+  lt_dlloader *node = 0, *ptr = 0;
+
+  if ((dlloader == 0)  /* diagnose null parameters */
+      || (dlloader->module_open == 0)
+      || (dlloader->module_close == 0)
+      || (dlloader->find_sym == 0))
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
+      return 1;
+    }
+
+  /* Create a new dlloader node with copies of the user callbacks.  */
+  node = LT_EMALLOC (lt_dlloader, 1);
+  if (!node)
+    return 1;
+
+  node->next           = 0;
+  node->loader_name    = loader_name;
+  node->sym_prefix     = dlloader->sym_prefix;
+  node->dlloader_exit  = dlloader->dlloader_exit;
+  node->module_open    = dlloader->module_open;
+  node->module_close   = dlloader->module_close;
+  node->find_sym       = dlloader->find_sym;
+  node->dlloader_data  = dlloader->dlloader_data;
+
+  LT_DLMUTEX_LOCK ();
+  if (!loaders)
+    {
+      /* If there are no loaders, NODE becomes the list! */
+      loaders = node;
+    }
+  else if (!place)
+    {
+      /* If PLACE is not set, add NODE to the end of the
+        LOADERS list. */
+      for (ptr = loaders; ptr->next; ptr = ptr->next)
+       {
+         /*NOWORK*/;
+       }
+
+      ptr->next = node;
+    }
+  else if (loaders == place)
+    {
+      /* If PLACE is the first loader, NODE goes first. */
+      node->next = place;
+      loaders = node;
+    }
+  else
+    {
+      /* Find the node immediately preceding PLACE. */
+      for (ptr = loaders; ptr->next != place; ptr = ptr->next)
+       {
+         /*NOWORK*/;
+       }
+
+      if (ptr->next != place)
+       {
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
+         ++errors;
+       }
+      else
+       {
+         /* Insert NODE between PTR and PLACE. */
+         node->next = place;
+         ptr->next  = node;
+       }
+    }
+
+  LT_DLMUTEX_UNLOCK ();
+
+  return errors;
+}
+
+int
+lt_dlloader_remove (loader_name)
+     const char *loader_name;
+{
+  lt_dlloader *place = lt_dlloader_find (loader_name);
+  lt_dlhandle handle;
+  int errors = 0;
+
+  if (!place)
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
+      return 1;
+    }
+
+  LT_DLMUTEX_LOCK ();
+
+  /* Fail if there are any open modules which use this loader. */
+  for  (handle = handles; handle; handle = handle->next)
+    {
+      if (handle->loader == place)
+       {
+         LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
+         ++errors;
+         goto done;
+       }
+    }
+
+  if (place == loaders)
+    {
+      /* PLACE is the first loader in the list. */
+      loaders = loaders->next;
+    }
+  else
+    {
+      /* Find the loader before the one being removed. */
+      lt_dlloader *prev;
+      for (prev = loaders; prev->next; prev = prev->next)
+       {
+         if (!strcmp (prev->next->loader_name, loader_name))
+           {
+             break;
+           }
+       }
+
+      place = prev->next;
+      prev->next = prev->next->next;
+    }
+
+  if (place->dlloader_exit)
+    {
+      errors = place->dlloader_exit (place->dlloader_data);
+    }
+
+  LT_DLFREE (place);
+
+ done:
+  LT_DLMUTEX_UNLOCK ();
+
+  return errors;
+}
+
+lt_dlloader *
+lt_dlloader_next (place)
+     lt_dlloader *place;
+{
+  lt_dlloader *next;
+
+  LT_DLMUTEX_LOCK ();
+  next = place ? place->next : loaders;
+  LT_DLMUTEX_UNLOCK ();
+
+  return next;
+}
+
+const char *
+lt_dlloader_name (place)
+     lt_dlloader *place;
+{
+  const char *name = 0;
+
+  if (place)
+    {
+      LT_DLMUTEX_LOCK ();
+      name = place ? place->loader_name : 0;
+      LT_DLMUTEX_UNLOCK ();
+    }
+  else
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
+    }
+
+  return name;
+}
+
+lt_user_data *
+lt_dlloader_data (place)
+     lt_dlloader *place;
+{
+  lt_user_data *data = 0;
+
+  if (place)
+    {
+      LT_DLMUTEX_LOCK ();
+      data = place ? &(place->dlloader_data) : 0;
+      LT_DLMUTEX_UNLOCK ();
+    }
+  else
+    {
+      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
+    }
+
+  return data;
+}
+
+lt_dlloader *
+lt_dlloader_find (loader_name)
+     const char *loader_name;
+{
+  lt_dlloader *place = 0;
+
+  LT_DLMUTEX_LOCK ();
+  for (place = loaders; place; place = place->next)
+    {
+      if (strcmp (place->loader_name, loader_name) == 0)
+       {
+         break;
+       }
+    }
+  LT_DLMUTEX_UNLOCK ();
+
+  return place;
+}
diff --git a/libltdl/ltdl.h b/libltdl/ltdl.h
new file mode 100644 (file)
index 0000000..1f2b971
--- /dev/null
@@ -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 */
diff --git a/libltdl/ltmain.sh b/libltdl/ltmain.sh
new file mode 100644 (file)
index 0000000..f924d30
--- /dev/null
@@ -0,0 +1,6938 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun configure.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
+# 2007  Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 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 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.
+#
+# 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.
+
+basename="s,^.*/,,g"
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+progname=`echo "$progpath" | $SED $basename`
+modename="$progname"
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION="1.5.24 Debian 1.5.24-1"
+TIMESTAMP=" (1.1220.2.456 2007/06/24 02:25:32)"
+
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell, and then maybe $echo will work.
+  exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit $EXIT_SUCCESS
+fi
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  SP2NL='tr \040 \012'
+  NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  SP2NL='tr \100 \n'
+  NL2SP='tr \r\n \100\100'
+  ;;
+esac
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+  eval "if test \"\${$lt_var+set}\" = set; then
+         save_$lt_var=\$$lt_var
+         $lt_var=C
+         export $lt_var
+       fi"
+done
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS="  $lt_nl"
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+  $echo "$modename: not configured to build any kind of library" 1>&2
+  $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+  exit $EXIT_FAILURE
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+duplicate_deps=no
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+#####################################
+# Shell function definitions:
+# This seems to be the best place for them
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible.  If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+    my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+    if test "$run" = ":"; then
+      # Return a directory name, but don't create it in dry-run mode
+      my_tmpdir="${my_template}-$$"
+    else
+
+      # If mktemp works, use that first and foremost
+      my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+      if test ! -d "$my_tmpdir"; then
+       # Failing that, at least try and use $RANDOM to avoid a race
+       my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+       save_mktempdir_umask=`umask`
+       umask 0077
+       $mkdir "$my_tmpdir"
+       umask $save_mktempdir_umask
+      fi
+
+      # If we're not in dry-run mode, bomb out on failure
+      test -d "$my_tmpdir" || {
+        $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2
+       exit $EXIT_FAILURE
+      }
+    fi
+
+    $echo "X$my_tmpdir" | $Xsed
+}
+
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid ()
+{
+  win32_libid_type="unknown"
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
+      $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+      win32_nmres=`eval $NM -f posix -A $1 | \
+       $SED -n -e '1,100{
+               / I /{
+                       s,.*,import,
+                       p
+                       q
+                       }
+               }'`
+      case $win32_nmres in
+      import*)  win32_libid_type="x86 archive import";;
+      *)        win32_libid_type="x86 archive static";;
+      esac
+    fi
+    ;;
+  *DLL*)
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $echo $win32_libid_type
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+    if test -n "$available_tags" && test -z "$tagname"; then
+      CC_quoted=
+      for arg in $CC; do
+       case $arg in
+         *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+         arg="\"$arg\""
+         ;;
+       esac
+       CC_quoted="$CC_quoted $arg"
+      done
+      case $@ in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+       for z in $available_tags; do
+         if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+           # Evaluate the configuration.
+           eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+           CC_quoted=
+           for arg in $CC; do
+           # Double-quote args containing other shell metacharacters.
+           case $arg in
+             *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \     ]*|*]*|"")
+             arg="\"$arg\""
+             ;;
+           esac
+           CC_quoted="$CC_quoted $arg"
+         done
+           case "$@ " in
+             " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*)
+             # The compiler in the base compile command matches
+             # the one in the tagged configuration.
+             # Assume this is the tagged configuration we want.
+             tagname=$z
+             break
+             ;;
+           esac
+         fi
+       done
+       # If $tagname still isn't set, then no tagged configuration
+       # was found and let the user know that the "--tag" command
+       # line option must be used.
+       if test -z "$tagname"; then
+         $echo "$modename: unable to infer tagged configuration"
+         $echo "$modename: specify a tag with \`--tag'" 1>&2
+         exit $EXIT_FAILURE
+#        else
+#          $echo "$modename: using $tagname tagged configuration"
+       fi
+       ;;
+      esac
+    fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    f_ex_an_ar_dir="$1"; shift
+    f_ex_an_ar_oldlib="$1"
+
+    $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
+    $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
+      exit $EXIT_FAILURE
+    fi
+}
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+    my_status=""
+
+    $show "${rm}r $my_gentop"
+    $run ${rm}r "$my_gentop"
+    $show "$mkdir $my_gentop"
+    $run $mkdir "$my_gentop"
+    my_status=$?
+    if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
+      exit $my_status
+    fi
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+       [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+       *) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
+      my_xlib_u=$my_xlib
+      while :; do
+        case " $extracted_archives " in
+       *" $my_xlib_u "*)
+         extracted_serial=`expr $extracted_serial + 1`
+         my_xlib_u=lt$extracted_serial-$my_xlib ;;
+       *) break ;;
+       esac
+      done
+      extracted_archives="$extracted_archives $my_xlib_u"
+      my_xdir="$my_gentop/$my_xlib_u"
+
+      $show "${rm}r $my_xdir"
+      $run ${rm}r "$my_xdir"
+      $show "$mkdir $my_xdir"
+      $run $mkdir "$my_xdir"
+      exit_status=$?
+      if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then
+       exit $exit_status
+      fi
+      case $host in
+      *-darwin*)
+       $show "Extracting $my_xabs"
+       # Do not bother doing anything if just a dry run
+       if test -z "$run"; then
+         darwin_orig_dir=`pwd`
+         cd $my_xdir || exit $?
+         darwin_archive=$my_xabs
+         darwin_curdir=`pwd`
+         darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
+         darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
+         if test -n "$darwin_arches"; then 
+           darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
+           darwin_arch=
+           $show "$darwin_base_archive has multiple architectures $darwin_arches"
+           for darwin_arch in  $darwin_arches ; do
+             mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+             lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+             cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+             func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+             cd "$darwin_curdir"
+             $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+           done # $darwin_arches
+      ## Okay now we have a bunch of thin objects, gotta fatten them up :)
+           darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
+           darwin_file=
+           darwin_files=
+           for darwin_file in $darwin_filelist; do
+             darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+             lipo -create -output "$darwin_file" $darwin_files
+           done # $darwin_filelist
+           ${rm}r unfat-$$
+           cd "$darwin_orig_dir"
+         else
+           cd "$darwin_orig_dir"
+           func_extract_an_archive "$my_xdir" "$my_xabs"
+         fi # $darwin_arches
+       fi # $run
+       ;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+        ;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+    done
+    func_extract_archives_result="$my_oldobjs"
+}
+# End of Shell function definitions
+#####################################
+
+# Darwin sucks
+eval std_shrext=\"$shrext_cmds\"
+
+disable_libs=no
+
+# Parse our command line options once, thoroughly.
+while test "$#" -gt 0
+do
+  arg="$1"
+  shift
+
+  case $arg in
+  -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$prev"; then
+    case $prev in
+    execute_dlfiles)
+      execute_dlfiles="$execute_dlfiles $arg"
+      ;;
+    tag)
+      tagname="$arg"
+      preserve_args="${preserve_args}=$arg"
+
+      # Check whether tagname contains only valid characters
+      case $tagname in
+      *[!-_A-Za-z0-9,/]*)
+       $echo "$progname: invalid tag name: $tagname" 1>&2
+       exit $EXIT_FAILURE
+       ;;
+      esac
+
+      case $tagname in
+      CC)
+       # Don't test for the "default" C tag, as we know, it's there, but
+       # not specially marked.
+       ;;
+      *)
+       if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then
+         taglist="$taglist $tagname"
+         # Evaluate the configuration.
+         eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`"
+       else
+         $echo "$progname: ignoring unknown tag $tagname" 1>&2
+       fi
+       ;;
+      esac
+      ;;
+    *)
+      eval "$prev=\$arg"
+      ;;
+    esac
+
+    prev=
+    prevopt=
+    continue
+  fi
+
+  # Have we seen a non-optional argument yet?
+  case $arg in
+  --help)
+    show_help=yes
+    ;;
+
+  --version)
+    echo "\
+$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP
+
+Copyright (C) 2007  Free Software Foundation, Inc.
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+    exit $?
+    ;;
+
+  --config)
+    ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
+    done
+    exit $?
+    ;;
+
+  --debug)
+    $echo "$progname: enabling shell trace mode"
+    set -x
+    preserve_args="$preserve_args $arg"
+    ;;
+
+  --dry-run | -n)
+    run=:
+    ;;
+
+  --features)
+    $echo "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      $echo "enable shared libraries"
+    else
+      $echo "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      $echo "enable static libraries"
+    else
+      $echo "disable static libraries"
+    fi
+    exit $?
+    ;;
+
+  --finish) mode="finish" ;;
+
+  --mode) prevopt="--mode" prev=mode ;;
+  --mode=*) mode="$optarg" ;;
+
+  --preserve-dup-deps) duplicate_deps="yes" ;;
+
+  --quiet | --silent)
+    show=:
+    preserve_args="$preserve_args $arg"
+    ;;
+
+  --tag)
+    prevopt="--tag"
+    prev=tag
+    preserve_args="$preserve_args --tag"
+    ;;
+  --tag=*)
+    set tag "$optarg" ${1+"$@"}
+    shift
+    prev=tag
+    preserve_args="$preserve_args --tag"
+    ;;
+
+  -dlopen)
+    prevopt="-dlopen"
+    prev=execute_dlfiles
+    ;;
+
+  -*)
+    $echo "$modename: unrecognized option \`$arg'" 1>&2
+    $echo "$help" 1>&2
+    exit $EXIT_FAILURE
+    ;;
+
+  *)
+    nonopt="$arg"
+    break
+    ;;
+  esac
+done
+
+if test -n "$prevopt"; then
+  $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+  $echo "$help" 1>&2
+  exit $EXIT_FAILURE
+fi
+
+case $disable_libs in
+no) 
+  ;;
+shared)
+  build_libtool_libs=no
+  build_old_libs=yes
+  ;;
+static)
+  build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+  ;;
+esac
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+if test -z "$show_help"; then
+
+  # Infer the operation mode.
+  if test -z "$mode"; then
+    $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
+    $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
+    case $nonopt in
+    *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
+      mode=link
+      for arg
+      do
+       case $arg in
+       -c)
+          mode=compile
+          break
+          ;;
+       esac
+      done
+      ;;
+    *db | *dbx | *strace | *truss)
+      mode=execute
+      ;;
+    *install*|cp|mv)
+      mode=install
+      ;;
+    *rm)
+      mode=uninstall
+      ;;
+    *)
+      # If we have no mode, but dlfiles were specified, then do execute mode.
+      test -n "$execute_dlfiles" && mode=execute
+
+      # Just use the default operation mode.
+      if test -z "$mode"; then
+       if test -n "$nonopt"; then
+         $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+       else
+         $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+       fi
+      fi
+      ;;
+    esac
+  fi
+
+  # Only execute mode is allowed to have -dlopen flags.
+  if test -n "$execute_dlfiles" && test "$mode" != execute; then
+    $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+    $echo "$help" 1>&2
+    exit $EXIT_FAILURE
+  fi
+
+  # Change the help message to a mode-specific one.
+  generic_help="$help"
+  help="Try \`$modename --help --mode=$mode' for more information."
+
+  # These modes are in order of execution frequency so that they run quickly.
+  case $mode in
+  # libtool compile mode
+  compile)
+    modename="$modename: compile"
+    # Get the compilation command and the source file.
+    base_compile=
+    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
+    suppress_opt=yes
+    suppress_output=
+    arg_mode=normal
+    libobj=
+    later=
+
+    for arg
+    do
+      case $arg_mode in
+      arg  )
+       # do not "continue".  Instead, add this to base_compile
+       lastarg="$arg"
+       arg_mode=normal
+       ;;
+
+      target )
+       libobj="$arg"
+       arg_mode=normal
+       continue
+       ;;
+
+      normal )
+       # Accept any command-line options.
+       case $arg in
+       -o)
+         if test -n "$libobj" ; then
+           $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+           exit $EXIT_FAILURE
+         fi
+         arg_mode=target
+         continue
+         ;;
+
+       -static | -prefer-pic | -prefer-non-pic)
+         later="$later $arg"
+         continue
+         ;;
+
+       -no-suppress)
+         suppress_opt=no
+         continue
+         ;;
+
+       -Xcompiler)
+         arg_mode=arg  #  the next one goes into the "base_compile" arg list
+         continue      #  The current "srcfile" will either be retained or
+         ;;            #  replaced later.  I would guess that would be a bug.
+
+       -Wc,*)
+         args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+         lastarg=
+         save_ifs="$IFS"; IFS=','
+         for arg in $args; do
+           IFS="$save_ifs"
+
+           # Double-quote args containing other shell metacharacters.
+           # Many Bourne shells cannot handle close brackets correctly
+           # in scan sets, so we specify it separately.
+           case $arg in
+             *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \     ]*|*]*|"")
+             arg="\"$arg\""
+             ;;
+           esac
+           lastarg="$lastarg $arg"
+         done
+         IFS="$save_ifs"
+         lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
+
+         # Add the arguments to base_compile.
+         base_compile="$base_compile $lastarg"
+         continue
+         ;;
+
+       * )
+         # Accept the current argument as the source file.
+         # The previous "srcfile" becomes the current argument.
+         #
+         lastarg="$srcfile"
+         srcfile="$arg"
+         ;;
+       esac  #  case $arg
+       ;;
+      esac    #  case $arg_mode
+
+      # Aesthetically quote the previous argument.
+      lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+      case $lastarg in
+      # Double-quote args containing other shell metacharacters.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, and some SunOS ksh mistreat backslash-escaping
+      # in scan sets (worked around with variable expansion),
+      # and furthermore cannot handle '|' '&' '(' ')' in scan sets 
+      # at all, so we specify them separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+       lastarg="\"$lastarg\""
+       ;;
+      esac
+
+      base_compile="$base_compile $lastarg"
+    done # for arg
+
+    case $arg_mode in
+    arg)
+      $echo "$modename: you must specify an argument for -Xcompile"
+      exit $EXIT_FAILURE
+      ;;
+    target)
+      $echo "$modename: you must specify a target with \`-o'" 1>&2
+      exit $EXIT_FAILURE
+      ;;
+    *)
+      # Get the name of the library object.
+      [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    xform='[cCFSifmso]'
+    case $libobj in
+    *.ada) xform=ada ;;
+    *.adb) xform=adb ;;
+    *.ads) xform=ads ;;
+    *.asm) xform=asm ;;
+    *.c++) xform=c++ ;;
+    *.cc) xform=cc ;;
+    *.ii) xform=ii ;;
+    *.class) xform=class ;;
+    *.cpp) xform=cpp ;;
+    *.cxx) xform=cxx ;;
+    *.[fF][09]?) xform=[fF][09]. ;;
+    *.for) xform=for ;;
+    *.java) xform=java ;;
+    *.obj) xform=obj ;;
+    esac
+
+    libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+    case $libobj in
+    *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+    *)
+      $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+      exit $EXIT_FAILURE
+      ;;
+    esac
+
+    func_infer_tag $base_compile
+
+    for arg in $later; do
+      case $arg in
+      -static)
+       build_old_libs=yes
+       continue
+       ;;
+
+      -prefer-pic)
+       pic_mode=yes
+       continue
+       ;;
+
+      -prefer-non-pic)
+       pic_mode=no
+       continue
+       ;;
+      esac
+    done
+
+    qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
+    case $qlibobj in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+       qlibobj="\"$qlibobj\"" ;;
+    esac
+    test "X$libobj" != "X$qlibobj" \
+       && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"'  &()|`$[]' \
+       && $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
+    objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+    xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+    if test "X$xdir" = "X$obj"; then
+      xdir=
+    else
+      xdir=$xdir/
+    fi
+    lobj=${xdir}$objdir/$objname
+
+    if test -z "$base_compile"; then
+      $echo "$modename: you must specify a compilation command" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $lobj $libobj ${libobj}T"
+    else
+      removelist="$lobj $libobj ${libobj}T"
+    fi
+
+    $run $rm $removelist
+    trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2*)
+      pic_mode=default
+      ;;
+    esac
+    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+      removelist="$removelist $output_obj $lockfile"
+      trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+    else
+      output_obj=
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until $run ln "$progpath" "$lockfile" 2>/dev/null; do
+       $show "Waiting for $lockfile to be removed"
+       sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+       $echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $run $rm $removelist
+       exit $EXIT_FAILURE
+      fi
+      $echo "$srcfile" > "$lockfile"
+    fi
+
+    if test -n "$fix_srcfile_path"; then
+      eval srcfile=\"$fix_srcfile_path\"
+    fi
+    qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
+    case $qsrcfile in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+      qsrcfile="\"$qsrcfile\"" ;;
+    esac
+
+    $run $rm "$libobj" "${libobj}T"
+
+    # Create a libtool object file (analogous to a ".la" file),
+    # but don't create it if we're doing a dry run.
+    test -z "$run" && cat > ${libobj}T <<EOF
+# $libobj - a libtool object file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+EOF
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test "$pic_mode" != no; then
+       command="$base_compile $qsrcfile $pic_flag"
+      else
+       # Don't build PIC code
+       command="$base_compile $qsrcfile"
+      fi
+
+      if test ! -d "${xdir}$objdir"; then
+       $show "$mkdir ${xdir}$objdir"
+       $run $mkdir ${xdir}$objdir
+       exit_status=$?
+       if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then
+         exit $exit_status
+       fi
+      fi
+
+      if test -z "$output_obj"; then
+       # Place PIC objects in $objdir
+       command="$command -o $lobj"
+      fi
+
+      $run $rm "$lobj" "$output_obj"
+
+      $show "$command"
+      if $run eval "$command"; then :
+      else
+       test -n "$output_obj" && $run $rm $removelist
+       exit $EXIT_FAILURE
+      fi
+
+      if test "$need_locks" = warn &&
+        test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+       $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $run $rm $removelist
+       exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+       $show "$mv $output_obj $lobj"
+       if $run $mv $output_obj $lobj; then :
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+      fi
+
+      # Append the name of the PIC object to the libtool object file.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object='$objdir/$objname'
+
+EOF
+
+      # Allow error messages only from the first compilation.
+      if test "$suppress_opt" = yes; then
+        suppress_output=' >/dev/null 2>&1'
+      fi
+    else
+      # No PIC object so indicate it doesn't exist in the libtool
+      # object file.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object=none
+
+EOF
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      if test "$pic_mode" != yes; then
+       # Don't build PIC code
+       command="$base_compile $qsrcfile"
+      else
+       command="$base_compile $qsrcfile $pic_flag"
+      fi
+      if test "$compiler_c_o" = yes; then
+       command="$command -o $obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      command="$command$suppress_output"
+      $run $rm "$obj" "$output_obj"
+      $show "$command"
+      if $run eval "$command"; then :
+      else
+       $run $rm $removelist
+       exit $EXIT_FAILURE
+      fi
+
+      if test "$need_locks" = warn &&
+        test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+       $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $run $rm $removelist
+       exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+       $show "$mv $output_obj $obj"
+       if $run $mv $output_obj $obj; then :
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+      fi
+
+      # Append the name of the non-PIC object the libtool object file.
+      # Only append if the libtool object file exists.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object='$objname'
+
+EOF
+    else
+      # Append the name of the non-PIC object the libtool object file.
+      # Only append if the libtool object file exists.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object=none
+
+EOF
+    fi
+
+    $run $mv "${libobj}T" "${libobj}"
+
+    # Unlock the critical section if it was locked
+    if test "$need_locks" != no; then
+      $run $rm "$lockfile"
+    fi
+
+    exit $EXIT_SUCCESS
+    ;;
+
+  # libtool link mode
+  link | relink)
+    modename="$modename: link"
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invocation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args="$nonopt"
+    base_compile="$nonopt $@"
+    compile_command="$nonopt"
+    finalize_command="$nonopt"
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+    inst_prefix_dir=
+
+    avoid_version=no
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    non_pic_objects=
+    notinst_path= # paths that contain not-installed libtool libraries
+    precious_files_regex=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+    vinfo_number=no
+
+    func_infer_tag $base_compile
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -all-static | -static | -static-libtool-libs)
+       case $arg in
+       -all-static)
+         if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+           $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+         fi
+         if test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+         prefer_static_libs=yes
+         ;;
+       -static)
+         if test -z "$pic_flag" && test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+         prefer_static_libs=built
+         ;;
+       -static-libtool-libs)
+         if test -z "$pic_flag" && test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+         prefer_static_libs=yes
+         ;;
+       esac
+       build_libtool_libs=no
+       build_old_libs=yes
+       break
+       ;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test "$#" -gt 0; do
+      arg="$1"
+      shift
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+       qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
+       ;;
+      *) qarg=$arg ;;
+      esac
+      libtool_args="$libtool_args $qarg"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+       case $prev in
+       output)
+         compile_command="$compile_command @OUTPUT@"
+         finalize_command="$finalize_command @OUTPUT@"
+         ;;
+       esac
+
+       case $prev in
+       dlfiles|dlprefiles)
+         if test "$preload" = no; then
+           # Add the symbol object into the linking commands.
+           compile_command="$compile_command @SYMFILE@"
+           finalize_command="$finalize_command @SYMFILE@"
+           preload=yes
+         fi
+         case $arg in
+         *.la | *.lo) ;;  # We handle these cases below.
+         force)
+           if test "$dlself" = no; then
+             dlself=needless
+             export_dynamic=yes
+           fi
+           prev=
+           continue
+           ;;
+         self)
+           if test "$prev" = dlprefiles; then
+             dlself=yes
+           elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+             dlself=yes
+           else
+             dlself=needless
+             export_dynamic=yes
+           fi
+           prev=
+           continue
+           ;;
+         *)
+           if test "$prev" = dlfiles; then
+             dlfiles="$dlfiles $arg"
+           else
+             dlprefiles="$dlprefiles $arg"
+           fi
+           prev=
+           continue
+           ;;
+         esac
+         ;;
+       expsyms)
+         export_symbols="$arg"
+         if test ! -f "$arg"; then
+           $echo "$modename: symbol file \`$arg' does not exist"
+           exit $EXIT_FAILURE
+         fi
+         prev=
+         continue
+         ;;
+       expsyms_regex)
+         export_symbols_regex="$arg"
+         prev=
+         continue
+         ;;
+       inst_prefix)
+         inst_prefix_dir="$arg"
+         prev=
+         continue
+         ;;
+       precious_regex)
+         precious_files_regex="$arg"
+         prev=
+         continue
+         ;;
+       release)
+         release="-$arg"
+         prev=
+         continue
+         ;;
+       objectlist)
+         if test -f "$arg"; then
+           save_arg=$arg
+           moreargs=
+           for fil in `cat $save_arg`
+           do
+#            moreargs="$moreargs $fil"
+             arg=$fil
+             # A libtool-controlled object.
+
+             # Check to see that this really is a libtool object.
+             if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+               pic_object=
+               non_pic_object=
+
+               # Read the .lo file
+               # If there is no directory component, then add one.
+               case $arg in
+               */* | *\\*) . $arg ;;
+               *) . ./$arg ;;
+               esac
+
+               if test -z "$pic_object" || \
+                  test -z "$non_pic_object" ||
+                  test "$pic_object" = none && \
+                  test "$non_pic_object" = none; then
+                 $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+                 exit $EXIT_FAILURE
+               fi
+
+               # Extract subdirectory from the argument.
+               xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+               if test "X$xdir" = "X$arg"; then
+                 xdir=
+               else
+                 xdir="$xdir/"
+               fi
+
+               if test "$pic_object" != none; then
+                 # Prepend the subdirectory the object is found in.
+                 pic_object="$xdir$pic_object"
+
+                 if test "$prev" = dlfiles; then
+                   if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+                     dlfiles="$dlfiles $pic_object"
+                     prev=
+                     continue
+                   else
+                     # If libtool objects are unsupported, then we need to preload.
+                     prev=dlprefiles
+                   fi
+                 fi
+
+                 # CHECK ME:  I think I busted this.  -Ossama
+                 if test "$prev" = dlprefiles; then
+                   # Preload the old-style object.
+                   dlprefiles="$dlprefiles $pic_object"
+                   prev=
+                 fi
+
+                 # A PIC object.
+                 libobjs="$libobjs $pic_object"
+                 arg="$pic_object"
+               fi
+
+               # Non-PIC object.
+               if test "$non_pic_object" != none; then
+                 # Prepend the subdirectory the object is found in.
+                 non_pic_object="$xdir$non_pic_object"
+
+                 # A standard non-PIC object
+                 non_pic_objects="$non_pic_objects $non_pic_object"
+                 if test -z "$pic_object" || test "$pic_object" = none ; then
+                   arg="$non_pic_object"
+                 fi
+               else
+                 # If the PIC object exists, use it instead.
+                 # $xdir was prepended to $pic_object above.
+                 non_pic_object="$pic_object"
+                 non_pic_objects="$non_pic_objects $non_pic_object"
+               fi
+             else
+               # Only an error if not doing a dry-run.
+               if test -z "$run"; then
+                 $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+                 exit $EXIT_FAILURE
+               else
+                 # Dry-run case.
+
+                 # Extract subdirectory from the argument.
+                 xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+                 if test "X$xdir" = "X$arg"; then
+                   xdir=
+                 else
+                   xdir="$xdir/"
+                 fi
+
+                 pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+                 non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+                 libobjs="$libobjs $pic_object"
+                 non_pic_objects="$non_pic_objects $non_pic_object"
+               fi
+             fi
+           done
+         else
+           $echo "$modename: link input file \`$save_arg' does not exist"
+           exit $EXIT_FAILURE
+         fi
+         arg=$save_arg
+         prev=
+         continue
+         ;;
+       rpath | xrpath)
+         # We need an absolute path.
+         case $arg in
+         [\\/]* | [A-Za-z]:[\\/]*) ;;
+         *)
+           $echo "$modename: only absolute run-paths are allowed" 1>&2
+           exit $EXIT_FAILURE
+           ;;
+         esac
+         if test "$prev" = rpath; then
+           case "$rpath " in
+           *" $arg "*) ;;
+           *) rpath="$rpath $arg" ;;
+           esac
+         else
+           case "$xrpath " in
+           *" $arg "*) ;;
+           *) xrpath="$xrpath $arg" ;;
+           esac
+         fi
+         prev=
+         continue
+         ;;
+       xcompiler)
+         compiler_flags="$compiler_flags $qarg"
+         prev=
+         compile_command="$compile_command $qarg"
+         finalize_command="$finalize_command $qarg"
+         continue
+         ;;
+       xlinker)
+         linker_flags="$linker_flags $qarg"
+         compiler_flags="$compiler_flags $wl$qarg"
+         prev=
+         compile_command="$compile_command $wl$qarg"
+         finalize_command="$finalize_command $wl$qarg"
+         continue
+         ;;
+       xcclinker)
+         linker_flags="$linker_flags $qarg"
+         compiler_flags="$compiler_flags $qarg"
+         prev=
+         compile_command="$compile_command $qarg"
+         finalize_command="$finalize_command $qarg"
+         continue
+         ;;
+       shrext)
+         shrext_cmds="$arg"
+         prev=
+         continue
+         ;;
+       darwin_framework|darwin_framework_skip)
+         test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg"
+         compile_command="$compile_command $arg"
+         finalize_command="$finalize_command $arg"
+         prev=
+         continue
+         ;;
+       *)
+         eval "$prev=\"\$arg\""
+         prev=
+         continue
+         ;;
+       esac
+      fi # test -n "$prev"
+
+      prevarg="$arg"
+
+      case $arg in
+      -all-static)
+       if test -n "$link_static_flag"; then
+         compile_command="$compile_command $link_static_flag"
+         finalize_command="$finalize_command $link_static_flag"
+       fi
+       continue
+       ;;
+
+      -allow-undefined)
+       # FIXME: remove this flag sometime in the future.
+       $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+       continue
+       ;;
+
+      -avoid-version)
+       avoid_version=yes
+       continue
+       ;;
+
+      -dlopen)
+       prev=dlfiles
+       continue
+       ;;
+
+      -dlpreopen)
+       prev=dlprefiles
+       continue
+       ;;
+
+      -export-dynamic)
+       export_dynamic=yes
+       continue
+       ;;
+
+      -export-symbols | -export-symbols-regex)
+       if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+         $echo "$modename: more than one -exported-symbols argument is not allowed"
+         exit $EXIT_FAILURE
+       fi
+       if test "X$arg" = "X-export-symbols"; then
+         prev=expsyms
+       else
+         prev=expsyms_regex
+       fi
+       continue
+       ;;
+
+      -framework|-arch|-isysroot)
+       case " $CC " in
+         *" ${arg} ${1} "* | *" ${arg} ${1} "*) 
+               prev=darwin_framework_skip ;;
+         *) compiler_flags="$compiler_flags $arg"
+            prev=darwin_framework ;;
+       esac
+       compile_command="$compile_command $arg"
+       finalize_command="$finalize_command $arg"
+       continue
+       ;;
+
+      -inst-prefix-dir)
+       prev=inst_prefix
+       continue
+       ;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+       case $with_gcc/$host in
+       no/*-*-irix* | /*-*-irix*)
+         compile_command="$compile_command $arg"
+         finalize_command="$finalize_command $arg"
+         ;;
+       esac
+       continue
+       ;;
+
+      -L*)
+       dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+       # We need an absolute path.
+       case $dir in
+       [\\/]* | [A-Za-z]:[\\/]*) ;;
+       *)
+         absdir=`cd "$dir" && pwd`
+         if test -z "$absdir"; then
+           $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+           absdir="$dir"
+           notinst_path="$notinst_path $dir"
+         fi
+         dir="$absdir"
+         ;;
+       esac
+       case "$deplibs " in
+       *" -L$dir "*) ;;
+       *)
+         deplibs="$deplibs -L$dir"
+         lib_search_path="$lib_search_path $dir"
+         ;;
+       esac
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+         testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'`
+         case :$dllsearchpath: in
+         *":$dir:"*) ;;
+         *) dllsearchpath="$dllsearchpath:$dir";;
+         esac
+         case :$dllsearchpath: in
+         *":$testbindir:"*) ;;
+         *) dllsearchpath="$dllsearchpath:$testbindir";;
+         esac
+         ;;
+       esac
+       continue
+       ;;
+
+      -l*)
+       if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+         case $host in
+         *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*)
+           # These systems don't actually have a C or math library (as such)
+           continue
+           ;;
+         *-*-os2*)
+           # These systems don't actually have a C library (as such)
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+           # Do not include libc due to us having libc/libc_r.
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-rhapsody* | *-*-darwin1.[012])
+           # Rhapsody C and math libraries are in the System framework
+           deplibs="$deplibs -framework System"
+           continue
+           ;;
+         *-*-sco3.2v5* | *-*-sco5v6*)
+           # Causes problems with __ctype
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+           # Compiler inserts libc in the correct place for threads to work
+           test "X$arg" = "X-lc" && continue
+           ;;
+         esac
+       elif test "X$arg" = "X-lc_r"; then
+        case $host in
+        *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+          # Do not include libc_r directly, use -pthread flag.
+          continue
+          ;;
+        esac
+       fi
+       deplibs="$deplibs $arg"
+       continue
+       ;;
+
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      -model)
+       compile_command="$compile_command $arg"
+       compiler_flags="$compiler_flags $arg"
+       finalize_command="$finalize_command $arg"
+       prev=xcompiler
+       continue
+       ;;
+
+     -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+       compiler_flags="$compiler_flags $arg"
+       compile_command="$compile_command $arg"
+       finalize_command="$finalize_command $arg"
+       continue
+       ;;
+
+      -module)
+       module=yes
+       continue
+       ;;
+
+      # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+      # -r[0-9][0-9]* specifies the processor on the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+      # +DA*, +DD* enable 64-bit mode on the HP compiler
+      # -q* pass through compiler args for the IBM compiler
+      # -m* pass through architecture-specific compiler args for GCC
+      # -m*, -t[45]*, -txscale* pass through architecture-specific
+      # compiler args for GCC
+      # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC
+      # -F/path gives path to uninstalled frameworks, gcc on darwin
+      # @file GCC response files
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*)
+
+       # Unknown arguments in both finalize_command and compile_command need
+       # to be aesthetically quoted because they are evaled later.
+       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+       case $arg in
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*|"")
+         arg="\"$arg\""
+         ;;
+       esac
+        compile_command="$compile_command $arg"
+        finalize_command="$finalize_command $arg"
+        compiler_flags="$compiler_flags $arg"
+        continue
+        ;;
+
+      -shrext)
+       prev=shrext
+       continue
+       ;;
+
+      -no-fast-install)
+       fast_install=no
+       continue
+       ;;
+
+      -no-install)
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin*)
+         # The PATH hackery in wrapper scripts is required on Windows
+         # and Darwin in order for the loader to find any dlls it needs.
+         $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
+         $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
+         fast_install=no
+         ;;
+       *) no_install=yes ;;
+       esac
+       continue
+       ;;
+
+      -no-undefined)
+       allow_undefined=no
+       continue
+       ;;
+
+      -objectlist)
+       prev=objectlist
+       continue
+       ;;
+
+      -o) prev=output ;;
+
+      -precious-files-regex)
+       prev=precious_regex
+       continue
+       ;;
+
+      -release)
+       prev=release
+       continue
+       ;;
+
+      -rpath)
+       prev=rpath
+       continue
+       ;;
+
+      -R)
+       prev=xrpath
+       continue
+       ;;
+
+      -R*)
+       dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+       # We need an absolute path.
+       case $dir in
+       [\\/]* | [A-Za-z]:[\\/]*) ;;
+       *)
+         $echo "$modename: only absolute run-paths are allowed" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+       case "$xrpath " in
+       *" $dir "*) ;;
+       *) xrpath="$xrpath $dir" ;;
+       esac
+       continue
+       ;;
+
+      -static | -static-libtool-libs)
+       # The effects of -static are defined in a previous loop.
+       # We used to do the same as -all-static on platforms that
+       # didn't have a PIC flag, but the assumption that the effects
+       # would be equivalent was wrong.  It would break on at least
+       # Digital Unix and AIX.
+       continue
+       ;;
+
+      -thread-safe)
+       thread_safe=yes
+       continue
+       ;;
+
+      -version-info)
+       prev=vinfo
+       continue
+       ;;
+      -version-number)
+       prev=vinfo
+       vinfo_number=yes
+       continue
+       ;;
+
+      -Wc,*)
+       args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+       arg=
+       save_ifs="$IFS"; IFS=','
+       for flag in $args; do
+         IFS="$save_ifs"
+         case $flag in
+           *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \       ]*|*]*|"")
+           flag="\"$flag\""
+           ;;
+         esac
+         arg="$arg $wl$flag"
+         compiler_flags="$compiler_flags $flag"
+       done
+       IFS="$save_ifs"
+       arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+       ;;
+
+      -Wl,*)
+       args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+       arg=
+       save_ifs="$IFS"; IFS=','
+       for flag in $args; do
+         IFS="$save_ifs"
+         case $flag in
+           *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \       ]*|*]*|"")
+           flag="\"$flag\""
+           ;;
+         esac
+         arg="$arg $wl$flag"
+         compiler_flags="$compiler_flags $wl$flag"
+         linker_flags="$linker_flags $flag"
+       done
+       IFS="$save_ifs"
+       arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+       ;;
+
+      -Xcompiler)
+       prev=xcompiler
+       continue
+       ;;
+
+      -Xlinker)
+       prev=xlinker
+       continue
+       ;;
+
+      -XCClinker)
+       prev=xcclinker
+       continue
+       ;;
+
+      # Some other compiler flag.
+      -* | +*)
+       # Unknown arguments in both finalize_command and compile_command need
+       # to be aesthetically quoted because they are evaled later.
+       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+       case $arg in
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*|"")
+         arg="\"$arg\""
+         ;;
+       esac
+       ;;
+
+      *.$objext)
+       # A standard object.
+       objs="$objs $arg"
+       ;;
+
+      *.lo)
+       # A libtool-controlled object.
+
+       # Check to see that this really is a libtool object.
+       if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+         pic_object=
+         non_pic_object=
+
+         # Read the .lo file
+         # If there is no directory component, then add one.
+         case $arg in
+         */* | *\\*) . $arg ;;
+         *) . ./$arg ;;
+         esac
+
+         if test -z "$pic_object" || \
+            test -z "$non_pic_object" ||
+            test "$pic_object" = none && \
+            test "$non_pic_object" = none; then
+           $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+           exit $EXIT_FAILURE
+         fi
+
+         # Extract subdirectory from the argument.
+         xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+         if test "X$xdir" = "X$arg"; then
+           xdir=
+         else
+           xdir="$xdir/"
+         fi
+
+         if test "$pic_object" != none; then
+           # Prepend the subdirectory the object is found in.
+           pic_object="$xdir$pic_object"
+
+           if test "$prev" = dlfiles; then
+             if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+               dlfiles="$dlfiles $pic_object"
+               prev=
+               continue
+             else
+               # If libtool objects are unsupported, then we need to preload.
+               prev=dlprefiles
+             fi
+           fi
+
+           # CHECK ME:  I think I busted this.  -Ossama
+           if test "$prev" = dlprefiles; then
+             # Preload the old-style object.
+             dlprefiles="$dlprefiles $pic_object"
+             prev=
+           fi
+
+           # A PIC object.
+           libobjs="$libobjs $pic_object"
+           arg="$pic_object"
+         fi
+
+         # Non-PIC object.
+         if test "$non_pic_object" != none; then
+           # Prepend the subdirectory the object is found in.
+           non_pic_object="$xdir$non_pic_object"
+
+           # A standard non-PIC object
+           non_pic_objects="$non_pic_objects $non_pic_object"
+           if test -z "$pic_object" || test "$pic_object" = none ; then
+             arg="$non_pic_object"
+           fi
+         else
+           # If the PIC object exists, use it instead.
+           # $xdir was prepended to $pic_object above.
+           non_pic_object="$pic_object"
+           non_pic_objects="$non_pic_objects $non_pic_object"
+         fi
+       else
+         # Only an error if not doing a dry-run.
+         if test -z "$run"; then
+           $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+           exit $EXIT_FAILURE
+         else
+           # Dry-run case.
+
+           # Extract subdirectory from the argument.
+           xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+           if test "X$xdir" = "X$arg"; then
+             xdir=
+           else
+             xdir="$xdir/"
+           fi
+
+           pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+           non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+           libobjs="$libobjs $pic_object"
+           non_pic_objects="$non_pic_objects $non_pic_object"
+         fi
+       fi
+       ;;
+
+      *.$libext)
+       # An archive.
+       deplibs="$deplibs $arg"
+       old_deplibs="$old_deplibs $arg"
+       continue
+       ;;
+
+      *.la)
+       # A libtool-controlled library.
+
+       if test "$prev" = dlfiles; then
+         # This library was specified with -dlopen.
+         dlfiles="$dlfiles $arg"
+         prev=
+       elif test "$prev" = dlprefiles; then
+         # The library was specified with -dlpreopen.
+         dlprefiles="$dlprefiles $arg"
+         prev=
+       else
+         deplibs="$deplibs $arg"
+       fi
+       continue
+       ;;
+
+      # Some other compiler argument.
+      *)
+       # Unknown arguments in both finalize_command and compile_command need
+       # to be aesthetically quoted because they are evaled later.
+       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+       case $arg in
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*|"")
+         arg="\"$arg\""
+         ;;
+       esac
+       ;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+       compile_command="$compile_command $arg"
+       finalize_command="$finalize_command $arg"
+      fi
+    done # argument parsing loop
+
+    if test -n "$prev"; then
+      $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval arg=\"$export_dynamic_flag_spec\"
+      compile_command="$compile_command $arg"
+      finalize_command="$finalize_command $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+    libobjs_save="$libobjs"
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+    output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+    if test "X$output_objdir" = "X$output"; then
+      output_objdir="$objdir"
+    else
+      output_objdir="$output_objdir/$objdir"
+    fi
+    # Create the object directory.
+    if test ! -d "$output_objdir"; then
+      $show "$mkdir $output_objdir"
+      $run $mkdir $output_objdir
+      exit_status=$?
+      if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then
+       exit $exit_status
+      fi
+    fi
+
+    # Determine the type of output
+    case $output in
+    "")
+      $echo "$modename: you must specify an output file" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    case $host in
+    *cygwin* | *mingw* | *pw32*)
+      # don't eliminate duplications in $postdeps and $predeps
+      duplicate_compiler_generated_deps=yes
+      ;;
+    *)
+      duplicate_compiler_generated_deps=$duplicate_deps
+      ;;
+    esac
+    specialdeplibs=
+
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if test "X$duplicate_deps" = "Xyes" ; then
+       case "$libs " in
+       *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+       esac
+      fi
+      libs="$libs $deplib"
+    done
+
+    if test "$linkmode" = lib; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
+       for pre_post_dep in $predeps $postdeps; do
+         case "$pre_post_deps " in
+         *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+         esac
+         pre_post_deps="$pre_post_deps $pre_post_dep"
+       done
+      fi
+      pre_post_deps=
+    fi
+
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    case $linkmode in
+    lib)
+       passes="conv link"
+       for file in $dlfiles $dlprefiles; do
+         case $file in
+         *.la) ;;
+         *)
+           $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
+           exit $EXIT_FAILURE
+           ;;
+         esac
+       done
+       ;;
+    prog)
+       compile_deplibs=
+       finalize_deplibs=
+       alldeplibs=no
+       newdlfiles=
+       newdlprefiles=
+       passes="conv scan dlopen dlpreopen link"
+       ;;
+    *)  passes="conv"
+       ;;
+    esac
+    for pass in $passes; do
+      if test "$linkmode,$pass" = "lib,link" ||
+        test "$linkmode,$pass" = "prog,scan"; then
+       libs="$deplibs"
+       deplibs=
+      fi
+      if test "$linkmode" = prog; then
+       case $pass in
+       dlopen) libs="$dlfiles" ;;
+       dlpreopen) libs="$dlprefiles" ;;
+       link)
+         libs="$deplibs %DEPLIBS%"
+         test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
+         ;;
+       esac
+      fi
+      if test "$pass" = dlopen; then
+       # Collect dlpreopened libraries
+       save_deplibs="$deplibs"
+       deplibs=
+      fi
+      for deplib in $libs; do
+       lib=
+       found=no
+       case $deplib in
+       -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+         if test "$linkmode,$pass" = "prog,link"; then
+           compile_deplibs="$deplib $compile_deplibs"
+           finalize_deplibs="$deplib $finalize_deplibs"
+         else
+           compiler_flags="$compiler_flags $deplib"
+         fi
+         continue
+         ;;
+       -l*)
+         if test "$linkmode" != lib && test "$linkmode" != prog; then
+           $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
+           continue
+         fi
+         name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
+         for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
+           for search_ext in .la $std_shrext .so .a; do
+             # Search the libtool library
+             lib="$searchdir/lib${name}${search_ext}"
+             if test -f "$lib"; then
+               if test "$search_ext" = ".la"; then
+                 found=yes
+               else
+                 found=no
+               fi
+               break 2
+             fi
+           done
+         done
+         if test "$found" != yes; then
+           # deplib doesn't seem to be a libtool library
+           if test "$linkmode,$pass" = "prog,link"; then
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           else
+             deplibs="$deplib $deplibs"
+             test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+           fi
+           continue
+         else # deplib is a libtool library
+           # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+           # We need to do some special things here, and not later.
+           if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+             case " $predeps $postdeps " in
+             *" $deplib "*)
+               if (${SED} -e '2q' $lib |
+                    grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+                 library_names=
+                 old_library=
+                 case $lib in
+                 */* | *\\*) . $lib ;;
+                 *) . ./$lib ;;
+                 esac
+                 for l in $old_library $library_names; do
+                   ll="$l"
+                 done
+                 if test "X$ll" = "X$old_library" ; then # only static version available
+                   found=no
+                   ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+                   test "X$ladir" = "X$lib" && ladir="."
+                   lib=$ladir/$old_library
+                   if test "$linkmode,$pass" = "prog,link"; then
+                     compile_deplibs="$deplib $compile_deplibs"
+                     finalize_deplibs="$deplib $finalize_deplibs"
+                   else
+                     deplibs="$deplib $deplibs"
+                     test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+                   fi
+                   continue
+                 fi
+               fi
+               ;;
+             *) ;;
+             esac
+           fi
+         fi
+         ;; # -l
+       -L*)
+         case $linkmode in
+         lib)
+           deplibs="$deplib $deplibs"
+           test "$pass" = conv && continue
+           newdependency_libs="$deplib $newdependency_libs"
+           newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+           ;;
+         prog)
+           if test "$pass" = conv; then
+             deplibs="$deplib $deplibs"
+             continue
+           fi
+           if test "$pass" = scan; then
+             deplibs="$deplib $deplibs"
+           else
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           fi
+           newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+           ;;
+         *)
+           $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
+           ;;
+         esac # linkmode
+         continue
+         ;; # -L
+       -R*)
+         if test "$pass" = link; then
+           dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+           # Make sure the xrpath contains only unique directories.
+           case "$xrpath " in
+           *" $dir "*) ;;
+           *) xrpath="$xrpath $dir" ;;
+           esac
+         fi
+         deplibs="$deplib $deplibs"
+         continue
+         ;;
+       *.la) lib="$deplib" ;;
+       *.$libext)
+         if test "$pass" = conv; then
+           deplibs="$deplib $deplibs"
+           continue
+         fi
+         case $linkmode in
+         lib)
+           valid_a_lib=no
+           case $deplibs_check_method in
+             match_pattern*)
+               set dummy $deplibs_check_method
+               match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+               if eval $echo \"$deplib\" 2>/dev/null \
+                   | $SED 10q \
+                   | $EGREP "$match_pattern_regex" > /dev/null; then
+                 valid_a_lib=yes
+               fi
+               ;;
+             pass_all)
+               valid_a_lib=yes
+               ;;
+            esac
+           if test "$valid_a_lib" != yes; then
+             $echo
+             $echo "*** Warning: Trying to link with static lib archive $deplib."
+             $echo "*** I have the capability to make that library automatically link in when"
+             $echo "*** you link to this library.  But I can only do this if you have a"
+             $echo "*** shared version of the library, which you do not appear to have"
+             $echo "*** because the file extensions .$libext of this argument makes me believe"
+             $echo "*** that it is just a static archive that I should not used here."
+           else
+             $echo
+             $echo "*** Warning: Linking the shared library $output against the"
+             $echo "*** static library $deplib is not portable!"
+             deplibs="$deplib $deplibs"
+           fi
+           continue
+           ;;
+         prog)
+           if test "$pass" != link; then
+             deplibs="$deplib $deplibs"
+           else
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           fi
+           continue
+           ;;
+         esac # linkmode
+         ;; # *.$libext
+       *.lo | *.$objext)
+         if test "$pass" = conv; then
+           deplibs="$deplib $deplibs"
+         elif test "$linkmode" = prog; then
+           if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+             # If there is no dlopen support or we're linking statically,
+             # we need to preload.
+             newdlprefiles="$newdlprefiles $deplib"
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           else
+             newdlfiles="$newdlfiles $deplib"
+           fi
+         fi
+         continue
+         ;;
+       %DEPLIBS%)
+         alldeplibs=yes
+         continue
+         ;;
+       esac # case $deplib
+       if test "$found" = yes || test -f "$lib"; then :
+       else
+         $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       # Check to see that this really is a libtool archive.
+       if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+       else
+         $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+       test "X$ladir" = "X$lib" && ladir="."
+
+       dlname=
+       dlopen=
+       dlpreopen=
+       libdir=
+       library_names=
+       old_library=
+       # If the library was installed with an old release of libtool,
+       # it will not redefine variables installed, or shouldnotlink
+       installed=yes
+       shouldnotlink=no
+       avoidtemprpath=
+
+
+       # Read the .la file
+       case $lib in
+       */* | *\\*) . $lib ;;
+       *) . ./$lib ;;
+       esac
+
+       if test "$linkmode,$pass" = "lib,link" ||
+          test "$linkmode,$pass" = "prog,scan" ||
+          { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+         test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+         test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+       fi
+
+       if test "$pass" = conv; then
+         # Only check for convenience libraries
+         deplibs="$lib $deplibs"
+         if test -z "$libdir"; then
+           if test -z "$old_library"; then
+             $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+             exit $EXIT_FAILURE
+           fi
+           # It is a libtool convenience library, so add in its objects.
+           convenience="$convenience $ladir/$objdir/$old_library"
+           old_convenience="$old_convenience $ladir/$objdir/$old_library"
+           tmp_libs=
+           for deplib in $dependency_libs; do
+             deplibs="$deplib $deplibs"
+              if test "X$duplicate_deps" = "Xyes" ; then
+               case "$tmp_libs " in
+               *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+               esac
+              fi
+             tmp_libs="$tmp_libs $deplib"
+           done
+         elif test "$linkmode" != prog && test "$linkmode" != lib; then
+           $echo "$modename: \`$lib' is not a convenience library" 1>&2
+           exit $EXIT_FAILURE
+         fi
+         continue
+       fi # $pass = conv
+
+
+       # Get the name of the library we link against.
+       linklib=
+       for l in $old_library $library_names; do
+         linklib="$l"
+       done
+       if test -z "$linklib"; then
+         $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       # This library was specified with -dlopen.
+       if test "$pass" = dlopen; then
+         if test -z "$libdir"; then
+           $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+           exit $EXIT_FAILURE
+         fi
+         if test -z "$dlname" ||
+            test "$dlopen_support" != yes ||
+            test "$build_libtool_libs" = no; then
+           # If there is no dlname, no dlopen support or we're linking
+           # statically, we need to preload.  We also need to preload any
+           # dependent libraries so libltdl's deplib preloader doesn't
+           # bomb out in the load deplibs phase.
+           dlprefiles="$dlprefiles $lib $dependency_libs"
+         else
+           newdlfiles="$newdlfiles $lib"
+         fi
+         continue
+       fi # $pass = dlopen
+
+       # We need an absolute path.
+       case $ladir in
+       [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+       *)
+         abs_ladir=`cd "$ladir" && pwd`
+         if test -z "$abs_ladir"; then
+           $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
+           $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+           abs_ladir="$ladir"
+         fi
+         ;;
+       esac
+       laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+
+       # Find the relevant object directory and library name.
+       if test "X$installed" = Xyes; then
+         if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+           $echo "$modename: warning: library \`$lib' was moved." 1>&2
+           dir="$ladir"
+           absdir="$abs_ladir"
+           libdir="$abs_ladir"
+         else
+           dir="$libdir"
+           absdir="$libdir"
+         fi
+         test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+       else
+         if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+           dir="$ladir"
+           absdir="$abs_ladir"
+           # Remove this search path later
+           notinst_path="$notinst_path $abs_ladir"
+         else
+           dir="$ladir/$objdir"
+           absdir="$abs_ladir/$objdir"
+           # Remove this search path later
+           notinst_path="$notinst_path $abs_ladir"
+         fi
+       fi # $installed = yes
+       name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+       # This library was specified with -dlpreopen.
+       if test "$pass" = dlpreopen; then
+         if test -z "$libdir"; then
+           $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+           exit $EXIT_FAILURE
+         fi
+         # Prefer using a static library (so that no silly _DYNAMIC symbols
+         # are required to link).
+         if test -n "$old_library"; then
+           newdlprefiles="$newdlprefiles $dir/$old_library"
+         # Otherwise, use the dlname, so that lt_dlopen finds it.
+         elif test -n "$dlname"; then
+           newdlprefiles="$newdlprefiles $dir/$dlname"
+         else
+           newdlprefiles="$newdlprefiles $dir/$linklib"
+         fi
+       fi # $pass = dlpreopen
+
+       if test -z "$libdir"; then
+         # Link the convenience library
+         if test "$linkmode" = lib; then
+           deplibs="$dir/$old_library $deplibs"
+         elif test "$linkmode,$pass" = "prog,link"; then
+           compile_deplibs="$dir/$old_library $compile_deplibs"
+           finalize_deplibs="$dir/$old_library $finalize_deplibs"
+         else
+           deplibs="$lib $deplibs" # used for prog,scan pass
+         fi
+         continue
+       fi
+
+
+       if test "$linkmode" = prog && test "$pass" != link; then
+         newlib_search_path="$newlib_search_path $ladir"
+         deplibs="$lib $deplibs"
+
+         linkalldeplibs=no
+         if test "$link_all_deplibs" != no || test -z "$library_names" ||
+            test "$build_libtool_libs" = no; then
+           linkalldeplibs=yes
+         fi
+
+         tmp_libs=
+         for deplib in $dependency_libs; do
+           case $deplib in
+           -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
+           esac
+           # Need to link against all dependency_libs?
+           if test "$linkalldeplibs" = yes; then
+             deplibs="$deplib $deplibs"
+           else
+             # Need to hardcode shared library paths
+             # or/and link against static libraries
+             newdependency_libs="$deplib $newdependency_libs"
+           fi
+           if test "X$duplicate_deps" = "Xyes" ; then
+             case "$tmp_libs " in
+             *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+             esac
+           fi
+           tmp_libs="$tmp_libs $deplib"
+         done # for deplib
+         continue
+       fi # $linkmode = prog...
+
+       if test "$linkmode,$pass" = "prog,link"; then
+         if test -n "$library_names" &&
+            { { test "$prefer_static_libs" = no ||
+                test "$prefer_static_libs,$installed" = "built,yes"; } ||
+              test -z "$old_library"; }; then
+           # We need to hardcode the library path
+           if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+             # Make sure the rpath contains only unique directories.
+             case "$temp_rpath " in
+             *" $dir "*) ;;
+             *" $absdir "*) ;;
+             *) temp_rpath="$temp_rpath $absdir" ;;
+             esac
+           fi
+
+           # Hardcode the library path.
+           # Skip directories that are in the system default run-time
+           # search path.
+           case " $sys_lib_dlsearch_path " in
+           *" $absdir "*) ;;
+           *)
+             case "$compile_rpath " in
+             *" $absdir "*) ;;
+             *) compile_rpath="$compile_rpath $absdir"
+             esac
+             ;;
+           esac
+           case " $sys_lib_dlsearch_path " in
+           *" $libdir "*) ;;
+           *)
+             case "$finalize_rpath " in
+             *" $libdir "*) ;;
+             *) finalize_rpath="$finalize_rpath $libdir"
+             esac
+             ;;
+           esac
+         fi # $linkmode,$pass = prog,link...
+
+         if test "$alldeplibs" = yes &&
+            { test "$deplibs_check_method" = pass_all ||
+              { test "$build_libtool_libs" = yes &&
+                test -n "$library_names"; }; }; then
+           # We only need to search for static libraries
+           continue
+         fi
+       fi
+
+       link_static=no # Whether the deplib will be linked statically
+       use_static_libs=$prefer_static_libs
+       if test "$use_static_libs" = built && test "$installed" = yes ; then
+         use_static_libs=no
+       fi
+       if test -n "$library_names" &&
+          { test "$use_static_libs" = no || test -z "$old_library"; }; then
+         if test "$installed" = no; then
+           notinst_deplibs="$notinst_deplibs $lib"
+           need_relink=yes
+         fi
+         # This is a shared library
+
+         # Warn about portability, can't link against -module's on
+         # some systems (darwin)
+         if test "$shouldnotlink" = yes && test "$pass" = link ; then
+           $echo
+           if test "$linkmode" = prog; then
+             $echo "*** Warning: Linking the executable $output against the loadable module"
+           else
+             $echo "*** Warning: Linking the shared library $output against the loadable module"
+           fi
+           $echo "*** $linklib is not portable!"
+         fi
+         if test "$linkmode" = lib &&
+            test "$hardcode_into_libs" = yes; then
+           # Hardcode the library path.
+           # Skip directories that are in the system default run-time
+           # search path.
+           case " $sys_lib_dlsearch_path " in
+           *" $absdir "*) ;;
+           *)
+             case "$compile_rpath " in
+             *" $absdir "*) ;;
+             *) compile_rpath="$compile_rpath $absdir"
+             esac
+             ;;
+           esac
+           case " $sys_lib_dlsearch_path " in
+           *" $libdir "*) ;;
+           *)
+             case "$finalize_rpath " in
+             *" $libdir "*) ;;
+             *) finalize_rpath="$finalize_rpath $libdir"
+             esac
+             ;;
+           esac
+         fi
+
+         if test -n "$old_archive_from_expsyms_cmds"; then
+           # figure out the soname
+           set dummy $library_names
+           realname="$2"
+           shift; shift
+           libname=`eval \\$echo \"$libname_spec\"`
+           # use dlname if we got it. it's perfectly good, no?
+           if test -n "$dlname"; then
+             soname="$dlname"
+           elif test -n "$soname_spec"; then
+             # bleh windows
+             case $host in
+             *cygwin* | mingw*)
+               major=`expr $current - $age`
+               versuffix="-$major"
+               ;;
+             esac
+             eval soname=\"$soname_spec\"
+           else
+             soname="$realname"
+           fi
+
+           # Make a new name for the extract_expsyms_cmds to use
+           soroot="$soname"
+           soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
+           newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
+
+           # If the library has no export list, then create one now
+           if test -f "$output_objdir/$soname-def"; then :
+           else
+             $show "extracting exported symbol list from \`$soname'"
+             save_ifs="$IFS"; IFS='~'
+             cmds=$extract_expsyms_cmds
+             for cmd in $cmds; do
+               IFS="$save_ifs"
+               eval cmd=\"$cmd\"
+               $show "$cmd"
+               $run eval "$cmd" || exit $?
+             done
+             IFS="$save_ifs"
+           fi
+
+           # Create $newlib
+           if test -f "$output_objdir/$newlib"; then :; else
+             $show "generating import library for \`$soname'"
+             save_ifs="$IFS"; IFS='~'
+             cmds=$old_archive_from_expsyms_cmds
+             for cmd in $cmds; do
+               IFS="$save_ifs"
+               eval cmd=\"$cmd\"
+               $show "$cmd"
+               $run eval "$cmd" || exit $?
+             done
+             IFS="$save_ifs"
+           fi
+           # make sure the library variables are pointing to the new library
+           dir=$output_objdir
+           linklib=$newlib
+         fi # test -n "$old_archive_from_expsyms_cmds"
+
+         if test "$linkmode" = prog || test "$mode" != relink; then
+           add_shlibpath=
+           add_dir=
+           add=
+           lib_linked=yes
+           case $hardcode_action in
+           immediate | unsupported)
+             if test "$hardcode_direct" = no; then
+               add="$dir/$linklib"
+               case $host in
+                 *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+                 *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+                 *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+                   *-*-unixware7*) add_dir="-L$dir" ;;
+                 *-*-darwin* )
+                   # if the lib is a module then we can not link against
+                   # it, someone is ignoring the new warnings I added
+                   if /usr/bin/file -L $add 2> /dev/null |
+                      $EGREP ": [^:]* bundle" >/dev/null ; then
+                     $echo "** Warning, lib $linklib is a module, not a shared library"
+                     if test -z "$old_library" ; then
+                       $echo
+                       $echo "** And there doesn't seem to be a static archive available"
+                       $echo "** The link will probably fail, sorry"
+                     else
+                       add="$dir/$old_library"
+                     fi
+                   fi
+               esac
+             elif test "$hardcode_minus_L" = no; then
+               case $host in
+               *-*-sunos*) add_shlibpath="$dir" ;;
+               esac
+               add_dir="-L$dir"
+               add="-l$name"
+             elif test "$hardcode_shlibpath_var" = no; then
+               add_shlibpath="$dir"
+               add="-l$name"
+             else
+               lib_linked=no
+             fi
+             ;;
+           relink)
+             if test "$hardcode_direct" = yes; then
+               add="$dir/$linklib"
+             elif test "$hardcode_minus_L" = yes; then
+               add_dir="-L$dir"
+               # Try looking first in the location we're being installed to.
+               if test -n "$inst_prefix_dir"; then
+                 case $libdir in
+                   [\\/]*)
+                     add_dir="$add_dir -L$inst_prefix_dir$libdir"
+                     ;;
+                 esac
+               fi
+               add="-l$name"
+             elif test "$hardcode_shlibpath_var" = yes; then
+               add_shlibpath="$dir"
+               add="-l$name"
+             else
+               lib_linked=no
+             fi
+             ;;
+           *) lib_linked=no ;;
+           esac
+
+           if test "$lib_linked" != yes; then
+             $echo "$modename: configuration error: unsupported hardcode properties"
+             exit $EXIT_FAILURE
+           fi
+
+           if test -n "$add_shlibpath"; then
+             case :$compile_shlibpath: in
+             *":$add_shlibpath:"*) ;;
+             *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+             esac
+           fi
+           if test "$linkmode" = prog; then
+             test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+             test -n "$add" && compile_deplibs="$add $compile_deplibs"
+           else
+             test -n "$add_dir" && deplibs="$add_dir $deplibs"
+             test -n "$add" && deplibs="$add $deplibs"
+             if test "$hardcode_direct" != yes && \
+                test "$hardcode_minus_L" != yes && \
+                test "$hardcode_shlibpath_var" = yes; then
+               case :$finalize_shlibpath: in
+               *":$libdir:"*) ;;
+               *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+               esac
+             fi
+           fi
+         fi
+
+         if test "$linkmode" = prog || test "$mode" = relink; then
+           add_shlibpath=
+           add_dir=
+           add=
+           # Finalize command for both is simple: just hardcode it.
+           if test "$hardcode_direct" = yes; then
+             add="$libdir/$linklib"
+           elif test "$hardcode_minus_L" = yes; then
+             add_dir="-L$libdir"
+             add="-l$name"
+           elif test "$hardcode_shlibpath_var" = yes; then
+             case :$finalize_shlibpath: in
+             *":$libdir:"*) ;;
+             *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+             esac
+             add="-l$name"
+           elif test "$hardcode_automatic" = yes; then
+             if test -n "$inst_prefix_dir" &&
+                test -f "$inst_prefix_dir$libdir/$linklib" ; then
+               add="$inst_prefix_dir$libdir/$linklib"
+             else
+               add="$libdir/$linklib"
+             fi
+           else
+             # We cannot seem to hardcode it, guess we'll fake it.
+             add_dir="-L$libdir"
+             # Try looking first in the location we're being installed to.
+             if test -n "$inst_prefix_dir"; then
+               case $libdir in
+                 [\\/]*)
+                   add_dir="$add_dir -L$inst_prefix_dir$libdir"
+                   ;;
+               esac
+             fi
+             add="-l$name"
+           fi
+
+           if test "$linkmode" = prog; then
+             test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+             test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+           else
+             test -n "$add_dir" && deplibs="$add_dir $deplibs"
+             test -n "$add" && deplibs="$add $deplibs"
+           fi
+         fi
+       elif test "$linkmode" = prog; then
+         # Here we assume that one of hardcode_direct or hardcode_minus_L
+         # is not unsupported.  This is valid on all known static and
+         # shared platforms.
+         if test "$hardcode_direct" != unsupported; then
+           test -n "$old_library" && linklib="$old_library"
+           compile_deplibs="$dir/$linklib $compile_deplibs"
+           finalize_deplibs="$dir/$linklib $finalize_deplibs"
+         else
+           compile_deplibs="-l$name -L$dir $compile_deplibs"
+           finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+         fi
+       elif test "$build_libtool_libs" = yes; then
+         # Not a shared library
+         if test "$deplibs_check_method" != pass_all; then
+           # We're trying link a shared library against a static one
+           # but the system doesn't support it.
+
+           # Just print a warning and add the library to dependency_libs so
+           # that the program can be linked against the static library.
+           $echo
+           $echo "*** Warning: This system can not link to static lib archive $lib."
+           $echo "*** I have the capability to make that library automatically link in when"
+           $echo "*** you link to this library.  But I can only do this if you have a"
+           $echo "*** shared version of the library, which you do not appear to have."
+           if test "$module" = yes; then
+             $echo "*** But as you try to build a module library, libtool will still create "
+             $echo "*** a static module, that should work as long as the dlopening application"
+             $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+             if test -z "$global_symbol_pipe"; then
+               $echo
+               $echo "*** However, this would only work if libtool was able to extract symbol"
+               $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+               $echo "*** not find such a program.  So, this module is probably useless."
+               $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+             fi
+             if test "$build_old_libs" = no; then
+               build_libtool_libs=module
+               build_old_libs=yes
+             else
+               build_libtool_libs=no
+             fi
+           fi
+         else
+           deplibs="$dir/$old_library $deplibs"
+           link_static=yes
+         fi
+       fi # link shared/static library?
+
+       if test "$linkmode" = lib; then
+         if test -n "$dependency_libs" &&
+            { test "$hardcode_into_libs" != yes ||
+              test "$build_old_libs" = yes ||
+              test "$link_static" = yes; }; then
+           # Extract -R from dependency_libs
+           temp_deplibs=
+           for libdir in $dependency_libs; do
+             case $libdir in
+             -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
+                  case " $xrpath " in
+                  *" $temp_xrpath "*) ;;
+                  *) xrpath="$xrpath $temp_xrpath";;
+                  esac;;
+             *) temp_deplibs="$temp_deplibs $libdir";;
+             esac
+           done
+           dependency_libs="$temp_deplibs"
+         fi
+
+         newlib_search_path="$newlib_search_path $absdir"
+         # Link against this library
+         test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+         # ... and its dependency_libs
+         tmp_libs=
+         for deplib in $dependency_libs; do
+           newdependency_libs="$deplib $newdependency_libs"
+           if test "X$duplicate_deps" = "Xyes" ; then
+             case "$tmp_libs " in
+             *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+             esac
+           fi
+           tmp_libs="$tmp_libs $deplib"
+         done
+
+         if test "$link_all_deplibs" != no; then
+           # Add the search paths of all dependency libraries
+           for deplib in $dependency_libs; do
+             case $deplib in
+             -L*) path="$deplib" ;;
+             *.la)
+               dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
+               test "X$dir" = "X$deplib" && dir="."
+               # We need an absolute path.
+               case $dir in
+               [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+               *)
+                 absdir=`cd "$dir" && pwd`
+                 if test -z "$absdir"; then
+                   $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+                   absdir="$dir"
+                 fi
+                 ;;
+               esac
+               if grep "^installed=no" $deplib > /dev/null; then
+                 path="$absdir/$objdir"
+               else
+                 eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+                 if test -z "$libdir"; then
+                   $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+                   exit $EXIT_FAILURE
+                 fi
+                 if test "$absdir" != "$libdir"; then
+                   $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
+                 fi
+                 path="$absdir"
+               fi
+               depdepl=
+               case $host in
+               *-*-darwin*)
+                 # we do not want to link against static libs,
+                 # but need to link against shared
+                 eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+                 if test -n "$deplibrary_names" ; then
+                   for tmp in $deplibrary_names ; do
+                     depdepl=$tmp
+                   done
+                   if test -f "$path/$depdepl" ; then
+                     depdepl="$path/$depdepl"
+                   fi
+                   # do not add paths which are already there
+                   case " $newlib_search_path " in
+                   *" $path "*) ;;
+                   *) newlib_search_path="$newlib_search_path $path";;
+                   esac
+                 fi
+                 path=""
+                 ;;
+               *)
+                 path="-L$path"
+                 ;;
+               esac
+               ;;
+             -l*)
+               case $host in
+               *-*-darwin*)
+                 # Again, we only want to link against shared libraries
+                 eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
+                 for tmp in $newlib_search_path ; do
+                   if test -f "$tmp/lib$tmp_libs.dylib" ; then
+                     eval depdepl="$tmp/lib$tmp_libs.dylib"
+                     break
+                   fi
+                 done
+                 path=""
+                 ;;
+               *) continue ;;
+               esac
+               ;;
+             *) continue ;;
+             esac
+             case " $deplibs " in
+             *" $path "*) ;;
+             *) deplibs="$path $deplibs" ;;
+             esac
+             case " $deplibs " in
+             *" $depdepl "*) ;;
+             *) deplibs="$depdepl $deplibs" ;;
+             esac
+           done
+         fi # link_all_deplibs != no
+       fi # linkmode = lib
+      done # for deplib in $libs
+      dependency_libs="$newdependency_libs"
+      if test "$pass" = dlpreopen; then
+       # Link the dlpreopened libraries before other libraries
+       for deplib in $save_deplibs; do
+         deplibs="$deplib $deplibs"
+       done
+      fi
+      if test "$pass" != dlopen; then
+       if test "$pass" != conv; then
+         # Make sure lib_search_path contains only unique directories.
+         lib_search_path=
+         for dir in $newlib_search_path; do
+           case "$lib_search_path " in
+           *" $dir "*) ;;
+           *) lib_search_path="$lib_search_path $dir" ;;
+           esac
+         done
+         newlib_search_path=
+       fi
+
+       if test "$linkmode,$pass" != "prog,link"; then
+         vars="deplibs"
+       else
+         vars="compile_deplibs finalize_deplibs"
+       fi
+       for var in $vars dependency_libs; do
+         # Add libraries to $var in reverse order
+         eval tmp_libs=\"\$$var\"
+         new_libs=
+         for deplib in $tmp_libs; do
+           # FIXME: Pedantically, this is the right thing to do, so
+           #        that some nasty dependency loop isn't accidentally
+           #        broken:
+           #new_libs="$deplib $new_libs"
+           # Pragmatically, this seems to cause very few problems in
+           # practice:
+           case $deplib in
+           -L*) new_libs="$deplib $new_libs" ;;
+           -R*) ;;
+           *)
+             # And here is the reason: when a library appears more
+             # than once as an explicit dependence of a library, or
+             # is implicitly linked in more than once by the
+             # compiler, it is considered special, and multiple
+             # occurrences thereof are not removed.  Compare this
+             # with having the same library being listed as a
+             # dependency of multiple other libraries: in this case,
+             # we know (pedantically, we assume) the library does not
+             # need to be listed more than once, so we keep only the
+             # last copy.  This is not always right, but it is rare
+             # enough that we require users that really mean to play
+             # such unportable linking tricks to link the library
+             # using -Wl,-lname, so that libtool does not consider it
+             # for duplicate removal.
+             case " $specialdeplibs " in
+             *" $deplib "*) new_libs="$deplib $new_libs" ;;
+             *)
+               case " $new_libs " in
+               *" $deplib "*) ;;
+               *) new_libs="$deplib $new_libs" ;;
+               esac
+               ;;
+             esac
+             ;;
+           esac
+         done
+         tmp_libs=
+         for deplib in $new_libs; do
+           case $deplib in
+           -L*)
+             case " $tmp_libs " in
+             *" $deplib "*) ;;
+             *) tmp_libs="$tmp_libs $deplib" ;;
+             esac
+             ;;
+           *) tmp_libs="$tmp_libs $deplib" ;;
+           esac
+         done
+         eval $var=\"$tmp_libs\"
+       done # for var
+      fi
+      # Last step: remove runtime libs from dependency_libs
+      # (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs ; do
+       case " $predeps $postdeps $compiler_lib_search_path " in
+       *" $i "*)
+         i=""
+         ;;
+       esac
+       if test -n "$i" ; then
+         tmp_libs="$tmp_libs $i"
+       fi
+      done
+      dependency_libs=$tmp_libs
+    done # for pass
+    if test "$linkmode" = prog; then
+      dlfiles="$newdlfiles"
+      dlprefiles="$newdlprefiles"
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$deplibs"; then
+       $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+      fi
+
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$rpath"; then
+       $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$xrpath"; then
+       $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$vinfo"; then
+       $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$release"; then
+       $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+       $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+      fi
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      objs="$objs$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case $outputname in
+      lib*)
+       name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+       eval shared_ext=\"$shrext_cmds\"
+       eval libname=\"$libname_spec\"
+       ;;
+      *)
+       if test "$module" = no; then
+         $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+         $echo "$help" 1>&2
+         exit $EXIT_FAILURE
+       fi
+       if test "$need_lib_prefix" != no; then
+         # Add the "lib" prefix for modules if required
+         name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+         eval shared_ext=\"$shrext_cmds\"
+         eval libname=\"$libname_spec\"
+       else
+         libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+       fi
+       ;;
+      esac
+
+      if test -n "$objs"; then
+       if test "$deplibs_check_method" != pass_all; then
+         $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
+         exit $EXIT_FAILURE
+       else
+         $echo
+         $echo "*** Warning: Linking the shared library $output against the non-libtool"
+         $echo "*** objects $objs is not portable!"
+         libobjs="$libobjs $objs"
+       fi
+      fi
+
+      if test "$dlself" != no; then
+       $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
+      fi
+
+      set dummy $rpath
+      if test "$#" -gt 2; then
+       $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+      fi
+      install_libdir="$2"
+
+      oldlibs=
+      if test -z "$rpath"; then
+       if test "$build_libtool_libs" = yes; then
+         # Building a libtool convenience library.
+         # Some compilers have problems with a `.al' extension so
+         # convenience libraries should have the same extension an
+         # archive normally would.
+         oldlibs="$output_objdir/$libname.$libext $oldlibs"
+         build_libtool_libs=convenience
+         build_old_libs=yes
+       fi
+
+       if test -n "$vinfo"; then
+         $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
+       fi
+
+       if test -n "$release"; then
+         $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+       fi
+      else
+
+       # Parse the version information argument.
+       save_ifs="$IFS"; IFS=':'
+       set dummy $vinfo 0 0 0
+       IFS="$save_ifs"
+
+       if test -n "$8"; then
+         $echo "$modename: too many parameters to \`-version-info'" 1>&2
+         $echo "$help" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       # convert absolute version numbers to libtool ages
+       # this retains compatibility with .la files and attempts
+       # to make the code below a bit more comprehensible
+
+       case $vinfo_number in
+       yes)
+         number_major="$2"
+         number_minor="$3"
+         number_revision="$4"
+         #
+         # There are really only two kinds -- those that
+         # use the current revision as the major version
+         # and those that subtract age and use age as
+         # a minor version.  But, then there is irix
+         # which has an extra 1 added just for fun
+         #
+         case $version_type in
+         darwin|linux|osf|windows|none)
+           current=`expr $number_major + $number_minor`
+           age="$number_minor"
+           revision="$number_revision"
+           ;;
+         freebsd-aout|freebsd-elf|sunos)
+           current="$number_major"
+           revision="$number_minor"
+           age="0"
+           ;;
+         irix|nonstopux)
+           current=`expr $number_major + $number_minor`
+           age="$number_minor"
+           revision="$number_minor"
+           lt_irix_increment=no
+           ;;
+         *)
+           $echo "$modename: unknown library version type \`$version_type'" 1>&2
+           $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+           exit $EXIT_FAILURE
+           ;;
+         esac
+         ;;
+       no)
+         current="$2"
+         revision="$3"
+         age="$4"
+         ;;
+       esac
+
+       # Check that each of the things are valid numbers.
+       case $current in
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+       *)
+         $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+
+       case $revision in
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+       *)
+         $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+
+       case $age in
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+       *)
+         $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+
+       if test "$age" -gt "$current"; then
+         $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       # Calculate the version variables.
+       major=
+       versuffix=
+       verstring=
+       case $version_type in
+       none) ;;
+
+       darwin)
+         # Like Linux, but with the current version available in
+         # verstring for coding it into the library header
+         major=.`expr $current - $age`
+         versuffix="$major.$age.$revision"
+         # Darwin ld doesn't like 0 for these options...
+         minor_current=`expr $current + 1`
+         xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+         verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+         ;;
+
+       freebsd-aout)
+         major=".$current"
+         versuffix=".$current.$revision";
+         ;;
+
+       freebsd-elf)
+         major=".$current"
+         versuffix=".$current";
+         ;;
+
+       irix | nonstopux)
+         if test "X$lt_irix_increment" = "Xno"; then
+           major=`expr $current - $age`
+         else
+           major=`expr $current - $age + 1`
+         fi
+         case $version_type in
+           nonstopux) verstring_prefix=nonstopux ;;
+           *)         verstring_prefix=sgi ;;
+         esac
+         verstring="$verstring_prefix$major.$revision"
+
+         # Add in all the interfaces that we are compatible with.
+         loop=$revision
+         while test "$loop" -ne 0; do
+           iface=`expr $revision - $loop`
+           loop=`expr $loop - 1`
+           verstring="$verstring_prefix$major.$iface:$verstring"
+         done
+
+         # Before this point, $major must not contain `.'.
+         major=.$major
+         versuffix="$major.$revision"
+         ;;
+
+       linux)
+         major=.`expr $current - $age`
+         versuffix="$major.$age.$revision"
+         ;;
+
+       osf)
+         major=.`expr $current - $age`
+         versuffix=".$current.$age.$revision"
+         verstring="$current.$age.$revision"
+
+         # Add in all the interfaces that we are compatible with.
+         loop=$age
+         while test "$loop" -ne 0; do
+           iface=`expr $current - $loop`
+           loop=`expr $loop - 1`
+           verstring="$verstring:${iface}.0"
+         done
+
+         # Make executables depend on our current version.
+         verstring="$verstring:${current}.0"
+         ;;
+
+       sunos)
+         major=".$current"
+         versuffix=".$current.$revision"
+         ;;
+
+       windows)
+         # Use '-' rather than '.', since we only want one
+         # extension on DOS 8.3 filesystems.
+         major=`expr $current - $age`
+         versuffix="-$major"
+         ;;
+
+       *)
+         $echo "$modename: unknown library version type \`$version_type'" 1>&2
+         $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+
+       # Clear the version info if we defaulted, and they specified a release.
+       if test -z "$vinfo" && test -n "$release"; then
+         major=
+         case $version_type in
+         darwin)
+           # we can't check for "0.0" in archive_cmds due to quoting
+           # problems, so we reset it completely
+           verstring=
+           ;;
+         *)
+           verstring="0.0"
+           ;;
+         esac
+         if test "$need_version" = no; then
+           versuffix=
+         else
+           versuffix=".0.0"
+         fi
+       fi
+
+       # Remove version info from name if versioning should be avoided
+       if test "$avoid_version" = yes && test "$need_version" = no; then
+         major=
+         versuffix=
+         verstring=""
+       fi
+
+       # Check to see if the archive will have undefined symbols.
+       if test "$allow_undefined" = yes; then
+         if test "$allow_undefined_flag" = unsupported; then
+           $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+           build_libtool_libs=no
+           build_old_libs=yes
+         fi
+       else
+         # Don't allow undefined symbols.
+         allow_undefined_flag="$no_undefined_flag"
+       fi
+      fi
+
+      if test "$mode" != relink; then
+       # Remove our outputs, but don't remove object files since they
+       # may have been created when compiling PIC objects.
+       removelist=
+       tempremovelist=`$echo "$output_objdir/*"`
+       for p in $tempremovelist; do
+         case $p in
+           *.$objext)
+              ;;
+           $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+              if test "X$precious_files_regex" != "X"; then
+                if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+                then
+                  continue
+                fi
+              fi
+              removelist="$removelist $p"
+              ;;
+           *) ;;
+         esac
+       done
+       if test -n "$removelist"; then
+         $show "${rm}r $removelist"
+         $run ${rm}r $removelist
+       fi
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+       oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+       # Transform .lo files to .o files.
+       oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      #for path in $notinst_path; do
+      #        lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
+      #        deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
+      #        dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
+      #done
+
+      if test -n "$xrpath"; then
+       # If the user specified any rpath flags, then add them.
+       temp_xrpath=
+       for libdir in $xrpath; do
+         temp_xrpath="$temp_xrpath -R$libdir"
+         case "$finalize_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_rpath="$finalize_rpath $libdir" ;;
+         esac
+       done
+       if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+         dependency_libs="$temp_xrpath $dependency_libs"
+       fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles="$dlfiles"
+      dlfiles=
+      for lib in $old_dlfiles; do
+       case " $dlprefiles $dlfiles " in
+       *" $lib "*) ;;
+       *) dlfiles="$dlfiles $lib" ;;
+       esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles="$dlprefiles"
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+       case "$dlprefiles " in
+       *" $lib "*) ;;
+       *) dlprefiles="$dlprefiles $lib" ;;
+       esac
+      done
+
+      if test "$build_libtool_libs" = yes; then
+       if test -n "$rpath"; then
+         case $host in
+         *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+           # these systems don't actually have a c library (as such)!
+           ;;
+         *-*-rhapsody* | *-*-darwin1.[012])
+           # Rhapsody C library is in the System framework
+           deplibs="$deplibs -framework System"
+           ;;
+         *-*-netbsd*)
+           # Don't link with libc until the a.out ld.so is fixed.
+           ;;
+         *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+           # Do not include libc due to us having libc/libc_r.
+           ;;
+         *-*-sco3.2v5* | *-*-sco5v6*)
+           # Causes problems with __ctype
+           ;;
+         *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+           # Compiler inserts libc in the correct place for threads to work
+           ;;
+         *)
+           # Add libc to deplibs on all other systems if necessary.
+           if test "$build_libtool_need_lc" = "yes"; then
+             deplibs="$deplibs -lc"
+           fi
+           ;;
+         esac
+       fi
+
+       # Transform deplibs into only deplibs that can be linked in shared.
+       name_save=$name
+       libname_save=$libname
+       release_save=$release
+       versuffix_save=$versuffix
+       major_save=$major
+       # I'm not sure if I'm treating the release correctly.  I think
+       # release should show up in the -l (ie -lgmp5) so we don't want to
+       # add it in twice.  Is that correct?
+       release=""
+       versuffix=""
+       major=""
+       newdeplibs=
+       droppeddeps=no
+       case $deplibs_check_method in
+       pass_all)
+         # Don't check for shared/static.  Everything works.
+         # This might be a little naive.  We might want to check
+         # whether the library exists or not.  But this is on
+         # osf3 & osf4 and I'm not really sure... Just
+         # implementing what was already the behavior.
+         newdeplibs=$deplibs
+         ;;
+       test_compile)
+         # This code stresses the "libraries are programs" paradigm to its
+         # limits. Maybe even breaks it.  We compile a program, linking it
+         # against the deplibs as a proxy for the library.  Then we can check
+         # whether they linked in statically or dynamically with ldd.
+         $rm conftest.c
+         cat > conftest.c <<EOF
+         int main() { return 0; }
+EOF
+         $rm conftest
+         if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+           ldd_output=`ldd conftest`
+           for i in $deplibs; do
+             name=`expr $i : '-l\(.*\)'`
+             # If $name is empty we are operating on a -L argument.
+              if test "$name" != "" && test "$name" != "0"; then
+               if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+                 case " $predeps $postdeps " in
+                 *" $i "*)
+                   newdeplibs="$newdeplibs $i"
+                   i=""
+                   ;;
+                 esac
+               fi
+               if test -n "$i" ; then
+                 libname=`eval \\$echo \"$libname_spec\"`
+                 deplib_matches=`eval \\$echo \"$library_names_spec\"`
+                 set dummy $deplib_matches
+                 deplib_match=$2
+                 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                   newdeplibs="$newdeplibs $i"
+                 else
+                   droppeddeps=yes
+                   $echo
+                   $echo "*** Warning: dynamic linker does not accept needed library $i."
+                   $echo "*** I have the capability to make that library automatically link in when"
+                   $echo "*** you link to this library.  But I can only do this if you have a"
+                   $echo "*** shared version of the library, which I believe you do not have"
+                   $echo "*** because a test_compile did reveal that the linker did not use it for"
+                   $echo "*** its dynamic dependency list that programs get resolved with at runtime."
+                 fi
+               fi
+             else
+               newdeplibs="$newdeplibs $i"
+             fi
+           done
+         else
+           # Error occurred in the first compile.  Let's try to salvage
+           # the situation: Compile a separate program for each library.
+           for i in $deplibs; do
+             name=`expr $i : '-l\(.*\)'`
+             # If $name is empty we are operating on a -L argument.
+              if test "$name" != "" && test "$name" != "0"; then
+               $rm conftest
+               if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+                 ldd_output=`ldd conftest`
+                 if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+                   case " $predeps $postdeps " in
+                   *" $i "*)
+                     newdeplibs="$newdeplibs $i"
+                     i=""
+                     ;;
+                   esac
+                 fi
+                 if test -n "$i" ; then
+                   libname=`eval \\$echo \"$libname_spec\"`
+                   deplib_matches=`eval \\$echo \"$library_names_spec\"`
+                   set dummy $deplib_matches
+                   deplib_match=$2
+                   if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                     newdeplibs="$newdeplibs $i"
+                   else
+                     droppeddeps=yes
+                     $echo
+                     $echo "*** Warning: dynamic linker does not accept needed library $i."
+                     $echo "*** I have the capability to make that library automatically link in when"
+                     $echo "*** you link to this library.  But I can only do this if you have a"
+                     $echo "*** shared version of the library, which you do not appear to have"
+                     $echo "*** because a test_compile did reveal that the linker did not use this one"
+                     $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+                   fi
+                 fi
+               else
+                 droppeddeps=yes
+                 $echo
+                 $echo "*** Warning!  Library $i is needed by this library but I was not able to"
+                 $echo "*** make it link in!  You will probably need to install it or some"
+                 $echo "*** library that it depends on before this library will be fully"
+                 $echo "*** functional.  Installing it before continuing would be even better."
+               fi
+             else
+               newdeplibs="$newdeplibs $i"
+             fi
+           done
+         fi
+         ;;
+       file_magic*)
+         set dummy $deplibs_check_method
+         file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+         for a_deplib in $deplibs; do
+           name=`expr $a_deplib : '-l\(.*\)'`
+           # If $name is empty we are operating on a -L argument.
+            if test "$name" != "" && test  "$name" != "0"; then
+             if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+               case " $predeps $postdeps " in
+               *" $a_deplib "*)
+                 newdeplibs="$newdeplibs $a_deplib"
+                 a_deplib=""
+                 ;;
+               esac
+             fi
+             if test -n "$a_deplib" ; then
+               libname=`eval \\$echo \"$libname_spec\"`
+               for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+                 potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+                 for potent_lib in $potential_libs; do
+                     # Follow soft links.
+                     if ls -lLd "$potent_lib" 2>/dev/null \
+                        | grep " -> " >/dev/null; then
+                       continue
+                     fi
+                     # The statement above tries to avoid entering an
+                     # endless loop below, in case of cyclic links.
+                     # We might still enter an endless loop, since a link
+                     # loop can be closed while we follow links,
+                     # but so what?
+                     potlib="$potent_lib"
+                     while test -h "$potlib" 2>/dev/null; do
+                       potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+                       case $potliblink in
+                       [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+                       *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+                       esac
+                     done
+                     if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+                        | ${SED} 10q \
+                        | $EGREP "$file_magic_regex" > /dev/null; then
+                       newdeplibs="$newdeplibs $a_deplib"
+                       a_deplib=""
+                       break 2
+                     fi
+                 done
+               done
+             fi
+             if test -n "$a_deplib" ; then
+               droppeddeps=yes
+               $echo
+               $echo "*** Warning: linker path does not have real file for library $a_deplib."
+               $echo "*** I have the capability to make that library automatically link in when"
+               $echo "*** you link to this library.  But I can only do this if you have a"
+               $echo "*** shared version of the library, which you do not appear to have"
+               $echo "*** because I did check the linker path looking for a file starting"
+               if test -z "$potlib" ; then
+                 $echo "*** with $libname but no candidates were found. (...for file magic test)"
+               else
+                 $echo "*** with $libname and none of the candidates passed a file format test"
+                 $echo "*** using a file magic. Last file checked: $potlib"
+               fi
+             fi
+           else
+             # Add a -L argument.
+             newdeplibs="$newdeplibs $a_deplib"
+           fi
+         done # Gone through all deplibs.
+         ;;
+       match_pattern*)
+         set dummy $deplibs_check_method
+         match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+         for a_deplib in $deplibs; do
+           name=`expr $a_deplib : '-l\(.*\)'`
+           # If $name is empty we are operating on a -L argument.
+           if test -n "$name" && test "$name" != "0"; then
+             if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+               case " $predeps $postdeps " in
+               *" $a_deplib "*)
+                 newdeplibs="$newdeplibs $a_deplib"
+                 a_deplib=""
+                 ;;
+               esac
+             fi
+             if test -n "$a_deplib" ; then
+               libname=`eval \\$echo \"$libname_spec\"`
+               for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+                 potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+                 for potent_lib in $potential_libs; do
+                   potlib="$potent_lib" # see symlink-check above in file_magic test
+                   if eval $echo \"$potent_lib\" 2>/dev/null \
+                       | ${SED} 10q \
+                       | $EGREP "$match_pattern_regex" > /dev/null; then
+                     newdeplibs="$newdeplibs $a_deplib"
+                     a_deplib=""
+                     break 2
+                   fi
+                 done
+               done
+             fi
+             if test -n "$a_deplib" ; then
+               droppeddeps=yes
+               $echo
+               $echo "*** Warning: linker path does not have real file for library $a_deplib."
+               $echo "*** I have the capability to make that library automatically link in when"
+               $echo "*** you link to this library.  But I can only do this if you have a"
+               $echo "*** shared version of the library, which you do not appear to have"
+               $echo "*** because I did check the linker path looking for a file starting"
+               if test -z "$potlib" ; then
+                 $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
+               else
+                 $echo "*** with $libname and none of the candidates passed a file format test"
+                 $echo "*** using a regex pattern. Last file checked: $potlib"
+               fi
+             fi
+           else
+             # Add a -L argument.
+             newdeplibs="$newdeplibs $a_deplib"
+           fi
+         done # Gone through all deplibs.
+         ;;
+       none | unknown | *)
+         newdeplibs=""
+         tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+           -e 's/ -[LR][^ ]*//g'`
+         if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+           for i in $predeps $postdeps ; do
+             # can't use Xsed below, because $i might contain '/'
+             tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
+           done
+         fi
+         if $echo "X $tmp_deplibs" | $Xsed -e 's/[     ]//g' \
+           | grep . >/dev/null; then
+           $echo
+           if test "X$deplibs_check_method" = "Xnone"; then
+             $echo "*** Warning: inter-library dependencies are not supported in this platform."
+           else
+             $echo "*** Warning: inter-library dependencies are not known to be supported."
+           fi
+           $echo "*** All declared inter-library dependencies are being dropped."
+           droppeddeps=yes
+         fi
+         ;;
+       esac
+       versuffix=$versuffix_save
+       major=$major_save
+       release=$release_save
+       libname=$libname_save
+       name=$name_save
+
+       case $host in
+       *-*-rhapsody* | *-*-darwin1.[012])
+         # On Rhapsody replace the C library is the System framework
+         newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
+         ;;
+       esac
+
+       if test "$droppeddeps" = yes; then
+         if test "$module" = yes; then
+           $echo
+           $echo "*** Warning: libtool could not satisfy all declared inter-library"
+           $echo "*** dependencies of module $libname.  Therefore, libtool will create"
+           $echo "*** a static module, that should work as long as the dlopening"
+           $echo "*** application is linked with the -dlopen flag."
+           if test -z "$global_symbol_pipe"; then
+             $echo
+             $echo "*** However, this would only work if libtool was able to extract symbol"
+             $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+             $echo "*** not find such a program.  So, this module is probably useless."
+             $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+           fi
+           if test "$build_old_libs" = no; then
+             oldlibs="$output_objdir/$libname.$libext"
+             build_libtool_libs=module
+             build_old_libs=yes
+           else
+             build_libtool_libs=no
+           fi
+         else
+           $echo "*** The inter-library dependencies that have been dropped here will be"
+           $echo "*** automatically added whenever a program is linked with this library"
+           $echo "*** or is declared to -dlopen it."
+
+           if test "$allow_undefined" = no; then
+             $echo
+             $echo "*** Since this library must not contain undefined symbols,"
+             $echo "*** because either the platform does not support them or"
+             $echo "*** it was explicitly requested with -no-undefined,"
+             $echo "*** libtool will only create a static version of it."
+             if test "$build_old_libs" = no; then
+               oldlibs="$output_objdir/$libname.$libext"
+               build_libtool_libs=module
+               build_old_libs=yes
+             else
+               build_libtool_libs=no
+             fi
+           fi
+         fi
+       fi
+       # Done checking deplibs!
+       deplibs=$newdeplibs
+      fi
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+       case " $new_libs " in
+       *" -L$path/$objdir "*) ;;
+       *)
+         case " $deplibs " in
+         *" -L$path/$objdir "*)
+           new_libs="$new_libs -L$path/$objdir" ;;
+         esac
+         ;;
+       esac
+      done
+      for deplib in $deplibs; do
+       case $deplib in
+       -L*)
+         case " $new_libs " in
+         *" $deplib "*) ;;
+         *) new_libs="$new_libs $deplib" ;;
+         esac
+         ;;
+       *) new_libs="$new_libs $deplib" ;;
+       esac
+      done
+      deplibs="$new_libs"
+
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+       if test "$hardcode_into_libs" = yes; then
+         # Hardcode the library paths
+         hardcode_libdirs=
+         dep_rpath=
+         rpath="$finalize_rpath"
+         test "$mode" != relink && rpath="$compile_rpath$rpath"
+         for libdir in $rpath; do
+           if test -n "$hardcode_libdir_flag_spec"; then
+             if test -n "$hardcode_libdir_separator"; then
+               if test -z "$hardcode_libdirs"; then
+                 hardcode_libdirs="$libdir"
+               else
+                 # Just accumulate the unique libdirs.
+                 case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+                 *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+                   ;;
+                 *)
+                   hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+                   ;;
+                 esac
+               fi
+             else
+               eval flag=\"$hardcode_libdir_flag_spec\"
+               dep_rpath="$dep_rpath $flag"
+             fi
+           elif test -n "$runpath_var"; then
+             case "$perm_rpath " in
+             *" $libdir "*) ;;
+             *) perm_rpath="$perm_rpath $libdir" ;;
+             esac
+           fi
+         done
+         # Substitute the hardcoded libdirs into the rpath.
+         if test -n "$hardcode_libdir_separator" &&
+            test -n "$hardcode_libdirs"; then
+           libdir="$hardcode_libdirs"
+           if test -n "$hardcode_libdir_flag_spec_ld"; then
+             case $archive_cmds in
+             *\$LD*) eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" ;;
+             *)      eval dep_rpath=\"$hardcode_libdir_flag_spec\" ;;
+             esac
+           else
+             eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+           fi
+         fi
+         if test -n "$runpath_var" && test -n "$perm_rpath"; then
+           # We should set the runpath_var.
+           rpath=
+           for dir in $perm_rpath; do
+             rpath="$rpath$dir:"
+           done
+           eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+         fi
+         test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+       fi
+
+       shlibpath="$finalize_shlibpath"
+       test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+       if test -n "$shlibpath"; then
+         eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+       fi
+
+       # Get the real and link names of the library.
+       eval shared_ext=\"$shrext_cmds\"
+       eval library_names=\"$library_names_spec\"
+       set dummy $library_names
+       realname="$2"
+       shift; shift
+
+       if test -n "$soname_spec"; then
+         eval soname=\"$soname_spec\"
+       else
+         soname="$realname"
+       fi
+       if test -z "$dlname"; then
+         dlname=$soname
+       fi
+
+       lib="$output_objdir/$realname"
+       linknames=
+       for link
+       do
+         linknames="$linknames $link"
+       done
+
+       # Use standard objects if they are pic
+       test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+       # Prepare the list of exported symbols
+       if test -z "$export_symbols"; then
+         if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+           $show "generating symbol list for \`$libname.la'"
+           export_symbols="$output_objdir/$libname.exp"
+           $run $rm $export_symbols
+           cmds=$export_symbols_cmds
+           save_ifs="$IFS"; IFS='~'
+           for cmd in $cmds; do
+             IFS="$save_ifs"
+             eval cmd=\"$cmd\"
+             if len=`expr "X$cmd" : ".*"` &&
+              test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+               $show "$cmd"
+               $run eval "$cmd" || exit $?
+               skipped_export=false
+             else
+               # The command line is too long to execute in one step.
+               $show "using reloadable object file for export list..."
+               skipped_export=:
+               # Break out early, otherwise skipped_export may be
+               # set to false by a later but shorter cmd.
+               break
+             fi
+           done
+           IFS="$save_ifs"
+           if test -n "$export_symbols_regex"; then
+             $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+             $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+             $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+             $run eval '$mv "${export_symbols}T" "$export_symbols"'
+           fi
+         fi
+       fi
+
+       if test -n "$export_symbols" && test -n "$include_expsyms"; then
+         $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+       fi
+
+       tmp_deplibs=
+       for test_deplib in $deplibs; do
+               case " $convenience " in
+               *" $test_deplib "*) ;;
+               *)
+                       tmp_deplibs="$tmp_deplibs $test_deplib"
+                       ;;
+               esac
+       done
+       deplibs="$tmp_deplibs"
+
+       if test -n "$convenience"; then
+         if test -n "$whole_archive_flag_spec"; then
+           save_libobjs=$libobjs
+           eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+         else
+           gentop="$output_objdir/${outputname}x"
+           generated="$generated $gentop"
+
+           func_extract_archives $gentop $convenience
+           libobjs="$libobjs $func_extract_archives_result"
+         fi
+       fi
+       
+       if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+         eval flag=\"$thread_safe_flag_spec\"
+         linker_flags="$linker_flags $flag"
+       fi
+
+       # Make a backup of the uninstalled library when relinking
+       if test "$mode" = relink; then
+         $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
+       fi
+
+       # Do each of the archive commands.
+       if test "$module" = yes && test -n "$module_cmds" ; then
+         if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+           eval test_cmds=\"$module_expsym_cmds\"
+           cmds=$module_expsym_cmds
+         else
+           eval test_cmds=\"$module_cmds\"
+           cmds=$module_cmds
+         fi
+       else
+       if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+         eval test_cmds=\"$archive_expsym_cmds\"
+         cmds=$archive_expsym_cmds
+       else
+         eval test_cmds=\"$archive_cmds\"
+         cmds=$archive_cmds
+         fi
+       fi
+
+       if test "X$skipped_export" != "X:" &&
+          len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+          test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+         :
+       else
+         # The command line is too long to link in one step, link piecewise.
+         $echo "creating reloadable object files..."
+
+         # Save the value of $output and $libobjs because we want to
+         # use them later.  If we have whole_archive_flag_spec, we
+         # want to use save_libobjs as it was before
+         # whole_archive_flag_spec was expanded, because we can't
+         # assume the linker understands whole_archive_flag_spec.
+         # This may have to be revisited, in case too many
+         # convenience libraries get linked in and end up exceeding
+         # the spec.
+         if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+           save_libobjs=$libobjs
+         fi
+         save_output=$output
+         output_la=`$echo "X$output" | $Xsed -e "$basename"`
+
+         # Clear the reloadable object creation command queue and
+         # initialize k to one.
+         test_cmds=
+         concat_cmds=
+         objlist=
+         delfiles=
+         last_robj=
+         k=1
+         output=$output_objdir/$output_la-${k}.$objext
+         # Loop over the list of objects to be linked.
+         for obj in $save_libobjs
+         do
+           eval test_cmds=\"$reload_cmds $objlist $last_robj\"
+           if test "X$objlist" = X ||
+              { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+                test "$len" -le "$max_cmd_len"; }; then
+             objlist="$objlist $obj"
+           else
+             # The command $test_cmds is almost too long, add a
+             # command to the queue.
+             if test "$k" -eq 1 ; then
+               # The first file doesn't have a previous command to add.
+               eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+             else
+               # All subsequent reloadable object files will link in
+               # the last one created.
+               eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
+             fi
+             last_robj=$output_objdir/$output_la-${k}.$objext
+             k=`expr $k + 1`
+             output=$output_objdir/$output_la-${k}.$objext
+             objlist=$obj
+             len=1
+           fi
+         done
+         # Handle the remaining objects by creating one last
+         # reloadable object file.  All subsequent reloadable object
+         # files will link in the last one created.
+         test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+         eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+
+         if ${skipped_export-false}; then
+           $show "generating symbol list for \`$libname.la'"
+           export_symbols="$output_objdir/$libname.exp"
+           $run $rm $export_symbols
+           libobjs=$output
+           # Append the command to create the export file.
+           eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
+          fi
+
+         # Set up a command to remove the reloadable object files
+         # after they are used.
+         i=0
+         while test "$i" -lt "$k"
+         do
+           i=`expr $i + 1`
+           delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
+         done
+
+         $echo "creating a temporary reloadable object file: $output"
+
+         # Loop through the commands generated above and execute them.
+         save_ifs="$IFS"; IFS='~'
+         for cmd in $concat_cmds; do
+           IFS="$save_ifs"
+           $show "$cmd"
+           $run eval "$cmd" || exit $?
+         done
+         IFS="$save_ifs"
+
+         libobjs=$output
+         # Restore the value of output.
+         output=$save_output
+
+         if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+           eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+         fi
+         # Expand the library linking commands again to reset the
+         # value of $libobjs for piecewise linking.
+
+         # Do each of the archive commands.
+         if test "$module" = yes && test -n "$module_cmds" ; then
+           if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+             cmds=$module_expsym_cmds
+           else
+             cmds=$module_cmds
+           fi
+         else
+         if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+           cmds=$archive_expsym_cmds
+         else
+           cmds=$archive_cmds
+           fi
+         fi
+
+         # Append the command to remove the reloadable object files
+         # to the just-reset $cmds.
+         eval cmds=\"\$cmds~\$rm $delfiles\"
+       fi
+       save_ifs="$IFS"; IFS='~'
+       for cmd in $cmds; do
+         IFS="$save_ifs"
+         eval cmd=\"$cmd\"
+         $show "$cmd"
+         $run eval "$cmd" || {
+           lt_exit=$?
+
+           # Restore the uninstalled library and exit
+           if test "$mode" = relink; then
+             $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+           fi
+
+           exit $lt_exit
+         }
+       done
+       IFS="$save_ifs"
+
+       # Restore the uninstalled library and exit
+       if test "$mode" = relink; then
+         $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+
+         if test -n "$convenience"; then
+           if test -z "$whole_archive_flag_spec"; then
+             $show "${rm}r $gentop"
+             $run ${rm}r "$gentop"
+           fi
+         fi
+
+         exit $EXIT_SUCCESS
+       fi
+
+       # Create links to the real library.
+       for linkname in $linknames; do
+         if test "$realname" != "$linkname"; then
+           $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+           $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+         fi
+       done
+
+       # If -module or -export-dynamic was specified, set the dlname.
+       if test "$module" = yes || test "$export_dynamic" = yes; then
+         # On all known operating systems, these are identical.
+         dlname="$soname"
+       fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$deplibs"; then
+       $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+      fi
+
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$rpath"; then
+       $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$xrpath"; then
+       $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$vinfo"; then
+       $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$release"; then
+       $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+      fi
+
+      case $output in
+      *.lo)
+       if test -n "$objs$old_deplibs"; then
+         $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+         exit $EXIT_FAILURE
+       fi
+       libobj="$output"
+       obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+       ;;
+      *)
+       libobj=
+       obj="$output"
+       ;;
+      esac
+
+      # Delete the old objects.
+      $run $rm $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec and hope we can get by with
+      # turning comma into space..
+      wl=
+
+      if test -n "$convenience"; then
+       if test -n "$whole_archive_flag_spec"; then
+         eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+         reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
+       else
+         gentop="$output_objdir/${obj}x"
+         generated="$generated $gentop"
+
+         func_extract_archives $gentop $convenience
+         reload_conv_objs="$reload_objs $func_extract_archives_result"
+       fi
+      fi
+
+      # Create the old-style object.
+      reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+      output="$obj"
+      cmds=$reload_cmds
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+       IFS="$save_ifs"
+       eval cmd=\"$cmd\"
+       $show "$cmd"
+       $run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+       if test -n "$gentop"; then
+         $show "${rm}r $gentop"
+         $run ${rm}r $gentop
+       fi
+
+       exit $EXIT_SUCCESS
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+       if test -n "$gentop"; then
+         $show "${rm}r $gentop"
+         $run ${rm}r $gentop
+       fi
+
+       # Create an invalid libtool object if no PIC, so that we don't
+       # accidentally link it into a program.
+       # $show "echo timestamp > $libobj"
+       # $run eval "echo timestamp > $libobj" || exit $?
+       exit $EXIT_SUCCESS
+      fi
+
+      if test -n "$pic_flag" || test "$pic_mode" != default; then
+       # Only do commands if we really have different PIC objects.
+       reload_objs="$libobjs $reload_conv_objs"
+       output="$libobj"
+       cmds=$reload_cmds
+       save_ifs="$IFS"; IFS='~'
+       for cmd in $cmds; do
+         IFS="$save_ifs"
+         eval cmd=\"$cmd\"
+         $show "$cmd"
+         $run eval "$cmd" || exit $?
+       done
+       IFS="$save_ifs"
+      fi
+
+      if test -n "$gentop"; then
+       $show "${rm}r $gentop"
+       $run ${rm}r $gentop
+      fi
+
+      exit $EXIT_SUCCESS
+      ;;
+
+    prog)
+      case $host in
+       *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
+      esac
+      if test -n "$vinfo"; then
+       $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+      fi
+
+      if test -n "$release"; then
+       $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+      fi
+
+      if test "$preload" = yes; then
+       if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
+          test "$dlopen_self_static" = unknown; then
+         $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+       fi
+      fi
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+       # On Rhapsody replace the C library is the System framework
+       compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+       finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+       ;;
+      esac
+
+      case $host in
+      *darwin*)
+        # Don't allow lazy linking, it breaks C++ global constructors
+        if test "$tagname" = CXX ; then
+        compile_command="$compile_command ${wl}-bind_at_load"
+        finalize_command="$finalize_command ${wl}-bind_at_load"
+        fi
+        ;;
+      esac
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+       case " $new_libs " in
+       *" -L$path/$objdir "*) ;;
+       *)
+         case " $compile_deplibs " in
+         *" -L$path/$objdir "*)
+           new_libs="$new_libs -L$path/$objdir" ;;
+         esac
+         ;;
+       esac
+      done
+      for deplib in $compile_deplibs; do
+       case $deplib in
+       -L*)
+         case " $new_libs " in
+         *" $deplib "*) ;;
+         *) new_libs="$new_libs $deplib" ;;
+         esac
+         ;;
+       *) new_libs="$new_libs $deplib" ;;
+       esac
+      done
+      compile_deplibs="$new_libs"
+
+
+      compile_command="$compile_command $compile_deplibs"
+      finalize_command="$finalize_command $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+       # If the user specified any rpath flags, then add them.
+       for libdir in $rpath $xrpath; do
+         # This is the magic to use -rpath.
+         case "$finalize_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_rpath="$finalize_rpath $libdir" ;;
+         esac
+       done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+       if test -n "$hardcode_libdir_flag_spec"; then
+         if test -n "$hardcode_libdir_separator"; then
+           if test -z "$hardcode_libdirs"; then
+             hardcode_libdirs="$libdir"
+           else
+             # Just accumulate the unique libdirs.
+             case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+               ;;
+             *)
+               hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+               ;;
+             esac
+           fi
+         else
+           eval flag=\"$hardcode_libdir_flag_spec\"
+           rpath="$rpath $flag"
+         fi
+       elif test -n "$runpath_var"; then
+         case "$perm_rpath " in
+         *" $libdir "*) ;;
+         *) perm_rpath="$perm_rpath $libdir" ;;
+         esac
+       fi
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+         testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'`
+         case :$dllsearchpath: in
+         *":$libdir:"*) ;;
+         *) dllsearchpath="$dllsearchpath:$libdir";;
+         esac
+         case :$dllsearchpath: in
+         *":$testbindir:"*) ;;
+         *) dllsearchpath="$dllsearchpath:$testbindir";;
+         esac
+         ;;
+       esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+        test -n "$hardcode_libdirs"; then
+       libdir="$hardcode_libdirs"
+       eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+       if test -n "$hardcode_libdir_flag_spec"; then
+         if test -n "$hardcode_libdir_separator"; then
+           if test -z "$hardcode_libdirs"; then
+             hardcode_libdirs="$libdir"
+           else
+             # Just accumulate the unique libdirs.
+             case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+               ;;
+             *)
+               hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+               ;;
+             esac
+           fi
+         else
+           eval flag=\"$hardcode_libdir_flag_spec\"
+           rpath="$rpath $flag"
+         fi
+       elif test -n "$runpath_var"; then
+         case "$finalize_perm_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+         esac
+       fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+        test -n "$hardcode_libdirs"; then
+       libdir="$hardcode_libdirs"
+       eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      finalize_rpath="$rpath"
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+       # Transform all the library objects into standard objects.
+       compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+       finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+      fi
+
+      dlsyms=
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       if test -n "$NM" && test -n "$global_symbol_pipe"; then
+         dlsyms="${outputname}S.c"
+       else
+         $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+       fi
+      fi
+
+      if test -n "$dlsyms"; then
+       case $dlsyms in
+       "") ;;
+       *.c)
+         # Discover the nlist of each of the dlfiles.
+         nlist="$output_objdir/${outputname}.nm"
+
+         $show "$rm $nlist ${nlist}S ${nlist}T"
+         $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+         # Parse the name list into a source file.
+         $show "creating $output_objdir/$dlsyms"
+
+         test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+         if test "$dlself" = yes; then
+           $show "generating symbol list for \`$output'"
+
+           test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+           # Add our own program objects to the symbol list.
+           progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+           for arg in $progfiles; do
+             $show "extracting global C symbols from \`$arg'"
+             $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+           done
+
+           if test -n "$exclude_expsyms"; then
+             $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+             $run eval '$mv "$nlist"T "$nlist"'
+           fi
+
+           if test -n "$export_symbols_regex"; then
+             $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+             $run eval '$mv "$nlist"T "$nlist"'
+           fi
+
+           # Prepare the list of exported symbols
+           if test -z "$export_symbols"; then
+             export_symbols="$output_objdir/$outputname.exp"
+             $run $rm $export_symbols
+             $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+              case $host in
+              *cygwin* | *mingw* )
+               $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+               $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+                ;;
+              esac
+           else
+             $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+             $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+             $run eval 'mv "$nlist"T "$nlist"'
+              case $host in
+              *cygwin* | *mingw* )
+               $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+               $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+                ;;
+              esac
+           fi
+         fi
+
+         for arg in $dlprefiles; do
+           $show "extracting global C symbols from \`$arg'"
+           name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
+           $run eval '$echo ": $name " >> "$nlist"'
+           $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+         done
+
+         if test -z "$run"; then
+           # Make sure we have at least an empty file.
+           test -f "$nlist" || : > "$nlist"
+
+           if test -n "$exclude_expsyms"; then
+             $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+             $mv "$nlist"T "$nlist"
+           fi
+
+           # Try sorting and uniquifying the output.
+           if grep -v "^: " < "$nlist" |
+               if sort -k 3 </dev/null >/dev/null 2>&1; then
+                 sort -k 3
+               else
+                 sort +2
+               fi |
+               uniq > "$nlist"S; then
+             :
+           else
+             grep -v "^: " < "$nlist" > "$nlist"S
+           fi
+
+           if test -f "$nlist"S; then
+             eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+           else
+             $echo '/* NONE */' >> "$output_objdir/$dlsyms"
+           fi
+
+           $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+"
+
+           case $host in
+           *cygwin* | *mingw* )
+         $echo >> "$output_objdir/$dlsyms" "\
+/* DATA imports from DLLs on WIN32 can't be const, because
+   runtime relocations are performed -- see ld's documentation
+   on pseudo-relocs */
+struct {
+"
+             ;;
+           * )
+         $echo >> "$output_objdir/$dlsyms" "\
+const struct {
+"
+             ;;
+           esac
+
+
+         $echo >> "$output_objdir/$dlsyms" "\
+  const char *name;
+  lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+           eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
+
+           $echo >> "$output_objdir/$dlsyms" "\
+  {0, (lt_ptr) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+         fi
+
+         pic_flag_for_symtable=
+         case $host in
+         # compiling the symbol table file with pic_flag works around
+         # a FreeBSD bug that causes programs to crash when -lm is
+         # linked before any other PIC object.  But we must not use
+         # pic_flag when linking with -static.  The problem exists in
+         # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+         *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+           case "$compile_command " in
+           *" -static "*) ;;
+           *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
+           esac;;
+         *-*-hpux*)
+           case "$compile_command " in
+           *" -static "*) ;;
+           *) pic_flag_for_symtable=" $pic_flag";;
+           esac
+         esac
+
+         # Now compile the dynamic symbol file.
+         $show "(cd $output_objdir && $LTCC  $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+         $run eval '(cd $output_objdir && $LTCC  $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+         # Clean up the generated files.
+         $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+         $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+         # Transform the symbol file into the correct name.
+          case $host in
+          *cygwin* | *mingw* )
+            if test -f "$output_objdir/${outputname}.def" ; then
+              compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP`
+              finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP`
+            else
+              compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+              finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+             fi
+            ;;
+          * )
+            compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+            finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+            ;;
+          esac
+         ;;
+       *)
+         $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+      else
+       # We keep going just in case the user didn't refer to
+       # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+       # really was required.
+
+       # Nullify the symbol file.
+       compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP`
+       finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP`
+      fi
+
+      if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+       # Replace the output file specification.
+       compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$output"'%g' | $NL2SP`
+       link_command="$compile_command$compile_rpath"
+
+       # We have no uninstalled library dependencies, so finalize right now.
+       $show "$link_command"
+       $run eval "$link_command"
+       exit_status=$?
+
+       # Delete the generated files.
+       if test -n "$dlsyms"; then
+         $show "$rm $output_objdir/${outputname}S.${objext}"
+         $run $rm "$output_objdir/${outputname}S.${objext}"
+       fi
+
+       exit $exit_status
+      fi
+
+      if test -n "$shlibpath_var"; then
+       # We should set the shlibpath_var
+       rpath=
+       for dir in $temp_rpath; do
+         case $dir in
+         [\\/]* | [A-Za-z]:[\\/]*)
+           # Absolute path.
+           rpath="$rpath$dir:"
+           ;;
+         *)
+           # Relative path: add a thisdir entry.
+           rpath="$rpath\$thisdir/$dir:"
+           ;;
+         esac
+       done
+       temp_rpath="$rpath"
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+       compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+       finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+       if test -n "$perm_rpath"; then
+         # We should set the runpath_var.
+         rpath=
+         for dir in $perm_rpath; do
+           rpath="$rpath$dir:"
+         done
+         compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+       fi
+       if test -n "$finalize_perm_rpath"; then
+         # We should set the runpath_var.
+         rpath=
+         for dir in $finalize_perm_rpath; do
+           rpath="$rpath$dir:"
+         done
+         finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+       fi
+      fi
+
+      if test "$no_install" = yes; then
+       # We don't need to create a wrapper script.
+       link_command="$compile_var$compile_command$compile_rpath"
+       # Replace the output file specification.
+       link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+       # Delete the old output file.
+       $run $rm $output
+       # Link the executable and exit
+       $show "$link_command"
+       $run eval "$link_command" || exit $?
+       exit $EXIT_SUCCESS
+      fi
+
+      if test "$hardcode_action" = relink; then
+       # Fast installation is not supported
+       link_command="$compile_var$compile_command$compile_rpath"
+       relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+       $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+       $echo "$modename: \`$output' will be relinked during installation" 1>&2
+      else
+       if test "$fast_install" != no; then
+         link_command="$finalize_var$compile_command$finalize_rpath"
+         if test "$fast_install" = yes; then
+           relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $SP2NL | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g' | $NL2SP`
+         else
+           # fast_install is set to needless
+           relink_command=
+         fi
+       else
+         link_command="$compile_var$compile_command$compile_rpath"
+         relink_command="$finalize_var$finalize_command$finalize_rpath"
+       fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      $show "$link_command"
+      $run eval "$link_command" || exit $?
+
+      # Now create the wrapper script.
+      $show "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+       # Preserve any variables that may affect compiler behavior
+       for var in $variables_saved_for_relink; do
+         if eval test -z \"\${$var+set}\"; then
+           relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+         elif eval var_value=\$$var; test -z "$var_value"; then
+           relink_command="$var=; export $var; $relink_command"
+         else
+           var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+           relink_command="$var=\"$var_value\"; export $var; $relink_command"
+         fi
+       done
+       relink_command="(cd `pwd`; $relink_command)"
+       relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP`
+      fi
+
+      # Quote $echo for shipping.
+      if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
+       case $progpath in
+       [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+       *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+       esac
+       qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+      else
+       qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if our run command is non-null.
+      if test -z "$run"; then
+       # win32 will think the script is a binary if it has
+       # a .exe suffix, so we strip it off here.
+       case $output in
+         *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
+       esac
+       # test for cygwin because mv fails w/o .exe extensions
+       case $host in
+         *cygwin*)
+           exeext=.exe
+           outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
+         *) exeext= ;;
+       esac
+       case $host in
+         *cygwin* | *mingw* )
+            output_name=`basename $output`
+            output_path=`dirname $output`
+            cwrappersource="$output_path/$objdir/lt-$output_name.c"
+            cwrapper="$output_path/$output_name.exe"
+            $rm $cwrappersource $cwrapper
+            trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+           cat > $cwrappersource <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+
+   Currently, it simply execs the wrapper *script* "/bin/sh $output",
+   but could eventually absorb all of the scripts functionality and
+   exec $objdir/$outputname directly.
+*/
+EOF
+           cat >> $cwrappersource<<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+  defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# ifndef DIR_SEPARATOR_2
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+#  define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+        (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+/* -DDEBUG is fairly common in CFLAGS.  */
+#undef DEBUG
+#if defined DEBUGWRAPPER
+# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
+#else
+# define DEBUG(format, ...)
+#endif
+
+const char *program_name = NULL;
+
+void * xmalloc (size_t num);
+char * xstrdup (const char *string);
+const char * base_name (const char *name);
+char * find_executable(const char *wrapper);
+int    check_executable(const char *path);
+char * strendzap(char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  DEBUG("(main) argv[0]      : %s\n",argv[0]);
+  DEBUG("(main) program_name : %s\n",program_name);
+  newargz = XMALLOC(char *, argc+2);
+EOF
+
+            cat >> $cwrappersource <<EOF
+  newargz[0] = (char *) xstrdup("$SHELL");
+EOF
+
+            cat >> $cwrappersource <<"EOF"
+  newargz[1] = find_executable(argv[0]);
+  if (newargz[1] == NULL)
+    lt_fatal("Couldn't find %s", argv[0]);
+  DEBUG("(main) found exe at : %s\n",newargz[1]);
+  /* we know the script has the same name, without the .exe */
+  /* so make sure newargz[1] doesn't end in .exe */
+  strendzap(newargz[1],".exe");
+  for (i = 1; i < argc; i++)
+    newargz[i+1] = xstrdup(argv[i]);
+  newargz[argc+1] = NULL;
+
+  for (i=0; i<argc+1; i++)
+  {
+    DEBUG("(main) newargz[%d]   : %s\n",i,newargz[i]);
+    ;
+  }
+
+EOF
+
+            case $host_os in
+              mingw*)
+                cat >> $cwrappersource <<EOF
+  execv("$SHELL",(char const **)newargz);
+EOF
+              ;;
+              *)
+                cat >> $cwrappersource <<EOF
+  execv("$SHELL",newargz);
+EOF
+              ;;
+            esac
+
+            cat >> $cwrappersource <<"EOF"
+  return 127;
+}
+
+void *
+xmalloc (size_t num)
+{
+  void * p = (void *) malloc (num);
+  if (!p)
+    lt_fatal ("Memory exhausted");
+
+  return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
+;
+}
+
+const char *
+base_name (const char *name)
+{
+  const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha ((unsigned char)name[0]) && name[1] == ':')
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return base;
+}
+
+int
+check_executable(const char * path)
+{
+  struct stat st;
+
+  DEBUG("(check_executable)  : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
+  if ((!path) || (!*path))
+    return 0;
+
+  if ((stat (path, &st) >= 0) &&
+      (
+        /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
+#if defined (S_IXOTH)
+       ((st.st_mode & S_IXOTH) == S_IXOTH) ||
+#endif
+#if defined (S_IXGRP)
+       ((st.st_mode & S_IXGRP) == S_IXGRP) ||
+#endif
+       ((st.st_mode & S_IXUSR) == S_IXUSR))
+      )
+    return 1;
+  else
+    return 0;
+}
+
+/* Searches for the full path of the wrapper.  Returns
+   newly allocated full path name if found, NULL otherwise */
+char *
+find_executable (const char* wrapper)
+{
+  int has_slash = 0;
+  const char* p;
+  const char* p_next;
+  /* static buffer for getcwd */
+  char tmp[LT_PATHMAX + 1];
+  int tmp_len;
+  char* concat_name;
+
+  DEBUG("(find_executable)  : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
+
+  if ((wrapper == NULL) || (*wrapper == '\0'))
+    return NULL;
+
+  /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':')
+  {
+    concat_name = xstrdup (wrapper);
+    if (check_executable(concat_name))
+      return concat_name;
+    XFREE(concat_name);
+  }
+  else
+  {
+#endif
+    if (IS_DIR_SEPARATOR (wrapper[0]))
+    {
+      concat_name = xstrdup (wrapper);
+      if (check_executable(concat_name))
+        return concat_name;
+      XFREE(concat_name);
+    }
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  }
+#endif
+
+  for (p = wrapper; *p; p++)
+    if (*p == '/')
+    {
+      has_slash = 1;
+      break;
+    }
+  if (!has_slash)
+  {
+    /* no slashes; search PATH */
+    const char* path = getenv ("PATH");
+    if (path != NULL)
+    {
+      for (p = path; *p; p = p_next)
+      {
+        const char* q;
+        size_t p_len;
+        for (q = p; *q; q++)
+          if (IS_PATH_SEPARATOR(*q))
+            break;
+        p_len = q - p;
+        p_next = (*q == '\0' ? q : q + 1);
+        if (p_len == 0)
+        {
+          /* empty path: current directory */
+          if (getcwd (tmp, LT_PATHMAX) == NULL)
+            lt_fatal ("getcwd failed");
+          tmp_len = strlen(tmp);
+          concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+          memcpy (concat_name, tmp, tmp_len);
+          concat_name[tmp_len] = '/';
+          strcpy (concat_name + tmp_len + 1, wrapper);
+        }
+        else
+        {
+          concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1);
+          memcpy (concat_name, p, p_len);
+          concat_name[p_len] = '/';
+          strcpy (concat_name + p_len + 1, wrapper);
+        }
+        if (check_executable(concat_name))
+          return concat_name;
+        XFREE(concat_name);
+      }
+    }
+    /* not found in PATH; assume curdir */
+  }
+  /* Relative path | not found in path: prepend cwd */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal ("getcwd failed");
+  tmp_len = strlen(tmp);
+  concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+  memcpy (concat_name, tmp, tmp_len);
+  concat_name[tmp_len] = '/';
+  strcpy (concat_name + tmp_len + 1, wrapper);
+
+  if (check_executable(concat_name))
+    return concat_name;
+  XFREE(concat_name);
+  return NULL;
+}
+
+char *
+strendzap(char *str, const char *pat)
+{
+  size_t len, patlen;
+
+  assert(str != NULL);
+  assert(pat != NULL);
+
+  len = strlen(str);
+  patlen = strlen(pat);
+
+  if (patlen <= len)
+  {
+    str += len - patlen;
+    if (strcmp(str, pat) == 0)
+      *str = '\0';
+  }
+  return str;
+}
+
+static void
+lt_error_core (int exit_status, const char * mode,
+          const char * message, va_list ap)
+{
+  fprintf (stderr, "%s: %s: ", program_name, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+  va_end (ap);
+}
+EOF
+          # we should really use a build-platform specific compiler
+          # here, but OTOH, the wrappers (shell script and this C one)
+          # are only useful if you want to execute the "real" binary.
+          # Since the "real" binary is built for $host, then this
+          # wrapper might as well be built for $host, too.
+          $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
+          ;;
+        esac
+        $rm $output
+        trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
+
+       $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variable:
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$echo are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    echo=\"$qecho\"
+    file=\"\$0\"
+    # Make sure echo works.
+    if test \"X\$1\" = X--no-reexec; then
+      # Discard the --no-reexec flag, and continue.
+      shift
+    elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+      # Yippee, \$echo works!
+      :
+    else
+      # Restart under the correct shell, and then maybe \$echo will work.
+      exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+    fi
+  fi\
+"
+       $echo >> $output "\
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+  done
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+       if test "$fast_install" = yes; then
+         $echo >> $output "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" || \\
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $mkdir \"\$progdir\"
+    else
+      $rm \"\$progdir/\$file\"
+    fi"
+
+         $echo >> $output "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+      else
+       $echo \"\$relink_command_output\" >&2
+       $rm \"\$progdir/\$file\"
+       exit $EXIT_FAILURE
+      fi
+    fi
+
+    $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $rm \"\$progdir/\$program\";
+      $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $rm \"\$progdir/\$file\"
+  fi"
+       else
+         $echo >> $output "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+       fi
+
+       $echo >> $output "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+       # Export our shlibpath_var if we have one.
+       if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+         $echo >> $output "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+       fi
+
+       # fixup the dll searchpath if we need to.
+       if test -n "$dllsearchpath"; then
+         $echo >> $output "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+       fi
+
+       $echo >> $output "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+"
+       case $host in
+       # Backslashes separate directories on plain windows
+       *-*-mingw | *-*-os2*)
+         $echo >> $output "\
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+         ;;
+
+       *)
+         $echo >> $output "\
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+         ;;
+       esac
+       $echo >> $output "\
+      \$echo \"\$0: cannot exec \$program \$*\"
+      exit $EXIT_FAILURE
+    fi
+  else
+    # The program doesn't exist.
+    \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+    \$echo \"This script is just a wrapper for \$program.\" 1>&2
+    $echo \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit $EXIT_FAILURE
+  fi
+fi\
+"
+       chmod +x $output
+      fi
+      exit $EXIT_SUCCESS
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+       oldobjs="$libobjs_save"
+       addlibs="$convenience"
+       build_libtool_libs=no
+      else
+       if test "$build_libtool_libs" = module; then
+         oldobjs="$libobjs_save"
+         build_libtool_libs=no
+       else
+         oldobjs="$old_deplibs $non_pic_objects"
+       fi
+       addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+       gentop="$output_objdir/${outputname}x"
+       generated="$generated $gentop"
+
+       func_extract_archives $gentop $addlibs
+       oldobjs="$oldobjs $func_extract_archives_result"
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+       cmds=$old_archive_from_new_cmds
+      else
+       # POSIX demands no paths to be encoded in archives.  We have
+       # to avoid creating archives with duplicate basenames if we
+       # might have to extract them afterwards, e.g., when creating a
+       # static archive out of a convenience library, or when linking
+       # the entirety of a libtool archive into another (currently
+       # not supported by libtool).
+       if (for obj in $oldobjs
+           do
+             $echo "X$obj" | $Xsed -e 's%^.*/%%'
+           done | sort | sort -uc >/dev/null 2>&1); then
+         :
+       else
+         $echo "copying selected object files to avoid basename conflicts..."
+
+         if test -z "$gentop"; then
+           gentop="$output_objdir/${outputname}x"
+           generated="$generated $gentop"
+
+           $show "${rm}r $gentop"
+           $run ${rm}r "$gentop"
+           $show "$mkdir $gentop"
+           $run $mkdir "$gentop"
+           exit_status=$?
+           if test "$exit_status" -ne 0 && test ! -d "$gentop"; then
+             exit $exit_status
+           fi
+         fi
+
+         save_oldobjs=$oldobjs
+         oldobjs=
+         counter=1
+         for obj in $save_oldobjs
+         do
+           objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+           case " $oldobjs " in
+           " ") oldobjs=$obj ;;
+           *[\ /]"$objbase "*)
+             while :; do
+               # Make sure we don't pick an alternate name that also
+               # overlaps.
+               newobj=lt$counter-$objbase
+               counter=`expr $counter + 1`
+               case " $oldobjs " in
+               *[\ /]"$newobj "*) ;;
+               *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+               esac
+             done
+             $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+             $run ln "$obj" "$gentop/$newobj" ||
+             $run cp "$obj" "$gentop/$newobj"
+             oldobjs="$oldobjs $gentop/$newobj"
+             ;;
+           *) oldobjs="$oldobjs $obj" ;;
+           esac
+         done
+       fi
+
+       eval cmds=\"$old_archive_cmds\"
+
+       if len=`expr "X$cmds" : ".*"` &&
+            test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+         cmds=$old_archive_cmds
+       else
+         # the command line is too long to link in one step, link in parts
+         $echo "using piecewise archive linking..."
+         save_RANLIB=$RANLIB
+         RANLIB=:
+         objlist=
+         concat_cmds=
+         save_oldobjs=$oldobjs
+
+         # Is there a better way of finding the last object in the list?
+         for obj in $save_oldobjs
+         do
+           last_oldobj=$obj
+         done
+         for obj in $save_oldobjs
+         do
+           oldobjs="$objlist $obj"
+           objlist="$objlist $obj"
+           eval test_cmds=\"$old_archive_cmds\"
+           if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+              test "$len" -le "$max_cmd_len"; then
+             :
+           else
+             # the above command should be used before it gets too long
+             oldobjs=$objlist
+             if test "$obj" = "$last_oldobj" ; then
+               RANLIB=$save_RANLIB
+             fi
+             test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+             eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+             objlist=
+           fi
+         done
+         RANLIB=$save_RANLIB
+         oldobjs=$objlist
+         if test "X$oldobjs" = "X" ; then
+           eval cmds=\"\$concat_cmds\"
+         else
+           eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+         fi
+       fi
+      fi
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+        eval cmd=\"$cmd\"
+       IFS="$save_ifs"
+       $show "$cmd"
+       $run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+    done
+
+    if test -n "$generated"; then
+      $show "${rm}r$generated"
+      $run ${rm}r$generated
+    fi
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      $show "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+       if eval test -z \"\${$var+set}\"; then
+         relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+       elif eval var_value=\$$var; test -z "$var_value"; then
+         relink_command="$var=; export $var; $relink_command"
+       else
+         var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+         relink_command="$var=\"$var_value\"; export $var; $relink_command"
+       fi
+      done
+      # Quote the link command for shipping.
+      relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+      relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP`
+      if test "$hardcode_automatic" = yes ; then
+       relink_command=
+      fi
+
+
+      # Only create the output if not a dry run.
+      if test -z "$run"; then
+       for installed in no yes; do
+         if test "$installed" = yes; then
+           if test -z "$install_libdir"; then
+             break
+           fi
+           output="$output_objdir/$outputname"i
+           # Replace all uninstalled libtool libraries with the installed ones
+           newdependency_libs=
+           for deplib in $dependency_libs; do
+             case $deplib in
+             *.la)
+               name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+               eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+               if test -z "$libdir"; then
+                 $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+                 exit $EXIT_FAILURE
+               fi
+               newdependency_libs="$newdependency_libs $libdir/$name"
+               ;;
+             *) newdependency_libs="$newdependency_libs $deplib" ;;
+             esac
+           done
+           dependency_libs="$newdependency_libs"
+           newdlfiles=
+           for lib in $dlfiles; do
+             name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+             eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+             if test -z "$libdir"; then
+               $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+               exit $EXIT_FAILURE
+             fi
+             newdlfiles="$newdlfiles $libdir/$name"
+           done
+           dlfiles="$newdlfiles"
+           newdlprefiles=
+           for lib in $dlprefiles; do
+             name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+             eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+             if test -z "$libdir"; then
+               $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+               exit $EXIT_FAILURE
+             fi
+             newdlprefiles="$newdlprefiles $libdir/$name"
+           done
+           dlprefiles="$newdlprefiles"
+         else
+           newdlfiles=
+           for lib in $dlfiles; do
+             case $lib in
+               [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+               *) abs=`pwd`"/$lib" ;;
+             esac
+             newdlfiles="$newdlfiles $abs"
+           done
+           dlfiles="$newdlfiles"
+           newdlprefiles=
+           for lib in $dlprefiles; do
+             case $lib in
+               [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+               *) abs=`pwd`"/$lib" ;;
+             esac
+             newdlprefiles="$newdlprefiles $abs"
+           done
+           dlprefiles="$newdlprefiles"
+         fi
+         $rm $output
+         # place dlname in correct position for cygwin
+         tdlname=$dlname
+         case $host,$output,$installed,$module,$dlname in
+           *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+         esac
+         $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+         if test "$installed" = no && test "$need_relink" = yes; then
+           $echo >> $output "\
+relink_command=\"$relink_command\""
+         fi
+       done
+      fi
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+      $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
+      ;;
+    esac
+    exit $EXIT_SUCCESS
+    ;;
+
+  # libtool install mode
+  install)
+    modename="$modename: install"
+
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+       # Allow the use of GNU shtool's install command.
+       $echo "X$nonopt" | grep shtool > /dev/null; then
+      # Aesthetically quote it.
+      arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+       arg="\"$arg\""
+       ;;
+      esac
+      install_prog="$arg "
+      arg="$1"
+      shift
+    else
+      install_prog=
+      arg=$nonopt
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+    case $arg in
+    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \      ]*|*]*|"")
+      arg="\"$arg\""
+      ;;
+    esac
+    install_prog="$install_prog$arg"
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    for arg
+    do
+      if test -n "$dest"; then
+       files="$files $dest"
+       dest=$arg
+       continue
+      fi
+
+      case $arg in
+      -d) isdir=yes ;;
+      -f) 
+       case " $install_prog " in
+       *[\\\ /]cp\ *) ;;
+       *) prev=$arg ;;
+       esac
+       ;;
+      -g | -m | -o) prev=$arg ;;
+      -s)
+       stripme=" -s"
+       continue
+       ;;
+      -*)
+       ;;
+      *)
+       # If the previous option needed an argument, then skip it.
+       if test -n "$prev"; then
+         prev=
+       else
+         dest=$arg
+         continue
+       fi
+       ;;
+      esac
+
+      # Aesthetically quote the argument.
+      arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+       arg="\"$arg\""
+       ;;
+      esac
+      install_prog="$install_prog $arg"
+    done
+
+    if test -z "$install_prog"; then
+      $echo "$modename: you must specify an install program" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    if test -n "$prev"; then
+      $echo "$modename: the \`$prev' option requires an argument" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+       $echo "$modename: no file or destination specified" 1>&2
+      else
+       $echo "$modename: you must specify a destination" 1>&2
+      fi
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    # Strip any trailing slash from the destination.
+    dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+      test "X$destdir" = "X$dest" && destdir=.
+      destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files
+      if test "$#" -gt 2; then
+       $echo "$modename: \`$dest' is not a directory" 1>&2
+       $echo "$help" 1>&2
+       exit $EXIT_FAILURE
+      fi
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+       case $file in
+       *.lo) ;;
+       *)
+         $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+         $echo "$help" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+       # Do the static libraries later.
+       staticlibs="$staticlibs $file"
+       ;;
+
+      *.la)
+       # Check to see that this really is a libtool archive.
+       if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+       else
+         $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+         $echo "$help" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       library_names=
+       old_library=
+       relink_command=
+       # If there is no directory component, then add one.
+       case $file in
+       */* | *\\*) . $file ;;
+       *) . ./$file ;;
+       esac
+
+       # Add the libdir to current_libdirs if it is the destination.
+       if test "X$destdir" = "X$libdir"; then
+         case "$current_libdirs " in
+         *" $libdir "*) ;;
+         *) current_libdirs="$current_libdirs $libdir" ;;
+         esac
+       else
+         # Note the libdir as a future libdir.
+         case "$future_libdirs " in
+         *" $libdir "*) ;;
+         *) future_libdirs="$future_libdirs $libdir" ;;
+         esac
+       fi
+
+       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
+       test "X$dir" = "X$file/" && dir=
+       dir="$dir$objdir"
+
+       if test -n "$relink_command"; then
+         # Determine the prefix the user has applied to our future dir.
+         inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
+
+         # Don't allow the user to place us outside of our expected
+         # location b/c this prevents finding dependent libraries that
+         # are installed to the same prefix.
+         # At present, this check doesn't affect windows .dll's that
+         # are installed into $libdir/../bin (currently, that works fine)
+         # but it's something to keep an eye on.
+         if test "$inst_prefix_dir" = "$destdir"; then
+           $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
+           exit $EXIT_FAILURE
+         fi
+
+         if test -n "$inst_prefix_dir"; then
+           # Stick the inst_prefix_dir data into the link command.
+           relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%" | $NL2SP`
+         else
+           relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%%" | $NL2SP`
+         fi
+
+         $echo "$modename: warning: relinking \`$file'" 1>&2
+         $show "$relink_command"
+         if $run eval "$relink_command"; then :
+         else
+           $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+           exit $EXIT_FAILURE
+         fi
+       fi
+
+       # See the names of the shared library.
+       set dummy $library_names
+       if test -n "$2"; then
+         realname="$2"
+         shift
+         shift
+
+         srcname="$realname"
+         test -n "$relink_command" && srcname="$realname"T
+
+         # Install the shared library and build the symlinks.
+         $show "$install_prog $dir/$srcname $destdir/$realname"
+         $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
+         if test -n "$stripme" && test -n "$striplib"; then
+           $show "$striplib $destdir/$realname"
+           $run eval "$striplib $destdir/$realname" || exit $?
+         fi
+
+         if test "$#" -gt 0; then
+           # Delete the old symlinks, and create new ones.
+           # Try `ln -sf' first, because the `ln' binary might depend on
+           # the symlink we replace!  Solaris /bin/ln does not understand -f,
+           # so we also need to try rm && ln -s.
+           for linkname
+           do
+             if test "$linkname" != "$realname"; then
+                $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+                $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+             fi
+           done
+         fi
+
+         # Do each command in the postinstall commands.
+         lib="$destdir/$realname"
+         cmds=$postinstall_cmds
+         save_ifs="$IFS"; IFS='~'
+         for cmd in $cmds; do
+           IFS="$save_ifs"
+           eval cmd=\"$cmd\"
+           $show "$cmd"
+           $run eval "$cmd" || {
+             lt_exit=$?
+
+             # Restore the uninstalled library and exit
+             if test "$mode" = relink; then
+               $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+             fi
+
+             exit $lt_exit
+           }
+         done
+         IFS="$save_ifs"
+       fi
+
+       # Install the pseudo-library for information purposes.
+       name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+       instname="$dir/$name"i
+       $show "$install_prog $instname $destdir/$name"
+       $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+       # Maybe install the static library, too.
+       test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+       ;;
+
+      *.lo)
+       # Install (i.e. copy) a libtool object.
+
+       # Figure out destination file name, if it wasn't already specified.
+       if test -n "$destname"; then
+         destfile="$destdir/$destname"
+       else
+         destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+         destfile="$destdir/$destfile"
+       fi
+
+       # Deduce the name of the destination old-style object file.
+       case $destfile in
+       *.lo)
+         staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+         ;;
+       *.$objext)
+         staticdest="$destfile"
+         destfile=
+         ;;
+       *)
+         $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+         $echo "$help" 1>&2
+         exit $EXIT_FAILURE
+         ;;
+       esac
+
+       # Install the libtool object if requested.
+       if test -n "$destfile"; then
+         $show "$install_prog $file $destfile"
+         $run eval "$install_prog $file $destfile" || exit $?
+       fi
+
+       # Install the old object if enabled.
+       if test "$build_old_libs" = yes; then
+         # Deduce the name of the old-style object file.
+         staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+         $show "$install_prog $staticobj $staticdest"
+         $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+       fi
+       exit $EXIT_SUCCESS
+       ;;
+
+      *)
+       # Figure out destination file name, if it wasn't already specified.
+       if test -n "$destname"; then
+         destfile="$destdir/$destname"
+       else
+         destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+         destfile="$destdir/$destfile"
+       fi
+
+       # If the file is missing, and there is a .exe on the end, strip it
+       # because it is most likely a libtool script we actually want to
+       # install
+       stripped_ext=""
+       case $file in
+         *.exe)
+           if test ! -f "$file"; then
+             file=`$echo $file|${SED} 's,.exe$,,'`
+             stripped_ext=".exe"
+           fi
+           ;;
+       esac
+
+       # Do a test to see if this is really a libtool program.
+       case $host in
+       *cygwin*|*mingw*)
+           wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
+           ;;
+       *)
+           wrapper=$file
+           ;;
+       esac
+       if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
+         notinst_deplibs=
+         relink_command=
+
+         # Note that it is not necessary on cygwin/mingw to append a dot to
+         # foo even if both foo and FILE.exe exist: automatic-append-.exe
+         # behavior happens only for exec(3), not for open(2)!  Also, sourcing
+         # `FILE.' does not work on cygwin managed mounts.
+         #
+         # If there is no directory component, then add one.
+         case $wrapper in
+         */* | *\\*) . ${wrapper} ;;
+         *) . ./${wrapper} ;;
+         esac
+
+         # Check the variables that should have been set.
+         if test -z "$notinst_deplibs"; then
+           $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+           exit $EXIT_FAILURE
+         fi
+
+         finalize=yes
+         for lib in $notinst_deplibs; do
+           # Check to see that each library is installed.
+           libdir=
+           if test -f "$lib"; then
+             # If there is no directory component, then add one.
+             case $lib in
+             */* | *\\*) . $lib ;;
+             *) . ./$lib ;;
+             esac
+           fi
+           libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+           if test -n "$libdir" && test ! -f "$libfile"; then
+             $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+             finalize=no
+           fi
+         done
+
+         relink_command=
+         # Note that it is not necessary on cygwin/mingw to append a dot to
+         # foo even if both foo and FILE.exe exist: automatic-append-.exe
+         # behavior happens only for exec(3), not for open(2)!  Also, sourcing
+         # `FILE.' does not work on cygwin managed mounts.
+         #
+         # If there is no directory component, then add one.
+         case $wrapper in
+         */* | *\\*) . ${wrapper} ;;
+         *) . ./${wrapper} ;;
+         esac
+
+         outputname=
+         if test "$fast_install" = no && test -n "$relink_command"; then
+           if test "$finalize" = yes && test -z "$run"; then
+             tmpdir=`func_mktempdir`
+             file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
+             outputname="$tmpdir/$file"
+             # Replace the output file specification.
+             relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g' | $NL2SP`
+
+             $show "$relink_command"
+             if $run eval "$relink_command"; then :
+             else
+               $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+               ${rm}r "$tmpdir"
+               continue
+             fi
+             file="$outputname"
+           else
+             $echo "$modename: warning: cannot relink \`$file'" 1>&2
+           fi
+         else
+           # Install the binary that we compiled earlier.
+           file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+         fi
+       fi
+
+       # remove .exe since cygwin /usr/bin/install will append another
+       # one anyway 
+       case $install_prog,$host in
+       */usr/bin/install*,*cygwin*)
+         case $file:$destfile in
+         *.exe:*.exe)
+           # this is ok
+           ;;
+         *.exe:*)
+           destfile=$destfile.exe
+           ;;
+         *:*.exe)
+           destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
+           ;;
+         esac
+         ;;
+       esac
+       $show "$install_prog$stripme $file $destfile"
+       $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+       test -n "$outputname" && ${rm}r "$tmpdir"
+       ;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+
+      $show "$install_prog $file $oldlib"
+      $run eval "$install_prog \$file \$oldlib" || exit $?
+
+      if test -n "$stripme" && test -n "$old_striplib"; then
+       $show "$old_striplib $oldlib"
+       $run eval "$old_striplib $oldlib" || exit $?
+      fi
+
+      # Do each command in the postinstall commands.
+      cmds=$old_postinstall_cmds
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+       IFS="$save_ifs"
+       eval cmd=\"$cmd\"
+       $show "$cmd"
+       $run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+    done
+
+    if test -n "$future_libdirs"; then
+      $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+    fi
+
+    if test -n "$current_libdirs"; then
+      # Maybe just do a dry run.
+      test -n "$run" && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+    else
+      exit $EXIT_SUCCESS
+    fi
+    ;;
+
+  # libtool finish mode
+  finish)
+    modename="$modename: finish"
+    libdirs="$nonopt"
+    admincmds=
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for dir
+      do
+       libdirs="$libdirs $dir"
+      done
+
+      for libdir in $libdirs; do
+       if test -n "$finish_cmds"; then
+         # Do each command in the finish commands.
+         cmds=$finish_cmds
+         save_ifs="$IFS"; IFS='~'
+         for cmd in $cmds; do
+           IFS="$save_ifs"
+           eval cmd=\"$cmd\"
+           $show "$cmd"
+           $run eval "$cmd" || admincmds="$admincmds
+       $cmd"
+         done
+         IFS="$save_ifs"
+       fi
+       if test -n "$finish_eval"; then
+         # Do the single finish_eval.
+         eval cmds=\"$finish_eval\"
+         $run eval "$cmds" || admincmds="$admincmds
+       $cmds"
+       fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    test "$show" = : && exit $EXIT_SUCCESS
+
+    $echo "X----------------------------------------------------------------------" | $Xsed
+    $echo "Libraries have been installed in:"
+    for libdir in $libdirs; do
+      $echo "   $libdir"
+    done
+    $echo
+    $echo "If you ever happen to want to link against installed libraries"
+    $echo "in a given directory, LIBDIR, you must either use libtool, and"
+    $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+    $echo "flag during linking and do at least one of the following:"
+    if test -n "$shlibpath_var"; then
+      $echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+      $echo "     during execution"
+    fi
+    if test -n "$runpath_var"; then
+      $echo "   - add LIBDIR to the \`$runpath_var' environment variable"
+      $echo "     during linking"
+    fi
+    if test -n "$hardcode_libdir_flag_spec"; then
+      libdir=LIBDIR
+      eval flag=\"$hardcode_libdir_flag_spec\"
+
+      $echo "   - use the \`$flag' linker flag"
+    fi
+    if test -n "$admincmds"; then
+      $echo "   - have your system administrator run these commands:$admincmds"
+    fi
+    if test -f /etc/ld.so.conf; then
+      $echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+    fi
+    $echo
+    $echo "See any operating system documentation about shared libraries for"
+    $echo "more information, such as the ld(1) and ld.so(8) manual pages."
+    $echo "X----------------------------------------------------------------------" | $Xsed
+    exit $EXIT_SUCCESS
+    ;;
+
+  # libtool execute mode
+  execute)
+    modename="$modename: execute"
+
+    # The first argument is the command name.
+    cmd="$nonopt"
+    if test -z "$cmd"; then
+      $echo "$modename: you must specify a COMMAND" 1>&2
+      $echo "$help"
+      exit $EXIT_FAILURE
+    fi
+
+    # Handle -dlopen flags immediately.
+    for file in $execute_dlfiles; do
+      if test ! -f "$file"; then
+       $echo "$modename: \`$file' is not a file" 1>&2
+       $echo "$help" 1>&2
+       exit $EXIT_FAILURE
+      fi
+
+      dir=
+      case $file in
+      *.la)
+       # Check to see that this really is a libtool archive.
+       if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+       else
+         $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+         $echo "$help" 1>&2
+         exit $EXIT_FAILURE
+       fi
+
+       # Read the libtool library.
+       dlname=
+       library_names=
+
+       # If there is no directory component, then add one.
+       case $file in
+       */* | *\\*) . $file ;;
+       *) . ./$file ;;
+       esac
+
+       # Skip this library if it cannot be dlopened.
+       if test -z "$dlname"; then
+         # Warn if it was a shared library.
+         test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+         continue
+       fi
+
+       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+       test "X$dir" = "X$file" && dir=.
+
+       if test -f "$dir/$objdir/$dlname"; then
+         dir="$dir/$objdir"
+       else
+         if test ! -f "$dir/$dlname"; then
+           $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+           exit $EXIT_FAILURE
+         fi
+       fi
+       ;;
+
+      *.lo)
+       # Just add the directory containing the .lo file.
+       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+       test "X$dir" = "X$file" && dir=.
+       ;;
+
+      *)
+       $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+       continue
+       ;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval "test -z \"\$$shlibpath_var\""; then
+       eval "$shlibpath_var=\"\$dir\""
+      else
+       eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -*) ;;
+      *)
+       # Do a test to see if this is really a libtool program.
+       if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+         # If there is no directory component, then add one.
+         case $file in
+         */* | *\\*) . $file ;;
+         *) . ./$file ;;
+         esac
+
+         # Transform arg to wrapped name.
+         file="$progdir/$program"
+       fi
+       ;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+      args="$args \"$file\""
+    done
+
+    if test -z "$run"; then
+      if test -n "$shlibpath_var"; then
+       # Export the shlibpath_var.
+       eval "export $shlibpath_var"
+      fi
+
+      # Restore saved environment variables
+      for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+      do
+       eval "if test \"\${save_$lt_var+set}\" = set; then
+               $lt_var=\$save_$lt_var; export $lt_var
+             fi"
+      done
+
+      # Now prepare to actually exec the command.
+      exec_cmd="\$cmd$args"
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+       eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+       $echo "export $shlibpath_var"
+      fi
+      $echo "$cmd$args"
+      exit $EXIT_SUCCESS
+    fi
+    ;;
+
+  # libtool clean and uninstall mode
+  clean | uninstall)
+    modename="$modename: $mode"
+    rm="$nonopt"
+    files=
+    rmforce=
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    for arg
+    do
+      case $arg in
+      -f) rm="$rm $arg"; rmforce=yes ;;
+      -*) rm="$rm $arg" ;;
+      *) files="$files $arg" ;;
+      esac
+    done
+
+    if test -z "$rm"; then
+      $echo "$modename: you must specify an RM program" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    rmdirs=
+
+    origobjdir="$objdir"
+    for file in $files; do
+      dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+      if test "X$dir" = "X$file"; then
+       dir=.
+       objdir="$origobjdir"
+      else
+       objdir="$dir/$origobjdir"
+      fi
+      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+      test "$mode" = uninstall && objdir="$dir"
+
+      # Remember objdir for removal later, being careful to avoid duplicates
+      if test "$mode" = clean; then
+       case " $rmdirs " in
+         *" $objdir "*) ;;
+         *) rmdirs="$rmdirs $objdir" ;;
+       esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if (test -L "$file") >/dev/null 2>&1 \
+       || (test -h "$file") >/dev/null 2>&1 \
+       || test -f "$file"; then
+       :
+      elif test -d "$file"; then
+       exit_status=1
+       continue
+      elif test "$rmforce" = yes; then
+       continue
+      fi
+
+      rmfiles="$file"
+
+      case $name in
+      *.la)
+       # Possibly a libtool archive, so verify it.
+       if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+         . $dir/$name
+
+         # Delete the libtool libraries and symlinks.
+         for n in $library_names; do
+           rmfiles="$rmfiles $objdir/$n"
+         done
+         test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+         case "$mode" in
+         clean)
+           case "  $library_names " in
+           # "  " in the beginning catches empty $dlname
+           *" $dlname "*) ;;
+           *) rmfiles="$rmfiles $objdir/$dlname" ;;
+           esac
+            test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+           ;;
+         uninstall)
+           if test -n "$library_names"; then
+             # Do each command in the postuninstall commands.
+             cmds=$postuninstall_cmds
+             save_ifs="$IFS"; IFS='~'
+             for cmd in $cmds; do
+               IFS="$save_ifs"
+               eval cmd=\"$cmd\"
+               $show "$cmd"
+               $run eval "$cmd"
+               if test "$?" -ne 0 && test "$rmforce" != yes; then
+                 exit_status=1
+               fi
+             done
+             IFS="$save_ifs"
+           fi
+
+           if test -n "$old_library"; then
+             # Do each command in the old_postuninstall commands.
+             cmds=$old_postuninstall_cmds
+             save_ifs="$IFS"; IFS='~'
+             for cmd in $cmds; do
+               IFS="$save_ifs"
+               eval cmd=\"$cmd\"
+               $show "$cmd"
+               $run eval "$cmd"
+               if test "$?" -ne 0 && test "$rmforce" != yes; then
+                 exit_status=1
+               fi
+             done
+             IFS="$save_ifs"
+           fi
+           # FIXME: should reinstall the best remaining shared library.
+           ;;
+         esac
+       fi
+       ;;
+
+      *.lo)
+       # Possibly a libtool object, so verify it.
+       if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+
+         # Read the .lo file
+         . $dir/$name
+
+         # Add PIC object to the list of files to remove.
+         if test -n "$pic_object" \
+            && test "$pic_object" != none; then
+           rmfiles="$rmfiles $dir/$pic_object"
+         fi
+
+         # Add non-PIC object to the list of files to remove.
+         if test -n "$non_pic_object" \
+            && test "$non_pic_object" != none; then
+           rmfiles="$rmfiles $dir/$non_pic_object"
+         fi
+       fi
+       ;;
+
+      *)
+       if test "$mode" = clean ; then
+         noexename=$name
+         case $file in
+         *.exe)
+           file=`$echo $file|${SED} 's,.exe$,,'`
+           noexename=`$echo $name|${SED} 's,.exe$,,'`
+           # $file with .exe has already been added to rmfiles,
+           # add $file without .exe
+           rmfiles="$rmfiles $file"
+           ;;
+         esac
+         # Do a test to see if this is a libtool program.
+         if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+           relink_command=
+           . $dir/$noexename
+
+           # note $name still contains .exe if it was in $file originally
+           # as does the version of $file that was added into $rmfiles
+           rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+           if test "$fast_install" = yes && test -n "$relink_command"; then
+             rmfiles="$rmfiles $objdir/lt-$name"
+           fi
+           if test "X$noexename" != "X$name" ; then
+             rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+           fi
+         fi
+       fi
+       ;;
+      esac
+      $show "$rm $rmfiles"
+      $run $rm $rmfiles || exit_status=1
+    done
+    objdir="$origobjdir"
+
+    # Try to remove the ${objdir}s in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+       $show "rmdir $dir"
+       $run rmdir $dir >/dev/null 2>&1
+      fi
+    done
+
+    exit $exit_status
+    ;;
+
+  "")
+    $echo "$modename: you must specify a MODE" 1>&2
+    $echo "$generic_help" 1>&2
+    exit $EXIT_FAILURE
+    ;;
+  esac
+
+  if test -z "$exec_cmd"; then
+    $echo "$modename: invalid operation mode \`$mode'" 1>&2
+    $echo "$generic_help" 1>&2
+    exit $EXIT_FAILURE
+  fi
+fi # test -z "$show_help"
+
+if test -n "$exec_cmd"; then
+  eval exec $exec_cmd
+  exit $EXIT_FAILURE
+fi
+
+# We need to display help for each of the modes.
+case $mode in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+    --config          show all configuration variables
+    --debug           enable verbose shell tracing
+-n, --dry-run         display commands without modifying any files
+    --features        display basic configuration information and exit
+    --finish          same as \`--mode=finish'
+    --help            display this help message and exit
+    --mode=MODE       use operation mode MODE [default=inferred from MODE-ARGS]
+    --quiet           same as \`--silent'
+    --silent          don't print informational messages
+    --tag=TAG         use configuration variables from tag TAG
+    --version         print version information
+
+MODE must be one of the following:
+
+      clean           remove files from the build directory
+      compile         compile a source file into a libtool object
+      execute         automatically set library path, then run a program
+      finish          complete the installation of libtool libraries
+      install         install libraries or executables
+      link            create a library or an executable
+      uninstall       remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE.  Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE.
+
+Report bugs to <bug-libtool@gnu.org>."
+  exit $EXIT_SUCCESS
+  ;;
+
+clean)
+  $echo \
+"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+  ;;
+
+compile)
+  $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -prefer-pic       try to building PIC objects only
+  -prefer-non-pic   try to building non-PIC objects only
+  -static           always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+  ;;
+
+execute)
+  $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+  ;;
+
+finish)
+  $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+  ;;
+
+install)
+  $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+  ;;
+
+link)
+  $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+                    try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+                    try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  Use a list of object files found in FILE to specify objects
+  -precious-files-regex REGEX
+                    don't remove output files matching REGEX
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -static           do not do any dynamic linking of uninstalled libtool libraries
+  -static-libtool-libs
+                    do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+                    specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+  ;;
+
+uninstall)
+  $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+  ;;
+
+*)
+  $echo "$modename: invalid operation mode \`$mode'" 1>&2
+  $echo "$help" 1>&2
+  exit $EXIT_FAILURE
+  ;;
+esac
+
+$echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit $?
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+disable_libs=shared
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+disable_libs=static
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/libltdl/missing b/libltdl/missing
new file mode 100755 (executable)
index 0000000..894e786
--- /dev/null
@@ -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:
diff --git a/libltdl/mkinstalldirs b/libltdl/mkinstalldirs
new file mode 100755 (executable)
index 0000000..ef7e16f
--- /dev/null
@@ -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:
diff --git a/libltdl/stamp-h1 b/libltdl/stamp-h1
new file mode 100644 (file)
index 0000000..4547fe1
--- /dev/null
@@ -0,0 +1 @@
+timestamp for config.h
diff --git a/pulseaudio-text.svg b/pulseaudio-text.svg
new file mode 100644 (file)
index 0000000..0e12613
--- /dev/null
@@ -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>
index 93f331d6bd0709755896d6bec5927b5641bf7ba0..e17e5ece42c02aca740b50e1b992be5e3224bcb3 100644 (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
index f92db74394b1e4c29be7461358429b219ce42e60..5b4008a58d8bd043d9429d1f5c90ae4c1be5c4d4 100644 (file)
 #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;
     }
 
index dc757c9c7763518733f96f4344ef4b12ea47c0ce..6b7b267120ad58ce9448105e81dd65f0e5a536f8 100644 (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");
index d4ac1d869d013506190352734a2d3cf4316c8227..ab212129e45ae7f62a6c5b60d7e14b9966e74dc8 100644 (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;
     }
 }
index 8cab327f83c285bb79f9f1189443f886052aa6db..920e3717306d7e98516e220966b781a2aa2a5927 100644 (file)
@@ -29,7 +29,6 @@
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 #include <unistd.h>
 
 #include <pulse/xmalloc.h>
 #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);
index 4843a610ea80f2a1fdcca605e19eb7024b84d01e..4d37861dba0c28c46b1e0ffd605e9845473ff70c 100644 (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 */
index 29b22a42c69e8a850bf01d3b88363d24278e0f36..2132bf3d0f98e9e41301fb9f364d17630962c692 100644 (file)
 ; 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
index af2a67893e88c84a8c19b700226dd8478334e1df..597993c4704a00e30fc0f20e5c1f941f5d788757 100755 (executable)
@@ -1,5 +1,4 @@
-#!@PA_BINARY@ -nF 
-
+#!@PA_BINARY@ -nF
 #
 # This file is part of PulseAudio.
 #
 # along with PulseAudio; if not, write to the Free Software Foundation,
 # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 
+.nofail
+
+### 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
 
-### Load audio drivers statically
+.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
 #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
index 6743622ac645de4620dc3c43a7bbe139aed0f1f4..ad7fab20f73cded8a415e379aca029933b36efd0 100644 (file)
 
 #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;
 
diff --git a/src/daemon/ltdl-bind-now.c b/src/daemon/ltdl-bind-now.c
new file mode 100644 (file)
index 0000000..6025c6e
--- /dev/null
@@ -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;
+}
+
diff --git a/src/daemon/ltdl-bind-now.h b/src/daemon/ltdl-bind-now.h
new file mode 100644 (file)
index 0000000..e19c7bc
--- /dev/null
@@ -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
+
index 91cc3a2f9d4db6b61fe34b7d4189abc6e8444587..6c9f662775aeea7f9c6e0cbb4c115ef276a88305 100644 (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>
 #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>
 #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;
-
-    r = pa_signal_init(pa_mainloop_get_api(mainloop));
-    assert(r == 0);
+    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;
+
+    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;
 }
diff --git a/src/daemon/pulseaudio-module-xsmp.desktop b/src/daemon/pulseaudio-module-xsmp.desktop
new file mode 100644 (file)
index 0000000..fa719a7
--- /dev/null
@@ -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=
index 40be53110860585a9cc54cf3db2964b04e424e33..906de58d5518e794265f4b30eeef1ab4bc7858dd 100644 (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);
-
-    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);
+    pa_assert(i != fdl->num_fds);
 
-    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);
 
index ea6c7e1df3870212e96be22c75752d35c2530785..6f1f927e2322c7970f402cbabc96167801935af7 100644 (file)
 
 #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);
index 48a45174650aaf0cc8b01d1d47234cd9b02c8fce..fc1e91ea8df10cc7981a7ac827d5adbd0304185b 100644 (file)
 #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,218 +134,195 @@ 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;
+
+    pa_assert(timeout);
+    pa_assert(c);
 
-    /* free the event */
-    if (NULL != ev)
+    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;
 
-    /* already disconnected, just free */
-    pa_property_remove(c->core, c->property_name);
-    c->core->mainloop->defer_free(c->dispatch_event);
-    dbus_connection_unref(c->connection);
-    pa_xfree(c);
-}
+    pa_assert(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);
 }
 
-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);
+static pa_dbus_connection* pa_dbus_connection_new(pa_core* c, DBusConnection *conn, const char* name) {
+    pa_dbus_connection *pconn;
 
-    pconn->refcount = 1;
+    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,
-                                                   (void*) 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)
-{
-    assert(c && c->connection);
+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)
-{
-    assert(c);
+void pa_dbus_connection_unref(pa_dbus_connection *c) {
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) > 0);
 
-    /* non-zero refcount, still outstanding refs */
-    if (--(c->refcount))
+    if (PA_REFCNT_DEC(c) > 0)
         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));
+         /* 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);
+
+    /* already disconnected, just free */
+    pa_property_remove(c->core, c->property_name);
+    c->core->mainloop->defer_free(c->dispatch_event);
+    dbus_connection_unref(c->connection);
+    pa_xfree(c);
 }
 
-pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *c)
-{
-    assert(c);
+pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *c) {
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) > 0);
 
-    ++(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;
index 3483b8451b84051c9bd2388a5a834cb469cca713..abd132875e8c6b75b53cb9700ae479d826e6529e 100644 (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);
index cbe17d200d58d815dc785231a2378d9a6d38717d..1c8866de2bd7cdb67b5a202644b7a7ab7563c14c 100644 (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 {
+
+#endif
+
+            max_fd = 1024;
 
 #ifdef HAVE_SYS_RESOURCE_H
-        {
-            struct rlimit r;
-            if (getrlimit(RLIMIT_NOFILE, &r) == 0)
-                max_fd = r.rlim_max;
-        }
+            {
+                struct rlimit r;
+                if (getrlimit(RLIMIT_NOFILE, &r) == 0)
+                    max_fd = r.rlim_max;
+            }
 #endif
 
-        for (i = 3; i < max_fd; i++)
-            close(i);
+            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);
diff --git a/src/modules/ladspa.h b/src/modules/ladspa.h
new file mode 100644 (file)
index 0000000..b1a9c4e
--- /dev/null
@@ -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 */
index 3d9f757747dd63cc5f28e584ff59107db522f818..a09247fea08bb83ff888b75a18fa3a1ebdeac446 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdio.h>
 
-#ifdef HAVE_SYS_POLL_H
-#include <sys/poll.h>
-#else
-#include "poll.h"
-#endif
-
 #include <asoundlib.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/util.h>
 
 #include <pulsecore/core.h>
 #include <pulsecore/module.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/sample-util.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/core-error.h>
+#include <pulsecore/thread-mq.h>
+#include <pulsecore/rtpoll.h>
 
 #include "alsa-util.h"
 #include "module-alsa-sink-symdef.h"
@@ -62,20 +61,38 @@ PA_MODULE_USAGE(
         "rate=<sample rate> "
         "fragments=<number of fragments> "
         "fragment_size=<fragment size> "
-        "channel_map=<channel map>")
+        "channel_map=<channel map> "
+        "mmap=<enable memory mapping?>")
+
+#define DEFAULT_DEVICE "default"
 
 struct userdata {
+    pa_core *core;
+    pa_module *module;
+    pa_sink *sink;
+
+    pa_thread *thread;
+    pa_thread_mq thread_mq;
+    pa_rtpoll *rtpoll;
+
     snd_pcm_t *pcm_handle;
+
+    pa_alsa_fdlist *mixer_fdl;
     snd_mixer_t *mixer_handle;
     snd_mixer_elem_t *mixer_elem;
-    pa_sink *sink;
-    struct pa_alsa_fdlist *pcm_fdl;
-    struct pa_alsa_fdlist *mixer_fdl;
     long hw_volume_max, hw_volume_min;
 
-    size_t frame_size, fragment_size;
-    pa_memchunk memchunk, silence;
-    pa_module *module;
+    size_t frame_size, fragment_size, hwbuf_size;
+    unsigned nfragments;
+    pa_memchunk memchunk;
+
+    char *device_name;
+
+    int use_mmap;
+
+    int first;
+
+    pa_rtpoll_item *alsa_rtpoll_item;
 };
 
 static const char* const valid_modargs[] = {
@@ -87,260 +104,440 @@ static const char* const valid_modargs[] = {
     "fragments",
     "fragment_size",
     "channel_map",
+    "mmap",
     NULL
 };
 
-#define DEFAULT_DEVICE "default"
+static int mmap_write(struct userdata *u) {
+    int work_done = 0;
 
-static void update_usage(struct userdata *u) {
-    pa_module_set_used(u->module, u->sink ? pa_sink_used_by(u->sink) : 0);
-}
+    pa_assert(u);
+    pa_sink_assert_ref(u->sink);
 
-static void clear_up(struct userdata *u) {
-    assert(u);
+    for (;;) {
+        pa_memchunk chunk;
+        void *p;
+        snd_pcm_sframes_t n;
+        int err;
+        const snd_pcm_channel_area_t *areas;
+        snd_pcm_uframes_t offset, frames;
+
+        if ((n = snd_pcm_avail_update(u->pcm_handle)) < 0) {
+
+            if (n == -EPIPE) {
+                pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
+                u->first = 1;
+            }
 
-    if (u->sink) {
-        pa_sink_disconnect(u->sink);
-        pa_sink_unref(u->sink);
-        u->sink = NULL;
-    }
+            if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0)
+                continue;
 
-    if (u->pcm_fdl)
-        pa_alsa_fdlist_free(u->pcm_fdl);
-    if (u->mixer_fdl)
-        pa_alsa_fdlist_free(u->mixer_fdl);
+            if (err == -EAGAIN)
+                return work_done;
 
-    u->pcm_fdl = u->mixer_fdl = NULL;
+            pa_log("snd_pcm_avail_update: %s", snd_strerror(err));
+            return -1;
+        }
 
-    if (u->mixer_handle) {
-        snd_mixer_close(u->mixer_handle);
-        u->mixer_handle = NULL;
-    }
+/*         pa_log("Got request for %i samples", (int) n); */
 
-    if (u->pcm_handle) {
-        snd_pcm_drop(u->pcm_handle);
-        snd_pcm_close(u->pcm_handle);
-        u->pcm_handle = NULL;
-    }
-}
+        if (n <= 0)
+            return work_done;
 
-static int xrun_recovery(struct userdata *u) {
-    int ret;
-    assert(u);
+        frames = n;
 
-    pa_log_info("*** ALSA-XRUN (playback) ***");
+        if ((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0) {
 
-    if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) {
-        pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret));
+            if (err == -EPIPE) {
+                pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
+                u->first = 1;
+            }
 
-        clear_up(u);
-        pa_module_unload_request(u->module);
-        return -1;
-    }
+            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
+                continue;
 
-    return ret;
-}
+            if (err == -EAGAIN)
+                return work_done;
 
-static int suspend_recovery(struct userdata *u) {
-    int ret;
-    assert(u);
+            pa_log("Failed to write data to DSP: %s", snd_strerror(err));
+            return -1;
+        }
 
-    pa_log_info("*** ALSA-SUSPEND (playback) ***");
+        /* Check these are multiples of 8 bit */
+        pa_assert((areas[0].first & 7) == 0);
+        pa_assert((areas[0].step & 7)== 0);
 
-    if ((ret = snd_pcm_resume(u->pcm_handle)) < 0) {
-        if (ret == -EAGAIN)
-            return -1;
+        /* We assume a single interleaved memory buffer */
+        pa_assert((areas[0].first >> 3) == 0);
+        pa_assert((areas[0].step >> 3) == u->frame_size);
 
-        if (ret != -ENOSYS)
-            pa_log("snd_pcm_resume() failed: %s", snd_strerror(-ret));
-        else {
-            if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0)
-                pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret));
-        }
+        p = (uint8_t*) areas[0].addr + (offset * u->frame_size);
+
+        chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, 1);
+        chunk.length = pa_memblock_get_length(chunk.memblock);
+        chunk.index = 0;
+
+        pa_sink_render_into_full(u->sink, &chunk);
+
+        /* FIXME: Maybe we can do something to keep this memory block
+         * a little bit longer around? */
+        pa_memblock_unref_fixed(chunk.memblock);
+
+        if ((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0) {
+
+            if (err == -EPIPE) {
+                pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!");
+                u->first = 1;
+            }
+
+            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
+                continue;
 
-        if (ret < 0) {
-            clear_up(u);
-            pa_module_unload_request(u->module);
+            if (err == -EAGAIN)
+                return work_done;
+
+            pa_log("Failed to write data to DSP: %s", snd_strerror(err));
             return -1;
         }
-    }
 
-    return ret;
+        work_done = 1;
+
+        if (frames >= (snd_pcm_uframes_t) n)
+            return work_done;
+
+/*         pa_log("wrote %i samples", (int) frames); */
+    }
 }
 
-static void do_write(struct userdata *u) {
-    assert(u);
+static int unix_write(struct userdata *u) {
+    snd_pcm_status_t *status;
+    int work_done = 0;
 
-    update_usage(u);
+    snd_pcm_status_alloca(&status);
+
+    pa_assert(u);
+    pa_sink_assert_ref(u->sink);
 
     for (;;) {
-        pa_memchunk *memchunk = NULL;
-        snd_pcm_sframes_t frames;
-
-        if (u->memchunk.memblock)
-            memchunk = &u->memchunk;
-        else {
-            if (pa_sink_render(u->sink, u->fragment_size, &u->memchunk) < 0)
-                memchunk = &u->silence;
-            else
-                memchunk = &u->memchunk;
+        void *p;
+        snd_pcm_sframes_t t;
+        ssize_t l;
+        int err;
+
+        if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) {
+            pa_log("Failed to query DSP status data: %s", snd_strerror(err));
+            return -1;
         }
 
-        assert(memchunk->memblock);
-        assert(memchunk->memblock->data);
-        assert(memchunk->length);
-        assert(memchunk->memblock->length);
-        assert((memchunk->length % u->frame_size) == 0);
+        if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size)
+            pa_log_debug("Buffer underrun!");
 
-        if ((frames = snd_pcm_writei(u->pcm_handle, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length / u->frame_size)) < 0) {
-            if (frames == -EAGAIN)
-                return;
+        l = snd_pcm_status_get_avail(status) * u->frame_size;
 
-            if (frames == -EPIPE) {
-                if (xrun_recovery(u) < 0)
-                    return;
+/*         pa_log("%u bytes to write", l); */
 
-                continue;
-            }
+        if (l <= 0)
+            return work_done;
+
+        if (u->memchunk.length <= 0)
+            pa_sink_render(u->sink, l, &u->memchunk);
+
+        pa_assert(u->memchunk.length > 0);
 
-            if (frames == -ESTRPIPE) {
-                if (suspend_recovery(u) < 0)
-                    return;
+        p = pa_memblock_acquire(u->memchunk.memblock);
+        t = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, u->memchunk.length / u->frame_size);
+        pa_memblock_release(u->memchunk.memblock);
 
+/*         pa_log("wrote %i bytes of %u (%u)", t*u->frame_size, u->memchunk.length, l); */
+
+        pa_assert(t != 0);
+
+        if (t < 0) {
+
+            if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)
                 continue;
+
+            if (t == -EAGAIN) {
+                pa_log_debug("EAGAIN");
+                return work_done;
+            } else {
+                pa_log("Failed to write data to DSP: %s", snd_strerror(t));
+                return -1;
             }
+        }
 
-            pa_log("snd_pcm_writei() failed: %s", snd_strerror(-frames));
+        u->memchunk.index += t * u->frame_size;
+        u->memchunk.length -= t * u->frame_size;
 
-            clear_up(u);
-            pa_module_unload_request(u->module);
-            return;
+        if (u->memchunk.length <= 0) {
+            pa_memblock_unref(u->memchunk.memblock);
+            pa_memchunk_reset(&u->memchunk);
         }
 
-        if (memchunk == &u->memchunk) {
-            size_t l = frames * u->frame_size;
-            memchunk->index += l;
-            memchunk->length -= l;
+        work_done = 1;
 
-            if (memchunk->length == 0) {
-                pa_memblock_unref(memchunk->memblock);
-                memchunk->memblock = NULL;
-                memchunk->index = memchunk->length = 0;
-            }
-        }
+        if (t * u->frame_size >= (unsigned) l)
+            return work_done;
+    }
+}
 
-        break;
+static pa_usec_t sink_get_latency(struct userdata *u) {
+    pa_usec_t r = 0;
+    snd_pcm_status_t *status;
+    snd_pcm_sframes_t frames = 0;
+    int err;
+
+    snd_pcm_status_alloca(&status);
+
+    pa_assert(u);
+    pa_assert(u->pcm_handle);
+
+    if ((err = snd_pcm_status(u->pcm_handle, status)) < 0)
+        pa_log("Failed to get delay: %s", snd_strerror(err));
+    else
+        frames = snd_pcm_status_get_delay(status);
+
+    if (frames > 0)
+        r = pa_bytes_to_usec(frames * u->frame_size, &u->sink->sample_spec);
+
+    if (u->memchunk.memblock)
+        r += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec);
+
+    return r;
+}
+
+static int build_pollfd(struct userdata *u) {
+    int err;
+    struct pollfd *pollfd;
+    int n;
+
+    pa_assert(u);
+    pa_assert(u->pcm_handle);
+
+    if ((n = snd_pcm_poll_descriptors_count(u->pcm_handle)) < 0) {
+        pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(n));
+        return -1;
+    }
+
+    if (u->alsa_rtpoll_item)
+        pa_rtpoll_item_free(u->alsa_rtpoll_item);
+
+    u->alsa_rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, n);
+    pollfd = pa_rtpoll_item_get_pollfd(u->alsa_rtpoll_item, NULL);
+
+    if ((err = snd_pcm_poll_descriptors(u->pcm_handle, pollfd, n)) < 0) {
+        pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err));
+        return -1;
     }
+
+    return 0;
 }
 
-static void fdl_callback(void *userdata) {
-    struct userdata *u = userdata;
-    assert(u);
+static int suspend(struct userdata *u) {
+    pa_assert(u);
+    pa_assert(u->pcm_handle);
 
-    if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN)
-        if (xrun_recovery(u) < 0)
-            return;
+    /* Let's suspend */
+    snd_pcm_drain(u->pcm_handle);
+    snd_pcm_close(u->pcm_handle);
+    u->pcm_handle = NULL;
 
-    if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_SUSPENDED)
-        if (suspend_recovery(u) < 0)
-            return;
+    if (u->alsa_rtpoll_item) {
+        pa_rtpoll_item_free(u->alsa_rtpoll_item);
+        u->alsa_rtpoll_item = NULL;
+    }
+
+    pa_log_info("Device suspended...");
 
-    do_write(u);
+    return 0;
 }
 
-static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
-    struct userdata *u = snd_mixer_elem_get_callback_private(elem);
+static int unsuspend(struct userdata *u) {
+    pa_sample_spec ss;
+    int err, b;
+    unsigned nfrags;
+    snd_pcm_uframes_t period_size;
 
-    assert(u && u->mixer_handle);
+    pa_assert(u);
+    pa_assert(!u->pcm_handle);
 
-    if (mask == SND_CTL_EVENT_MASK_REMOVE)
-        return 0;
+    pa_log_info("Trying resume...");
 
-    if (mask & SND_CTL_EVENT_MASK_VALUE) {
-        if (u->sink->get_hw_volume)
-            u->sink->get_hw_volume(u->sink);
-        if (u->sink->get_hw_mute)
-            u->sink->get_hw_mute(u->sink);
-        pa_subscription_post(u->sink->core,
-            PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE,
-            u->sink->index);
+    snd_config_update_free_global();
+    if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
+        pa_log("Error opening PCM device %s: %s", u->device_name, snd_strerror(err));
+        goto fail;
+    }
+
+    ss = u->sink->sample_spec;
+    nfrags = u->nfragments;
+    period_size = u->fragment_size / u->frame_size;
+    b = u->use_mmap;
+
+    if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) {
+        pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
+        goto fail;
+    }
+
+    if (b != u->use_mmap) {
+        pa_log_warn("Resume failed, couldn't get original access mode.");
+        goto fail;
+    }
+
+    if (!pa_sample_spec_equal(&ss, &u->sink->sample_spec)) {
+        pa_log_warn("Resume failed, couldn't restore original sample settings.");
+        goto fail;
+    }
+
+    if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
+        pa_log_warn("Resume failed, couldn't restore original fragment settings.");
+        goto fail;
+    }
+
+    if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) {
+        pa_log("Failed to set software parameters: %s", snd_strerror(err));
+        goto fail;
     }
 
+    if (build_pollfd(u) < 0)
+        goto fail;
+
+    /* FIXME: We need to reload the volume somehow */
+
+    u->first = 1;
+
+    pa_log_info("Resumed successfully...");
+
     return 0;
+
+fail:
+    if (u->pcm_handle) {
+        snd_pcm_close(u->pcm_handle);
+        u->pcm_handle = NULL;
+    }
+
+    return -1;
 }
 
-static pa_usec_t sink_get_latency_cb(pa_sink *s) {
-    pa_usec_t r = 0;
-    struct userdata *u = s->userdata;
-    snd_pcm_sframes_t frames;
-    int err;
+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;
 
-    assert(s && u && u->sink);
+    switch (code) {
 
-    if ((err = snd_pcm_delay(u->pcm_handle, &frames)) < 0) {
-        pa_log("failed to get delay: %s", snd_strerror(err));
-        s->get_latency = NULL;
-        return 0;
+        case PA_SINK_MESSAGE_GET_LATENCY: {
+            pa_usec_t r = 0;
+
+            if (u->pcm_handle)
+                r = sink_get_latency(u);
+
+            *((pa_usec_t*) data) = r;
+
+            return 0;
+        }
+
+        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));
+
+                    if (suspend(u) < 0)
+                        return -1;
+
+                    break;
+
+                case PA_SINK_IDLE:
+                case PA_SINK_RUNNING:
+
+                    if (u->sink->thread_info.state == PA_SINK_INIT) {
+                        if (build_pollfd(u) < 0)
+                            return -1;
+                    }
+
+                    if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
+                        if (unsuspend(u) < 0)
+                            return -1;
+                    }
+
+                    break;
+
+                case PA_SINK_UNLINKED:
+                case PA_SINK_INIT:
+                    ;
+            }
+
+            break;
     }
 
-    if (frames < 0)
-        frames = 0;
+    return pa_sink_process_msg(o, code, data, offset, chunk);
+}
 
-    r += pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec);
+static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
+    struct userdata *u = snd_mixer_elem_get_callback_private(elem);
 
-    if (u->memchunk.memblock)
-        r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec);
+    pa_assert(u);
+    pa_assert(u->mixer_handle);
 
-    return r;
+    if (mask == SND_CTL_EVENT_MASK_REMOVE)
+        return 0;
+
+    if (mask & SND_CTL_EVENT_MASK_VALUE) {
+        pa_sink_get_volume(u->sink);
+        pa_sink_get_mute(u->sink);
+    }
+
+    return 0;
 }
 
-static int sink_get_hw_volume_cb(pa_sink *s) {
+static int sink_get_volume_cb(pa_sink *s) {
     struct userdata *u = s->userdata;
     int err;
     int i;
 
-    assert(u);
-    assert(u->mixer_elem);
+    pa_assert(u);
+    pa_assert(u->mixer_elem);
 
-    for (i = 0; i < s->hw_volume.channels; i++) {
+    for (i = 0; i < s->sample_spec.channels; i++) {
         long set_vol, vol;
 
-        assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i));
+        pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i));
 
         if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, i, &vol)) < 0)
             goto fail;
 
-        set_vol = (long) roundf(((float) s->hw_volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
+        set_vol = (long) roundf(((float) s->volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
 
         /* Try to avoid superfluous volume changes */
         if (set_vol != vol)
-            s->hw_volume.values[i] = (pa_volume_t) roundf(((float) (vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
+            s->volume.values[i] = (pa_volume_t) roundf(((float) (vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
     }
 
     return 0;
 
 fail:
     pa_log_error("Unable to read volume: %s", snd_strerror(err));
-    s->get_hw_volume = NULL;
-    s->set_hw_volume = NULL;
+
+    s->get_volume = NULL;
+    s->set_volume = NULL;
     return -1;
 }
 
-static int sink_set_hw_volume_cb(pa_sink *s) {
+static int sink_set_volume_cb(pa_sink *s) {
     struct userdata *u = s->userdata;
     int err;
     int i;
-    pa_volume_t vol;
 
-    assert(u);
-    assert(u->mixer_elem);
+    pa_assert(u);
+    pa_assert(u->mixer_elem);
 
-    for (i = 0; i < s->hw_volume.channels; i++) {
+    for (i = 0; i < s->sample_spec.channels; i++) {
         long alsa_vol;
+        pa_volume_t vol;
 
-        assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i));
+        pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i));
 
-        vol = s->hw_volume.values[i];
+        vol = s->volume.values[i];
 
         if (vol > PA_VOLUME_NORM)
             vol = PA_VOLUME_NORM;
@@ -355,55 +552,166 @@ static int sink_set_hw_volume_cb(pa_sink *s) {
 
 fail:
     pa_log_error("Unable to set volume: %s", snd_strerror(err));
-    s->get_hw_volume = NULL;
-    s->set_hw_volume = NULL;
+
+    s->get_volume = NULL;
+    s->set_volume = NULL;
     return -1;
 }
 
-static int sink_get_hw_mute_cb(pa_sink *s) {
+static int sink_get_mute_cb(pa_sink *s) {
     struct userdata *u = s->userdata;
     int err, sw;
 
-    assert(u && u->mixer_elem);
+    pa_assert(u);
+    pa_assert(u->mixer_elem);
 
-    err = snd_mixer_selem_get_playback_switch(u->mixer_elem, 0, &sw);
-    if (err) {
+    if ((err = snd_mixer_selem_get_playback_switch(u->mixer_elem, 0, &sw)) < 0) {
         pa_log_error("Unable to get switch: %s", snd_strerror(err));
-        s->get_hw_mute = NULL;
-        s->set_hw_mute = NULL;
+
+        s->get_mute = NULL;
+        s->set_mute = NULL;
         return -1;
     }
 
-    s->hw_muted = !sw;
+    s->muted = !sw;
 
     return 0;
 }
 
-static int sink_set_hw_mute_cb(pa_sink *s) {
+static int sink_set_mute_cb(pa_sink *s) {
     struct userdata *u = s->userdata;
     int err;
 
-    assert(u && u->mixer_elem);
+    pa_assert(u);
+    pa_assert(u->mixer_elem);
 
-    err = snd_mixer_selem_set_playback_switch_all(u->mixer_elem, !s->hw_muted);
-    if (err) {
+    if ((err = snd_mixer_selem_set_playback_switch_all(u->mixer_elem, !s->muted)) < 0) {
         pa_log_error("Unable to set switch: %s", snd_strerror(err));
-        s->get_hw_mute = NULL;
-        s->set_hw_mute = NULL;
+
+        s->get_mute = NULL;
+        s->set_mute = NULL;
         return -1;
     }
 
     return 0;
 }
 
-int pa__init(pa_core *c, pa_module*m) {
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
+
+    pa_assert(u);
+
+    pa_log_debug("Thread starting up");
+
+    if (u->core->high_priority)
+        pa_make_realtime();
+
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
+
+    for (;;) {
+        int ret;
+
+        /* Render some data and write it to the dsp */
+        if (PA_SINK_OPENED(u->sink->thread_info.state)) {
+            int work_done = 0;
+
+            if (u->use_mmap) {
+                if ((work_done = mmap_write(u)) < 0)
+                    goto fail;
+            } else {
+                if ((work_done = unix_write(u)) < 0)
+                    goto fail;
+            }
+
+            if (work_done && u->first) {
+                pa_log_info("Starting playback.");
+                snd_pcm_start(u->pcm_handle);
+                u->first = 0;
+                continue;
+            }
+        }
+
+        /* Hmm, nothing to do. Let's sleep */
+        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
+            goto fail;
+
+        if (ret == 0)
+            goto finish;
+
+        /* Tell ALSA about this and process its response */
+        if (PA_SINK_OPENED(u->sink->thread_info.state)) {
+            struct pollfd *pollfd;
+            unsigned short revents = 0;
+            int err;
+            unsigned n;
+
+            pollfd = pa_rtpoll_item_get_pollfd(u->alsa_rtpoll_item, &n);
+
+            if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, pollfd, n, &revents)) < 0) {
+                pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err));
+                goto fail;
+            }
+
+            if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
+
+                if (revents & POLLERR)
+                    pa_log_warn("Got POLLERR from ALSA");
+                if (revents & POLLNVAL)
+                    pa_log_warn("Got POLLNVAL from ALSA");
+                if (revents & POLLHUP)
+                    pa_log_warn("Got POLLHUP from ALSA");
+
+                /* Try to recover from this error */
+
+                switch (snd_pcm_state(u->pcm_handle)) {
+
+                    case SND_PCM_STATE_XRUN:
+                        if ((err = snd_pcm_recover(u->pcm_handle, -EPIPE, 1)) != 0) {
+                            pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", snd_strerror(err));
+                            goto fail;
+                        }
+                        break;
+
+                    case SND_PCM_STATE_SUSPENDED:
+                        if ((err = snd_pcm_recover(u->pcm_handle, -ESTRPIPE, 1)) != 0) {
+                            pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", snd_strerror(err));
+                            goto fail;
+                        }
+                        break;
+
+                    default:
+
+                        snd_pcm_drop(u->pcm_handle);
+
+                        if ((err = snd_pcm_prepare(u->pcm_handle)) < 0) {
+                            pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", snd_strerror(err));
+                            goto fail;
+                        }
+                        break;
+                }
+            }
+        }
+    }
+
+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_module*m) {
+
     pa_modargs *ma = NULL;
-    int ret = -1;
     struct userdata *u = NULL;
-    const char *dev;
+    char *dev;
     pa_sample_spec ss;
     pa_channel_map map;
-    uint32_t periods, fragsize;
+    uint32_t nfrags, frag_size;
     snd_pcm_uframes_t period_size;
     size_t frame_size;
     snd_pcm_info_t *pcm_info = NULL;
@@ -412,48 +720,107 @@ int pa__init(pa_core *c, pa_module*m) {
     const char *name;
     char *name_buf = NULL;
     int namereg_fail;
+    int use_mmap = 1, b;
+
+    snd_pcm_info_alloca(&pcm_info);
+
+    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_ALSA) < 0) {
-        pa_log("failed to parse sample specification and channel map");
+        pa_log("Failed to parse sample specification and channel map");
         goto fail;
     }
 
     frame_size = pa_frame_size(&ss);
 
-    /* Fix latency to 100ms */
-    periods = 8;
-    fragsize = pa_bytes_per_second(&ss)/128;
+    nfrags = m->core->default_n_fragments;
+    frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*1000, &ss);
+    if (frag_size <= 0)
+        frag_size = frame_size;
+
+    if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0) {
+        pa_log("Failed to parse buffer metrics");
+        goto fail;
+    }
+    period_size = frag_size/frame_size;
 
-    if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) {
-        pa_log("failed to parse buffer metrics");
+    if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
+        pa_log("Failed to parse mmap argument.");
         goto fail;
     }
-    period_size = fragsize/frame_size;
 
     u = pa_xnew0(struct userdata, 1);
-    m->userdata = u;
+    u->core = m->core;
     u->module = m;
+    m->userdata = u;
+    u->use_mmap = use_mmap;
+    u->first = 1;
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
+    u->rtpoll = pa_rtpoll_new();
+    u->alsa_rtpoll_item = NULL;
+    pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
 
     snd_config_update_free_global();
-    if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
-        pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err));
-        goto fail;
+
+    dev = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE));
+
+    for (;;) {
+
+        if ((err = snd_pcm_open(&u->pcm_handle, dev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
+            pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err));
+            pa_xfree(dev);
+            goto fail;
+        }
+
+        b = use_mmap;
+        if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) {
+
+            if (err == -EPERM) {
+                /* Hmm, some hw is very exotic, so we retry with plughw, if hw didn't work */
+
+                if (pa_startswith(dev, "hw:")) {
+                    char *d = pa_sprintf_malloc("plughw:%s", dev+3);
+                    pa_log_debug("Opening the device as '%s' didn't work, retrying with '%s'.", dev, d);
+                    pa_xfree(dev);
+                    dev = d;
+
+                    snd_pcm_close(u->pcm_handle);
+                    u->pcm_handle = NULL;
+                    continue;
+                }
+            }
+
+            pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
+            pa_xfree(dev);
+            goto fail;
+        }
+
+        break;
     }
 
-    if ((err = snd_pcm_info_malloc(&pcm_info)) < 0 ||
-        (err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) {
+    u->device_name = dev;
+
+    if (use_mmap && !b) {
+        pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
+        u->use_mmap = use_mmap = b;
+    }
+
+    if (u->use_mmap)
+        pa_log_info("Successfully enabled mmap() mode.");
+
+    if ((err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) {
         pa_log("Error fetching PCM info: %s", snd_strerror(err));
         goto fail;
     }
 
-    if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size)) < 0) {
-        pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
+    if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) {
+        pa_log("Failed to set software parameters: %s", snd_strerror(err));
         goto fail;
     }
 
@@ -464,15 +831,16 @@ int pa__init(pa_core *c, pa_module*m) {
         /* Seems ALSA didn't like the channel number, so let's fix the channel map */
         pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA);
 
-    if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) {
-        pa_log("Error opening mixer: %s", snd_strerror(err));
-        goto fail;
-    }
+    if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0)
+        pa_log_warn("Error opening mixer: %s", snd_strerror(err));
+    else {
 
-    if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) ||
-        !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "PCM", "Master"))) {
-        snd_mixer_close(u->mixer_handle);
-        u->mixer_handle = NULL;
+        if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) ||
+            !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM"))) {
+
+            snd_mixer_close(u->mixer_handle);
+            u->mixer_handle = NULL;
+        }
     }
 
     if ((name = pa_modargs_get_value(ma, "sink_name", NULL)))
@@ -482,114 +850,146 @@ int pa__init(pa_core *c, pa_module*m) {
         namereg_fail = 0;
     }
 
-    if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &ss, &map))) {
+    u->sink = pa_sink_new(m->core, __FILE__, name, namereg_fail, &ss, &map);
+    pa_xfree(name_buf);
+
+    if (!u->sink) {
         pa_log("Failed to create sink object");
         goto fail;
     }
 
-    u->sink->is_hardware = 1;
-    u->sink->get_latency = sink_get_latency_cb;
+    u->sink->parent.process_msg = sink_process_msg;
+    u->sink->userdata = u;
+
+    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(
+                                    "ALSA PCM on %s (%s)%s",
+                                    dev,
+                                    snd_pcm_info_get_name(pcm_info),
+                                    use_mmap ? " via DMA" : ""));
+    pa_xfree(t);
+
+    u->sink->flags = PA_SINK_HARDWARE|PA_SINK_HW_VOLUME_CTRL|PA_SINK_LATENCY;
+
+    u->frame_size = frame_size;
+    u->fragment_size = frag_size = period_size * frame_size;
+    u->nfragments = nfrags;
+    u->hwbuf_size = u->fragment_size * nfrags;
+
+    pa_log_info("Using %u fragments of size %lu bytes.", nfrags, (long unsigned) u->fragment_size);
+
+    pa_memchunk_reset(&u->memchunk);
+
     if (u->mixer_handle) {
-        assert(u->mixer_elem);
+        /* Initialize mixer code */
+
+        pa_assert(u->mixer_elem);
+
         if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) {
             int i;
 
-            for (i = 0;i < ss.channels;i++) {
+            for (i = 0; i < ss.channels; i++)
                 if (!snd_mixer_selem_has_playback_channel(u->mixer_elem, i))
                     break;
-            }
 
             if (i == ss.channels) {
-                u->sink->get_hw_volume = sink_get_hw_volume_cb;
-                u->sink->set_hw_volume = sink_set_hw_volume_cb;
-                snd_mixer_selem_get_playback_volume_range(
-                    u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max);
-            }
+                pa_log_debug("ALSA device has separate volumes controls for all %u channels.", ss.channels);
+                u->sink->get_volume = sink_get_volume_cb;
+                u->sink->set_volume = sink_set_volume_cb;
+                snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max);
+            } else
+                pa_log_info("ALSA device lacks separate volumes controls for all %u channels (%u available), falling back to software volume control.", ss.channels, i+1);
         }
+
         if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) {
-            u->sink->get_hw_mute = sink_get_hw_mute_cb;
-            u->sink->set_hw_mute = sink_set_hw_mute_cb;
+            u->sink->get_mute = sink_get_mute_cb;
+            u->sink->set_mute = sink_set_mute_cb;
         }
-    }
-    u->sink->userdata = u;
-    pa_sink_set_owner(u->sink, m);
-    pa_sink_set_description(u->sink, t = pa_sprintf_malloc("ALSA PCM on %s (%s)", dev, snd_pcm_info_get_name(pcm_info)));
-    pa_xfree(t);
-
-    u->pcm_fdl = pa_alsa_fdlist_new();
-    assert(u->pcm_fdl);
-    if (pa_alsa_fdlist_init_pcm(u->pcm_fdl, u->pcm_handle, c->mainloop, fdl_callback, u) < 0) {
-        pa_log("failed to initialise file descriptor monitoring");
-        goto fail;
-    }
 
-    if (u->mixer_handle) {
         u->mixer_fdl = pa_alsa_fdlist_new();
-        assert(u->mixer_fdl);
-        if (pa_alsa_fdlist_init_mixer(u->mixer_fdl, u->mixer_handle, c->mainloop) < 0) {
+
+        if (pa_alsa_fdlist_set_mixer(u->mixer_fdl, u->mixer_handle, m->core->mainloop) < 0) {
             pa_log("failed to initialise file descriptor monitoring");
             goto fail;
         }
+
         snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback);
         snd_mixer_elem_set_callback_private(u->mixer_elem, u);
     } else
         u->mixer_fdl = NULL;
 
-    u->frame_size = frame_size;
-    u->fragment_size = period_size * frame_size;
-
-    pa_log_info("using %u fragments of size %lu bytes.", periods, (long unsigned)u->fragment_size);
-
-    u->silence.memblock = pa_memblock_new(c->mempool, u->silence.length = u->fragment_size);
-    assert(u->silence.memblock);
-    pa_silence_memblock(u->silence.memblock, &ss);
-    u->silence.index = 0;
-
-    u->memchunk.memblock = NULL;
-    u->memchunk.index = u->memchunk.length = 0;
-
-    ret = 0;
+    if (!(u->thread = pa_thread_new(thread_func, u))) {
+        pa_log("Failed to create thread.");
+        goto fail;
+    }
 
     /* Get initial mixer settings */
-    if (u->sink->get_hw_volume)
-        u->sink->get_hw_volume(u->sink);
-    if (u->sink->get_hw_mute)
-        u->sink->get_hw_mute(u->sink);
+    if (u->sink->get_volume)
+        u->sink->get_volume(u->sink);
+    if (u->sink->get_mute)
+        u->sink->get_mute(u->sink);
 
-finish:
-
-    pa_xfree(name_buf);
+    pa_sink_put(u->sink);
 
-     if (ma)
-         pa_modargs_free(ma);
+    pa_modargs_free(ma);
 
-    if (pcm_info)
-        snd_pcm_info_free(pcm_info);
-
-    return ret;
+    return 0;
 
 fail:
 
-    if (u)
-        pa__done(c, m);
+    if (ma)
+        pa_modargs_free(ma);
 
-    goto finish;
+    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;
 
-    clear_up(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->memchunk.memblock)
         pa_memblock_unref(u->memchunk.memblock);
-    if (u->silence.memblock)
-        pa_memblock_unref(u->silence.memblock);
 
+    if (u->alsa_rtpoll_item)
+        pa_rtpoll_item_free(u->alsa_rtpoll_item);
+
+    if (u->rtpoll)
+        pa_rtpoll_free(u->rtpoll);
+
+    if (u->mixer_fdl)
+        pa_alsa_fdlist_free(u->mixer_fdl);
+
+    if (u->mixer_handle)
+        snd_mixer_close(u->mixer_handle);
+
+    if (u->pcm_handle) {
+        snd_pcm_drop(u->pcm_handle);
+        snd_pcm_close(u->pcm_handle);
+    }
+
+    pa_xfree(u->device_name);
     pa_xfree(u);
-}
 
+    snd_config_update_free_global();
+}
index 4061d668c2ceaf5555e63d22fa1333ae571c1f7a..d840cac3090a873bb31f1c141183d4910ac25fa7 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdio.h>
 
-#ifdef HAVE_SYS_POLL_H
-#include <sys/poll.h>
-#else
-#include "poll.h"
-#endif
-
 #include <asoundlib.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/util.h>
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/core.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/sample-util.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/core-error.h>
+#include <pulsecore/thread-mq.h>
+#include <pulsecore/rtpoll.h>
 
 #include "alsa-util.h"
 #include "module-alsa-source-symdef.h"
@@ -63,20 +62,35 @@ PA_MODULE_USAGE(
         "rate=<sample rate> "
         "fragments=<number of fragments> "
         "fragment_size=<fragment size> "
-        "channel_map=<channel map>")
+        "channel_map=<channel map> "
+        "mmap=<enable memory mapping?>")
+
+#define DEFAULT_DEVICE "default"
 
 struct userdata {
+    pa_core *core;
+    pa_module *module;
+    pa_source *source;
+
+    pa_thread *thread;
+    pa_thread_mq thread_mq;
+    pa_rtpoll *rtpoll;
+
     snd_pcm_t *pcm_handle;
+
+    pa_alsa_fdlist *mixer_fdl;
     snd_mixer_t *mixer_handle;
     snd_mixer_elem_t *mixer_elem;
-    pa_source *source;
-    struct pa_alsa_fdlist *pcm_fdl;
-    struct pa_alsa_fdlist *mixer_fdl;
     long hw_volume_max, hw_volume_min;
 
-    size_t frame_size, fragment_size;
-    pa_memchunk memchunk;
-    pa_module *module;
+    size_t frame_size, fragment_size, hwbuf_size;
+    unsigned nfragments;
+
+    char *device_name;
+
+    int use_mmap;
+
+    pa_rtpoll_item *alsa_rtpoll_item;
 };
 
 static const char* const valid_modargs[] = {
@@ -88,257 +102,438 @@ static const char* const valid_modargs[] = {
     "fragments",
     "fragment_size",
     "channel_map",
+    "mmap",
     NULL
 };
 
-#define DEFAULT_DEVICE "default"
+static int mmap_read(struct userdata *u) {
+    int work_done = 0;
 
-static void update_usage(struct userdata *u) {
-   pa_module_set_used(u->module, u->source ? pa_source_used_by(u->source) : 0);
-}
+    pa_assert(u);
+    pa_source_assert_ref(u->source);
 
-static void clear_up(struct userdata *u) {
-    assert(u);
+    for (;;) {
+        snd_pcm_sframes_t n;
+        int err;
+        const snd_pcm_channel_area_t *areas;
+        snd_pcm_uframes_t offset, frames;
+        pa_memchunk chunk;
+        void *p;
 
-    if (u->source) {
-        pa_source_disconnect(u->source);
-        pa_source_unref(u->source);
-        u->source = NULL;
-    }
+        if ((n = snd_pcm_avail_update(u->pcm_handle)) < 0) {
 
-    if (u->pcm_fdl)
-        pa_alsa_fdlist_free(u->pcm_fdl);
-    if (u->mixer_fdl)
-        pa_alsa_fdlist_free(u->mixer_fdl);
+            if (n == -EPIPE)
+                pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
 
-    u->pcm_fdl = u->mixer_fdl = NULL;
+            if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0)
+                continue;
 
-    if (u->mixer_handle) {
-        snd_mixer_close(u->mixer_handle);
-        u->mixer_handle = NULL;
-    }
+            if (err == -EAGAIN)
+                return work_done;
 
-    if (u->pcm_handle) {
-        snd_pcm_drop(u->pcm_handle);
-        snd_pcm_close(u->pcm_handle);
-        u->pcm_handle = NULL;
-    }
-}
+            pa_log("snd_pcm_avail_update: %s", snd_strerror(err));
+            return -1;
+        }
 
-static int xrun_recovery(struct userdata *u) {
-    int ret;
-    assert(u);
+/*         pa_log("Got request for %i samples", (int) n); */
 
-    pa_log_info("*** ALSA-XRUN (capture) ***");
+        if (n <= 0)
+            return work_done;
 
-    if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) {
-        pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret));
+        frames = n;
 
-        clear_up(u);
-        pa_module_unload_request(u->module);
+        if ((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0) {
 
-        return -1;
-    }
+            if (err == -EPIPE)
+                pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
 
-    return 0;
-}
+            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
+                continue;
 
+            if (err == -EAGAIN)
+                return work_done;
 
-static int suspend_recovery(struct userdata *u) {
-    int ret;
-    assert(u);
+            pa_log("Failed to write data to DSP: %s", snd_strerror(err));
+            return -1;
+        }
 
-    pa_log_info("*** ALSA-SUSPEND (capture) ***");
+        /* Check these are multiples of 8 bit */
+        pa_assert((areas[0].first & 7) == 0);
+        pa_assert((areas[0].step & 7)== 0);
 
-    if ((ret = snd_pcm_resume(u->pcm_handle)) < 0) {
-        if (ret == -EAGAIN)
-            return -1;
+        /* We assume a single interleaved memory buffer */
+        pa_assert((areas[0].first >> 3) == 0);
+        pa_assert((areas[0].step >> 3) == u->frame_size);
 
-        if (ret != -ENOSYS)
-            pa_log("snd_pcm_resume() failed: %s", snd_strerror(-ret));
-        else {
-            if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0)
-                pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret));
-        }
+        p = (uint8_t*) areas[0].addr + (offset * u->frame_size);
+
+        chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, 1);
+        chunk.length = pa_memblock_get_length(chunk.memblock);
+        chunk.index = 0;
+
+        pa_source_post(u->source, &chunk);
+
+        /* FIXME: Maybe we can do something to keep this memory block
+         * a little bit longer around? */
+        pa_memblock_unref_fixed(chunk.memblock);
+
+        if ((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0) {
+
+            if (err == -EPIPE)
+                pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!");
 
-        if (ret < 0) {
-            clear_up(u);
-            pa_module_unload_request(u->module);
+            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
+                continue;
+
+            if (err == -EAGAIN)
+                return work_done;
+
+            pa_log("Failed to write data to DSP: %s", snd_strerror(err));
             return -1;
         }
-    }
 
-    return ret;
+        work_done = 1;
+
+/*         pa_log("wrote %i samples", (int) frames); */
+    }
 }
 
-static void do_read(struct userdata *u) {
-    assert(u);
+static int unix_read(struct userdata *u) {
+    snd_pcm_status_t *status;
+    int work_done = 0;
 
-    update_usage(u);
+    snd_pcm_status_alloca(&status);
 
-    for (;;) {
-        pa_memchunk post_memchunk;
-        snd_pcm_sframes_t frames;
-        size_t l;
+    pa_assert(u);
+    pa_source_assert_ref(u->source);
 
-        if (!u->memchunk.memblock) {
-            u->memchunk.memblock = pa_memblock_new(u->source->core->mempool, u->memchunk.length = u->fragment_size);
-            u->memchunk.index = 0;
+    for (;;) {
+        void *p;
+        snd_pcm_sframes_t t, k;
+        ssize_t l;
+        int err;
+        pa_memchunk chunk;
+
+        if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) {
+            pa_log("Failed to query DSP status data: %s", snd_strerror(err));
+            return -1;
         }
 
-        assert(u->memchunk.memblock);
-        assert(u->memchunk.length);
-        assert(u->memchunk.memblock->data);
-        assert(u->memchunk.memblock->length);
-        assert(u->memchunk.length % u->frame_size == 0);
+        if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size)
+            pa_log_debug("Buffer overrun!");
 
-        if ((frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) {
-            if (frames == -EAGAIN)
-                return;
+        l = snd_pcm_status_get_avail(status) * u->frame_size;
 
-            if (frames == -EPIPE) {
-                if (xrun_recovery(u) < 0)
-                    return;
+        if (l <= 0)
+            return work_done;
 
-                continue;
-            }
+        chunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1);
+
+        k = pa_memblock_get_length(chunk.memblock);
+
+        if (k > l)
+            k = l;
+
+        k = (k/u->frame_size)*u->frame_size;
 
-            if (frames == -ESTRPIPE) {
-                if (suspend_recovery(u) < 0)
-                    return;
+        p = pa_memblock_acquire(chunk.memblock);
+        t = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, k / u->frame_size);
+        pa_memblock_release(chunk.memblock);
 
+/*                     pa_log("wrote %i bytes of %u (%u)", t*u->frame_size, u->memchunk.length, l);   */
+
+        pa_assert(t != 0);
+
+        if (t < 0) {
+            pa_memblock_unref(chunk.memblock);
+
+            if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)
                 continue;
+
+            if (t == -EAGAIN) {
+                pa_log_debug("EAGAIN");
+                return work_done;
+            } else {
+                pa_log("Failed to read data from DSP: %s", snd_strerror(t));
+                return -1;
             }
+        }
 
-            pa_log("snd_pcm_readi() failed: %s", snd_strerror(-frames));
+        chunk.index = 0;
+        chunk.length = t * u->frame_size;
 
-            clear_up(u);
-            pa_module_unload_request(u->module);
-            return;
-        }
+        pa_source_post(u->source, &chunk);
+        pa_memblock_unref(chunk.memblock);
 
-        l = frames * u->frame_size;
+        work_done = 1;
 
-        post_memchunk = u->memchunk;
-        post_memchunk.length = l;
+        if (t * u->frame_size >= (unsigned) l)
+            return work_done;
+    }
+}
 
-        pa_source_post(u->source, &post_memchunk);
+static pa_usec_t source_get_latency(struct userdata *u) {
+    pa_usec_t r = 0;
+    snd_pcm_status_t *status;
+    snd_pcm_sframes_t frames = 0;
+    int err;
 
-        u->memchunk.index += l;
-        u->memchunk.length -= l;
+    snd_pcm_status_alloca(&status);
 
-        if (u->memchunk.length == 0) {
-            pa_memblock_unref(u->memchunk.memblock);
-            u->memchunk.memblock = NULL;
-            u->memchunk.index = u->memchunk.length = 0;
-        }
+    pa_assert(u);
+    pa_assert(u->pcm_handle);
 
-        break;
+    if ((err = snd_pcm_status(u->pcm_handle, status)) < 0)
+        pa_log("Failed to get delay: %s", snd_strerror(err));
+    else
+        frames = snd_pcm_status_get_delay(status);
+
+    if (frames > 0)
+        r = pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec);
+
+    return r;
+}
+
+static int build_pollfd(struct userdata *u) {
+    int err;
+    struct pollfd *pollfd;
+    int n;
+
+    pa_assert(u);
+    pa_assert(u->pcm_handle);
+
+    if ((n = snd_pcm_poll_descriptors_count(u->pcm_handle)) < 0) {
+        pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(n));
+        return -1;
     }
+
+    if (u->alsa_rtpoll_item)
+        pa_rtpoll_item_free(u->alsa_rtpoll_item);
+
+    u->alsa_rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, n);
+    pollfd = pa_rtpoll_item_get_pollfd(u->alsa_rtpoll_item, NULL);
+
+    if ((err = snd_pcm_poll_descriptors(u->pcm_handle, pollfd, n)) < 0) {
+        pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err));
+        return -1;
+    }
+
+    return 0;
 }
 
-static void fdl_callback(void *userdata) {
-    struct userdata *u = userdata;
-    assert(u);
+static int suspend(struct userdata *u) {
+    pa_assert(u);
+    pa_assert(u->pcm_handle);
 
-    if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN)
-        if (xrun_recovery(u) < 0)
-            return;
+    /* Let's suspend */
+    snd_pcm_close(u->pcm_handle);
+    u->pcm_handle = NULL;
 
-    if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_SUSPENDED)
-        if (suspend_recovery(u) < 0)
-            return;
+    if (u->alsa_rtpoll_item) {
+        pa_rtpoll_item_free(u->alsa_rtpoll_item);
+        u->alsa_rtpoll_item = NULL;
+    }
 
-    do_read(u);
+    pa_log_info("Device suspended...");
+
+    return 0;
 }
 
-static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
-    struct userdata *u = snd_mixer_elem_get_callback_private(elem);
+static int unsuspend(struct userdata *u) {
+    pa_sample_spec ss;
+    int err, b;
+    unsigned nfrags;
+    snd_pcm_uframes_t period_size;
 
-    assert(u && u->mixer_handle);
+    pa_assert(u);
+    pa_assert(!u->pcm_handle);
 
-    if (mask == SND_CTL_EVENT_MASK_REMOVE)
-        return 0;
+    pa_log_info("Trying resume...");
 
-    if (mask & SND_CTL_EVENT_MASK_VALUE) {
-        if (u->source->get_hw_volume)
-            u->source->get_hw_volume(u->source);
-        if (u->source->get_hw_mute)
-            u->source->get_hw_mute(u->source);
+    snd_config_update_free_global();
+    if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
+        pa_log("Error opening PCM device %s: %s", u->device_name, snd_strerror(err));
+        goto fail;
+    }
 
-        pa_subscription_post(u->source->core,
-            PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE,
-            u->source->index);
+    ss = u->source->sample_spec;
+    nfrags = u->nfragments;
+    period_size = u->fragment_size / u->frame_size;
+    b = u->use_mmap;
+
+    if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) {
+        pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
+        goto fail;
     }
 
+    if (b != u->use_mmap) {
+        pa_log_warn("Resume failed, couldn't get original access mode.");
+        goto fail;
+    }
+
+    if (!pa_sample_spec_equal(&ss, &u->source->sample_spec)) {
+        pa_log_warn("Resume failed, couldn't restore original sample settings.");
+        goto fail;
+    }
+
+    if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
+        pa_log_warn("Resume failed, couldn't restore original fragment settings.");
+        goto fail;
+    }
+
+    if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) {
+        pa_log("Failed to set software parameters: %s", snd_strerror(err));
+        goto fail;
+    }
+
+    if (build_pollfd(u) < 0)
+        goto fail;
+
+    snd_pcm_start(u->pcm_handle);
+
+    /* FIXME: We need to reload the volume somehow */
+
+    pa_log_info("Resumed successfully...");
+
     return 0;
+
+fail:
+    if (u->pcm_handle) {
+        snd_pcm_close(u->pcm_handle);
+        u->pcm_handle = NULL;
+    }
+
+    return -1;
 }
 
-static pa_usec_t source_get_latency_cb(pa_source *s) {
-    struct userdata *u = s->userdata;
-    snd_pcm_sframes_t frames;
-    assert(s && u && u->source);
+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;
+
+    switch (code) {
+
+        case PA_SOURCE_MESSAGE_GET_LATENCY: {
+            pa_usec_t r = 0;
+
+            if (u->pcm_handle)
+                r = source_get_latency(u);
+
+            *((pa_usec_t*) data) = r;
+
+            return 0;
+        }
+
+        case PA_SOURCE_MESSAGE_SET_STATE:
+
+            switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
+
+                case PA_SOURCE_SUSPENDED:
+                    pa_assert(PA_SOURCE_OPENED(u->source->thread_info.state));
+
+                    if (suspend(u) < 0)
+                        return -1;
+
+                    break;
+
+                case PA_SOURCE_IDLE:
+                case PA_SOURCE_RUNNING:
+
+                    if (u->source->thread_info.state == PA_SOURCE_INIT) {
+                        if (build_pollfd(u) < 0)
+                            return -1;
+
+                        snd_pcm_start(u->pcm_handle);
+                    }
+
+                    if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
+                        if (unsuspend(u) < 0)
+                            return -1;
+                    }
+
+                    break;
 
-    if (snd_pcm_delay(u->pcm_handle, &frames) < 0) {
-        pa_log("failed to get delay");
-        s->get_latency = NULL;
+                case PA_SOURCE_UNLINKED:
+                case PA_SOURCE_INIT:
+                    ;
+            }
+
+            break;
+    }
+
+    return pa_source_process_msg(o, code, data, offset, chunk);
+}
+
+static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
+    struct userdata *u = snd_mixer_elem_get_callback_private(elem);
+
+    pa_assert(u);
+    pa_assert(u->mixer_handle);
+
+    if (mask == SND_CTL_EVENT_MASK_REMOVE)
         return 0;
+
+    if (mask & SND_CTL_EVENT_MASK_VALUE) {
+        pa_source_get_volume(u->source);
+        pa_source_get_mute(u->source);
     }
 
-    return pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec);
+    return 0;
 }
 
-static int source_get_hw_volume_cb(pa_source *s) {
+static int source_get_volume_cb(pa_source *s) {
     struct userdata *u = s->userdata;
-    long vol;
     int err;
     int i;
 
-    assert(u && u->mixer_elem);
+    pa_assert(u);
+    pa_assert(u->mixer_elem);
 
-    for (i = 0;i < s->hw_volume.channels;i++) {
-        long set_vol;
+    for (i = 0; i < s->sample_spec.channels; i++) {
+        long set_vol, vol;
 
-        assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i));
+        pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i));
 
         if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, i, &vol)) < 0)
             goto fail;
 
-        set_vol = (long) roundf(((float) s->hw_volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
+        set_vol = (long) roundf(((float) s->volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
 
         /* Try to avoid superfluous volume changes */
         if (set_vol != vol)
-            s->hw_volume.values[i] = (pa_volume_t) roundf(((float) (vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
+            s->volume.values[i] = (pa_volume_t) roundf(((float) (vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
     }
 
     return 0;
 
 fail:
     pa_log_error("Unable to read volume: %s", snd_strerror(err));
-    s->get_hw_volume = NULL;
-    s->set_hw_volume = NULL;
+
+    s->get_volume = NULL;
+    s->set_volume = NULL;
     return -1;
 }
 
-static int source_set_hw_volume_cb(pa_source *s) {
+static int source_set_volume_cb(pa_source *s) {
     struct userdata *u = s->userdata;
     int err;
-    pa_volume_t vol;
     int i;
 
-    assert(u && u->mixer_elem);
+    pa_assert(u);
+    pa_assert(u->mixer_elem);
 
-    for (i = 0;i < s->hw_volume.channels;i++) {
-        assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i));
+    for (i = 0; i < s->sample_spec.channels; i++) {
+        long alsa_vol;
+        pa_volume_t vol;
 
-        vol = s->hw_volume.values[i];
+        pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i));
+
+        vol = s->volume.values[i];
 
         if (vol > PA_VOLUME_NORM)
             vol = PA_VOLUME_NORM;
 
-        vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
+        alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
 
-        if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, i, vol)) < 0)
+        if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, i, alsa_vol)) < 0)
             goto fail;
     }
 
@@ -346,55 +541,159 @@ static int source_set_hw_volume_cb(pa_source *s) {
 
 fail:
     pa_log_error("Unable to set volume: %s", snd_strerror(err));
-    s->get_hw_volume = NULL;
-    s->set_hw_volume = NULL;
+
+    s->get_volume = NULL;
+    s->set_volume = NULL;
     return -1;
 }
 
-static int source_get_hw_mute_cb(pa_source *s) {
+static int source_get_mute_cb(pa_source *s) {
     struct userdata *u = s->userdata;
     int err, sw;
 
-    assert(u && u->mixer_elem);
+    pa_assert(u);
+    pa_assert(u->mixer_elem);
 
-    err = snd_mixer_selem_get_capture_switch(u->mixer_elem, 0, &sw);
-    if (err) {
+    if ((err = snd_mixer_selem_get_capture_switch(u->mixer_elem, 0, &sw)) < 0) {
         pa_log_error("Unable to get switch: %s", snd_strerror(err));
-        s->get_hw_mute = NULL;
-        s->set_hw_mute = NULL;
+
+        s->get_mute = NULL;
+        s->set_mute = NULL;
         return -1;
     }
 
-    s->hw_muted = !sw;
+    s->muted = !sw;
 
     return 0;
 }
 
-static int source_set_hw_mute_cb(pa_source *s) {
+static int source_set_mute_cb(pa_source *s) {
     struct userdata *u = s->userdata;
     int err;
 
-    assert(u && u->mixer_elem);
+    pa_assert(u);
+    pa_assert(u->mixer_elem);
 
-    err = snd_mixer_selem_set_capture_switch_all(u->mixer_elem, !s->hw_muted);
-    if (err) {
+    if ((err = snd_mixer_selem_set_capture_switch_all(u->mixer_elem, !s->muted)) < 0) {
         pa_log_error("Unable to set switch: %s", snd_strerror(err));
-        s->get_hw_mute = NULL;
-        s->set_hw_mute = NULL;
+
+        s->get_mute = NULL;
+        s->set_mute = NULL;
         return -1;
     }
 
     return 0;
 }
 
-int pa__init(pa_core *c, pa_module*m) {
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
+
+    pa_assert(u);
+
+    pa_log_debug("Thread starting up");
+
+    if (u->core->high_priority)
+        pa_make_realtime();
+
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
+
+    for (;;) {
+        int ret;
+
+        /* Read some data and pass it to the sources */
+        if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
+
+            if (u->use_mmap) {
+                if (mmap_read(u) < 0)
+                    goto fail;
+
+            } else {
+                if (unix_read(u) < 0)
+                    goto fail;
+            }
+        }
+
+        /* Hmm, nothing to do. Let's sleep */
+        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
+            goto fail;
+
+        if (ret == 0)
+            goto finish;
+
+        /* Tell ALSA about this and process its response */
+        if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
+            struct pollfd *pollfd;
+            unsigned short revents = 0;
+            int err;
+            unsigned n;
+
+            pollfd = pa_rtpoll_item_get_pollfd(u->alsa_rtpoll_item, &n);
+
+            if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, pollfd, n, &revents)) < 0) {
+                pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err));
+                goto fail;
+            }
+
+            if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
+
+                if (revents & POLLERR)
+                    pa_log_warn("Got POLLERR from ALSA");
+                if (revents & POLLNVAL)
+                    pa_log_warn("Got POLLNVAL from ALSA");
+                if (revents & POLLHUP)
+                    pa_log_warn("Got POLLHUP from ALSA");
+
+                /* Try to recover from this error */
+
+                switch (snd_pcm_state(u->pcm_handle)) {
+
+                    case SND_PCM_STATE_XRUN:
+                        if ((err = snd_pcm_recover(u->pcm_handle, -EPIPE, 1)) != 0) {
+                            pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", snd_strerror(err));
+                            goto fail;
+                        }
+                        break;
+
+                    case SND_PCM_STATE_SUSPENDED:
+                        if ((err = snd_pcm_recover(u->pcm_handle, -ESTRPIPE, 1)) != 0) {
+                            pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", snd_strerror(err));
+                            goto fail;
+                        }
+                        break;
+
+                    default:
+
+                        snd_pcm_drop(u->pcm_handle);
+
+                        if ((err = snd_pcm_prepare(u->pcm_handle)) < 0) {
+                            pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", snd_strerror(err));
+                            goto fail;
+                        }
+                        break;
+                }
+            }
+        }
+    }
+
+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_module*m) {
+
     pa_modargs *ma = NULL;
-    int ret = -1;
     struct userdata *u = NULL;
-    const char *dev;
+    char *dev;
     pa_sample_spec ss;
     pa_channel_map map;
-    unsigned periods, fragsize;
+    unsigned nfrags, frag_size;
     snd_pcm_uframes_t period_size;
     size_t frame_size;
     snd_pcm_info_t *pcm_info = NULL;
@@ -403,64 +702,125 @@ int pa__init(pa_core *c, pa_module*m) {
     const char *name;
     char *name_buf = NULL;
     int namereg_fail;
+    int use_mmap = 1, b;
+
+    snd_pcm_info_alloca(&pcm_info);
+
+    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_ALSA) < 0) {
-        pa_log("failed to parse sample specification");
+        pa_log("Failed to parse sample specification");
         goto fail;
     }
 
     frame_size = pa_frame_size(&ss);
 
-    /* Fix latency to 100ms */
-    periods = 12;
-    fragsize = pa_bytes_per_second(&ss)/128;
+    nfrags = m->core->default_n_fragments;
+    frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*1000, &ss);
+    if (frag_size <= 0)
+        frag_size = frame_size;
+
+    if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0) {
+        pa_log("Failed to parse buffer metrics");
+        goto fail;
+    }
+    period_size = frag_size/frame_size;
 
-    if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) {
-        pa_log("failed to parse buffer metrics");
+    if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
+        pa_log("Failed to parse mmap argument.");
         goto fail;
     }
-    period_size = fragsize/frame_size;
 
     u = pa_xnew0(struct userdata, 1);
-    m->userdata = u;
+    u->core = m->core;
     u->module = m;
+    m->userdata = u;
+    u->use_mmap = use_mmap;
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
+    u->rtpoll = pa_rtpoll_new();
+    u->alsa_rtpoll_item = NULL;
+    pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
 
     snd_config_update_free_global();
-    if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
-        pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err));
-        goto fail;
+
+    dev = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE));
+
+    for (;;) {
+
+        if ((err = snd_pcm_open(&u->pcm_handle, dev, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
+            pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err));
+            pa_xfree(dev);
+            goto fail;
+        }
+
+        b = use_mmap;
+        if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) {
+
+            if (err == -EPERM) {
+                /* Hmm, some hw is very exotic, so we retry with plughw, if hw didn't work */
+
+                if (pa_startswith(dev, "hw:")) {
+                    char *d = pa_sprintf_malloc("plughw:%s", dev+3);
+                    pa_log_debug("Opening the device as '%s' didn't work, retrying with '%s'.", dev, d);
+                    pa_xfree(dev);
+                    dev = d;
+
+                    snd_pcm_close(u->pcm_handle);
+                    u->pcm_handle = NULL;
+                    continue;
+                }
+            }
+
+            pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
+            pa_xfree(dev);
+            goto fail;
+        }
+
+        break;
     }
 
-    if ((err = snd_pcm_info_malloc(&pcm_info)) < 0 ||
-        (err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) {
+    u->device_name = dev;
+
+    if (use_mmap && !b) {
+        pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
+        u->use_mmap = use_mmap = b;
+    }
+
+    if (u->use_mmap)
+        pa_log_info("Successfully enabled mmap() mode.");
+
+    if ((err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) {
         pa_log("Error fetching PCM info: %s", snd_strerror(err));
         goto fail;
     }
 
-    if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size)) < 0) {
-        pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
+    if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) {
+        pa_log("Failed to set software parameters: %s", snd_strerror(err));
         goto fail;
     }
 
+    /* ALSA might tweak the sample spec, so recalculate the frame size */
+    frame_size = pa_frame_size(&ss);
+
     if (ss.channels != map.channels)
         /* Seems ALSA didn't like the channel number, so let's fix the channel map */
         pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA);
 
-    if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) {
+    if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0)
         pa_log("Error opening mixer: %s", snd_strerror(err));
-        goto fail;
-    }
+    else {
 
-    if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) ||
-        !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", "Mic"))) {
-        snd_mixer_close(u->mixer_handle);
-        u->mixer_handle = NULL;
+        if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) ||
+            !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", NULL))) {
+            snd_mixer_close(u->mixer_handle);
+            u->mixer_handle = NULL;
+        }
     }
 
     if ((name = pa_modargs_get_value(ma, "source_name", NULL)))
@@ -470,16 +830,39 @@ int pa__init(pa_core *c, pa_module*m) {
         namereg_fail = 0;
     }
 
-    if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map))) {
+    u->source = pa_source_new(m->core, __FILE__, name, namereg_fail, &ss, &map);
+    pa_xfree(name_buf);
+
+    if (!u->source) {
         pa_log("Failed to create source object");
         goto fail;
     }
 
-    u->source->is_hardware = 1;
+    u->source->parent.process_msg = source_process_msg;
     u->source->userdata = u;
-    u->source->get_latency = source_get_latency_cb;
+
+    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(
+                                      "ALSA PCM on %s (%s)%s",
+                                      dev,
+                                      snd_pcm_info_get_name(pcm_info),
+                                      use_mmap ? " via DMA" : ""));
+    pa_xfree(t);
+
+    u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL;
+
+    u->frame_size = frame_size;
+    u->fragment_size = frag_size = period_size * frame_size;
+    u->nfragments = nfrags;
+    u->hwbuf_size = u->fragment_size * nfrags;
+
+    pa_log_info("Using %u fragments of size %lu bytes.", nfrags, (long unsigned) u->fragment_size);
+
     if (u->mixer_handle) {
-        assert(u->mixer_elem);
+        pa_assert(u->mixer_elem);
+
         if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) {
             int i;
 
@@ -489,89 +872,95 @@ int pa__init(pa_core *c, pa_module*m) {
             }
 
             if (i == ss.channels) {
-                u->source->get_hw_volume = source_get_hw_volume_cb;
-                u->source->set_hw_volume = source_set_hw_volume_cb;
-                snd_mixer_selem_get_capture_volume_range(
-                    u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max);
+                u->source->get_volume = source_get_volume_cb;
+                u->source->set_volume = source_set_volume_cb;
+                snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max);
             }
         }
+
         if (snd_mixer_selem_has_capture_switch(u->mixer_elem)) {
-            u->source->get_hw_mute = source_get_hw_mute_cb;
-            u->source->set_hw_mute = source_set_hw_mute_cb;
+            u->source->get_mute = source_get_mute_cb;
+            u->source->set_mute = source_set_mute_cb;
         }
-    }
-    pa_source_set_owner(u->source, m);
-    pa_source_set_description(u->source, t = pa_sprintf_malloc("ALSA PCM on %s (%s)", dev, snd_pcm_info_get_name(pcm_info)));
-    pa_xfree(t);
 
-    u->pcm_fdl = pa_alsa_fdlist_new();
-    assert(u->pcm_fdl);
-    if (pa_alsa_fdlist_init_pcm(u->pcm_fdl, u->pcm_handle, c->mainloop, fdl_callback, u) < 0) {
-        pa_log("failed to initialise file descriptor monitoring");
-        goto fail;
-    }
-
-    if (u->mixer_handle) {
         u->mixer_fdl = pa_alsa_fdlist_new();
-        assert(u->mixer_fdl);
-        if (pa_alsa_fdlist_init_mixer(u->mixer_fdl, u->mixer_handle, c->mainloop) < 0) {
+
+        if (pa_alsa_fdlist_set_mixer(u->mixer_fdl, u->mixer_handle, m->core->mainloop) < 0) {
             pa_log("failed to initialise file descriptor monitoring");
             goto fail;
         }
+
         snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback);
         snd_mixer_elem_set_callback_private(u->mixer_elem, u);
     } else
         u->mixer_fdl = NULL;
 
-    u->frame_size = frame_size;
-    u->fragment_size = period_size * frame_size;
-
-    pa_log_info("using %u fragments of size %lu bytes.", periods, (long unsigned) u->fragment_size);
-
-    u->memchunk.memblock = NULL;
-    u->memchunk.index = u->memchunk.length = 0;
-
-    snd_pcm_start(u->pcm_handle);
-
-    ret = 0;
-
+    if (!(u->thread = pa_thread_new(thread_func, u))) {
+        pa_log("Failed to create thread.");
+        goto fail;
+    }
     /* Get initial mixer settings */
-    if (u->source->get_hw_volume)
-        u->source->get_hw_volume(u->source);
-    if (u->source->get_hw_mute)
-        u->source->get_hw_mute(u->source);
+    if (u->source->get_volume)
+        u->source->get_volume(u->source);
+    if (u->source->get_mute)
+        u->source->get_mute(u->source);
 
-finish:
-    pa_xfree(name_buf);
-
-    if (ma)
-         pa_modargs_free(ma);
+    pa_source_put(u->source);
 
-    if (pcm_info)
-        snd_pcm_info_free(pcm_info);
+    pa_modargs_free(ma);
 
-    return ret;
+    return 0;
 
 fail:
 
-    if (u)
-        pa__done(c, m);
+    if (ma)
+        pa_modargs_free(ma);
 
-    goto finish;
+    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;
 
-    clear_up(u);
+    if (u->source)
+        pa_source_unlink(u->source);
 
-    if (u->memchunk.memblock)
-        pa_memblock_unref(u->memchunk.memblock);
+    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->source)
+        pa_source_unref(u->source);
+
+    if (u->alsa_rtpoll_item)
+        pa_rtpoll_item_free(u->alsa_rtpoll_item);
+
+    if (u->rtpoll)
+        pa_rtpoll_free(u->rtpoll);
+
+    if (u->mixer_fdl)
+        pa_alsa_fdlist_free(u->mixer_fdl);
+
+    if (u->mixer_handle)
+        snd_mixer_close(u->mixer_handle);
+
+    if (u->pcm_handle) {
+        snd_pcm_drop(u->pcm_handle);
+        snd_pcm_close(u->pcm_handle);
+    }
+
+    pa_xfree(u->device_name);
     pa_xfree(u);
-}
 
+    snd_config_update_free_global();
+}
index 19ac0c26cf86379f06ae0d30923c8078be19ab2e..84125214bbcdc81d91859fdddbb0641d8d3b47f5 100644 (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();
     }
index 716c20b2403fcebd7c0aa8ce3a80689f935c3050..665bf9dd4fcc8ee8bb32d4b9acc7150ffc0b6b0c 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdio.h>
+#include <errno.h>
 
 #include <pulse/timeval.h>
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/macro.h>
 #include <pulsecore/module.h>
 #include <pulsecore/llist.h>
 #include <pulsecore/sink.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/modargs.h>
 #include <pulsecore/namereg.h>
+#include <pulsecore/mutex.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/thread-mq.h>
+#include <pulsecore/rtpoll.h>
+#include <pulsecore/rtclock.h>
+#include <pulsecore/core-error.h>
 
 #include "module-combine-symdef.h"
 
@@ -55,13 +62,12 @@ PA_MODULE_USAGE(
         "format=<sample format> "
         "channels=<number of channels> "
         "rate=<sample rate> "
-        "channel_map=<channel map> ")
+        "channel_map=<channel map>")
 
 #define DEFAULT_SINK_NAME "combined"
 #define MEMBLOCKQ_MAXLENGTH (1024*170)
-#define RENDER_SIZE (1024*10)
 
-#define DEFAULT_ADJUST_TIME 20
+#define DEFAULT_ADJUST_TIME 10
 
 static const char* const valid_modargs[] = {
     "sink_name",
@@ -78,170 +84,689 @@ static const char* const valid_modargs[] = {
 
 struct output {
     struct userdata *userdata;
+
+    pa_sink *sink;
     pa_sink_input *sink_input;
-    size_t counter;
+
+    pa_asyncmsgq *inq,    /* Message queue from the sink thread to this sink input */
+                 *outq;   /* Message queue from this sink input to the sink thread */
+    pa_rtpoll_item *inq_rtpoll_item, *outq_rtpoll_item;
+
     pa_memblockq *memblockq;
+
     pa_usec_t total_latency;
+
     PA_LLIST_FIELDS(struct output);
 };
 
 struct userdata {
-    pa_module *module;
     pa_core *core;
+    pa_module *module;
     pa_sink *sink;
-    unsigned n_outputs;
-    struct output *master;
+
+    pa_thread *thread;
+    pa_thread_mq thread_mq;
+    pa_rtpoll *rtpoll;
+
     pa_time_event *time_event;
     uint32_t adjust_time;
 
-    PA_LLIST_HEAD(struct output, outputs);
+    pa_bool_t automatic;
+    size_t block_size;
+
+    pa_hook_slot *sink_new_slot, *sink_unlink_slot, *sink_state_changed_slot;
+
+    pa_resample_method_t resample_method;
+
+    struct timeval adjust_timestamp;
+
+    struct output *master;
+    pa_idxset* outputs; /* managed in main context */
+
+    struct {
+        PA_LLIST_HEAD(struct output, active_outputs); /* managed in IO thread context */
+        pa_atomic_t running;  /* we cache that value here, so that every thread can query it cheaply */
+        struct timeval timestamp;
+        pa_bool_t in_null_mode;
+    } thread_info;
 };
 
-static void output_free(struct output *o);
-static void clear_up(struct userdata *u);
+enum {
+    SINK_MESSAGE_ADD_OUTPUT = PA_SINK_MESSAGE_MAX,
+    SINK_MESSAGE_REMOVE_OUTPUT,
+    SINK_MESSAGE_NEED
+};
 
-static void update_usage(struct userdata *u) {
-    pa_module_set_used(u->module, u->sink ? pa_sink_used_by(u->sink) : 0);
-}
+enum {
+    SINK_INPUT_MESSAGE_POST = PA_SINK_INPUT_MESSAGE_MAX
+};
+
+static void output_free(struct output *o);
+static int output_create_sink_input(struct output *o);
+static void update_master(struct userdata *u, struct output *o);
+static void pick_master(struct userdata *u, struct output *except);
 
 static void adjust_rates(struct userdata *u) {
     struct output *o;
     pa_usec_t max_sink_latency = 0, min_total_latency = (pa_usec_t) -1, target_latency;
     uint32_t base_rate;
-    assert(u && u->sink);
+    uint32_t idx;
 
-    for (o = u->outputs; o; o = o->next) {
-        uint32_t sink_latency = o->sink_input->sink ? pa_sink_get_latency(o->sink_input->sink) : 0;
+    pa_assert(u);
+    pa_sink_assert_ref(u->sink);
 
+    if (pa_idxset_size(u->outputs) <= 0)
+        return;
+
+    if (!u->master)
+        return;
+
+    if (!PA_SINK_OPENED(pa_sink_get_state(u->sink)))
+        return;
+
+    for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) {
+        pa_usec_t sink_latency;
+
+        if (!o->sink_input || !PA_SINK_OPENED(pa_sink_get_state(o->sink)))
+            continue;
+
+        sink_latency = pa_sink_get_latency(o->sink);
         o->total_latency = sink_latency + pa_sink_input_get_latency(o->sink_input);
 
         if (sink_latency > max_sink_latency)
             max_sink_latency = sink_latency;
 
-        if (o->total_latency < min_total_latency)
+        if (min_total_latency == (pa_usec_t) -1 || o->total_latency < min_total_latency)
             min_total_latency = o->total_latency;
     }
 
-    assert(min_total_latency != (pa_usec_t) -1);
+    if (min_total_latency == (pa_usec_t) -1)
+        return;
 
     target_latency = max_sink_latency > min_total_latency ? max_sink_latency : min_total_latency;
 
     pa_log_info("[%s] target latency is %0.0f usec.", u->sink->name, (float) target_latency);
+    pa_log_info("[%s] master %s latency %0.0f usec.", u->sink->name, u->master->sink->name, (float) u->master->total_latency);
 
     base_rate = u->sink->sample_spec.rate;
 
-    for (o = u->outputs; o; o = o->next) {
+    for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) {
         uint32_t r = base_rate;
 
+        if (!o->sink_input || !PA_SINK_OPENED(pa_sink_get_state(o->sink)))
+            continue;
+
         if (o->total_latency < target_latency)
-            r -= (uint32_t) (((((double) target_latency - o->total_latency))/u->adjust_time)*r/ 1000000);
+            r -= (uint32_t) (((((double) target_latency - o->total_latency))/u->adjust_time)*r/PA_USEC_PER_SEC);
         else if (o->total_latency > target_latency)
-            r += (uint32_t) (((((double) o->total_latency - target_latency))/u->adjust_time)*r/ 1000000);
+            r += (uint32_t) (((((double) o->total_latency - target_latency))/u->adjust_time)*r/PA_USEC_PER_SEC);
 
-        if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1))
+        if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1)) {
             pa_log_warn("[%s] sample rates too different, not adjusting (%u vs. %u).", o->sink_input->name, base_rate, r);
-        else {
+            pa_sink_input_set_rate(o->sink_input, base_rate);
+        } else {
             pa_log_info("[%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.", o->sink_input->name, r, (double) r / base_rate, (float) o->total_latency);
             pa_sink_input_set_rate(o->sink_input, r);
         }
     }
 }
 
-static void request_memblock(struct userdata *u) {
-    pa_memchunk chunk;
-    struct output *o;
-    assert(u && u->sink);
+static void time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) {
+    struct userdata *u = userdata;
+    struct timeval n;
+
+    pa_assert(u);
+    pa_assert(a);
+    pa_assert(u->time_event == e);
 
-    update_usage(u);
+    adjust_rates(u);
+
+    pa_gettimeofday(&n);
+    n.tv_sec += u->adjust_time;
+    u->sink->core->mainloop->time_restart(e, &n);
+}
+
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
 
-    if (pa_sink_render(u->sink, RENDER_SIZE, &chunk) < 0)
+    pa_assert(u);
+
+    pa_log_debug("Thread starting up");
+
+    if (u->core->high_priority)
+        pa_make_realtime();
+
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
+
+    pa_rtclock_get(&u->thread_info.timestamp);
+    u->thread_info.in_null_mode = FALSE;
+
+    for (;;) {
+        int ret;
+
+        /* If no outputs are connected, render some data and drop it immediately. */
+        if (u->sink->thread_info.state == PA_SINK_RUNNING && !u->thread_info.active_outputs) {
+            struct timeval now;
+
+            pa_rtclock_get(&now);
+
+            if (!u->thread_info.in_null_mode || pa_timeval_cmp(&u->thread_info.timestamp, &now) <= 0) {
+                pa_sink_skip(u->sink, u->block_size);
+
+                if (!u->thread_info.in_null_mode)
+                    u->thread_info.timestamp = now;
+
+                pa_timeval_add(&u->thread_info.timestamp, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec));
+            }
+
+            pa_rtpoll_set_timer_absolute(u->rtpoll, &u->thread_info.timestamp);
+            u->thread_info.in_null_mode = TRUE;
+
+        } else {
+            pa_rtpoll_set_timer_disabled(u->rtpoll);
+            u->thread_info.in_null_mode = FALSE;
+        }
+
+        /* Hmm, nothing to do. Let's sleep */
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) {
+            pa_log_info("pa_rtpoll_run() = %i", ret);
+            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");
+}
+
+/* Called from I/O thread context */
+static void render_memblock(struct userdata *u, struct output *o, size_t length) {
+    pa_assert(u);
+    pa_assert(o);
+
+    /* We are run by the sink thread, on behalf of an output (o). The
+     * other output is waiting for us, hence it is safe to access its
+     * mainblockq and asyncmsgq directly. */
+
+    /* If we are not running, we cannot produce any data */
+    if (!pa_atomic_load(&u->thread_info.running))
         return;
 
-    for (o = u->outputs; o; o = o->next)
-        pa_memblockq_push_align(o->memblockq, &chunk);
+    /* Maybe there's some data in the requesting output's queue
+     * now? */
+    while (pa_asyncmsgq_process_one(o->inq) > 0)
+        ;
+
+    /* Ok, now let's prepare some data if we really have to */
+    while (!pa_memblockq_is_readable(o->memblockq)) {
+        struct output *j;
+        pa_memchunk chunk;
+
+        /* Render data! */
+        pa_sink_render(u->sink, length, &chunk);
+
+        /* OK, let's send this data to the other threads */
+        for (j = u->thread_info.active_outputs; j; j = j->next)
 
-    pa_memblock_unref(chunk.memblock);
+            /* Send to other outputs, which are not the requesting
+             * one */
+
+            if (j != o)
+                pa_asyncmsgq_post(j->inq, PA_MSGOBJECT(j->sink_input), SINK_INPUT_MESSAGE_POST, NULL, 0, &chunk, NULL);
+
+        /* And place it directly into the requesting output's queue */
+        if (o)
+            pa_memblockq_push_align(o->memblockq, &chunk);
+
+        pa_memblock_unref(chunk.memblock);
+    }
 }
 
-static void time_callback(pa_mainloop_api*a, pa_time_event* e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) {
-    struct userdata *u = userdata;
-    struct timeval n;
-    assert(u && a && u->time_event == e);
+/* Called from I/O thread context */
+static void request_memblock(struct output *o, size_t length) {
+    pa_assert(o);
+    pa_sink_input_assert_ref(o->sink_input);
+    pa_sink_assert_ref(o->userdata->sink);
 
-    adjust_rates(u);
+    /* If another thread already prepared some data we received
+     * the data over the asyncmsgq, hence let's first process
+     * it. */
+    while (pa_asyncmsgq_process_one(o->inq) > 0)
+        ;
 
-    pa_gettimeofday(&n);
-    n.tv_sec += u->adjust_time;
-    u->sink->core->mainloop->time_restart(e, &n);
+    /* Check whether we're now readable */
+    if (pa_memblockq_is_readable(o->memblockq))
+        return;
+
+    /* OK, we need to prepare new data, but only if the sink is actually running */
+    if (pa_atomic_load(&o->userdata->thread_info.running))
+        pa_asyncmsgq_send(o->outq, PA_MSGOBJECT(o->userdata->sink), SINK_MESSAGE_NEED, o, length, NULL);
 }
 
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
-    struct output *o = i->userdata;
-    assert(i && o && o->sink_input && chunk);
+/* Called from I/O thread context */
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+    struct output *o;
 
-    if (pa_memblockq_peek(o->memblockq, chunk) >= 0)
-        return 0;
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(o = i->userdata);
 
-    /* Try harder */
-    request_memblock(o->userdata);
+    /* If necessary, get some new data */
+    request_memblock(o, length);
 
     return pa_memblockq_peek(o->memblockq, chunk);
 }
 
-static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
-    struct output *o = i->userdata;
-    assert(i && o && o->sink_input && chunk && length);
+/* Called from I/O thread context */
+static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
+    struct output *o;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert(length > 0);
+    pa_assert_se(o = i->userdata);
+
+    pa_memblockq_drop(o->memblockq, length);
+}
+
+/* Called from I/O thread context */
+static void sink_input_attach_cb(pa_sink_input *i) {
+    struct output *o;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(o = i->userdata);
+
+    /* Set up the queue from the sink thread to us */
+    pa_assert(!o->inq_rtpoll_item);
+    o->inq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
+            i->sink->rtpoll,
+            PA_RTPOLL_LATE,  /* This one is not that important, since we check for data in _peek() anyway. */
+            o->inq);
+}
+
+/* Called from I/O thread context */
+static void sink_input_detach_cb(pa_sink_input *i) {
+    struct output *o;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(o = i->userdata);
 
-    pa_memblockq_drop(o->memblockq, chunk, length);
-    o->counter += length;
+    /* Shut down the queue from the sink thread to us */
+    pa_assert(o->inq_rtpoll_item);
+    pa_rtpoll_item_free(o->inq_rtpoll_item);
+    o->inq_rtpoll_item = NULL;
 }
 
+/* Called from main context */
 static void sink_input_kill_cb(pa_sink_input *i) {
-    struct output *o = i->userdata;
-    assert(i && o && o->sink_input);
+    struct output *o;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert(o = i->userdata);
+
     pa_module_unload_request(o->userdata->module);
-    clear_up(o->userdata);
+    output_free(o);
+}
+
+/* Called from thread context */
+static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
+    struct output *o = PA_SINK_INPUT(obj)->userdata;
+
+    switch (code) {
+
+        case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
+             pa_usec_t *r = data;
+
+            *r = pa_bytes_to_usec(pa_memblockq_get_length(o->memblockq), &o->sink_input->sample_spec);
+
+            /* Fall through, the default handler will add in the extra
+             * latency added by the resampler */
+            break;
+        }
+
+        case SINK_INPUT_MESSAGE_POST:
+
+            if (PA_SINK_OPENED(o->sink_input->sink->thread_info.state))
+                pa_memblockq_push_align(o->memblockq, chunk);
+            else
+                pa_memblockq_flush(o->memblockq);
+
+            break;
+    }
+
+    return pa_sink_input_process_msg(obj, code, data, offset, chunk);
 }
 
-static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) {
-    struct output *o = i->userdata;
-    assert(i && o && o->sink_input);
+/* Called from main context */
+static void disable_output(struct output *o) {
+    pa_assert(o);
+
+    if (!o->sink_input)
+        return;
+
+    pa_asyncmsgq_send(o->userdata->sink->asyncmsgq, PA_MSGOBJECT(o->userdata->sink), SINK_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
+    pa_sink_input_unlink(o->sink_input);
+    pa_sink_input_unref(o->sink_input);
+    o->sink_input = NULL;
 
-    return pa_bytes_to_usec(pa_memblockq_get_length(o->memblockq), &i->sample_spec);
 }
 
-static pa_usec_t sink_get_latency_cb(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    assert(s && u && u->sink && u->master);
+/* Called from main context */
+static void enable_output(struct output *o) {
+    pa_assert(o);
+
+    if (o->sink_input)
+        return;
+
+    if (output_create_sink_input(o) >= 0) {
+
+        pa_memblockq_flush(o->memblockq);
+
+        pa_sink_input_put(o->sink_input);
+
+        if (o->userdata->sink && PA_SINK_LINKED(pa_sink_get_state(o->userdata->sink)))
+            pa_asyncmsgq_send(o->userdata->sink->asyncmsgq, PA_MSGOBJECT(o->userdata->sink), SINK_MESSAGE_ADD_OUTPUT, o, 0, NULL);
+    }
+}
+
+/* Called from main context */
+static void suspend(struct userdata *u) {
+    struct output *o;
+    uint32_t idx;
+
+    pa_assert(u);
+
+    /* Let's suspend by unlinking all streams */
+    for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx))
+        disable_output(o);
+
+    pick_master(u, NULL);
+
+    pa_log_info("Device suspended...");
+}
+
+/* Called from main context */
+static void unsuspend(struct userdata *u) {
+    struct output *o;
+    uint32_t idx;
+
+    pa_assert(u);
+
+    /* Let's resume */
+    for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) {
+
+        pa_sink_suspend(o->sink, FALSE);
+
+        if (PA_SINK_OPENED(pa_sink_get_state(o->sink)))
+            enable_output(o);
+    }
+
+    pick_master(u, NULL);
+
+    pa_log_info("Resumed successfully...");
+}
+
+/* Called from main context */
+static int sink_set_state(pa_sink *sink, pa_sink_state_t state) {
+    struct userdata *u;
+
+    pa_sink_assert_ref(sink);
+    pa_assert_se(u = sink->userdata);
+
+    /* Please note that in contrast to the ALSA modules we call
+     * suspend/unsuspend from main context here! */
+
+    switch (state) {
+        case PA_SINK_SUSPENDED:
+            pa_assert(PA_SINK_OPENED(pa_sink_get_state(u->sink)));
+
+            suspend(u);
+            break;
+
+        case PA_SINK_IDLE:
+        case PA_SINK_RUNNING:
+
+            if (pa_sink_get_state(u->sink) == PA_SINK_SUSPENDED)
+                unsuspend(u);
+
+            break;
+
+        case PA_SINK_UNLINKED:
+        case PA_SINK_INIT:
+            ;
+    }
+
+    return 0;
+}
+
+/* Called from thread context of the master */
+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:
+            pa_atomic_store(&u->thread_info.running, PA_PTR_TO_UINT(data) == PA_SINK_RUNNING);
+            break;
+
+        case PA_SINK_MESSAGE_GET_LATENCY:
+
+            /* This code will only be called when running in NULL
+             * mode, i.e. when no output is attached. See
+             * sink_get_latency_cb() below */
+
+            if (u->thread_info.in_null_mode) {
+                struct timeval now;
+
+                if (pa_timeval_cmp(&u->thread_info.timestamp, pa_rtclock_get(&now)) > 0) {
+                    *((pa_usec_t*) data) = pa_timeval_diff(&u->thread_info.timestamp, &now);
+                    break;
+                }
+            }
+
+            *((pa_usec_t*) data) = 0;
+
+            break;
+
+        case SINK_MESSAGE_ADD_OUTPUT: {
+            struct output *op = data;
+
+            PA_LLIST_PREPEND(struct output, u->thread_info.active_outputs, op);
+
+            pa_assert(!op->outq_rtpoll_item);
+
+            /* Create pa_asyncmsgq to the sink thread */
+
+            op->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
+                    u->rtpoll,
+                    PA_RTPOLL_EARLY-1,  /* This item is very important */
+                    op->outq);
+
+            return 0;
+        }
+
+        case SINK_MESSAGE_REMOVE_OUTPUT: {
+            struct output *op = data;
 
-    return
-        pa_sink_input_get_latency(u->master->sink_input) +
-        pa_sink_get_latency(u->master->sink_input->sink);
+            PA_LLIST_REMOVE(struct output, u->thread_info.active_outputs, op);
+
+            /* Remove the q that leads from this output to the sink thread */
+
+            pa_assert(op->outq_rtpoll_item);
+            pa_rtpoll_item_free(op->outq_rtpoll_item);
+            op->outq_rtpoll_item = NULL;
+
+            return 0;
+        }
+
+        case SINK_MESSAGE_NEED:
+            render_memblock(u, data, (size_t) offset);
+            return 0;
+    }
+
+    return pa_sink_process_msg(o, code, data, offset, chunk);
 }
 
-static void sink_notify(pa_sink *s) {
+/* Called from main context */
+static pa_usec_t sink_get_latency_cb(pa_sink *s) {
     struct userdata *u;
+
+    pa_sink_assert_ref(s);
+    pa_assert_se(u = s->userdata);
+
+    if (u->master) {
+        /* If we have a master sink, we just return the latency of it
+         * and add our own buffering on top */
+
+        if (!u->master->sink_input)
+            return 0;
+
+        return
+            pa_sink_input_get_latency(u->master->sink_input) +
+            pa_sink_get_latency(u->master->sink);
+
+    } else {
+        pa_usec_t usec = 0;
+
+        /* We have no master, hence let's ask our own thread which
+         * implements the NULL sink */
+
+        if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
+            return 0;
+
+        return usec;
+    }
+}
+
+static void update_description(struct userdata *u) {
+    int first = 1;
+    char *t;
+    struct output *o;
+    uint32_t idx;
+
+    pa_assert(u);
+
+    if (pa_idxset_isempty(u->outputs)) {
+        pa_sink_set_description(u->sink, "Simultaneous output");
+        return;
+    }
+
+    t = pa_xstrdup("Simultaneous output to");
+
+    for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) {
+        char *e;
+
+        if (first) {
+            e = pa_sprintf_malloc("%s %s", t, o->sink->description);
+            first = 0;
+        } else
+            e = pa_sprintf_malloc("%s, %s", t, o->sink->description);
+
+        pa_xfree(t);
+        t = e;
+    }
+
+    pa_sink_set_description(u->sink, t);
+    pa_xfree(t);
+}
+
+static void update_master(struct userdata *u, struct output *o) {
+    pa_assert(u);
+
+    if (u->master == o)
+        return;
+
+    if ((u->master = o))
+        pa_log_info("Master sink is now '%s'", o->sink_input->sink->name);
+    else
+        pa_log_info("No master selected, lacking suitable outputs.");
+}
+
+static void pick_master(struct userdata *u, struct output *except) {
     struct output *o;
+    uint32_t idx;
+    pa_assert(u);
+
+    if (u->master &&
+        u->master != except &&
+        u->master->sink_input &&
+        PA_SINK_OPENED(pa_sink_get_state(u->master->sink))) {
+        update_master(u, u->master);
+        return;
+    }
 
-    assert(s);
-    u = s->userdata;
-    assert(u);
+    for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx))
+        if (o != except &&
+            o->sink_input &&
+            PA_SINK_OPENED(pa_sink_get_state(o->sink))) {
+            update_master(u, o);
+            return;
+        }
 
-    for (o = u->outputs; o; o = o->next)
-        pa_sink_notify(o->sink_input->sink);
+    update_master(u, NULL);
 }
 
-static struct output *output_new(struct userdata *u, pa_sink *sink, int resample_method) {
-    struct output *o = NULL;
-    char t[256];
+static int output_create_sink_input(struct output *o) {
     pa_sink_input_new_data data;
+    char *t;
 
-    assert(u && sink && u->sink);
+    pa_assert(o);
 
-    o = pa_xmalloc(sizeof(struct output));
-    o->userdata = u;
+    if (o->sink_input)
+        return 0;
+
+    t = pa_sprintf_malloc("Simultaneous output on %s", o->sink->description);
 
-    o->counter = 0;
+    pa_sink_input_new_data_init(&data);
+    data.sink = o->sink;
+    data.driver = __FILE__;
+    data.name = t;
+    pa_sink_input_new_data_set_sample_spec(&data, &o->userdata->sink->sample_spec);
+    pa_sink_input_new_data_set_channel_map(&data, &o->userdata->sink->channel_map);
+    data.module = o->userdata->module;
+    data.resample_method = o->userdata->resample_method;
+
+    o->sink_input = pa_sink_input_new(o->userdata->core, &data, PA_SINK_INPUT_VARIABLE_RATE|PA_SINK_INPUT_DONT_MOVE);
+
+    pa_xfree(t);
+
+    if (!o->sink_input)
+        return -1;
+
+    o->sink_input->parent.process_msg = sink_input_process_msg;
+    o->sink_input->peek = sink_input_peek_cb;
+    o->sink_input->drop = sink_input_drop_cb;
+    o->sink_input->attach = sink_input_attach_cb;
+    o->sink_input->detach = sink_input_detach_cb;
+    o->sink_input->kill = sink_input_kill_cb;
+    o->sink_input->userdata = o;
+
+
+    return 0;
+}
+
+static struct output *output_new(struct userdata *u, pa_sink *sink) {
+    struct output *o;
+
+    pa_assert(u);
+    pa_assert(sink);
+    pa_assert(u->sink);
+
+    o = pa_xnew(struct output, 1);
+    o->userdata = u;
+    o->inq = pa_asyncmsgq_new(0);
+    o->outq = pa_asyncmsgq_new(0);
+    o->inq_rtpoll_item = NULL;
+    o->outq_rtpoll_item = NULL;
+    o->sink = sink;
+    o->sink_input = NULL;
     o->memblockq = pa_memblockq_new(
             0,
             MEMBLOCKQ_MAXLENGTH,
@@ -251,90 +776,151 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample
             0,
             NULL);
 
-    snprintf(t, sizeof(t), "Output stream #%u of sink %s", u->n_outputs+1, u->sink->name);
+    pa_assert_se(pa_idxset_put(u->outputs, o, NULL) == 0);
 
-    pa_sink_input_new_data_init(&data);
-    data.sink = sink;
-    data.driver = __FILE__;
-    data.name = t;
-    pa_sink_input_new_data_set_sample_spec(&data, &u->sink->sample_spec);
-    pa_sink_input_new_data_set_channel_map(&data, &u->sink->channel_map);
-    data.module = u->module;
+    if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink)))
+        pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_ADD_OUTPUT, o, 0, NULL);
+    else {
+        /* If the sink is not yet started, we need to do the activation ourselves */
+        PA_LLIST_PREPEND(struct output, u->thread_info.active_outputs, o);
 
-    if (!(o->sink_input = pa_sink_input_new(u->core, &data, PA_SINK_INPUT_VARIABLE_RATE)))
-        goto fail;
+        o->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
+                u->rtpoll,
+                PA_RTPOLL_EARLY-1,  /* This item is very important */
+                o->outq);
+    }
 
-    o->sink_input->get_latency = sink_input_get_latency_cb;
-    o->sink_input->peek = sink_input_peek_cb;
-    o->sink_input->drop = sink_input_drop_cb;
-    o->sink_input->kill = sink_input_kill_cb;
-    o->sink_input->userdata = o;
+    if (PA_SINK_OPENED(pa_sink_get_state(u->sink)) || pa_sink_get_state(u->sink) == PA_SINK_INIT) {
+        pa_sink_suspend(sink, FALSE);
+
+        if (PA_SINK_OPENED(pa_sink_get_state(sink)))
+            if (output_create_sink_input(o) < 0)
+                goto fail;
+    }
+
+
+    update_description(u);
 
-    PA_LLIST_PREPEND(struct output, u->outputs, o);
-    u->n_outputs++;
     return o;
 
 fail:
 
     if (o) {
+        pa_idxset_remove_by_data(u->outputs, o, NULL);
+
         if (o->sink_input) {
-            pa_sink_input_disconnect(o->sink_input);
+            pa_sink_input_unlink(o->sink_input);
             pa_sink_input_unref(o->sink_input);
         }
 
         if (o->memblockq)
             pa_memblockq_free(o->memblockq);
 
+        if (o->inq)
+            pa_asyncmsgq_unref(o->inq);
+
+        if (o->outq)
+            pa_asyncmsgq_unref(o->outq);
+
         pa_xfree(o);
     }
 
     return NULL;
 }
 
-static void output_free(struct output *o) {
-    assert(o);
-    PA_LLIST_REMOVE(struct output, o->userdata->outputs, o);
-    o->userdata->n_outputs--;
-    pa_memblockq_free(o->memblockq);
-    pa_sink_input_disconnect(o->sink_input);
-    pa_sink_input_unref(o->sink_input);
-    pa_xfree(o);
+static pa_hook_result_t sink_new_hook_cb(pa_core *c, pa_sink *s, struct userdata* u) {
+    struct output *o;
+
+    pa_core_assert_ref(c);
+    pa_sink_assert_ref(s);
+    pa_assert(u);
+    pa_assert(u->automatic);
+
+    if (!(s->flags & PA_SINK_HARDWARE) || s == u->sink)
+        return PA_HOOK_OK;
+
+    pa_log_info("Configuring new sink: %s", s->name);
+
+    if (!(o = output_new(u, s))) {
+        pa_log("Failed to create sink input on sink '%s'.", s->name);
+        return PA_HOOK_OK;
+    }
+
+    if (o->sink_input)
+        pa_sink_input_put(o->sink_input);
+
+    pick_master(u, NULL);
+
+    return PA_HOOK_OK;
 }
 
-static void clear_up(struct userdata *u) {
+static pa_hook_result_t sink_unlink_hook_cb(pa_core *c, pa_sink *s, struct userdata* u) {
     struct output *o;
-    assert(u);
+    uint32_t idx;
 
-    if (u->time_event) {
-        u->core->mainloop->time_free(u->time_event);
-        u->time_event = NULL;
-    }
+    pa_assert(c);
+    pa_sink_assert_ref(s);
+    pa_assert(u);
 
-    while ((o = u->outputs))
-        output_free(o);
+    if (s == u->sink)
+        return PA_HOOK_OK;
 
-    u->master = NULL;
+    for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx))
+        if (o->sink == s)
+            break;
 
-    if (u->sink) {
-        pa_sink_disconnect(u->sink);
-        pa_sink_unref(u->sink);
-        u->sink = NULL;
+    if (!o)
+        return PA_HOOK_OK;
+
+    pa_log_info("Unconfiguring sink: %s", s->name);
+
+    output_free(o);
+
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_state_changed_hook_cb(pa_core *c, pa_sink *s, struct userdata* u) {
+    struct output *o;
+    uint32_t idx;
+    pa_sink_state_t state;
+
+    if (s == u->sink)
+        return PA_HOOK_OK;
+
+    for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx))
+        if (o->sink == s)
+            break;
+
+    if (!o)
+        return PA_HOOK_OK;
+
+    state = pa_sink_get_state(s);
+
+    if (PA_SINK_OPENED(state) && PA_SINK_OPENED(pa_sink_get_state(u->sink)) && !o->sink_input) {
+        enable_output(o);
+        pick_master(u, NULL);
+    }
+
+    if (state == PA_SINK_SUSPENDED && o->sink_input) {
+        disable_output(o);
+        pick_master(u, o);
     }
+
+    return PA_HOOK_OK;
 }
 
-int pa__init(pa_core *c, pa_module*m) {
+int pa__init(pa_module*m) {
     struct userdata *u;
     pa_modargs *ma = NULL;
     const char *master_name, *slaves, *rm;
-    pa_sink *master_sink;
-    char *n = NULL;
-    const char*split_state;
-    struct timeval tv;
-    int resample_method = -1;
+    pa_sink *master_sink = NULL;
+    int resample_method = PA_RESAMPLER_TRIVIAL;
     pa_sample_spec ss;
     pa_channel_map map;
+    struct output *o;
+    uint32_t idx;
 
-    assert(c && m);
+    pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
         pa_log("failed to parse module arguments");
@@ -349,116 +935,256 @@ int pa__init(pa_core *c, pa_module*m) {
     }
 
     u = pa_xnew(struct userdata, 1);
+    u->core = m->core;
+    u->module = m;
     m->userdata = u;
     u->sink = NULL;
-    u->n_outputs = 0;
     u->master = NULL;
-    u->module = m;
-    u->core = c;
     u->time_event = NULL;
     u->adjust_time = DEFAULT_ADJUST_TIME;
-    PA_LLIST_HEAD_INIT(struct output, u->outputs);
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
+    u->rtpoll = pa_rtpoll_new();
+    u->thread = NULL;
+    u->resample_method = resample_method;
+    u->outputs = pa_idxset_new(NULL, NULL);
+    memset(&u->adjust_timestamp, 0, sizeof(u->adjust_timestamp));
+    u->sink_new_slot = u->sink_unlink_slot = u->sink_state_changed_slot = NULL;
+    PA_LLIST_HEAD_INIT(struct output, u->thread_info.active_outputs);
+    pa_atomic_store(&u->thread_info.running, FALSE);
+    u->thread_info.in_null_mode = FALSE;
+    pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
 
     if (pa_modargs_get_value_u32(ma, "adjust_time", &u->adjust_time) < 0) {
-        pa_log("failed to parse adjust_time value");
+        pa_log("Failed to parse adjust_time value");
         goto fail;
     }
 
-    if (!(master_name = pa_modargs_get_value(ma, "master", NULL)) || !(slaves = pa_modargs_get_value(ma, "slaves", NULL))) {
-        pa_log("no master or slave sinks specified");
+    master_name = pa_modargs_get_value(ma, "master", NULL);
+    slaves = pa_modargs_get_value(ma, "slaves", NULL);
+    if (!master_name != !slaves) {
+        pa_log("No master or slave sinks specified");
         goto fail;
     }
 
-    if (!(master_sink = pa_namereg_get(c, master_name, PA_NAMEREG_SINK, 1))) {
-        pa_log("invalid master sink '%s'", master_name);
-        goto fail;
+    if (master_name) {
+        if (!(master_sink = pa_namereg_get(m->core, master_name, PA_NAMEREG_SINK, 1))) {
+            pa_log("Invalid master sink '%s'", master_name);
+            goto fail;
+        }
+
+        ss = master_sink->sample_spec;
+        u->automatic = FALSE;
+    } else {
+        master_sink = NULL;
+        ss = m->core->default_sample_spec;
+        u->automatic = TRUE;
     }
 
-    ss = master_sink->sample_spec;
     if ((pa_modargs_get_sample_spec(ma, &ss) < 0)) {
-        pa_log("invalid sample specification.");
+        pa_log("Invalid sample specification.");
         goto fail;
     }
 
-    if (ss.channels == master_sink->sample_spec.channels)
+    if (master_sink && ss.channels == master_sink->sample_spec.channels)
         map = master_sink->channel_map;
     else
         pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_DEFAULT);
 
-    if ((pa_modargs_get_channel_map(ma, &map) < 0)) {
-        pa_log("invalid channel map.");
+    if ((pa_modargs_get_channel_map(ma, NULL, &map) < 0)) {
+        pa_log("Invalid channel map.");
         goto fail;
     }
 
     if (ss.channels != map.channels) {
-        pa_log("channel map and sample specification don't match.");
+        pa_log("Channel map and sample specification don't match.");
         goto fail;
     }
 
-    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;
     }
 
-    pa_sink_set_owner(u->sink, m);
-    pa_sink_set_description(u->sink, "Combined Sink");
+    u->sink->parent.process_msg = sink_process_msg;
     u->sink->get_latency = sink_get_latency_cb;
-    u->sink->notify = sink_notify;
+    u->sink->set_state = sink_set_state;
     u->sink->userdata = u;
 
-    if (!(u->master = output_new(u, master_sink, resample_method))) {
-        pa_log("failed to create master sink input on sink '%s'.", u->sink->name);
-        goto fail;
-    }
+    u->sink->flags = PA_SINK_LATENCY;
+    pa_sink_set_module(u->sink, m);
+    pa_sink_set_description(u->sink, "Simultaneous output");
+    pa_sink_set_rtpoll(u->sink, u->rtpoll);
+    pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
+
+    u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */
+    if (u->block_size <= 0)
+        u->block_size = pa_frame_size(&ss);
 
-    split_state = NULL;
-    while ((n = pa_split(slaves, ",", &split_state))) {
-        pa_sink *slave_sink;
+    if (!u->automatic) {
+        const char*split_state;
+        char *n = NULL;
+        pa_assert(slaves);
 
-        if (!(slave_sink = pa_namereg_get(c, n, PA_NAMEREG_SINK, 1))) {
-            pa_log("invalid slave sink '%s'", n);
+        /* The master and slaves have been specified manually */
+
+        if (!(u->master = output_new(u, master_sink))) {
+            pa_log("Failed to create master sink input on sink '%s'.", master_sink->name);
             goto fail;
         }
 
-        pa_xfree(n);
+        split_state = NULL;
+        while ((n = pa_split(slaves, ",", &split_state))) {
+            pa_sink *slave_sink;
 
-        if (!output_new(u, slave_sink, resample_method)) {
-            pa_log("failed to create slave sink input on sink '%s'.", slave_sink->name);
-            goto fail;
+            if (!(slave_sink = pa_namereg_get(m->core, n, PA_NAMEREG_SINK, 1)) || slave_sink == u->sink) {
+                pa_log("Invalid slave sink '%s'", n);
+                pa_xfree(n);
+                goto fail;
+            }
+
+            pa_xfree(n);
+
+            if (!output_new(u, slave_sink)) {
+                pa_log("Failed to create slave sink input on sink '%s'.", slave_sink->name);
+                goto fail;
+            }
         }
+
+        if (pa_idxset_size(u->outputs) <= 1)
+            pa_log_warn("No slave sinks specified.");
+
+        u->sink_new_slot = NULL;
+
+    } else {
+        pa_sink *s;
+
+        /* We're in automatic mode, we elect one hw sink to the master
+         * and attach all other hw sinks as slaves to it */
+
+        for (s = pa_idxset_first(m->core->sinks, &idx); s; s = pa_idxset_next(m->core->sinks, &idx)) {
+
+            if (!(s->flags & PA_SINK_HARDWARE) || s == u->sink)
+                continue;
+
+            if (!output_new(u, s)) {
+                pa_log("Failed to create sink input on sink '%s'.", s->name);
+                goto fail;
+            }
+        }
+
+        u->sink_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_NEW_POST], (pa_hook_cb_t) sink_new_hook_cb, u);
     }
 
-    if (u->n_outputs <= 1)
-        pa_log_warn("WARNING: no slave sinks specified.");
+    u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], (pa_hook_cb_t) sink_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) sink_state_changed_hook_cb, u);
+
+    pick_master(u, NULL);
+
+    if (!(u->thread = pa_thread_new(thread_func, u))) {
+        pa_log("Failed to create thread.");
+        goto fail;
+    }
+
+    /* Activate the sink and the sink inputs */
+    pa_sink_put(u->sink);
+
+    for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx))
+        if (o->sink_input)
+            pa_sink_input_put(o->sink_input);
 
     if (u->adjust_time > 0) {
+        struct timeval tv;
         pa_gettimeofday(&tv);
         tv.tv_sec += u->adjust_time;
-        u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u);
+        u->time_event = m->core->mainloop->time_new(m->core->mainloop, &tv, time_callback, u);
     }
 
     pa_modargs_free(ma);
+
     return 0;
 
 fail:
-    pa_xfree(n);
 
     if (ma)
         pa_modargs_free(ma);
 
-    pa__done(c, m);
+    pa__done(m);
+
     return -1;
 }
 
-void pa__done(pa_core *c, pa_module*m) {
+static void output_free(struct output *o) {
+    pa_assert(o);
+
+    pick_master(o->userdata, o);
+
+    disable_output(o);
+
+    pa_assert_se(pa_idxset_remove_by_data(o->userdata->outputs, o, NULL));
+
+    update_description(o->userdata);
+
+    if (o->inq_rtpoll_item)
+        pa_rtpoll_item_free(o->inq_rtpoll_item);
+
+    if (o->outq_rtpoll_item)
+        pa_rtpoll_item_free(o->outq_rtpoll_item);
+
+    if (o->inq)
+        pa_asyncmsgq_unref(o->inq);
+
+    if (o->outq)
+        pa_asyncmsgq_unref(o->outq);
+
+    if (o->memblockq)
+        pa_memblockq_free(o->memblockq);
+
+    pa_xfree(o);
+}
+
+void pa__done(pa_module*m) {
     struct userdata *u;
-    assert(c && m);
+    struct output *o;
+
+    pa_assert(m);
 
     if (!(u = m->userdata))
         return;
 
-    clear_up(u);
-    pa_xfree(u);
-}
+    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->outputs) {
+        while ((o = pa_idxset_first(u->outputs, NULL)))
+            output_free(o);
+
+        pa_idxset_free(u->outputs, NULL, NULL);
+    }
 
+    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->rtpoll)
+        pa_rtpoll_free(u->rtpoll);
+
+    if (u->time_event)
+        u->core->mainloop->time_free(u->time_event);
+
+    pa_xfree(u);
+}
diff --git a/src/modules/module-default-device-restore.c b/src/modules/module-default-device-restore.c
new file mode 100644 (file)
index 0000000..a816eae
--- /dev/null
@@ -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);
+    }
+}
+
+
+
index c961412d8b956992299f49f2663540123853b833..5bff748e3abe2d13e4853dbc74c9890b54fd68f1 100644 (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);
index 41b68ac3e826cfabc8de536cc8d00c3063d82731..7dc2524347fb23d5f772fb9cca9123d3100c6422 100644 (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 */
-}
-
index 1aecade506248324b3f3e6abe5ec382501970d4b..f0f73fcf386744f0a7b59ed0ddbeae005e91c262 100644 (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);
-}
-
-
index a9fd166d4b74c81cbab08e8e3ede67fe4e79b37d..6562fe281739eca1cf4a7b35540f755ba96fc499 100644 (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);
-}
-
-
index 26638d9dc31445f9d492c3a7a454d9dfca6f25de..8b46637e1858cb1ba5fac75dc3525ae4e43a63d0 100644 (file)
 #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>
 #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) {
 
-    if (u->defer_event) {
-        u->core->mainloop->defer_free(u->defer_event);
-        u->defer_event = NULL;
-    }
+        case PA_SINK_MESSAGE_SET_STATE:
 
-    if (u->sink) {
-        pa_sink_disconnect(u->sink);
-        pa_sink_unref(u->sink);
-        u->sink = NULL;
+            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->module) {
-        pa_module_unload_request(u->module);
-        u->module = 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;
+            }
+        }
     }
+
+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 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);
+static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
+    struct userdata *u = userdata;
+    pa_assert(u);
 
-    return
-        u->latency +
-        (u->memchunk.memblock ? pa_bytes_to_usec(u->memchunk.length, &s->sample_spec) : 0);
-}
+    if (do_read(u) < 0 || do_write(u) < 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);
-}
+        if (u->io) {
+            pa_iochannel_free(u->io);
+            u->io = NULL;
+        }
 
-static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
-    struct userdata *u = userdata;
-    assert(u);
-    do_work(u);
+       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);
 
-    pa_xfree(u);
-}
-
+    if (u->smoother)
+        pa_smoother_free(u->smoother);
 
+    if (u->fd >= 0)
+        pa_close(u->fd);
 
+    pa_xfree(u);
+}
index 1f48a452e795107e5f6025b806c0b976744eca38..a8ca7df3697d1f3ec02d6fe226389cfa4ce32bc8 100644 (file)
@@ -1,25 +1,25 @@
 /* $Id$ */
 
 /***
-  This file is part of PulseAudio.
+    This file is part of PulseAudio.
 
-  Copyright 2006 Lennart Poettering
-  Copyright 2006 Shams E. King
+    Copyright 2006 Lennart Poettering
+    Copyright 2006 Shams E. King
 
-  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 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.
+    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.
+    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
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <unistd.h>
 #include <string.h>
 #include <stdlib.h>
@@ -45,6 +44,9 @@
 #include <pulsecore/hashmap.h>
 #include <pulsecore/idxset.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/namereg.h>
+#include <pulsecore/core-scache.h>
+#include <pulsecore/modargs.h>
 
 #include <hal/libhal.h>
 
 PA_MODULE_AUTHOR("Shahms King")
 PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers")
 PA_MODULE_VERSION(PACKAGE_VERSION)
-
-typedef enum {
-#ifdef HAVE_ALSA
-    CAP_ALSA,
-#endif
-#ifdef HAVE_OSS
-    CAP_OSS,
-#endif
-    CAP_MAX
-} capability_t;
-
-static const char* const capabilities[CAP_MAX] = {
-#ifdef HAVE_ALSA
-    [CAP_ALSA] = "alsa",
-#endif
-#ifdef HAVE_OSS
-    [CAP_OSS] = "oss",
+#if defined(HAVE_ALSA) && defined(HAVE_OSS)
+PA_MODULE_USAGE("api=<alsa or oss>")
+#elif defined(HAVE_ALSA)
+PA_MODULE_USAGE("api=<alsa>")
+#elif defined(HAVE_OSS)
+PA_MODULE_USAGE("api=<oss>")
 #endif
-};
 
 struct device {
     uint32_t index;
     char *udi;
+    char *sink_name, *source_name;
+    int acl_race_fix;
 };
 
 struct userdata {
     pa_core *core;
-    LibHalContext *ctx;
-    capability_t capability;
-    pa_dbus_connection *conn;
+    LibHalContext *context;
+    pa_dbus_connection *connection;
     pa_hashmap *devices;
-#if defined(HAVE_ALSA) && defined(HAVE_OSS)
-    int use_oss;
-#endif
+    const char *capability;
 };
 
 struct timerdata {
@@ -95,23 +84,30 @@ struct timerdata {
     char *udi;
 };
 
-static const char* get_capability_name(capability_t cap) {
-    if (cap >= CAP_MAX)
-        return NULL;
-    return capabilities[cap];
-}
+#define CAPABILITY_ALSA "alsa"
+#define CAPABILITY_OSS "oss"
+
+static const char* const valid_modargs[] = {
+    "api",
+    NULL
+};
 
 static void hal_device_free(struct device* d) {
+    pa_assert(d);
+
     pa_xfree(d->udi);
+    pa_xfree(d->sink_name);
+    pa_xfree(d->source_name);
     pa_xfree(d);
 }
 
 static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) {
-    hal_device_free((struct device*) d);
+    hal_device_free(d);
 }
 
 static const char *strip_udi(const char *udi) {
     const char *slash;
+
     if ((slash = strrchr(udi, '/')))
         return slash+1;
 
@@ -119,6 +115,7 @@ static const char *strip_udi(const char *udi) {
 }
 
 #ifdef HAVE_ALSA
+
 typedef enum {
     ALSA_TYPE_SINK,
     ALSA_TYPE_SOURCE,
@@ -126,234 +123,297 @@ typedef enum {
     ALSA_TYPE_MAX
 } alsa_type_t;
 
-static alsa_type_t hal_device_get_alsa_type(LibHalContext *ctx, const char *udi,
-                                            DBusError *error)
-{
+static alsa_type_t hal_alsa_device_get_type(LibHalContext *context, const char *udi, DBusError *error) {
     char *type;
     alsa_type_t t;
 
-    type = libhal_device_get_property_string(ctx, udi, "alsa.type", error);
-    if (!type || dbus_error_is_set(error))
-        return FALSE;
+    if (!(type = libhal_device_get_property_string(context, udi, "alsa.type", error)))
+        return ALSA_TYPE_OTHER;
 
-    if (!strcmp(type, "playback")) {
+    if (!strcmp(type, "playback"))
         t = ALSA_TYPE_SINK;
-    } else if (!strcmp(type, "capture")) {
+    else if (!strcmp(type, "capture"))
         t = ALSA_TYPE_SOURCE;
-    } else {
+    else
         t = ALSA_TYPE_OTHER;
-    }
+
     libhal_free_string(type);
 
     return t;
 }
 
-static int hal_device_get_alsa_card(LibHalContext *ctx, const char *udi,
-                                    DBusError *error)
-{
-    return libhal_device_get_property_int(ctx, udi, "alsa.card", error);
-}
+static int hal_alsa_device_is_modem(LibHalContext *context, const char *udi, DBusError *error) {
+    char *class;
+    int r;
+
+    if (!(class = libhal_device_get_property_string(context, udi, "alsa.pcm_class", error)))
+        return 0;
+
+    r = strcmp(class, "modem") == 0;
+    pa_xfree(class);
 
-static int hal_device_get_alsa_device(LibHalContext *ctx, const char *udi,
-                                      DBusError *error)
-{
-    return libhal_device_get_property_int(ctx, udi, "alsa.device", error);
+    return r;
 }
 
-static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi,
-                                       DBusError  *error)
-{
-    char args[128];
+static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, char **sink_name, char **source_name) {
+    char *args;
     alsa_type_t type;
     int device, card;
     const char *module_name;
+    DBusError error;
+    pa_module *m;
 
-    type = hal_device_get_alsa_type(u->ctx, udi, error);
-    if (dbus_error_is_set(error) || type == ALSA_TYPE_OTHER)
-        return NULL;
+    dbus_error_init(&error);
 
-    device = hal_device_get_alsa_device(u->ctx, udi, error);
-    if (dbus_error_is_set(error) || device != 0)
-        return NULL;
+    pa_assert(u);
+    pa_assert(sink_name);
+    pa_assert(source_name);
 
-    card = hal_device_get_alsa_card(u->ctx, udi, error);
-    if (dbus_error_is_set(error))
-        return NULL;
+    *sink_name = *source_name = NULL;
+
+    type = hal_alsa_device_get_type(u->context, udi, &error);
+    if (dbus_error_is_set(&error) || type == ALSA_TYPE_OTHER)
+        goto fail;
+
+    device = libhal_device_get_property_int(u->context, udi, "alsa.device", &error);
+    if (dbus_error_is_set(&error) || device != 0)
+        goto fail;
+
+    card = libhal_device_get_property_int(u->context, udi, "alsa.card", &error);
+    if (dbus_error_is_set(&error))
+        goto fail;
+
+    if (hal_alsa_device_is_modem(u->context, udi, &error))
+        goto fail;
 
     if (type == ALSA_TYPE_SINK) {
+        *sink_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi));
+
         module_name = "module-alsa-sink";
-        snprintf(args, sizeof(args), "device=hw:%u sink_name=alsa_output.%s", card, strip_udi(udi));
+        args = pa_sprintf_malloc("device=hw:%u sink_name=%s", card, *sink_name);
     } else {
+        *source_name = pa_sprintf_malloc("alsa_input.%s", strip_udi(udi));
+
         module_name = "module-alsa-source";
-        snprintf(args, sizeof(args), "device=hw:%u source_name=alsa_input.%s", card, strip_udi(udi));
+        args = pa_sprintf_malloc("device=hw:%u source_name=%s", card, *source_name);
     }
 
     pa_log_debug("Loading %s with arguments '%s'", module_name, args);
 
-    return pa_module_load(u->core, module_name, args);
+    m = pa_module_load(u->core, module_name, args);
+
+    pa_xfree(args);
+
+    if (!m) {
+        pa_xfree(*sink_name);
+        pa_xfree(*source_name);
+        *sink_name = *source_name = NULL;
+    }
+
+    return m;
+
+fail:
+    if (dbus_error_is_set(&error)) {
+        pa_log_error("D-Bus error while parsing ALSA data: %s: %s", error.name, error.message);
+        dbus_error_free(&error);
+    }
+
+    return NULL;
 }
 
 #endif
 
 #ifdef HAVE_OSS
-static dbus_bool_t hal_device_is_oss_pcm(LibHalContext *ctx, const char *udi,
-                                         DBusError *error)
-{
-    dbus_bool_t rv = FALSE;
-    char* type, *device_file = NULL;
+
+static int hal_oss_device_is_pcm(LibHalContext *context, const char *udi, DBusError *error) {
+    char *class = NULL, *dev = NULL, *e;
     int device;
+    int r = 0;
 
-    type = libhal_device_get_property_string(ctx, udi, "oss.type", error);
-    if (!type || dbus_error_is_set(error))
-        return FALSE;
+    class = libhal_device_get_property_string(context, udi, "oss.type", error);
+    if (dbus_error_is_set(error) || !class)
+        goto finish;
 
-    if (!strcmp(type, "pcm")) {
-        char *e;
+    if (strcmp(class, "pcm"))
+        goto finish;
 
-        device = libhal_device_get_property_int(ctx, udi, "oss.device", error);
-        if (dbus_error_is_set(error) || device != 0)
-            goto exit;
+    dev = libhal_device_get_property_string(context, udi, "oss.device_file", error);
+    if (dbus_error_is_set(error) || !dev)
+        goto finish;
 
-        device_file = libhal_device_get_property_string(ctx, udi, "oss.device_file",
-                                                   error);
-        if (!device_file || dbus_error_is_set(error))
-            goto exit;
+    if ((e = strrchr(dev, '/')))
+        if (pa_startswith(e + 1, "audio"))
+            goto finish;
 
-        /* hack to ignore /dev/audio style devices */
-        if ((e = strrchr(device_file, '/')))
-            rv = !pa_startswith(e + 1, "audio");
-    }
+    device = libhal_device_get_property_int(context, udi, "oss.device", error);
+    if (dbus_error_is_set(error) || device != 0)
+        goto finish;
 
-exit:
-    libhal_free_string(type);
-    libhal_free_string(device_file);
-    return rv;
+    r = 1;
+
+finish:
+
+    libhal_free_string(class);
+    libhal_free_string(dev);
+
+    return r;
 }
 
-static pa_module* hal_device_load_oss(struct userdata *u, const char *udi,
-                                      DBusError  *error)
-{
-    char args[256];
+static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, char **sink_name, char **source_name) {
+    char* args;
     char* device;
+    DBusError error;
+    pa_module *m;
 
-    if (!hal_device_is_oss_pcm(u->ctx, udi, error) || dbus_error_is_set(error))
-        return NULL;
+    dbus_error_init(&error);
 
-    device = libhal_device_get_property_string(u->ctx, udi, "oss.device_file",
-                                               error);
-    if (!device || dbus_error_is_set(error))
-        return NULL;
+    pa_assert(u);
+    pa_assert(sink_name);
+    pa_assert(source_name);
+
+    *sink_name = *source_name = NULL;
 
-    snprintf(args, sizeof(args), "device=%s sink_name=oss_output.%s source_name=oss_input.%s", device, strip_udi(udi), strip_udi(udi));
+    if (!hal_oss_device_is_pcm(u->context, udi, &error) || dbus_error_is_set(&error))
+        goto fail;
+
+    device = libhal_device_get_property_string(u->context, udi, "oss.device_file", &error);
+    if (!device || dbus_error_is_set(&error))
+        goto fail;
+
+    *sink_name = pa_sprintf_malloc("oss_output.%s", strip_udi(udi));
+    *source_name = pa_sprintf_malloc("oss_input.%s", strip_udi(udi));
+
+    args = pa_sprintf_malloc("device=%s sink_name=%s source_name=%s", device, *sink_name, *source_name);
     libhal_free_string(device);
 
     pa_log_debug("Loading module-oss with arguments '%s'", args);
+    m = pa_module_load(u->core, "module-oss", args);
+    pa_xfree(args);
+
+    if (!m) {
+        pa_xfree(*sink_name);
+        pa_xfree(*source_name);
+        *sink_name = *source_name = NULL;
+    }
+
+    return m;
+
+fail:
+    if (dbus_error_is_set(&error)) {
+        pa_log_error("D-Bus error while parsing OSS data: %s: %s", error.name, error.message);
+        dbus_error_free(&error);
+    }
 
-    return pa_module_load(u->core, "module-oss", args);
+    return NULL;
 }
 #endif
 
-static dbus_bool_t hal_device_add(struct userdata *u, const char *udi,
-                                  DBusError *error)
-{
+static struct device* hal_device_add(struct userdata *u, const char *udi) {
     pa_module* m = NULL;
     struct device *d;
+    char *sink_name = NULL, *source_name = NULL;
+
+    pa_assert(u);
+    pa_assert(u->capability);
+    pa_assert(!pa_hashmap_get(u->devices, udi));
 
-    switch(u->capability) {
 #ifdef HAVE_ALSA
-        case CAP_ALSA:
-            m = hal_device_load_alsa(u, udi, error);
-            break;
+    if (strcmp(u->capability, CAPABILITY_ALSA) == 0)
+        m = hal_device_load_alsa(u, udi, &sink_name, &source_name);
 #endif
 #ifdef HAVE_OSS
-        case CAP_OSS:
-#ifdef HAVE_ALSA
-            if (u->use_oss)
-#endif
-                m = hal_device_load_oss(u, udi, error);
-            break;
+    if (strcmp(u->capability, CAPABILITY_OSS) == 0)
+        m = hal_device_load_oss(u, udi, &sink_name, &source_name);
 #endif
-        default:
-            assert(FALSE); /* never reached */
-            break;
-    }
 
-    if (!m || dbus_error_is_set(error))
-        return FALSE;
+    if (!m)
+        return NULL;
 
     d = pa_xnew(struct device, 1);
+    d->acl_race_fix = 0;
     d->udi = pa_xstrdup(udi);
     d->index = m->index;
-
+    d->sink_name = sink_name;
+    d->source_name = source_name;
     pa_hashmap_put(u->devices, d->udi, d);
 
-    return TRUE;
+    return d;
 }
 
-static int hal_device_add_all(struct userdata *u, capability_t capability)
-{
+static int hal_device_add_all(struct userdata *u, const char *capability) {
     DBusError error;
-    int i,n,count;
-    dbus_bool_t r;
+    int i, n, count = 0;
     char** udis;
-    const char* cap = get_capability_name(capability);
 
-    assert(capability < CAP_MAX);
+    pa_assert(u);
 
-    pa_log_info("Trying capability %u (%s)", capability, cap);
     dbus_error_init(&error);
-    udis = libhal_find_device_by_capability(u->ctx, cap, &n, &error);
+
+    if (u->capability && strcmp(u->capability, capability) != 0)
+        return 0;
+
+    pa_log_info("Trying capability %s", capability);
+
+    udis = libhal_find_device_by_capability(u->context, capability, &n, &error);
     if (dbus_error_is_set(&error)) {
-        pa_log_error("Error finding devices: %s: %s", error.name,
-                     error.message);
+        pa_log_error("Error finding devices: %s: %s", error.name, error.message);
         dbus_error_free(&error);
         return -1;
     }
-    count = 0;
-    u->capability = capability;
-    for (i = 0; i < n; ++i) {
-        r = hal_device_add(u, udis[i], &error);
-        if (dbus_error_is_set(&error)) {
-            pa_log_error("Error adding device: %s: %s", error.name,
-                         error.message);
-            dbus_error_free(&error);
-            count = -1;
-            break;
+
+    if (n > 0) {
+        u->capability = capability;
+
+        for (i = 0; i < n; i++) {
+            struct device *d;
+
+            if (!(d = hal_device_add(u, udis[i])))
+                pa_log_debug("Not loaded device %s", udis[i]);
+            else {
+                if (d->sink_name)
+                    pa_scache_play_item_by_name(u->core, "pulse-coldplug", d->sink_name, PA_VOLUME_NORM, 0);
+                count++;
+            }
         }
-        if (r)
-            ++count;
     }
 
     libhal_free_string_array(udis);
     return count;
 }
 
-static dbus_bool_t device_has_capability(LibHalContext *ctx, const char *udi,
-                                         const char* cap, DBusError *error)
-{
+static dbus_bool_t device_has_capability(LibHalContext *context, const char *udi, const char* cap, DBusError *error){
     dbus_bool_t has_prop;
-    has_prop = libhal_device_property_exists(ctx, udi, "info.capabilities",
-                                             error);
+
+    has_prop = libhal_device_property_exists(context, udi, "info.capabilities", error);
     if (!has_prop || dbus_error_is_set(error))
         return FALSE;
 
-    return libhal_device_query_capability(ctx, udi, cap, error);
+    return libhal_device_query_capability(context, udi, cap, error);
 }
 
-static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev,
-                                 const struct timeval *tv, void *userdata)
-{
+static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, const struct timeval *tv, void *userdata) {
     DBusError error;
-    struct timerdata *td = (struct timerdata*) userdata;
+    struct timerdata *td = userdata;
 
     dbus_error_init(&error);
-    if (libhal_device_exists(td->u->ctx, td->udi, &error))
-        hal_device_add(td->u, td->udi, &error);
 
-    if (dbus_error_is_set(&error)) {
-        pa_log_error("Error adding device: %s: %s", error.name,
-                     error.message);
-        dbus_error_free(&error);
+    if (!pa_hashmap_get(td->u->devices, td->udi)) {
+        int b;
+        struct device *d;
+
+        b = libhal_device_exists(td->u->context, td->udi, &error);
+
+        if (dbus_error_is_set(&error)) {
+            pa_log_error("Error adding device: %s: %s", error.name, error.message);
+            dbus_error_free(&error);
+        } else if (b) {
+            if (!(d = hal_device_add(td->u, td->udi)))
+                pa_log_debug("Not loaded device %s", td->udi);
+            else {
+                if (d->sink_name)
+                    pa_scache_play_item_by_name(td->u->core, "pulse-hotplug", d->sink_name, PA_VOLUME_NORM, 0);
+            }
+        }
     }
 
     pa_xfree(td->udi);
@@ -361,28 +421,68 @@ static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev,
     ea->time_free(ev);
 }
 
-static void device_added_cb(LibHalContext *ctx, const char *udi)
-{
+static void device_added_cb(LibHalContext *context, const char *udi) {
     DBusError error;
     struct timeval tv;
-    dbus_bool_t has_cap;
     struct timerdata *t;
-    struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx);
-    const char* cap = get_capability_name(u->capability);
+    struct userdata *u;
+    int good = 0;
+
+    pa_assert_se(u = libhal_ctx_get_user_data(context));
+
+    if (pa_hashmap_get(u->devices, udi))
+        return;
 
     pa_log_debug("HAL Device added: %s", udi);
 
     dbus_error_init(&error);
-    has_cap = device_has_capability(ctx, udi, cap, &error);
-    if (dbus_error_is_set(&error)) {
-        pa_log_error("Error getting capability: %s: %s", error.name,
-                     error.message);
-        dbus_error_free(&error);
-        return;
+
+    if (u->capability) {
+
+        good = device_has_capability(context, udi, u->capability, &error);
+
+        if (dbus_error_is_set(&error)) {
+            pa_log_error("Error getting capability: %s: %s", error.name, error.message);
+            dbus_error_free(&error);
+            return;
+        }
+
+    } else {
+
+#ifdef HAVE_ALSA
+        good = device_has_capability(context, udi, CAPABILITY_ALSA, &error);
+
+        if (dbus_error_is_set(&error)) {
+            pa_log_error("Error getting capability: %s: %s", error.name, error.message);
+            dbus_error_free(&error);
+            return;
+        }
+
+        if (good)
+            u->capability = CAPABILITY_ALSA;
+#endif
+#if defined(HAVE_OSS) && defined(HAVE_ALSA)
+        if (!good) {
+#endif
+#ifdef HAS_OSS
+            good = device_has_capability(context, udi, CAPABILITY_OSS, &error);
+
+            if (dbus_error_is_set(&error)) {
+                pa_log_error("Error getting capability: %s: %s", error.name, error.message);
+                dbus_error_free(&error);
+                return;
+            }
+
+            if (good)
+                u->capability = CAPABILITY_OSS;
+
+#endif
+#if defined(HAVE_OSS) && defined(HAVE_ALSA)
+        }
+#endif
     }
 
-    /* skip it */
-    if (!has_cap)
+    if (!good)
         return;
 
     /* actually add the device 1/2 second later */
@@ -392,187 +492,359 @@ static void device_added_cb(LibHalContext *ctx, const char *udi)
 
     pa_gettimeofday(&tv);
     pa_timeval_add(&tv, 500000);
-    u->core->mainloop->time_new(u->core->mainloop, &tv,
-                                device_added_time_cb, t);
+    u->core->mainloop->time_new(u->core->mainloop, &tv, device_added_time_cb, t);
 }
 
-static void device_removed_cb(LibHalContext* ctx, const char *udi)
-{
+static void device_removed_cb(LibHalContext* context, const char *udi) {
     struct device *d;
-    struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx);
+    struct userdata *u;
+
+    pa_assert_se(u = libhal_ctx_get_user_data(context));
 
     pa_log_debug("Device removed: %s", udi);
+
     if ((d = pa_hashmap_remove(u->devices, udi))) {
         pa_module_unload_by_index(u->core, d->index);
         hal_device_free(d);
     }
 }
 
-static void new_capability_cb(LibHalContext *ctx, const char *udi,
-                              const char* capability)
-{
-    struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx);
-    const char* capname = get_capability_name(u->capability);
+static void new_capability_cb(LibHalContext *context, const char *udi, const char* capability) {
+    struct userdata *u;
+
+    pa_assert_se(u = libhal_ctx_get_user_data(context));
 
-    if (capname && !strcmp(capname, capability)) {
+    if (!u->capability || strcmp(u->capability, capability) == 0)
         /* capability we care about, pretend it's a new device */
-        device_added_cb(ctx, udi);
-    }
+        device_added_cb(context, udi);
 }
 
-static void lost_capability_cb(LibHalContext *ctx, const char *udi,
-                               const char* capability)
-{
-    struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx);
-    const char* capname = get_capability_name(u->capability);
+static void lost_capability_cb(LibHalContext *context, const char *udi, const char* capability) {
+    struct userdata *u;
 
-    if (capname && !strcmp(capname, capability)) {
-        /* capability we care about, pretend it was removed */
-        device_removed_cb(ctx, udi);
-    }
-}
+    pa_assert_se(u = libhal_ctx_get_user_data(context));
 
-#if 0
-static void property_modified_cb(LibHalContext *ctx, const char *udi,
-                                 const char* key,
-                                 dbus_bool_t is_removed,
-                                 dbus_bool_t is_added)
-{
+    if (u->capability && strcmp(u->capability, capability) == 0)
+        /* capability we care about, pretend it was removed */
+        device_removed_cb(context, udi);
 }
-#endif
 
-static void pa_hal_context_free(LibHalContext* hal_ctx)
-{
+static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata) {
+    struct userdata*u = userdata;
     DBusError error;
 
+    pa_assert(bus);
+    pa_assert(message);
+    pa_assert(u);
+
     dbus_error_init(&error);
-    libhal_ctx_shutdown(hal_ctx, &error);
-    libhal_ctx_free(hal_ctx);
 
-    if (dbus_error_is_set(&error)) {
-        dbus_error_free(&error);
+    pa_log_debug("dbus: interface=%s, path=%s, member=%s\n",
+                 dbus_message_get_interface(message),
+                 dbus_message_get_path(message),
+                 dbus_message_get_member(message));
+
+    if (dbus_message_is_signal(message, "org.freedesktop.Hal.Device.AccessControl", "ACLAdded") ||
+        dbus_message_is_signal(message, "org.freedesktop.Hal.Device.AccessControl", "ACLRemoved")) {
+        uint32_t uid;
+        int suspend = strcmp(dbus_message_get_member(message), "ACLRemoved") == 0;
+
+        if (!dbus_message_get_args(message, &error, DBUS_TYPE_UINT32, &uid, DBUS_TYPE_INVALID) || dbus_error_is_set(&error)) {
+            pa_log_error("Failed to parse ACL message: %s: %s", error.name, error.message);
+            goto finish;
+        }
+
+        if (uid == getuid() || uid == geteuid()) {
+            struct device *d;
+            const char *udi;
+
+            udi = dbus_message_get_path(message);
+
+            if ((d = pa_hashmap_get(u->devices, udi))) {
+                int send_acl_race_fix_message = 0;
+
+                d->acl_race_fix = 0;
+
+                if (d->sink_name) {
+                    pa_sink *sink;
+
+                    if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK, 0))) {
+                        int prev_suspended = pa_sink_get_state(sink) == PA_SINK_SUSPENDED;
+
+                        if (prev_suspended && !suspend) {
+                            /* resume */
+                            if (pa_sink_suspend(sink, 0) >= 0)
+                                pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, 0);
+                            else
+                                d->acl_race_fix = 1;
+
+                        } else if (!prev_suspended && suspend) {
+                            /* suspend */
+                            if (pa_sink_suspend(sink, 1) >= 0)
+                                send_acl_race_fix_message = 1;
+                        }
+                    }
+                }
+
+                if (d->source_name) {
+                    pa_source *source;
+
+                    if ((source = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_SOURCE, 0))) {
+                        int prev_suspended = pa_source_get_state(source) == PA_SOURCE_SUSPENDED;
+
+                        if (prev_suspended && !suspend) {
+                            /* resume */
+                            if (pa_source_suspend(source, 0) < 0)
+                                d->acl_race_fix = 1;
+
+                        } else if (!prev_suspended && suspend) {
+                            /* suspend */
+                            if (pa_source_suspend(source, 0) >= 0)
+                                send_acl_race_fix_message = 1;
+                        }
+                    }
+                }
+
+                if (send_acl_race_fix_message) {
+                    DBusMessage *msg;
+                    msg = dbus_message_new_signal(udi, "org.pulseaudio.Server", "DirtyGiveUpMessage");
+                    dbus_connection_send(pa_dbus_connection_get(u->connection), msg, NULL);
+                    dbus_message_unref(msg);
+                }
+
+            } else if (!suspend)
+                device_added_cb(u->context, udi);
+        }
+
+    } else if (dbus_message_is_signal(message, "org.pulseaudio.Server", "DirtyGiveUpMessage")) {
+        /* We use this message to avoid a dirty race condition when we
+           get an ACLAdded message before the previously owning PA
+           sever has closed the device. We can remove this as
+           soon as HAL learns frevoke() */
+
+        const char *udi;
+        struct device *d;
+
+        udi = dbus_message_get_path(message);
+
+        if ((d = pa_hashmap_get(u->devices, udi)) && d->acl_race_fix) {
+            pa_log_debug("Got dirty give up message for '%s', trying resume ...", udi);
+
+            d->acl_race_fix = 0;
+
+            if (d->sink_name) {
+                pa_sink *sink;
+
+                if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK, 0))) {
+
+                    int prev_suspended = pa_sink_get_state(sink) == PA_SINK_SUSPENDED;
+
+                    if (prev_suspended) {
+                        /* resume */
+                        if (pa_sink_suspend(sink, 0) >= 0)
+                            pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, 0);
+                    }
+                }
+            }
+
+            if (d->source_name) {
+                pa_source *source;
+
+                if ((source = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_SOURCE, 0))) {
+
+                    int prev_suspended = pa_source_get_state(source) == PA_SOURCE_SUSPENDED;
+
+                    if (prev_suspended)
+                        pa_source_suspend(source, 0);
+                }
+            }
+
+        } else
+            /* Yes, we don't check the UDI for validity, but hopefully HAL will */
+            device_added_cb(u->context, udi);
     }
+
+finish:
+    dbus_error_free(&error);
+
+    return DBUS_HANDLER_RESULT_HANDLED;
 }
 
-static void userdata_free(struct userdata *u) {
-    pa_hal_context_free(u->ctx);
-    /* free the devices with the hashmap */
-    pa_hashmap_free(u->devices, hal_device_free_cb, NULL);
-    pa_dbus_connection_unref(u->conn);
-    pa_xfree(u);
+static void hal_context_free(LibHalContext* hal_context) {
+    DBusError error;
+
+    dbus_error_init(&error);
+
+    libhal_ctx_shutdown(hal_context, &error);
+    libhal_ctx_free(hal_context);
+
+    dbus_error_free(&error);
 }
 
-static LibHalContext* pa_hal_context_new(pa_core* c, DBusConnection *conn)
-{
+static LibHalContext* hal_context_new(pa_core* c, DBusConnection *conn) {
     DBusError error;
-    LibHalContext *hal_ctx = NULL;
+    LibHalContext *hal_context = NULL;
 
     dbus_error_init(&error);
-    if (!(hal_ctx = libhal_ctx_new())) {
+
+    if (!(hal_context = libhal_ctx_new())) {
         pa_log_error("libhal_ctx_new() failed");
         goto fail;
     }
 
-    if (!libhal_ctx_set_dbus_connection(hal_ctx, conn)) {
-        pa_log_error("Error establishing DBUS connection: %s: %s",
-                     error.name, error.message);
+    if (!libhal_ctx_set_dbus_connection(hal_context, conn)) {
+        pa_log_error("Error establishing DBUS connection: %s: %s", error.name, error.message);
         goto fail;
     }
 
-    if (!libhal_ctx_init(hal_ctx, &error)) {
-        pa_log_error("Couldn't connect to hald: %s: %s",
-                     error.name, error.message);
+    if (!libhal_ctx_init(hal_context, &error)) {
+        pa_log_error("Couldn't connect to hald: %s: %s", error.name, error.message);
         goto fail;
     }
 
-    return hal_ctx;
+    return hal_context;
 
 fail:
-    if (hal_ctx)
-        pa_hal_context_free(hal_ctx);
+    if (hal_context)
+        hal_context_free(hal_context);
 
-    if (dbus_error_is_set(&error))
-        dbus_error_free(&error);
+    dbus_error_free(&error);
 
     return NULL;
 }
 
-int pa__init(pa_core *c, pa_module*m) {
+int pa__init(pa_module*m) {
     DBusError error;
     pa_dbus_connection *conn;
     struct userdata *u = NULL;
-    LibHalContext *hal_ctx = NULL;
+    LibHalContext *hal_context = NULL;
     int n = 0;
+    pa_modargs *ma;
+    const char *api;
 
-    assert(c);
-    assert(m);
+    pa_assert(m);
 
     dbus_error_init(&error);
-    if (!(conn = pa_dbus_bus_get(c, DBUS_BUS_SYSTEM, &error))) {
-        pa_log_error("Unable to contact DBUS system bus: %s: %s",
-                     error.name, error.message);
-        dbus_error_free(&error);
-        return -1;
+
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log("Failed to parse module arguments");
+        goto fail;
     }
 
-    if (!(hal_ctx = pa_hal_context_new(c, pa_dbus_connection_get(conn)))) {
+    if ((api = pa_modargs_get_value(ma, "api", NULL))) {
+        int good = 0;
+
+#ifdef HAVE_ALSA
+        if (strcmp(api, CAPABILITY_ALSA) == 0) {
+            good = 1;
+            api = CAPABILITY_ALSA;
+        }
+#endif
+#ifdef HAVE_OSS
+        if (strcmp(api, CAPABILITY_OSS) == 0) {
+            good = 1;
+            api = CAPABILITY_OSS;
+        }
+#endif
+
+        if (!good) {
+            pa_log_error("Invalid API specification.");
+            goto fail;
+        }
+    }
+
+    if (!(conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &error)) || dbus_error_is_set(&error)) {
+        if (conn)
+            pa_dbus_connection_unref(conn);
+        pa_log_error("Unable to contact DBUS system bus: %s: %s", error.name, error.message);
+        goto fail;
+    }
+
+    if (!(hal_context = hal_context_new(m->core, pa_dbus_connection_get(conn)))) {
         /* pa_hal_context_new() logs appropriate errors */
-        return -1;
+        pa_dbus_connection_unref(conn);
+        goto fail;
     }
 
     u = pa_xnew(struct userdata, 1);
-    u->core = c;
-    u->ctx = hal_ctx;
-    u->conn = conn;
-    u->devices = pa_hashmap_new(pa_idxset_string_hash_func,
-                                pa_idxset_string_compare_func);
-    m->userdata = (void*) u;
+    u->core = m->core;
+    u->context = hal_context;
+    u->connection = conn;
+    u->devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
+    u->capability = api;
+    m->userdata = u;
 
 #ifdef HAVE_ALSA
-    n = hal_device_add_all(u, CAP_ALSA);
+    n = hal_device_add_all(u, CAPABILITY_ALSA);
 #endif
 #if defined(HAVE_ALSA) && defined(HAVE_OSS)
-    u->use_oss = 0;
-
-    if (n <= 0) {
+    if (n <= 0)
 #endif
 #ifdef HAVE_OSS
-        n += hal_device_add_all(u, CAP_OSS);
+        n += hal_device_add_all(u, CAPABILITY_OSS);
 #endif
-#if defined(HAVE_ALSA) && defined(HAVE_OSS)
 
-        /* We found something with OSS, but didn't find anything with
-         * ALSA. Then let's use only OSS from now on. */
-        if (n > 0)
-            u->use_oss = 1;
+    libhal_ctx_set_user_data(hal_context, u);
+    libhal_ctx_set_device_added(hal_context, device_added_cb);
+    libhal_ctx_set_device_removed(hal_context, device_removed_cb);
+    libhal_ctx_set_device_new_capability(hal_context, new_capability_cb);
+    libhal_ctx_set_device_lost_capability(hal_context, lost_capability_cb);
+
+    if (!libhal_device_property_watch_all(hal_context, &error)) {
+        pa_log_error("Error monitoring device list: %s: %s", error.name, error.message);
+        goto fail;
     }
-#endif
 
-    libhal_ctx_set_user_data(hal_ctx, u);
-    libhal_ctx_set_device_added(hal_ctx, device_added_cb);
-    libhal_ctx_set_device_removed(hal_ctx, device_removed_cb);
-    libhal_ctx_set_device_new_capability(hal_ctx, new_capability_cb);
-    libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability_cb);
-    /*libhal_ctx_set_device_property_modified(hal_ctx, property_modified_cb);*/
+    if (!dbus_connection_add_filter(pa_dbus_connection_get(conn), filter_cb, u, NULL)) {
+        pa_log_error("Failed to add filter function");
+        goto fail;
+    }
 
-    dbus_error_init(&error);
-    if (!libhal_device_property_watch_all(hal_ctx, &error)) {
-        pa_log_error("error monitoring device list: %s: %s",
-                     error.name, error.message);
-        dbus_error_free(&error);
-        userdata_free(u);
-        return -1;
+    dbus_bus_add_match(pa_dbus_connection_get(conn), "type='signal',sender='org.freedesktop.Hal', interface='org.freedesktop.Hal.Device.AccessControl'", &error);
+    if (dbus_error_is_set(&error)) {
+        pa_log_error("Unable to subscribe to HAL ACL signals: %s: %s", error.name, error.message);
+        goto fail;
+    }
+
+    dbus_bus_add_match(pa_dbus_connection_get(conn), "type='signal',interface='org.pulseaudio.Server'", &error);
+    if (dbus_error_is_set(&error)) {
+        pa_log_error("Unable to subscribe to PulseAudio signals: %s: %s", error.name, error.message);
+        goto fail;
     }
 
-    pa_log_info("loaded %i modules.", n);
+    pa_log_info("Loaded %i modules.", n);
+
+    pa_modargs_free(ma);
 
     return 0;
+
+fail:
+    if (ma)
+        pa_modargs_free(ma);
+
+    dbus_error_free(&error);
+    pa__done(m);
+
+    return -1;
 }
 
 
-void pa__done(PA_GCC_UNUSED pa_core *c, pa_module *m) {
-    assert (c && m);
+void pa__done(pa_module *m) {
+    struct userdata *u;
+
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+    if (u->context)
+        hal_context_free(u->context);
 
-    /* free the user data */
-    userdata_free(m->userdata);
+    if (u->devices)
+        pa_hashmap_free(u->devices, hal_device_free_cb, NULL);
+
+    if (u->connection)
+        pa_dbus_connection_unref(u->connection);
+
+    pa_xfree(u);
 }
index a40ebe290dc1dfa77d28b807146c5f58bbe444ba..5019d6564dbb04a0ebf654fa62d478510cd3acee 100644 (file)
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2006, 2007 Lennart Poettering and Tanu Kaskinen
+  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
 #include <config.h>
 #endif
 
-#include <pthread.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>
 
 #include <jack/jack.h>
-#include <jack/ringbuffer.h>
-#include <jack/types.h>
 
-#include <pulse/mainloop-api.h>
-#include <pulse/sample.h>
-#include <pulse/channelmap.h>
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/core-error.h>
 #include <pulsecore/sink.h>
 #include <pulsecore/module.h>
-#include <pulsecore/core.h>
-#include <pulsecore/log.h>
 #include <pulsecore/core-util.h>
-#include <pulsecore/core-error.h>
-#include <pulsecore/pipe.h>
 #include <pulsecore/modargs.h>
-#include <pulsecore/strbuf.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-jack-sink-symdef.h"
 
-PA_MODULE_AUTHOR("Lennart Poettering & Tanu Kaskinen")
-PA_MODULE_DESCRIPTION("Jack Sink")
+/* General overview:
+ *
+ * Because JACK has a very unflexible event loop management, which
+ * doesn't allow us to add our own event sources to the event thread
+ * we cannot use the JACK real-time thread for dispatching our PA
+ * work. Instead, we run an additional RT thread which does most of
+ * the PA handling, and have the JACK RT thread request data from it
+ * via pa_asyncmsgq. The cost is an additional context switch which
+ * should hopefully not be that expensive if RT scheduling is
+ * enabled. A better fix would only be possible with additional event
+ * source support in JACK.
+ */
+
+PA_MODULE_AUTHOR("Lennart Poettering")
+PA_MODULE_DESCRIPTION("JACK Sink")
 PA_MODULE_VERSION(PACKAGE_VERSION)
 PA_MODULE_USAGE(
         "sink_name=<name of sink> "
         "server_name=<jack server name> "
         "client_name=<jack client name> "
         "channels=<number of channels> "
-        "connect=<connect ports automatically?> "
-        "buffersize=<intermediate buffering in frames> "
+        "connect=<connect ports?> "
         "channel_map=<channel map>")
 
 #define DEFAULT_SINK_NAME "jack_out"
-#define DEFAULT_CLIENT_NAME "PulseAudio(output)"
-#define DEFAULT_RINGBUFFER_SIZE 4096
-
 
 struct userdata {
+    pa_core *core;
+    pa_module *module;
     pa_sink *sink;
 
     unsigned channels;
-    unsigned frame_size;
 
-    jack_port_t* j_ports[PA_CHANNELS_MAX];
-    jack_client_t *j_client;
+    jack_port_t* port[PA_CHANNELS_MAX];
+    jack_client_t *client;
 
-    jack_nframes_t j_buffersize;
+    void *buffer[PA_CHANNELS_MAX];
 
-    /* For avoiding j_buffersize changes at a wrong moment. */
-    pthread_mutex_t buffersize_mutex;
+    pa_thread_mq thread_mq;
+    pa_asyncmsgq *jack_msgq;
+    pa_rtpoll *rtpoll;
+    pa_rtpoll_item *rtpoll_item;
 
-    /* The intermediate store where the pulse side writes to and the jack side
-       reads from. */
-    jack_ringbuffer_t* ringbuffer;
-    
-    /* For signaling when there's room in the ringbuffer. */
-    pthread_mutex_t cond_mutex;
-    pthread_cond_t ringbuffer_cond;
+    pa_thread *thread;
 
-    pthread_t filler_thread; /* Keeps the ringbuffer filled. */
+    jack_nframes_t frames_in_buffer;
+    jack_nframes_t saved_frame_time;
+    pa_bool_t saved_frame_time_valid;
+};
 
-    int ringbuffer_is_full;
-    int filler_thread_is_running;
-    int quit_requested;
+static const char* const valid_modargs[] = {
+    "sink_name",
+    "server_name",
+    "client_name",
+    "channels",
+    "connect",
+    "channel_map",
+    NULL
+};
 
-    int pipe_fd_type;
-    int pipe_fds[2];
-    pa_io_event *io_event;
+enum {
+    SINK_MESSAGE_RENDER = PA_SINK_MESSAGE_MAX,
+    SINK_MESSAGE_ON_SHUTDOWN
 };
 
+static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *memchunk) {
+    struct userdata *u = PA_SINK(o)->userdata;
 
-struct options {
-    char* sink_name;
-    int sink_name_given;
+    switch (code) {
 
-    char* server_name; /* May be NULL */
-    int server_name_given;
+        case SINK_MESSAGE_RENDER:
 
-    char* client_name;
-    int client_name_given;
+            /* Handle the request from the JACK thread */
 
-    unsigned channels;
-    int channels_given;
+            if (u->sink->thread_info.state == PA_SINK_RUNNING) {
+                pa_memchunk chunk;
+                size_t nbytes;
+                void *p;
 
-    int connect;
-    int connect_given;
+                pa_assert(offset > 0);
+                nbytes = offset * pa_frame_size(&u->sink->sample_spec);
 
-    unsigned buffersize;
-    int buffersize_given;
+                pa_sink_render_full(u->sink, nbytes, &chunk);
 
-    pa_channel_map map;
-    int map_given;
-};
+                p = (uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index;
+                pa_deinterleave(p, u->buffer, u->channels, sizeof(float), offset);
+                pa_memblock_release(chunk.memblock);
 
+                pa_memblock_unref(chunk.memblock);
+            } else {
+                unsigned c;
+                pa_sample_spec ss;
 
-static const char* const valid_modargs[] = {
-    "sink_name",
-    "server_name",
-    "client_name",
-    "channels",
-    "connect",
-    "buffersize",
-    "channel_map",
-    NULL
-};
+                /* Humm, we're not RUNNING, hence let's write some silence */
 
+                ss = u->sink->sample_spec;
+                ss.channels = 1;
 
-/* Initialization functions. */
-static int parse_options(struct options* o, const char* argument);
-static void set_default_channels(pa_module* self, struct options* o);
-static int create_sink(pa_module* self, struct options *o);
-static void connect_ports(pa_module* self);
-static int start_filling_ringbuffer(pa_module* self);
+                for (c = 0; c < u->channels; c++)
+                    pa_silence_memory(u->buffer[c], offset * pa_sample_size(&ss), &ss);
+            }
 
-/* Various callbacks. */
-static void jack_error_func(const char* t);
-static pa_usec_t sink_get_latency_cb(pa_sink* s);
-static int jack_process(jack_nframes_t nframes, void* arg);
-static int jack_blocksize_cb(jack_nframes_t nframes, void* arg);
-static void jack_shutdown(void* arg);
-static void io_event_cb(pa_mainloop_api* m, pa_io_event* e, int fd,
-                        pa_io_event_flags_t flags, void* userdata);
+            u->frames_in_buffer = offset;
+            u->saved_frame_time = * (jack_nframes_t*) data;
+            u->saved_frame_time_valid = TRUE;
 
-/* The ringbuffer filler thread runs in this function. */
-static void* fill_ringbuffer(void* arg);
+            return 0;
 
-/* request_render asks asynchronously the mainloop to call io_event_cb. */
-static void request_render(struct userdata* u);
+        case SINK_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;
 
+        case PA_SINK_MESSAGE_GET_LATENCY: {
+            jack_nframes_t l, ft, d;
+            size_t n;
 
-int pa__init(pa_core* c, pa_module* self) {
-    struct userdata* u = NULL;
-    struct options o;
-    unsigned i;
-    
-    assert(c);
-    assert(self);
-
-    o.sink_name = NULL;
-    o.server_name = NULL;
-    o.client_name = NULL;
-    
-    self->userdata = pa_xnew0(struct userdata, 1);
-    u = self->userdata;
-    
-    u->pipe_fds[0] = u->pipe_fds[1] = -1;
-    u->pipe_fd_type = 0;
-    u->ringbuffer_is_full = 0;
-    u->filler_thread_is_running = 0;
-    u->quit_requested = 0;
-    pthread_mutex_init(&u->buffersize_mutex, NULL);
-    pthread_mutex_init(&u->cond_mutex, NULL);
-    pthread_cond_init(&u->ringbuffer_cond, NULL);
-    
-    if (parse_options(&o, self->argument) != 0)
-        goto fail;
-    
-    jack_set_error_function(jack_error_func);
-    
-    if (!(u->j_client = jack_client_open(
-                          o.client_name,
-                          o.server_name ? JackServerName : JackNullOption,
-                          NULL, o.server_name))) {
-        pa_log_error("jack_client_open() failed.");
-        goto fail;
-    }
-    pa_log_info("Successfully connected as '%s'",
-                jack_get_client_name(u->j_client));
-    
-    if (!o.channels_given)
-        set_default_channels(self, &o);
-    
-    u->channels = o.channels;
-    
-    if (!o.map_given)
-        pa_channel_map_init_auto(&o.map, u->channels, PA_CHANNEL_MAP_ALSA);
-    
-    for (i = 0; i < u->channels; i++) {
-        char* port_name = pa_sprintf_malloc(
-                              "out_%i:%s", i+1,
-                              pa_channel_position_to_string(o.map.map[i]));
-        
-        if (!(u->j_ports[i] = jack_port_register(
-                                  u->j_client, port_name,
-                                  JACK_DEFAULT_AUDIO_TYPE,
-                                  JackPortIsOutput|JackPortIsTerminal, 0))) {
-            pa_log("jack_port_register() failed.");
-            goto fail;
+            /* This is the "worst-case" latency */
+            l = jack_port_get_total_latency(u->client, u->port[0]) + u->frames_in_buffer;
+
+            if (u->saved_frame_time_valid) {
+                /* Adjust the worst case latency by the time that
+                 * passed since we last handed data to JACK */
+
+                ft = jack_frame_time(u->client);
+                d = ft > u->saved_frame_time ? ft - u->saved_frame_time : 0;
+                l = l > d ? l - d : 0;
+            }
+
+            /* Convert it to usec */
+            n = l * pa_frame_size(&u->sink->sample_spec);
+            *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->sink->sample_spec);
+
+            return 0;
         }
-        
-        pa_xfree(port_name);
     }
-    
-    if (pipe(u->pipe_fds) < 0) {
-        pa_log("pipe() failed: %s", pa_cstrerror(errno));
-        goto fail;
-    }
-    pa_make_nonblock_fd(u->pipe_fds[1]);
-    
-    if (create_sink(self, &o) != 0)
-        goto fail;
 
-    u->frame_size = pa_frame_size(&u->sink->sample_spec);
-    u->j_buffersize = jack_get_buffer_size(u->j_client);
-    
-    /* If the ringbuffer size were equal to the jack buffer size, a full block
-       would never fit in the ringbuffer, because the ringbuffer can never be
-       totally full: one slot is always wasted. */
-    if (o.buffersize <= u->j_buffersize) {
-        o.buffersize = u->j_buffersize + 1;
-    }
-    /* The actual ringbuffer size will be rounded up to the nearest power of
-       two. */
-    if (!(u->ringbuffer = jack_ringbuffer_create(
-                              o.buffersize * u->frame_size))) {
-        pa_log("jack_ringbuffer_create() failed.");
-        goto fail;
-    }
-    assert((u->ringbuffer->size % sizeof(float)) == 0);
-    pa_log_info("buffersize is %u frames (%u samples, %u bytes).",
-                u->ringbuffer->size / u->frame_size,
-                u->ringbuffer->size / sizeof(float),
-                u->ringbuffer->size);
-    
-    jack_set_process_callback(u->j_client, jack_process, u);
-    jack_set_buffer_size_callback(u->j_client, jack_blocksize_cb, u);
-    jack_on_shutdown(u->j_client, jack_shutdown, u);
-    
-    if (jack_activate(u->j_client)) {
-        pa_log("jack_activate() failed.");
-        goto fail;
-    }
+    return pa_sink_process_msg(o, code, data, offset, memchunk);
+}
 
-    if (o.connect)
-        connect_ports(self);
+static int jack_process(jack_nframes_t nframes, void *arg) {
+    struct userdata *u = arg;
+    unsigned c;
+    jack_nframes_t frame_time;
+    pa_assert(u);
 
-    u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0],
-                                      PA_IO_EVENT_INPUT, io_event_cb, self);
-    
-    if (start_filling_ringbuffer(self) != 0)
-        goto fail;
+    /* We just forward the request to our other RT thread */
 
-    pa_xfree(o.sink_name);
-    pa_xfree(o.server_name);
-    pa_xfree(o.client_name);
-    
-    return 0;
+    for (c = 0; c < u->channels; c++)
+        pa_assert_se(u->buffer[c] = jack_port_get_buffer(u->port[c], nframes));
 
-fail:
-    pa_xfree(o.sink_name);
-    pa_xfree(o.server_name);
-    pa_xfree(o.client_name);
-    pa__done(c, self);
+    frame_time = jack_frame_time(u->client);
 
-    return -1;
+    pa_assert_se(pa_asyncmsgq_send(u->jack_msgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_RENDER, &frame_time, nframes, NULL) == 0);
+    return 0;
 }
 
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
 
-static int parse_options(struct options* o, const char* argument) {
-    pa_modargs *ma = NULL;
-    const char* arg_val;
-    pa_strbuf* strbuf;
-    
-    assert(o);
+    pa_assert(u);
 
-    if (!(ma = pa_modargs_new(argument, valid_modargs))) {
-        pa_log_error("Failed to parse module arguments.");
-        goto fail;
-    }
+    pa_log_debug("Thread starting up");
 
-    strbuf = pa_strbuf_new();
-    if ((arg_val = pa_modargs_get_value(ma, "sink_name", NULL))) {
-        pa_strbuf_puts(strbuf, arg_val);
-        o->sink_name = pa_strbuf_tostring(strbuf);
-        o->sink_name_given = 1;
-    } else {
-        pa_strbuf_puts(strbuf, DEFAULT_SINK_NAME);
-        o->sink_name = pa_strbuf_tostring(strbuf);
-        o->sink_name_given = 0;
-    }
-    pa_strbuf_free(strbuf);
-
-    strbuf = pa_strbuf_new();
-    if ((arg_val = pa_modargs_get_value(ma, "server_name", NULL))) {
-        pa_strbuf_puts(strbuf, arg_val);
-        o->server_name = pa_strbuf_tostring(strbuf);
-        o->server_name_given = 1;
-    } else {
-        o->server_name = NULL;
-        o->server_name_given = 0;
-    }
-    pa_strbuf_free(strbuf);
-
-    strbuf = pa_strbuf_new();
-    if ((arg_val = pa_modargs_get_value(ma, "client_name", NULL))) {
-        pa_strbuf_puts(strbuf, arg_val);
-        o->client_name = pa_strbuf_tostring(strbuf);
-        o->client_name_given = 1;
-    } else {
-        pa_strbuf_puts(strbuf, DEFAULT_CLIENT_NAME);
-        o->client_name = pa_strbuf_tostring(strbuf);
-        o->client_name_given = 1;
-    }
-    pa_strbuf_free(strbuf);
-
-    if (pa_modargs_get_value(ma, "channels", NULL)) {
-        o->channels_given = 1;
-        if (pa_modargs_get_value_u32(ma, "channels", &o->channels) < 0 ||
-            o->channels == 0 ||
-            o->channels >= PA_CHANNELS_MAX) {
-            pa_log_error("Failed to parse the \"channels\" argument.");
-            goto fail;
-        }
-    } else {
-        o->channels = 0; /* The actual default value is the number of physical
-                            input ports in jack (unknown at the moment), or if
-                            that's zero, then the default_sample_spec.channels
-                            of the core. */
-        o->channels_given = 0;
-    }
+    if (u->core->high_priority)
+        pa_make_realtime();
 
-    if (pa_modargs_get_value(ma, "connect", NULL)) {
-        o->connect_given = 1;
-        if (pa_modargs_get_value_boolean(ma, "connect", &o->connect) < 0) {
-            pa_log_error("Failed to parse the \"connect\" argument.");
-            goto fail;
-        }
-    } else {
-        o->connect = 1;
-        o->connect_given = 0;
-    }
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
 
-    if (pa_modargs_get_value(ma, "buffersize", NULL)) {
-        o->buffersize_given = 1;
-        if (pa_modargs_get_value_u32(ma, "buffersize", &o->buffersize) < 0) {
-            pa_log_error("Failed to parse the \"buffersize\" argument.");
-            goto fail;
-        }
-    } else {
-        o->buffersize = DEFAULT_RINGBUFFER_SIZE;
-        o->buffersize_given = 0;
-    }
+    for (;;) {
+        int ret;
 
-    if (pa_modargs_get_value(ma, "channel_map", NULL)) {
-        o->map_given = 1;
-        if (pa_modargs_get_channel_map(ma, &o->map) < 0) {
-            pa_log_error("Failed to parse the \"channel_map\" argument.");
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
-        }
 
-        /* channel_map specifies the channel count too. */
-        if (o->channels_given && (o->channels != o->map.channels)) {
-            pa_log_error(
-                "\"channels\" and \"channel_map\" arguments conficted. If you "
-                "use the \"channel_map\" argument, you can omit the "
-                "\"channels\" argument.");
-            goto fail;
-        } else {
-            o->channels = o->map.channels;
-            o->channels_given = 1;
-        }
-    } else {
-        /* The actual default value is the default alsa mappings, but that
-           can't be set until the channel count is known. Here we initialize
-           the map to some valid value, although the value won't be used. */
-        pa_channel_map_init_stereo(&o->map);
-        o->map_given = 0;
+        if (ret == 0)
+            goto finish;
     }
 
-    pa_modargs_free(ma);
-
-    return 0;
-
 fail:
-    if (ma)
-      pa_modargs_free(ma);
+    /* 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);
 
-    return -1;
+finish:
+    pa_log_debug("Thread shutting down");
 }
 
+static void jack_error_func(const char*t) {
+    char *s;
 
-static void set_default_channels(pa_module* self, struct options* o) {
-    struct userdata* u;
-    const char **ports, **p;
-    
-    assert(self);
-    assert(o);
-    assert(self->userdata);
-
-    u = self->userdata;
-    
-    assert(u->j_client);
-    assert(self->core);
-    
-    o->channels = 0;
-    
-    ports = jack_get_ports(u->j_client, NULL, JACK_DEFAULT_AUDIO_TYPE,
-                           JackPortIsPhysical|JackPortIsInput);
-    
-    for (p = ports; *p; p++)
-        o->channels++;
-    
-    free(ports);
-    
-    if (o->channels >= PA_CHANNELS_MAX)
-        o->channels = PA_CHANNELS_MAX - 1;
-    
-    if (o->channels == 0)
-        o->channels = self->core->default_sample_spec.channels;
+    s = pa_xstrndup(t, strcspn(t, "\n\r"));
+    pa_log_warn("JACK error >%s<", s);
+    pa_xfree(s);
 }
 
+static void jack_init(void *arg) {
+    struct userdata *u = arg;
 
-static int create_sink(pa_module* self, struct options* o) {
-    struct userdata* u;
-    pa_sample_spec ss;
-    char *t;
-    
-    assert(self);
-    assert(o);
-    assert(self->userdata);
-
-    u = self->userdata;
-    
-    assert(u->j_client);
-    
-    ss.channels = u->channels;
-    ss.rate = jack_get_sample_rate(u->j_client);
-    ss.format = PA_SAMPLE_FLOAT32NE;
-    assert(pa_sample_spec_valid(&ss));
+    pa_log_info("JACK thread starting up.");
 
-    if (!(u->sink = pa_sink_new(self->core, __FILE__, o->sink_name, 0, &ss,
-                                &o->map))) {
-        pa_log("failed to create sink.");
-        return -1;
-    }
-    
-    u->sink->userdata = u;
-    pa_sink_set_owner(u->sink, self);
-    
-    pa_sink_set_description(
-        u->sink,
-        t = pa_sprintf_malloc("Jack sink (%s)",
-                              jack_get_client_name(u->j_client)));
-    pa_xfree(t);
-    
-    u->sink->get_latency = sink_get_latency_cb;
-    
-    return 0;
+    if (u->core->high_priority)
+        pa_make_realtime();
 }
 
+static void jack_shutdown(void* arg) {
+    struct userdata *u = arg;
 
-static void connect_ports(pa_module* self) {
-    struct userdata* u;
-    unsigned i;
-    const char **ports, **p;
-    
-    assert(self);
-    assert(self->userdata);
-
-    u = self->userdata;
-    
-    assert(u->j_client);
-    
-    ports = jack_get_ports(u->j_client, NULL, JACK_DEFAULT_AUDIO_TYPE,
-                           JackPortIsPhysical|JackPortIsInput);
-    
-    for (i = 0, p = ports; i < u->channels; i++, p++) {
-        assert(u->j_ports[i]);
-        
-        if (!*p) {
-            pa_log("Not enough physical output ports, leaving unconnected.");
-            break;
-        }
-        
-        pa_log_info("connecting %s to %s",
-                    jack_port_name(u->j_ports[i]), *p);
-        
-        if (jack_connect(u->j_client, jack_port_name(u->j_ports[i]), *p)) {
-            pa_log("Failed to connect %s to %s, leaving unconnected.",
-                   jack_port_name(u->j_ports[i]), *p);
-            break;
-        }
-    }
-    
-    free(ports);
+    pa_log_info("JACK thread shutting down..");
+    pa_asyncmsgq_post(u->jack_msgq, PA_MSGOBJECT(u->sink), SINK_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;
+    pa_modargs *ma = NULL;
+    jack_status_t status;
+    const char *server_name, *client_name;
+    uint32_t channels = 0;
+    int do_connect = 1;
+    unsigned i;
+    const char **ports = NULL, **p;
+    char *t;
 
-static int start_filling_ringbuffer(pa_module* self) {
-    struct userdata* u;
-    pthread_attr_t thread_attributes;
+    pa_assert(m);
 
-    assert(self);
-    assert(self->userdata);
+    jack_set_error_function(jack_error_func);
 
-    u = self->userdata;
-    
-    pthread_attr_init(&thread_attributes);
-    
-    if (pthread_attr_setinheritsched(&thread_attributes,
-                                     PTHREAD_INHERIT_SCHED) != 0) {
-        pa_log("pthread_attr_setinheritsched() failed.");
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log("Failed to parse module arguments.");
         goto fail;
     }
-    else if (pthread_create(&u->filler_thread, &thread_attributes,
-                            fill_ringbuffer, u) != 0) {
-        pa_log("pthread_create() failed.");
+
+    if (pa_modargs_get_value_boolean(ma, "connect", &do_connect) < 0) {
+        pa_log("Failed to parse connect= argument.");
         goto fail;
     }
-    
-    u->filler_thread_is_running = 1;
-    
-    pthread_attr_destroy(&thread_attributes);
-
-    return 0;
-    
-fail:
-    pthread_attr_destroy(&thread_attributes);
-    return -1;
-}
 
+    server_name = pa_modargs_get_value(ma, "server_name", NULL);
+    client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio JACK Sink");
+
+    u = pa_xnew0(struct userdata, 1);
+    u->core = m->core;
+    u->module = m;
+    m->userdata = u;
+    u->saved_frame_time_valid = FALSE;
+    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);
+
+    /* The queue linking the JACK thread and our RT thread */
+    u->jack_msgq = pa_asyncmsgq_new(0);
+
+    /* The msgq from the JACK RT thread should have an even higher
+     * priority than the normal message queues, to match the guarantee
+     * all other drivers make: supplying the audio device with data is
+     * the top priority -- and as long as that is possible we don't do
+     * anything else */
+    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.");
+        goto fail;
+    }
 
-static void jack_error_func(const char* t) {
-    pa_log_warn("JACK error >%s<", t);
-}
-
+    ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
 
-static pa_usec_t sink_get_latency_cb(pa_sink* s) {
-    /* The latency is approximately the sum of the first port's latency,
-       buffersize of jack and the ringbuffer size. Maybe instead of using just
-       the first port, the max of all ports' latencies should be used? */
-    struct userdata* u;
-    jack_nframes_t l;
-    
-    assert(s);
-    assert(s->userdata);
-
-    u = s->userdata;
-    
-    l = jack_port_get_total_latency(u->j_client, u->j_ports[0]) +
-        u->j_buffersize + u->ringbuffer->size / u->frame_size;
-    
-    return pa_bytes_to_usec(l * u->frame_size, &s->sample_spec);
-}
+    channels = 0;
+    for (p = ports; *p; p++)
+        channels++;
 
+    if (!channels)
+        channels = m->core->default_sample_spec.channels;
 
-static int jack_process(jack_nframes_t nframes, void* arg) {
-    struct userdata* u = arg;
-    float* j_buffers[PA_CHANNELS_MAX];
-    unsigned nsamples = u->channels * nframes;
-    unsigned sample_idx_part1, sample_idx_part2;
-    jack_nframes_t frame_idx;
-    jack_ringbuffer_data_t data[2]; /* In case the readable area in the
-                                       ringbuffer is non-continuous, the data
-                                       will be split in two parts. */
-    unsigned chan;
-    unsigned samples_left_over;
-    
-    for (chan = 0; chan < u->channels; chan++) {
-        j_buffers[chan] = jack_port_get_buffer(u->j_ports[chan], nframes);
-    }
-    
-    jack_ringbuffer_get_read_vector(u->ringbuffer, data);
-    
-    /* We assume that the possible discontinuity doesn't happen in the middle
-     * of a sample. Should be a safe assumption. */
-    assert(((data[0].len % sizeof(float)) == 0) ||
-           (data[1].len == 0));
-    
-    /* Copy from the first part of data until enough samples are copied or the
-       first part ends. */
-    sample_idx_part1 = 0;
-    chan = 0;
-    frame_idx = 0;
-    while (sample_idx_part1 < nsamples &&
-           ((sample_idx_part1 + 1) * sizeof(float)) <= data[0].len) {
-        float *s = ((float*) data[0].buf) + sample_idx_part1;
-        float *d = j_buffers[chan] + frame_idx;
-        *d = *s;
-
-        sample_idx_part1++;
-        chan = (chan + 1) % u->channels;
-        frame_idx = sample_idx_part1 / u->channels;
-    }
-    
-    samples_left_over = nsamples - sample_idx_part1;
-    
-    /* Copy from the second part of data until enough samples are copied or the
-       second part ends. */
-    sample_idx_part2 = 0;
-    while (sample_idx_part2 < samples_left_over &&
-           ((sample_idx_part2 + 1) * sizeof(float)) <= data[1].len) {
-        float *s = ((float*) data[1].buf) + sample_idx_part2;
-        float *d = j_buffers[chan] + frame_idx;
-        *d = *s;
-
-        sample_idx_part2++;
-        chan = (chan + 1) % u->channels;
-        frame_idx = (sample_idx_part1 + sample_idx_part2) / u->channels;
+    if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) {
+        pa_log("Failed to parse channels= argument.");
+        goto fail;
     }
-    
-    samples_left_over -= sample_idx_part2;
-    
-    /* If there's still samples left, fill the buffers with zeros. */
-    while (samples_left_over > 0) {
-        float *d = j_buffers[chan] + frame_idx;
-        *d = 0.0;
-
-        samples_left_over--;
-        chan = (chan + 1) % u->channels;
-        frame_idx = (nsamples - samples_left_over) / u->channels;
+
+    pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_ALSA);
+    if (pa_modargs_get_channel_map(ma, NULL, &map) < 0 || map.channels != channels) {
+        pa_log("Failed to parse channel_map= argument.");
+        goto fail;
     }
-    
-    jack_ringbuffer_read_advance(
-        u->ringbuffer, (sample_idx_part1 + sample_idx_part2) * sizeof(float));
-    
-    /* Tell the rendering part that there is room in the ringbuffer. */
-    u->ringbuffer_is_full = 0;
-    pthread_cond_signal(&u->ringbuffer_cond);
-    
-    return 0;
-}
 
+    pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client));
+
+    ss.channels = u->channels = channels;
+    ss.rate = jack_get_sample_rate(u->client);
+    ss.format = PA_SAMPLE_FLOAT32NE;
 
-static int jack_blocksize_cb(jack_nframes_t nframes, void* arg) {
-    /* This gets called in the processing thread, so do we have to be realtime
-       safe? No, we can do whatever we want. User gets silence while we do it.
-       
-       In addition to just updating the j_buffersize field in userdata, we have
-       to create a new ringbuffer, if the new buffer size is bigger or equal to
-       the old ringbuffer size. */
-    struct userdata* u = arg;
-    
-    assert(u);
-    
-    /* We don't want to change the blocksize and the ringbuffer while rendering
-       is going on. */
-    pthread_mutex_lock(&u->buffersize_mutex);
-    
-    u->j_buffersize = nframes;
-    
-    if ((u->ringbuffer->size / u->frame_size) <= nframes) {
-        /* We have to create a new ringbuffer. What are we going to do with the
-           old data in the old buffer? We throw it away, because we're lazy
-           coders. The listening experience is likely to get ruined anyway
-           during the blocksize change. */
-        jack_ringbuffer_free(u->ringbuffer);
-        
-        /* The actual ringbuffer size will be rounded up to the nearest power
-           of two. */
-        if (!(u->ringbuffer =
-                  jack_ringbuffer_create((nframes + 1) * u->frame_size))) {
-            pa_log_error(
-                "jack_ringbuffer_create() failed while changing jack's buffer "
-                "size, module exiting.");
-            jack_client_close(u->j_client);
-            u->quit_requested = 1;
+    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, JackPortIsOutput|JackPortIsTerminal, 0))) {
+            pa_log("jack_port_register() failed.");
+            goto fail;
         }
-        assert((u->ringbuffer->size % sizeof(float)) == 0);
-        pa_log_info("buffersize is %u frames (%u samples, %u bytes).",
-                    u->ringbuffer->size / u->frame_size,
-                    u->ringbuffer->size / sizeof(float),
-                    u->ringbuffer->size);
     }
-    
-    pthread_mutex_unlock(&u->buffersize_mutex);
-    
-    return 0;
-}
 
+    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;
+    }
 
-static void jack_shutdown(void* arg) {
-    struct userdata* u = arg;
-    assert(u);
+    u->sink->parent.process_msg = sink_process_msg;
+    u->sink->userdata = u;
+    u->sink->flags = PA_SINK_LATENCY;
 
-    u->quit_requested = 1;
-    request_render(u);
-}
+    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("Jack sink (%s)", jack_get_client_name(u->client)));
+    pa_xfree(t);
 
+    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);
 
-static void io_event_cb(pa_mainloop_api* m, pa_io_event* e, int fd,
-                        pa_io_event_flags_t flags, void* userdata) {
-    pa_module* self = userdata;
-    struct userdata* u;
-    char x;
-    jack_ringbuffer_data_t buffer[2]; /* The write area in the ringbuffer may
-                                         be split in two parts. */
-    pa_memchunk chunk; /* This is the data source. */
-    unsigned part1_length, part2_length;
-    unsigned sample_idx_part1, sample_idx_part2;
-    unsigned chan;
-    unsigned frame_size;
-    int rem;
-    
-    assert(m);
-    assert(e);
-    assert(flags == PA_IO_EVENT_INPUT);
-    assert(self);
-    assert(self->userdata);
-
-    u = self->userdata;
-    
-    assert(u->pipe_fds[0] == fd);
-
-    pa_read(fd, &x, 1, &u->pipe_fd_type);
-
-    if (u->quit_requested) {
-        pa_module_unload_request(self);
-        return;
+    if (!(u->thread = pa_thread_new(thread_func, u))) {
+        pa_log("Failed to create thread.");
+        goto fail;
     }
 
-    frame_size = u->frame_size;
-    
-    /* No blocksize changes during rendering, please. */
-    pthread_mutex_lock(&u->buffersize_mutex);
-    
-    jack_ringbuffer_get_write_vector(u->ringbuffer, buffer);
-    assert(((buffer[0].len % sizeof(float)) == 0) || (buffer[1].len == 0));
-    
-    part1_length = buffer[0].len / sizeof(float);
-    part2_length = buffer[1].len / sizeof(float);
-
-    /* If the amount of free space is not a multiple of the frame size, we have
-       to truncate the lengths so that we process only complete frames. */
-    if ((rem = (part1_length + part2_length) % u->channels) != 0) {
-        if (part2_length >= rem) {
-            part2_length -= rem;
-        } else {
-            part1_length -= rem - part2_length;
-            part2_length = 0;
-        }
+    if (jack_activate(u->client)) {
+        pa_log("jack_activate() failed");
+        goto fail;
     }
-    
-    /* pa_sink_render_full doesn't accept zero length, so we have do the
-       copying only if there's data to copy, which actually makes a kind of
-       sense. */
-    if (part1_length > 0 || part2_length > 0) {
-        pa_sink_render_full(u->sink,
-                            (part1_length + part2_length) * sizeof(float),
-                            &chunk);
-        
-        /* Write to the first part of the buffer. */
-        for (sample_idx_part1 = 0;
-             sample_idx_part1 < part1_length;
-             sample_idx_part1++) {
-            float *s =
-                ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) +
-                sample_idx_part1;
-            float *d = ((float*) buffer[0].buf) + sample_idx_part1;
-            *d = *s;
-        }
-        
-        /* Write to the second part of the buffer. */
-        for (sample_idx_part2 = 0;
-             sample_idx_part2 < part2_length;
-             sample_idx_part2++) {
-            float *s =
-                ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) +
-                sample_idx_part1 + sample_idx_part2;
-            float *d = ((float*) buffer[1].buf) + sample_idx_part2;
-            *d = *s;
+
+    if (do_connect) {
+        for (i = 0, p = ports; i < ss.channels; i++, p++) {
+
+            if (!*p) {
+                pa_log("Not enough physical output ports, leaving unconnected.");
+                break;
+            }
+
+            pa_log_info("Connecting %s to %s", jack_port_name(u->port[i]), *p);
+
+            if (jack_connect(u->client, jack_port_name(u->port[i]), *p)) {
+                pa_log("Failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p);
+                break;
+            }
         }
-        
-        pa_memblock_unref(chunk.memblock);
-        
-        jack_ringbuffer_write_advance(
-            u->ringbuffer, (part1_length + part2_length) * sizeof(float));
     }
-    
-    /* Blocksize can be changed again. */
-    pthread_mutex_unlock(&u->buffersize_mutex);
-}
 
+    pa_sink_put(u->sink);
 
-static void* fill_ringbuffer(void* arg) {
-    struct userdata* u = arg;
-    
-    assert(u);
-    
-    while (!u->quit_requested) {
-        if (u->ringbuffer_is_full) {
-            pthread_mutex_lock(&u->cond_mutex);
-            pthread_cond_wait(&u->ringbuffer_cond,
-                              &u->cond_mutex);
-            pthread_mutex_unlock(&u->cond_mutex);
-        }
-        /* No, it's not full yet, but this must be set to one as soon as
-           possible, because if the jack thread manages to process another
-           block before we set this to one, we may end up waiting without
-           a reason. */
-        u->ringbuffer_is_full = 1;
+    free(ports);
+    pa_modargs_free(ma);
 
-        request_render(u);
-    }
-    
-    return NULL;
-}
+    return 0;
+
+fail:
+    if (ma)
+        pa_modargs_free(ma);
+
+    free(ports);
 
+    pa__done(m);
 
-static void request_render(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);
+    return -1;
 }
 
-void pa__done(pa_core* c, pa_module* self) {
-    struct userdata* u;
-    
-    assert(c);
-    assert(self);
+void pa__done(pa_module*m) {
+    struct userdata *u;
+
+    pa_assert(m);
 
-    if (!self->userdata)
+    if (!(u = m->userdata))
         return;
 
-    u = self->userdata;
-    
-    if (u->filler_thread_is_running) {
-        u->quit_requested = 1;
-        pthread_cond_signal(&u->ringbuffer_cond);
-        pthread_join(u->filler_thread, NULL);
+    if (u->client)
+        jack_client_close(u->client);
+
+    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);
     }
-    
-    if (u->j_client)
-        jack_client_close(u->j_client);
 
-    if (u->io_event)
-        c->mainloop->io_free(u->io_event);
+    pa_thread_mq_done(&u->thread_mq);
 
-    if (u->sink) {
-        pa_sink_disconnect(u->sink);
+    if (u->sink)
         pa_sink_unref(u->sink);
-    }
-    
-    if (u->ringbuffer)
-        jack_ringbuffer_free(u->ringbuffer);
-
-    if (u->pipe_fds[0] >= 0)
-        pa_close(u->pipe_fds[0]);
-    if (u->pipe_fds[1] >= 0)
-        pa_close(u->pipe_fds[1]);
-    
-    pthread_mutex_destroy(&u->buffersize_mutex);
-    pthread_cond_destroy(&u->ringbuffer_cond);
-    pthread_mutex_destroy(&u->cond_mutex);
-    pa_xfree(self->userdata);
-    self->userdata = NULL;
+
+    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);
+
+    pa_xfree(u);
 }
index 8ca24035fe3ef4afed372b7e6fc5096bb5622f38..b62ebe7a1b49fe2c8a617886e1fc11c1a7abece2 100644 (file)
 #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);
-
-    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);
-}
+enum {
+    SOURCE_MESSAGE_POST = PA_SOURCE_MESSAGE_MAX,
+    SOURCE_MESSAGE_ON_SHUTDOWN
+};
 
-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;
+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;
 
-    assert(m);
-    assert(flags == PA_IO_EVENT_INPUT);
-    assert(u);
-    assert(u->pipe_fds[0] == fd);
+    switch (code) {
 
-    pa_read(fd, &x, 1, &u->pipe_fd_type);
+        case SOURCE_MESSAGE_POST:
 
-    if (u->quit_requested) {
-        stop_source(u);
-        u->quit_requested = 0;
-        return;
-    }
+            /* Handle the new block from the JACK thread */
+            pa_assert(chunk);
+            pa_assert(chunk->length > 0);
 
-    pthread_mutex_lock(&u->mutex);
+            if (u->source->thread_info.state == PA_SOURCE_RUNNING)
+                pa_source_post(u->source, chunk);
 
-    if (u->frames_posted > 0) {
-        unsigned fs;
-        jack_nframes_t frame_idx;
-        pa_memchunk chunk;
+            u->saved_frame_time = offset;
+            u->saved_frame_time_valid = TRUE;
 
-        fs = pa_frame_size(&u->source->sample_spec);
+            return 0;
 
-        chunk.memblock = pa_memblock_new(u->core->mempool, chunk.length = u->frames_posted * fs);
-        chunk.index = 0;
+        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;
 
-        for (frame_idx = 0; frame_idx < u->frames_posted; frame_idx ++) {
-            unsigned c;
+        case PA_SOURCE_MESSAGE_GET_LATENCY: {
+            jack_nframes_t l, ft, d;
+            size_t n;
 
-            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;
+            /* This is the "worst-case" latency */
+            l = jack_port_get_total_latency(u->client, u->port[0]);
 
-                *d = *s;
-            }
-        }
+            if (u->saved_frame_time_valid) {
+                /* Adjust the worst case latency by the time that
+                 * passed since we last handed data to JACK */
 
-        pa_source_post(u->source, &chunk);
-        pa_memblock_unref(chunk.memblock);
+                ft = jack_frame_time(u->client);
+                d = ft > u->saved_frame_time ? ft - u->saved_frame_time : 0;
+                l += d;
+            }
 
-        u->frames_posted = 0;
+            /* 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);
 
-        pthread_cond_signal(&u->cond);
+            return 0;
+        }
     }
 
-    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);
-
-    if (jack_transport_query(u->client, NULL) == JackTransportRolling) {
-        unsigned c;
+    const void *buffer[PA_CHANNELS_MAX];
+    void *p;
+    jack_nframes_t frame_time;
+    pa_memchunk chunk;
 
-        pthread_mutex_lock(&u->mutex);
+    pa_assert(u);
 
-        u->frames_posted = nframes;
+    for (c = 0; c < u->channels; c++)
+        pa_assert(buffer[c] = jack_port_get_buffer(u->port[c], nframes));
 
-        for (c = 0; c < u->channels; c++) {
-            u->buffer[c] = jack_port_get_buffer(u->port[c], nframes);
-            assert(u->buffer[c]);
-        }
+    /* We interleave the data and pass it on to the other RT thread */
 
-        request_post(u);
+    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);
 
-        pthread_cond_wait(&u->cond, &u->mutex);
+    frame_time = jack_frame_time(u->client);
 
-        u->frames_in_buffer = nframes;
-        u->timestamp = jack_get_current_transport_frame(u->client);
+    pa_asyncmsgq_post(u->jack_msgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_POST, NULL, frame_time, &chunk, NULL);
 
-        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;
+
+    pa_assert(u);
 
-    assert(s);
-    u = s->userdata;
+    pa_log_debug("Thread starting up");
 
-    if (jack_transport_query(u->client, NULL) != JackTransportRolling)
-        return 0;
+    if (u->core->high_priority)
+        pa_make_realtime();
 
-    n = jack_get_current_transport_frame(u->client);
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
 
-    if (n < u->timestamp)
-        return 0;
+    for (;;) {
+        int ret;
 
-    d = n - u->timestamp;
-    l = jack_port_get_total_latency(u->client, u->port[0]);
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
+            goto fail;
+
+        if (ret == 0)
+            goto finish;
+    }
 
-    return pa_bytes_to_usec((l + d) * pa_frame_size(&s->sample_spec), &s->sample_spec);
+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);
+}
+
+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();
 }
 
-int pa__init(pa_core *c, pa_module*m) {
+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;
-
-    pthread_mutex_init(&u->mutex, NULL);
-    pthread_cond_init(&u->cond, NULL);
+    m->userdata = u;
+    u->saved_frame_time_valid = FALSE;
 
-    if (pipe(u->pipe_fds) < 0) {
-        pa_log("pipe() failed: %s", pa_cstrerror(errno));
-        goto fail;
-    }
+    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);
 
-    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);
 }
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
new file mode 100644 (file)
index 0000000..0265d97
--- /dev/null
@@ -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);
+}
index c8adbc8bec9d05ffec7d6a707dcb133101bc84b9..21d93837c912a31d834920cf4d07aea18eb392b1 100644 (file)
 #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;
index 0b051facbf7ef121414b9ad8e13d0d97004b2871..0155b2af622a8bf2b67c687570cd5d26be6052c6 100644 (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;
index b7433ac8250e4131f8b32d6c7f24956a50dbc8e9..47a106456646f42514e94cd27381e53eeb39b505 100644 (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);
index 3c1c2bca4877d6b89a36b1d8eabf028db1b62ccc..2ef61c88e94a52752f3157d7f6aa262d01d1e25f 100644 (file)
 #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);
 }
index 54a8e89023cb7ff80cc1cb1e9046f7645160363d..3a4edec7083a0df868d7d5a161f8d29d5358aef7 100644 (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>
 #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) {
-    struct userdata *u = userdata;
-    pa_memchunk chunk;
-    struct timeval ntv = *tv;
-    size_t l;
+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:
 
-    assert(u);
+            if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING)
+                pa_rtclock_get(&u->timestamp);
 
-    if (pa_sink_render(u->sink, u->block_size, &chunk) >= 0) {
-        l = chunk.length;
-        pa_memblock_unref(chunk.memblock);
-    } else
-        l = u->block_size;
+            break;
 
-    pa_timeval_add(&ntv, pa_bytes_to_usec(l, &u->sink->sample_spec));
-    m->time_restart(e, &ntv);
+        case PA_SINK_MESSAGE_GET_LATENCY: {
+            struct timeval now;
 
-    u->n_bytes += l;
+            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 pa_usec_t get_latency(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    pa_usec_t a, b;
-    struct timeval now;
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
+
+    pa_assert(u);
+
+    pa_log_debug("Thread starting up");
+
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
+
+    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);
 
-    a = pa_timeval_diff(pa_gettimeofday(&now), &u->start_time);
-    b = pa_bytes_to_usec(u->n_bytes, &s->sample_spec);
+            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));
+            }
 
-    return b > a ? b - a : 0;
+            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");
 }
 
-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);
+
+    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);
 
-    u->core->mainloop->time_free(u->time_event);
+    if (u->rtpoll)
+        pa_rtpoll_free(u->rtpoll);
 
     pa_xfree(u);
 }
diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c
deleted file mode 100644 (file)
index 16c9b31..0000000
+++ /dev/null
@@ -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);
-}
index 9d4d0eac12b78edeba875f2b9923181417e7c5aa..19dceef2779ab55350ed3bf5b5a8032e140ae543 100644 (file)
   USA.
 ***/
 
+/* General power management rules:
+ *
+ *   When SUSPENDED we close the audio device.
+ *
+ *   We make no difference between IDLE and RUNNING in our handling.
+ *
+ *   As long as we are in RUNNING/IDLE state we will *always* write data to
+ *   the device. If none is avilable from the inputs, we write silence
+ *   instead.
+ *
+ *   If power should be saved on IDLE module-suspend-on-idle should be used.
+ *
+ */
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.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>
+#include <signal.h>
+#include <poll.h>
 
 #include <pulse/xmalloc.h>
 #include <pulse/util.h>
 
 #include <pulsecore/core-error.h>
-#include <pulsecore/iochannel.h>
+#include <pulsecore/thread.h>
 #include <pulsecore/sink.h>
 #include <pulsecore/source.h>
 #include <pulsecore/module.h>
@@ -50,6 +69,9 @@
 #include <pulsecore/core-util.h>
 #include <pulsecore/modargs.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/thread-mq.h>
+#include <pulsecore/rtpoll.h>
 
 #include "oss-util.h"
 #include "module-oss-symdef.h"
@@ -68,21 +90,48 @@ PA_MODULE_USAGE(
         "rate=<sample rate> "
         "fragments=<number of fragments> "
         "fragment_size=<fragment size> "
-        "channel_map=<channel map>")
+        "channel_map=<channel map> "
+        "mmap=<enable memory mapping?>")
+
+#define DEFAULT_DEVICE "/dev/dsp"
 
 struct userdata {
+    pa_core *core;
+    pa_module *module;
     pa_sink *sink;
     pa_source *source;
-    pa_iochannel *io;
-    pa_core *core;
 
-    pa_memchunk memchunk, silence;
+    pa_thread *thread;
+    pa_thread_mq thread_mq;
+    pa_rtpoll *rtpoll;
+
+    char *device_name;
+
+    pa_memchunk memchunk;
 
-    uint32_t in_fragment_size, out_fragment_size, sample_size;
-    int use_getospace, use_getispace;
+    size_t frame_size;
+    uint32_t in_fragment_size, out_fragment_size, in_nfrags, out_nfrags, in_hwbuf_size, out_hwbuf_size;
+    pa_bool_t use_getospace, use_getispace;
+    pa_bool_t use_getodelay;
+
+    pa_bool_t sink_suspended, source_suspended;
 
     int fd;
-    pa_module *module;
+    int mode;
+
+    int mixer_fd;
+    int mixer_devmask;
+
+    int nfrags, frag_size;
+
+    pa_bool_t use_mmap;
+    unsigned out_mmap_current, in_mmap_current;
+    void *in_mmap, *out_mmap;
+    pa_memblock **in_mmap_memblocks, **out_mmap_memblocks;
+
+    int in_mmap_saved_nfrags, out_mmap_saved_nfrags;
+
+    pa_rtpoll_item *rtpoll_item;
 };
 
 static const char* const valid_modargs[] = {
@@ -97,280 +146,1010 @@ static const char* const valid_modargs[] = {
     "rate",
     "channels",
     "channel_map",
+    "mmap",
     NULL
 };
 
-#define DEFAULT_DEVICE "/dev/dsp"
+static void trigger(struct userdata *u, pa_bool_t quick) {
+    int enable_bits = 0, zero = 0;
 
-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));
-}
+    pa_assert(u);
 
-static void clear_up(struct userdata *u) {
-    assert(u);
+    if (u->fd < 0)
+        return;
 
-    if (u->sink) {
-        pa_sink_disconnect(u->sink);
-        pa_sink_unref(u->sink);
-        u->sink = NULL;
-    }
+     pa_log_debug("trigger");
 
-    if (u->source) {
-        pa_source_disconnect(u->source);
-        pa_source_unref(u->source);
-        u->source = NULL;
-    }
+    if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state))
+        enable_bits |= PCM_ENABLE_INPUT;
 
-    if (u->io) {
-        pa_iochannel_free(u->io);
-        u->io = NULL;
-    }
-}
+    if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state))
+        enable_bits |= PCM_ENABLE_OUTPUT;
 
-static void do_write(struct userdata *u) {
-    pa_memchunk *memchunk;
-    ssize_t r;
-    size_t l;
-    int loop = 0;
+    pa_log_debug("trigger: %i", enable_bits);
 
-    assert(u);
 
-    if (!u->sink || !pa_iochannel_is_writable(u->io))
-        return;
+    if (u->use_mmap) {
 
-    update_usage(u);
+        if (!quick)
+            ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero);
 
-    l = u->out_fragment_size;
+#ifdef SNDCTL_DSP_HALT
+        if (enable_bits == 0)
+            if (ioctl(u->fd, SNDCTL_DSP_HALT, NULL) < 0)
+                pa_log_warn("SNDCTL_DSP_HALT: %s", pa_cstrerror(errno));
+#endif
 
-    if (u->use_getospace) {
-        audio_buf_info info;
+        if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0)
+            pa_log_warn("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno));
 
-        if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0)
-            u->use_getospace = 0;
-        else {
-            if (info.bytes/l > 0) {
-                l = (info.bytes/l)*l;
-                loop = 1;
+        if (u->sink && !(enable_bits & PCM_ENABLE_OUTPUT)) {
+            pa_log_debug("clearing playback buffer");
+            pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &u->sink->sample_spec);
+        }
+
+    } else {
+
+        if (enable_bits)
+            if (ioctl(u->fd, SNDCTL_DSP_POST, NULL) < 0)
+                pa_log_warn("SNDCTL_DSP_POST: %s", pa_cstrerror(errno));
+
+        if (!quick) {
+            /*
+             * Some crappy drivers do not start the recording until we
+             * read something.  Without this snippet, poll will never
+             * register the fd as ready.
+             */
+
+            if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) {
+                uint8_t *buf = pa_xnew(uint8_t, u->in_fragment_size);
+                pa_read(u->fd, buf, u->in_fragment_size, NULL);
+                pa_xfree(buf);
             }
         }
     }
+}
 
-    do {
-        memchunk = &u->memchunk;
+static void mmap_fill_memblocks(struct userdata *u, unsigned n) {
+    pa_assert(u);
+    pa_assert(u->out_mmap_memblocks);
 
-        if (!memchunk->length)
-            if (pa_sink_render(u->sink, l, memchunk) < 0)
-                memchunk = &u->silence;
+/*     pa_log("Mmmap writing %u blocks", n); */
 
-        assert(memchunk->memblock);
-        assert(memchunk->memblock->data);
-        assert(memchunk->length);
+    while (n > 0) {
+        pa_memchunk chunk;
 
-        if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) {
+        if (u->out_mmap_memblocks[u->out_mmap_current])
+            pa_memblock_unref_fixed(u->out_mmap_memblocks[u->out_mmap_current]);
 
-            if (errno != EAGAIN) {
-                pa_log("write() failed: %s", pa_cstrerror(errno));
+        chunk.memblock = u->out_mmap_memblocks[u->out_mmap_current] =
+            pa_memblock_new_fixed(
+                    u->core->mempool,
+                    (uint8_t*) u->out_mmap + u->out_fragment_size * u->out_mmap_current,
+                    u->out_fragment_size,
+                    1);
 
-                clear_up(u);
-                pa_module_unload_request(u->module);
-            }
+        chunk.length = pa_memblock_get_length(chunk.memblock);
+        chunk.index = 0;
 
-            break;
-        }
+        pa_sink_render_into_full(u->sink, &chunk);
 
-        if (memchunk == &u->silence)
-            assert(r % u->sample_size == 0);
-        else {
-            u->memchunk.index += r;
-            u->memchunk.length -= r;
+        u->out_mmap_current++;
+        while (u->out_mmap_current >= u->out_nfrags)
+            u->out_mmap_current -= u->out_nfrags;
 
-            if (u->memchunk.length <= 0) {
-                pa_memblock_unref(u->memchunk.memblock);
-                u->memchunk.memblock = NULL;
-            }
-        }
+        n--;
+    }
+}
+
+static int mmap_write(struct userdata *u) {
+    struct count_info info;
+
+    pa_assert(u);
+    pa_assert(u->sink);
+
+/*     pa_log("Mmmap writing..."); */
+
+    if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) {
+        pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno));
+        return -1;
+    }
+
+    info.blocks += u->out_mmap_saved_nfrags;
+    u->out_mmap_saved_nfrags = 0;
+
+    if (info.blocks > 0)
+        mmap_fill_memblocks(u, info.blocks);
 
-        l = l > (size_t) r ? l - r : 0;
-    } while (loop && l > 0);
+    return info.blocks;
 }
 
-static void do_read(struct userdata *u) {
-    pa_memchunk memchunk;
-    ssize_t r;
-    size_t l;
-    int loop = 0;
-    assert(u);
+static void mmap_post_memblocks(struct userdata *u, unsigned n) {
+    pa_assert(u);
+    pa_assert(u->in_mmap_memblocks);
 
-    if (!u->source || !pa_iochannel_is_readable(u->io) || !pa_idxset_size(u->source->outputs))
-        return;
+/*     pa_log("Mmmap reading %u blocks", n); */
 
-    update_usage(u);
+    while (n > 0) {
+        pa_memchunk chunk;
 
-    l = u->in_fragment_size;
+        if (!u->in_mmap_memblocks[u->in_mmap_current]) {
 
-    if (u->use_getispace) {
-        audio_buf_info info;
+            chunk.memblock = u->in_mmap_memblocks[u->in_mmap_current] =
+                pa_memblock_new_fixed(
+                        u->core->mempool,
+                        (uint8_t*) u->in_mmap + u->in_fragment_size*u->in_mmap_current,
+                        u->in_fragment_size,
+                        1);
 
-        if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0)
-            u->use_getispace = 0;
-        else {
-            if (info.bytes/l > 0) {
-                l = (info.bytes/l)*l;
-                loop = 1;
-            }
+            chunk.length = pa_memblock_get_length(chunk.memblock);
+            chunk.index = 0;
+
+            pa_source_post(u->source, &chunk);
         }
+
+        u->in_mmap_current++;
+        while (u->in_mmap_current >= u->in_nfrags)
+            u->in_mmap_current -= u->in_nfrags;
+
+        n--;
     }
+}
 
-    do {
-        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);
+static void mmap_clear_memblocks(struct userdata*u, unsigned n) {
+    unsigned i = u->in_mmap_current;
 
-            if (errno != EAGAIN) {
-                pa_log("read() failed: %s", pa_cstrerror(errno));
+    pa_assert(u);
+    pa_assert(u->in_mmap_memblocks);
 
-                clear_up(u);
-                pa_module_unload_request(u->module);
-            }
+    if (n > u->in_nfrags)
+        n = u->in_nfrags;
 
-            break;
+    while (n > 0) {
+        if (u->in_mmap_memblocks[i]) {
+            pa_memblock_unref_fixed(u->in_mmap_memblocks[i]);
+            u->in_mmap_memblocks[i] = NULL;
         }
 
-        assert(r <= (ssize_t) memchunk.memblock->length);
-        memchunk.length = memchunk.memblock->length = r;
-        memchunk.index = 0;
+        i++;
+        while (i >= u->in_nfrags)
+            i -= u->in_nfrags;
 
-        pa_source_post(u->source, &memchunk);
-        pa_memblock_unref(memchunk.memblock);
+        n--;
+    }
+}
 
-        l = l > (size_t) r ? l - r : 0;
-    } while (loop && l > 0);
+static int mmap_read(struct userdata *u) {
+    struct count_info info;
+    pa_assert(u);
+    pa_assert(u->source);
+
+/*     pa_log("Mmmap reading..."); */
+
+    if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) {
+        pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno));
+        return -1;
+    }
+
+/*     pa_log("... %i", info.blocks); */
+
+    info.blocks += u->in_mmap_saved_nfrags;
+    u->in_mmap_saved_nfrags = 0;
+
+    if (info.blocks > 0) {
+        mmap_post_memblocks(u, info.blocks);
+        mmap_clear_memblocks(u, u->in_nfrags/2);
+    }
+
+    return info.blocks;
 }
 
-static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
-    struct userdata *u = userdata;
-    assert(u);
-    do_write(u);
-    do_read(u);
+static pa_usec_t mmap_sink_get_latency(struct userdata *u) {
+    struct count_info info;
+    size_t bpos, n;
+
+    pa_assert(u);
+
+    if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) {
+        pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno));
+        return 0;
+    }
+
+    u->out_mmap_saved_nfrags += info.blocks;
+
+    bpos = ((u->out_mmap_current + u->out_mmap_saved_nfrags) * u->out_fragment_size) % u->out_hwbuf_size;
+
+    if (bpos <= (size_t) info.ptr)
+        n = u->out_hwbuf_size - (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, &u->sink->sample_spec);
 }
 
-static void source_notify_cb(pa_source *s) {
-    struct userdata *u = s->userdata;
-    assert(u);
-    do_read(u);
+static pa_usec_t mmap_source_get_latency(struct userdata *u) {
+    struct count_info info;
+    size_t bpos, n;
+
+    pa_assert(u);
+
+    if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) {
+        pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno));
+        return 0;
+    }
+
+    u->in_mmap_saved_nfrags += info.blocks;
+    bpos = ((u->in_mmap_current + u->in_mmap_saved_nfrags) * u->in_fragment_size) % u->in_hwbuf_size;
+
+    if (bpos <= (size_t) info.ptr)
+        n = info.ptr - bpos;
+    else
+        n = u->in_hwbuf_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, &u->source->sample_spec);
 }
 
-static pa_usec_t sink_get_latency_cb(pa_sink *s) {
+static pa_usec_t io_sink_get_latency(struct userdata *u) {
     pa_usec_t r = 0;
-    int arg;
-    struct userdata *u = s->userdata;
-    assert(s && u && u->sink);
 
-    if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) {
-        pa_log_info("device doesn't support SNDCTL_DSP_GETODELAY: %s", pa_cstrerror(errno));
-        s->get_latency = NULL;
-        return 0;
+    pa_assert(u);
+
+    if (u->use_getodelay) {
+        int arg;
+
+        if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) {
+            pa_log_info("Device doesn't support SNDCTL_DSP_GETODELAY: %s", pa_cstrerror(errno));
+            u->use_getodelay = 0;
+        } else
+            r = pa_bytes_to_usec(arg, &u->sink->sample_spec);
+
     }
 
-    r += pa_bytes_to_usec(arg, &s->sample_spec);
+    if (!u->use_getodelay && u->use_getospace) {
+        struct audio_buf_info info;
+
+        if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
+            pa_log_info("Device doesn't support SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno));
+            u->use_getospace = 0;
+        } else
+            r = pa_bytes_to_usec(info.bytes, &u->sink->sample_spec);
+    }
 
     if (u->memchunk.memblock)
-        r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec);
+        r += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec);
 
     return r;
 }
 
-static pa_usec_t source_get_latency_cb(pa_source *s) {
-    struct userdata *u = s->userdata;
-    audio_buf_info info;
-    assert(s && u && u->source);
 
-    if (!u->use_getispace)
-        return 0;
+static pa_usec_t io_source_get_latency(struct userdata *u) {
+    pa_usec_t r = 0;
 
-    if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) {
-        u->use_getispace = 0;
-        return 0;
+    pa_assert(u);
+
+    if (u->use_getispace) {
+        struct audio_buf_info info;
+
+        if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) {
+            pa_log_info("Device doesn't support SNDCTL_DSP_GETISPACE: %s", pa_cstrerror(errno));
+            u->use_getispace = 0;
+        } else
+            r = pa_bytes_to_usec(info.bytes, &u->source->sample_spec);
     }
 
-    if (info.bytes <= 0)
-        return 0;
+    return r;
+}
+
+static void build_pollfd(struct userdata *u) {
+    struct pollfd *pollfd;
 
-    return pa_bytes_to_usec(info.bytes, &s->sample_spec);
+    pa_assert(u);
+    pa_assert(u->fd >= 0);
+
+    if (u->rtpoll_item)
+        pa_rtpoll_item_free(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 = 0;
+    pollfd->revents = 0;
 }
 
-static int sink_get_hw_volume(pa_sink *s) {
-    struct userdata *u = s->userdata;
+static int suspend(struct userdata *u) {
+    pa_assert(u);
+    pa_assert(u->fd >= 0);
 
-    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;
+    pa_log_info("Suspending...");
+
+    if (u->out_mmap_memblocks) {
+        unsigned i;
+        for (i = 0; i < u->out_nfrags; i++)
+            if (u->out_mmap_memblocks[i]) {
+                pa_memblock_unref_fixed(u->out_mmap_memblocks[i]);
+                u->out_mmap_memblocks[i] = NULL;
+            }
     }
 
+    if (u->in_mmap_memblocks) {
+        unsigned i;
+        for (i = 0; i < u->in_nfrags; i++)
+            if (u->in_mmap_memblocks[i]) {
+                pa_memblock_unref_fixed(u->in_mmap_memblocks[i]);
+                u->in_mmap_memblocks[i] = NULL;
+            }
+    }
+
+    if (u->in_mmap && u->in_mmap != MAP_FAILED) {
+        munmap(u->in_mmap, u->in_hwbuf_size);
+        u->in_mmap = NULL;
+    }
+
+    if (u->out_mmap && u->out_mmap != MAP_FAILED) {
+        munmap(u->out_mmap, u->out_hwbuf_size);
+        u->out_mmap = NULL;
+    }
+
+    /* Let's suspend */
+    ioctl(u->fd, SNDCTL_DSP_SYNC, NULL);
+    pa_close(u->fd);
+    u->fd = -1;
+
+    if (u->rtpoll_item) {
+        pa_rtpoll_item_free(u->rtpoll_item);
+        u->rtpoll_item = NULL;
+    }
+
+    pa_log_info("Device suspended...");
+
     return 0;
 }
 
-static int sink_set_hw_volume(pa_sink *s) {
-    struct userdata *u = s->userdata;
+static int unsuspend(struct userdata *u) {
+    int m;
+    pa_sample_spec ss, *ss_original;
+    int frag_size, in_frag_size, out_frag_size;
+    int in_nfrags, out_nfrags;
+    struct audio_buf_info info;
+
+    pa_assert(u);
+    pa_assert(u->fd < 0);
+
+    m = u->mode;
+
+    pa_log_info("Trying resume...");
 
-    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;
+    if ((u->fd = pa_oss_open(u->device_name, &m, NULL)) < 0) {
+        pa_log_warn("Resume failed, device busy (%s)", pa_cstrerror(errno));
         return -1;
+
+    if (m != u->mode)
+        pa_log_warn("Resume failed, couldn't open device with original access mode.");
+        goto fail;
+    }
+
+    if (u->nfrags >= 2 && u->frag_size >= 1)
+        if (pa_oss_set_fragments(u->fd, u->nfrags, u->frag_size) < 0) {
+            pa_log_warn("Resume failed, couldn't set original fragment settings.");
+            goto fail;
+        }
+
+    ss = *(ss_original = u->sink ? &u->sink->sample_spec : &u->source->sample_spec);
+    if (pa_oss_auto_format(u->fd, &ss) < 0 || !pa_sample_spec_equal(&ss, ss_original)) {
+        pa_log_warn("Resume failed, couldn't set original sample format settings.");
+        goto fail;
+    }
+
+    if (ioctl(u->fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) {
+        pa_log_warn("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno));
+        goto fail;
+    }
+
+    in_frag_size = out_frag_size = frag_size;
+    in_nfrags = out_nfrags = u->nfrags;
+
+    if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
+        in_frag_size = info.fragsize;
+        in_nfrags = info.fragstotal;
+    }
+
+    if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) {
+        out_frag_size = info.fragsize;
+        out_nfrags = info.fragstotal;
+    }
+
+    if ((u->source && (in_frag_size != (int) u->in_fragment_size || in_nfrags != (int) u->in_nfrags)) ||
+        (u->sink && (out_frag_size != (int) u->out_fragment_size || out_nfrags != (int) u->out_nfrags))) {
+        pa_log_warn("Resume failed, input fragment settings don't match.");
+        goto fail;
+    }
+
+    if (u->use_mmap) {
+        if (u->source) {
+            if ((u->in_mmap = mmap(NULL, u->in_hwbuf_size, PROT_READ, MAP_SHARED, u->fd, 0)) == MAP_FAILED) {
+                pa_log("Resume failed, mmap(): %s", pa_cstrerror(errno));
+                goto fail;
+            }
+        }
+
+        if (u->sink) {
+            if ((u->out_mmap = mmap(NULL, u->out_hwbuf_size, PROT_WRITE, MAP_SHARED, u->fd, 0)) == MAP_FAILED) {
+                pa_log("Resume failed, mmap(): %s", pa_cstrerror(errno));
+                if (u->in_mmap && u->in_mmap != MAP_FAILED) {
+                    munmap(u->in_mmap, u->in_hwbuf_size);
+                    u->in_mmap = NULL;
+                }
+
+                goto fail;
+            }
+
+            pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &ss);
+        }
     }
 
+    u->out_mmap_current = u->in_mmap_current = 0;
+    u->out_mmap_saved_nfrags = u->in_mmap_saved_nfrags = 0;
+
+    pa_assert(!u->rtpoll_item);
+
+    build_pollfd(u);
+
+    if (u->sink)
+        pa_sink_get_volume(u->sink);
+    if (u->source)
+        pa_source_get_volume(u->source);
+
+    pa_log_info("Resumed successfully...");
+
     return 0;
+
+fail:
+    pa_close(u->fd);
+    u->fd = -1;
+    return -1;
 }
 
-static int source_get_hw_volume(pa_source *s) {
-    struct userdata *u = s->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;
+    int ret;
+    pa_bool_t do_trigger = FALSE, quick = TRUE;
+
+    switch (code) {
+
+        case PA_SINK_MESSAGE_GET_LATENCY: {
+            pa_usec_t r = 0;
+
+            if (u->fd >= 0) {
+                if (u->use_mmap)
+                    r = mmap_sink_get_latency(u);
+                else
+                    r = io_sink_get_latency(u);
+            }
+
+            *((pa_usec_t*) data) = r;
+
+            return 0;
+        }
+
+        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));
+
+                    if (!u->source || u->source_suspended) {
+                        if (suspend(u) < 0)
+                            return -1;
+                    }
+
+                    do_trigger = TRUE;
+
+                    u->sink_suspended = TRUE;
+                    break;
+
+                case PA_SINK_IDLE:
+                case PA_SINK_RUNNING:
+
+                    if (u->sink->thread_info.state == PA_SINK_INIT) {
+                        do_trigger = TRUE;
+                        quick = u->source && PA_SOURCE_OPENED(u->source->thread_info.state);
+                    }
+
+                    if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
+
+                        if (!u->source || u->source_suspended) {
+                            if (unsuspend(u) < 0)
+                                return -1;
+                            quick = FALSE;
+                        }
+
+                        do_trigger = TRUE;
+
+                        u->out_mmap_current = 0;
+                        u->out_mmap_saved_nfrags = 0;
+
+                        u->sink_suspended = FALSE;
+                    }
+
+                    break;
+
+                case PA_SINK_UNLINKED:
+                case PA_SINK_INIT:
+                    ;
+            }
+
+            break;
 
-    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;
+    ret = pa_sink_process_msg(o, code, data, offset, chunk);
+
+    if (do_trigger)
+        trigger(u, quick);
+
+    return ret;
 }
 
-static int source_set_hw_volume(pa_source *s) {
-    struct userdata *u = s->userdata;
+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 ret;
+    int do_trigger = FALSE, quick = TRUE;
+
+    switch (code) {
+
+        case PA_SOURCE_MESSAGE_GET_LATENCY: {
+            pa_usec_t r = 0;
+
+            if (u->fd >= 0) {
+                if (u->use_mmap)
+                    r = mmap_source_get_latency(u);
+                else
+                    r = io_source_get_latency(u);
+            }
+
+            *((pa_usec_t*) data) = r;
+            return 0;
+        }
+
+        case PA_SOURCE_MESSAGE_SET_STATE:
+
+            switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
+                case PA_SOURCE_SUSPENDED:
+                    pa_assert(PA_SOURCE_OPENED(u->source->thread_info.state));
+
+                    if (!u->sink || u->sink_suspended) {
+                        if (suspend(u) < 0)
+                            return -1;
+                    }
+
+                    do_trigger = TRUE;
+
+                    u->source_suspended = TRUE;
+                    break;
+
+                case PA_SOURCE_IDLE:
+                case PA_SOURCE_RUNNING:
+
+                    if (u->source->thread_info.state == PA_SOURCE_INIT) {
+                        do_trigger = TRUE;
+                        quick = u->sink && PA_SINK_OPENED(u->sink->thread_info.state);
+                    }
+
+                    if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
+
+                        if (!u->sink || u->sink_suspended) {
+                            if (unsuspend(u) < 0)
+                                return -1;
+                            quick = FALSE;
+                        }
+
+                        do_trigger = TRUE;
+
+                        u->in_mmap_current = 0;
+                        u->in_mmap_saved_nfrags = 0;
+
+                        u->source_suspended = FALSE;
+                    }
+                    break;
+
+                case PA_SOURCE_UNLINKED:
+                case PA_SOURCE_INIT:
+                    ;
+
+            }
+            break;
 
-    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;
+    ret = pa_source_process_msg(o, code, data, offset, chunk);
+
+    if (do_trigger)
+        trigger(u, quick);
+
+    return ret;
+}
+
+static int sink_get_volume(pa_sink *s) {
+    struct userdata *u;
+    int r;
+
+    pa_assert_se(u = s->userdata);
+
+    pa_assert(u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM));
+
+    if (u->mixer_devmask & SOUND_MASK_VOLUME)
+        if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_VOLUME, &s->sample_spec, &s->volume)) >= 0)
+            return r;
+
+    if (u->mixer_devmask & SOUND_MASK_PCM)
+        if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_PCM, &s->sample_spec, &s->volume)) >= 0)
+            return r;
+
+    pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
+    return -1;
+}
+
+static int sink_set_volume(pa_sink *s) {
+    struct userdata *u;
+    int r;
+
+    pa_assert_se(u = s->userdata);
+
+    pa_assert(u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM));
+
+    if (u->mixer_devmask & SOUND_MASK_VOLUME)
+        if ((r = pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_VOLUME, &s->sample_spec, &s->volume)) >= 0)
+            return r;
+
+    if (u->mixer_devmask & SOUND_MASK_PCM)
+        if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_WRITE_PCM, &s->sample_spec, &s->volume)) >= 0)
+            return r;
+
+    pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
+    return -1;
 }
 
-int pa__init(pa_core *c, pa_module*m) {
+static int source_get_volume(pa_source *s) {
+    struct userdata *u;
+    int r;
+
+    pa_assert_se(u = s->userdata);
+
+    pa_assert(u->mixer_devmask & (SOUND_MASK_IGAIN|SOUND_MASK_RECLEV));
+
+    if (u->mixer_devmask & SOUND_MASK_IGAIN)
+        if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_IGAIN, &s->sample_spec, &s->volume)) >= 0)
+            return r;
+
+    if (u->mixer_devmask & SOUND_MASK_RECLEV)
+        if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_RECLEV, &s->sample_spec, &s->volume)) >= 0)
+            return r;
+
+    pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
+    return -1;
+}
+
+static int source_set_volume(pa_source *s) {
+    struct userdata *u;
+    int r;
+
+    pa_assert_se(u = s->userdata);
+
+    pa_assert(u->mixer_devmask & (SOUND_MASK_IGAIN|SOUND_MASK_RECLEV));
+
+    if (u->mixer_devmask & SOUND_MASK_IGAIN)
+        if ((r = pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_IGAIN, &s->sample_spec, &s->volume)) >= 0)
+            return r;
+
+    if (u->mixer_devmask & SOUND_MASK_RECLEV)
+        if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_WRITE_RECLEV, &s->sample_spec, &s->volume)) >= 0)
+            return r;
+
+    pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
+    return -1;
+}
+
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
+    int write_type = 0, read_type = 0;
+    unsigned short revents = 0;
+
+    pa_assert(u);
+
+    pa_log_debug("Thread starting up");
+
+    if (u->core->high_priority)
+        pa_make_realtime();
+
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
+
+    for (;;) {
+        int ret;
+
+/*        pa_log("loop");    */
+
+        /* Render some data and write it to the dsp */
+
+        if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state) && ((revents & POLLOUT) || u->use_mmap || u->use_getospace)) {
+
+            if (u->use_mmap) {
+
+                if ((ret = mmap_write(u)) < 0)
+                    goto fail;
+
+                revents &= ~POLLOUT;
+
+                if (ret > 0)
+                    continue;
+
+            } else {
+                ssize_t l;
+                pa_bool_t loop = FALSE, work_done = FALSE;
+
+                l = u->out_fragment_size;
+
+                if (u->use_getospace) {
+                    audio_buf_info info;
+
+                    if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
+                        pa_log_info("Device doesn't support SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno));
+                        u->use_getospace = FALSE;
+                    } else {
+                        l = info.bytes;
+
+                        /* We loop only if GETOSPACE worked and we
+                         * actually *know* that we can write more than
+                         * one fragment at a time */
+                        loop = TRUE;
+                    }
+                }
+
+                /* Round down to multiples of the fragment size,
+                 * because OSS needs that (at least some versions
+                 * do) */
+                l = (l/u->out_fragment_size) * u->out_fragment_size;
+
+                /* Hmm, so poll() signalled us that we can read
+                 * something, but GETOSPACE told us there was nothing?
+                 * Hmm, make the best of it, try to read some data, to
+                 * avoid spinning forever. */
+                if (l <= 0 && (revents & POLLOUT)) {
+                    l = u->out_fragment_size;
+                    loop = FALSE;
+                }
+
+                while (l > 0) {
+                    void *p;
+                    ssize_t t;
+
+                    if (u->memchunk.length <= 0)
+                        pa_sink_render(u->sink, l, &u->memchunk);
+
+                    pa_assert(u->memchunk.length > 0);
+
+                    p = pa_memblock_acquire(u->memchunk.memblock);
+                    t = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, &write_type);
+                    pa_memblock_release(u->memchunk.memblock);
+
+/*                     pa_log("wrote %i bytes of %u", t, l); */
+
+                    pa_assert(t != 0);
+
+                    if (t < 0) {
+
+                        if (errno == EINTR)
+                            continue;
+
+                        else if (errno == EAGAIN) {
+                            pa_log_debug("EAGAIN");
+
+                            revents &= ~POLLOUT;
+                            break;
+
+                        } else {
+                            pa_log("Failed to write data to DSP: %s", pa_cstrerror(errno));
+                            goto fail;
+                        }
+
+                    } else {
+
+                        u->memchunk.index += t;
+                        u->memchunk.length -= t;
+
+                        if (u->memchunk.length <= 0) {
+                            pa_memblock_unref(u->memchunk.memblock);
+                            pa_memchunk_reset(&u->memchunk);
+                        }
+
+                        l -= t;
+
+                        revents &= ~POLLOUT;
+                        work_done = TRUE;
+                    }
+
+                    if (!loop)
+                        break;
+                }
+
+                if (work_done)
+                    continue;
+            }
+        }
+
+        /* 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) || u->use_mmap || u->use_getispace)) {
+
+            if (u->use_mmap) {
+
+                if ((ret = mmap_read(u)) < 0)
+                    goto fail;
+
+                revents &= ~POLLIN;
+
+                if (ret > 0)
+                    continue;
+
+            } else {
+
+                void *p;
+                ssize_t l;
+                pa_memchunk memchunk;
+                pa_bool_t loop = FALSE, work_done = FALSE;
+
+                l = u->in_fragment_size;
+
+                if (u->use_getispace) {
+                    audio_buf_info info;
+
+                    if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) {
+                        pa_log_info("Device doesn't support SNDCTL_DSP_GETISPACE: %s", pa_cstrerror(errno));
+                        u->use_getispace = FALSE;
+                    } else {
+                        l = info.bytes;
+                        loop = TRUE;
+                    }
+                }
+
+                l = (l/u->in_fragment_size) * u->in_fragment_size;
+
+                if (l <= 0 && (revents & POLLIN)) {
+                    l = u->in_fragment_size;
+                    loop = FALSE;
+                }
+
+                while (l > 0) {
+                    ssize_t t, k;
+
+                    pa_assert(l > 0);
+
+                    memchunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1);
+
+                    k = pa_memblock_get_length(memchunk.memblock);
+
+                    if (k > l)
+                        k = l;
+
+                    k = (k/u->frame_size)*u->frame_size;
+
+                    p = pa_memblock_acquire(memchunk.memblock);
+                    t = pa_read(u->fd, p, k, &read_type);
+                    pa_memblock_release(memchunk.memblock);
+
+                    pa_assert(t != 0); /* EOF cannot happen */
+
+/*                     pa_log("read %i bytes of %u", t, l); */
+
+                    if (t < 0) {
+                        pa_memblock_unref(memchunk.memblock);
+
+                        if (errno == EINTR)
+                            continue;
+
+                        else if (errno == EAGAIN) {
+                            pa_log_debug("EAGAIN");
+
+                            revents &= ~POLLIN;
+                            break;
+
+                        } else {
+                            pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno));
+                            goto fail;
+                        }
+
+                    } else {
+                        memchunk.index = 0;
+                        memchunk.length = t;
+
+                        pa_source_post(u->source, &memchunk);
+                        pa_memblock_unref(memchunk.memblock);
+
+                        l -= t;
+
+                        revents &= ~POLLIN;
+                        work_done = TRUE;
+                    }
+
+                    if (!loop)
+                        break;
+                }
+
+                if (work_done)
+                    continue;
+            }
+        }
+
+/*         pa_log("loop2 revents=%i", revents); */
+
+        if (u->rtpoll_item) {
+            struct pollfd *pollfd;
+
+            pa_assert(u->fd >= 0);
+
+            pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+            pollfd->events =
+                ((u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) ? POLLIN : 0) |
+                ((u->sink && PA_SINK_OPENED(u->sink->thread_info.state)) ? POLLOUT : 0);
+        }
+
+        /* Hmm, nothing to do. Let's sleep */
+        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|POLLIN)) {
+                pa_log("DSP shutdown.");
+                goto fail;
+            }
+
+            revents = pollfd->revents;
+        } else
+            revents = 0;
+    }
+
+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_module*m) {
+
     struct audio_buf_info info;
     struct userdata *u = NULL;
-    const char *p;
+    const char *dev;
     int fd = -1;
-    int nfrags, frag_size, in_frag_size, out_frag_size;
-    int mode;
-    int record = 1, playback = 1;
+    int nfrags, frag_size;
+    int mode, caps;
+    int record = 1, playback = 1, use_mmap = 1;
     pa_sample_spec ss;
     pa_channel_map map;
     pa_modargs *ma = NULL;
     char hwdesc[64], *t;
     const char *name;
-    char *name_buf = NULL;
     int namereg_fail;
 
-    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;
     }
 
@@ -380,36 +1159,52 @@ int pa__init(pa_core *c, pa_module*m) {
     }
 
     if (!playback && !record) {
-        pa_log("neither playback nor record enabled for device.");
+        pa_log("Neither playback nor record enabled for device.");
         goto fail;
     }
 
-    mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
+    mode = (playback && record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
 
-    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_OSS) < 0) {
-        pa_log("failed to parse sample specification or channel map");
+        pa_log("Failed to parse sample specification or channel map");
         goto fail;
     }
 
-    /* Fix latency to 100ms */
-    nfrags = 12;
-    frag_size = pa_bytes_per_second(&ss)/128;
+    nfrags = m->core->default_n_fragments;
+    frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*1000, &ss);
+    if (frag_size <= 0)
+        frag_size = pa_frame_size(&ss);
 
     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");
+        pa_log("Failed to parse fragments arguments");
         goto fail;
     }
 
-    if ((fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, NULL)) < 0)
+    if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
+        pa_log("Failed to parse mmap argument.");
         goto fail;
+    }
 
-    if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0)
-        pa_log_info("hardware name is '%s'.", hwdesc);
+    if ((fd = pa_oss_open(dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0)
+        goto fail;
+
+    if (use_mmap && (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_TRIGGER))) {
+        pa_log_info("OSS device not mmap capable, falling back to UNIX read/write mode.");
+        use_mmap = 0;
+    }
+
+    if (use_mmap && mode == O_WRONLY) {
+        pa_log_info("Device opened for playback only, cannot do memory mapping, falling back to UNIX write() mode.");
+        use_mmap = 0;
+    }
+
+    if (pa_oss_get_hw_description(dev, hwdesc, sizeof(hwdesc)) >= 0)
+        pa_log_info("Hardware name is '%s'.", hwdesc);
     else
         hwdesc[0] = 0;
 
-    pa_log_info("device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR"));
+    pa_log_info("Device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR"));
 
     if (nfrags >= 2 && frag_size >= 1)
         if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0)
@@ -422,152 +1217,282 @@ int pa__init(pa_core *c, pa_module*m) {
         pa_log("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno));
         goto fail;
     }
-    assert(frag_size);
-    in_frag_size = out_frag_size = frag_size;
+    pa_assert(frag_size > 0);
 
-    u = pa_xmalloc(sizeof(struct userdata));
-    u->core = c;
-    u->use_getospace = u->use_getispace = 0;
+    u = pa_xnew0(struct userdata, 1);
+    u->core = m->core;
+    u->module = m;
+    m->userdata = u;
+    u->fd = fd;
+    u->mixer_fd = -1;
+    u->use_getospace = u->use_getispace = 1;
+    u->use_getodelay = 1;
+    u->mode = mode;
+    u->frame_size = pa_frame_size(&ss);
+    u->device_name = pa_xstrdup(dev);
+    u->in_nfrags = u->out_nfrags = u->nfrags = nfrags;
+    u->out_fragment_size = u->in_fragment_size = u->frag_size = frag_size;
+    u->use_mmap = use_mmap;
+    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;
+    build_pollfd(u);
 
     if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
-        pa_log_info("input -- %u fragments of size %u.", info.fragstotal, info.fragsize);
-        in_frag_size = info.fragsize;
+        pa_log_info("Input -- %u fragments of size %u.", info.fragstotal, info.fragsize);
+        u->in_fragment_size = info.fragsize;
+        u->in_nfrags = info.fragstotal;
         u->use_getispace = 1;
     }
 
     if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) {
-        pa_log_info("output -- %u fragments of size %u.", info.fragstotal, info.fragsize);
-        out_frag_size = info.fragsize;
+        pa_log_info("Output -- %u fragments of size %u.", info.fragstotal, info.fragsize);
+        u->out_fragment_size = info.fragsize;
+        u->out_nfrags = info.fragstotal;
         u->use_getospace = 1;
     }
 
+    u->in_hwbuf_size = u->in_nfrags * u->in_fragment_size;
+    u->out_hwbuf_size = u->out_nfrags * u->out_fragment_size;
+
     if (mode != O_WRONLY) {
+        char *name_buf = NULL;
+
+        if (use_mmap) {
+            if ((u->in_mmap = mmap(NULL, u->in_hwbuf_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
+                pa_log_warn("mmap(PROT_READ) failed, reverting to non-mmap mode: %s", pa_cstrerror(errno));
+                use_mmap = u->use_mmap = 0;
+                u->in_mmap = NULL;
+            } else
+                pa_log_debug("Successfully mmap()ed input buffer.");
+        }
+
         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));
+            name = name_buf = pa_sprintf_malloc("oss_input.%s", pa_path_get_filename(dev));
             namereg_fail = 0;
         }
 
-        if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map)))
+        u->source = pa_source_new(m->core, __FILE__, name, namereg_fail, &ss, &map);
+        pa_xfree(name_buf);
+        if (!u->source) {
+            pa_log("Failed to create source object");
             goto fail;
+        }
 
+        u->source->parent.process_msg = source_process_msg;
         u->source->userdata = u;
-        u->source->notify = source_notify_cb;
-        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 on %s%s%s%s",
-                                                                 p,
-                                                                 hwdesc[0] ? " (" : "",
-                                                                 hwdesc[0] ? hwdesc : "",
-                                                                 hwdesc[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(
+                                          "OSS PCM on %s%s%s%s%s",
+                                          dev,
+                                          hwdesc[0] ? " (" : "",
+                                          hwdesc[0] ? hwdesc : "",
+                                          hwdesc[0] ? ")" : "",
+                                          use_mmap ? " via DMA" : ""));
         pa_xfree(t);
-        u->source->is_hardware = 1;
-    } else
-        u->source = NULL;
+        u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY;
+        u->source->refresh_volume = TRUE;
 
-    pa_xfree(name_buf);
-    name_buf = NULL;
+        if (use_mmap)
+            u->in_mmap_memblocks = pa_xnew0(pa_memblock*, u->in_nfrags);
+    }
 
     if (mode != O_RDONLY) {
+        char *name_buf = NULL;
+
+        if (use_mmap) {
+            if ((u->out_mmap = mmap(NULL, u->out_hwbuf_size, PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
+                if (mode == O_RDWR) {
+                    pa_log_debug("mmap() failed for input. Changing to O_WRONLY mode.");
+                    mode = O_WRONLY;
+                    goto go_on;
+                } else {
+                    pa_log_warn("mmap(PROT_WRITE) failed, reverting to non-mmap mode: %s", pa_cstrerror(errno));
+                    u->use_mmap = (use_mmap = FALSE);
+                    u->out_mmap = NULL;
+                }
+            } else {
+                pa_log_debug("Successfully mmap()ed output buffer.");
+                pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &ss);
+            }
+        }
+
         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));
+            name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(dev));
             namereg_fail = 0;
         }
 
-        if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &ss, &map)))
+        u->sink = pa_sink_new(m->core, __FILE__, name, namereg_fail, &ss, &map);
+        pa_xfree(name_buf);
+        if (!u->sink) {
+            pa_log("Failed to create sink object");
             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->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("OSS PCM on %s%s%s%s",
-                                                           p,
-                                                           hwdesc[0] ? " (" : "",
-                                                           hwdesc[0] ? hwdesc : "",
-                                                           hwdesc[0] ? ")" : ""));
+
+        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(
+                                        "OSS PCM on %s%s%s%s%s",
+                                        dev,
+                                        hwdesc[0] ? " (" : "",
+                                        hwdesc[0] ? hwdesc : "",
+                                        hwdesc[0] ? ")" : "",
+                                        use_mmap ? " via DMA" : ""));
         pa_xfree(t);
-        u->sink->is_hardware = 1;
-    } else
-        u->sink = NULL;
+        u->sink->flags = PA_SINK_HARDWARE|PA_SINK_LATENCY;
+        u->sink->refresh_volume = TRUE;
 
-    pa_xfree(name_buf);
-    name_buf = NULL;
+        if (use_mmap)
+            u->out_mmap_memblocks = pa_xnew0(pa_memblock*, u->out_nfrags);
+    }
 
-    assert(u->source || u->sink);
+    if ((u->mixer_fd = pa_oss_open_mixer_for_device(u->device_name)) >= 0) {
+        int do_close = 1;
+        u->mixer_devmask = 0;
 
-    u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : -1);
-    assert(u->io);
-    pa_iochannel_set_callback(u->io, io_callback, u);
-    u->fd = fd;
+        if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &u->mixer_devmask) < 0)
+            pa_log_warn("SOUND_MIXER_READ_DEVMASK failed: %s", pa_cstrerror(errno));
 
-    u->memchunk.memblock = NULL;
-    u->memchunk.length = 0;
-    u->sample_size = pa_frame_size(&ss);
+        else {
+            if (u->sink && (u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM))) {
+                pa_log_debug("Found hardware mixer track for playback.");
+                u->sink->flags |= PA_SINK_HW_VOLUME_CTRL;
+                u->sink->get_volume = sink_get_volume;
+                u->sink->set_volume = sink_set_volume;
+                do_close = 0;
+            }
 
-    u->out_fragment_size = out_frag_size;
-    u->in_fragment_size = in_frag_size;
-    u->silence.memblock = pa_memblock_new(u->core->mempool, u->silence.length = u->out_fragment_size);
-    assert(u->silence.memblock);
-    pa_silence_memblock(u->silence.memblock, &ss);
-    u->silence.index = 0;
+            if (u->source && (u->mixer_devmask & (SOUND_MASK_RECLEV|SOUND_MASK_IGAIN))) {
+                pa_log_debug("Found hardware mixer track for recording.");
+                u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL;
+                u->source->get_volume = source_get_volume;
+                u->source->set_volume = source_set_volume;
+                do_close = 0;
+            }
+        }
 
-    u->module = m;
-    m->userdata = u;
+        if (do_close) {
+            pa_close(u->mixer_fd);
+            u->mixer_fd = -1;
+        }
+    }
 
-    pa_modargs_free(ma);
+go_on:
+
+    pa_assert(u->source || u->sink);
 
-    /*
-     * Some crappy drivers do not start the recording until we read something.
-     * Without this snippet, poll will never register the fd as ready.
-     */
-    if (u->source) {
-        char *buf = pa_xnew(char, u->sample_size);
-        pa_read(u->fd, buf, u->sample_size, NULL);
-        pa_xfree(buf);
+    pa_memchunk_reset(&u->memchunk);
+
+    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(u->source);
+    if (u->sink && u->sink->get_volume)
+        sink_get_volume(u->sink);
+    if (u->source && u->source->get_volume)
+        source_get_volume(u->source);
+
     if (u->sink)
-        sink_get_hw_volume(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)
-        close(fd);
+
+    if (u)
+        pa__done(m);
+    else if (fd >= 0)
+        pa_close(fd);
 
     if (ma)
         pa_modargs_free(ma);
 
-    pa_xfree(name_buf);
-
     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;
 
-    clear_up(u);
+    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->silence.memblock)
-        pa_memblock_unref(u->silence.memblock);
+
+    if (u->rtpoll_item)
+        pa_rtpoll_item_free(u->rtpoll_item);
+
+    if (u->rtpoll)
+        pa_rtpoll_free(u->rtpoll);
+
+    if (u->out_mmap_memblocks) {
+        unsigned i;
+        for (i = 0; i < u->out_nfrags; i++)
+            if (u->out_mmap_memblocks[i])
+                pa_memblock_unref_fixed(u->out_mmap_memblocks[i]);
+        pa_xfree(u->out_mmap_memblocks);
+    }
+
+    if (u->in_mmap_memblocks) {
+        unsigned i;
+        for (i = 0; i < u->in_nfrags; i++)
+            if (u->in_mmap_memblocks[i])
+                pa_memblock_unref_fixed(u->in_mmap_memblocks[i]);
+        pa_xfree(u->in_mmap_memblocks);
+    }
+
+    if (u->in_mmap && u->in_mmap != MAP_FAILED)
+        munmap(u->in_mmap, u->in_hwbuf_size);
+
+    if (u->out_mmap && u->out_mmap != MAP_FAILED)
+        munmap(u->out_mmap, u->out_hwbuf_size);
+
+    if (u->fd >= 0)
+        pa_close(u->fd);
+
+    if (u->mixer_fd >= 0)
+        pa_close(u->mixer_fd);
+
+    pa_xfree(u->device_name);
 
     pa_xfree(u);
 }
index 170b046efb4c41c8ea608409d570dbab6a199f08..75748474533dcbc88462d459fc137615dc79eb00 100644 (file)
 #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;
 
-    char *filename;
+    pa_thread *thread;
+    pa_thread_mq thread_mq;
+    pa_rtpoll *rtpoll;
 
-    pa_sink *sink;
-    pa_iochannel *io;
-    pa_defer_event *defer_event;
+    char *filename;
+    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));
-
-    if (!u->memchunk.length)
-        if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0)
-            return;
+#ifdef TIOCINQ
+            if (ioctl(u->fd, TIOCINQ, &l) >= 0 && l > 0)
+                n = (size_t) l;
+#endif
 
-    assert(u->memchunk.memblock && u->memchunk.length);
+            n += 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;
-
-    if (u->memchunk.length <= 0) {
-        pa_memblock_unref(u->memchunk.memblock);
-        u->memchunk.memblock = NULL;
-    }
+    return pa_sink_process_msg(o, code, data, offset, chunk);
 }
 
-static void notify_cb(pa_sink*s) {
-    struct userdata *u = s->userdata;
-    assert(s && u);
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
+    int write_type = 0;
 
-    if (pa_iochannel_is_writable(u->io))
-        u->core->mainloop->defer_enable(u->defer_event, 1);
-}
+    pa_assert(u);
 
-static pa_usec_t get_latency_cb(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    assert(s && u);
+    pa_log_debug("Thread starting up");
 
-    return u->memchunk.memblock ? pa_bytes_to_usec(u->memchunk.length, &s->sample_spec) : 0;
-}
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
 
-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);
-}
+    for (;;) {
+        struct pollfd *pollfd;
+        int ret;
 
-static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
-    struct userdata *u = userdata;
-    assert(u);
-    do_write(u);
+        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");
 }
 
-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);
+
+    if (u->rtpoll)
+        pa_rtpoll_free(u->rtpoll);
+
+    if (u->filename) {
+        unlink(u->filename);
+        pa_xfree(u->filename);
+    }
 
-    assert(u->filename);
-    unlink(u->filename);
-    pa_xfree(u->filename);
+    if (u->fd >= 0)
+        pa_assert_se(pa_close(u->fd) == 0);
 
     pa_xfree(u);
 }
index 56c721b0f38f332a93cccb016bfdb05e6b5ca48f..45708c687cec821cd44af26657b8a3bfdb31eaed 100644 (file)
 #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);
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
+    int read_type = 0;
 
-    if (!pa_iochannel_is_readable(u->io))
-        return;
+    pa_assert(u);
 
-    pa_module_set_used(u->module, pa_idxset_size(u->source->outputs));
+    pa_log_debug("Thread starting up");
 
-    if (!u->chunk.memblock) {
-        u->chunk.memblock = pa_memblock_new(u->core->mempool, PIPE_BUF);
-        u->chunk.index = chunk.length = 0;
-    }
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
 
-    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;
-    }
+    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;
 
-    u->chunk.length = r;
-    pa_source_post(u->source, &u->chunk);
-    u->chunk.index += r;
+            if (!u->memchunk.memblock) {
+                u->memchunk.memblock = pa_memblock_new(u->core->mempool, PIPE_BUF);
+                u->memchunk.index = u->memchunk.length = 0;
+            }
 
-    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;
+            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;
+        }
     }
-}
 
-static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
-    struct userdata *u = userdata;
-    assert(u);
-    do_read(u);
+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);
+
+    u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
 
-    if ((fd = open(p, O_RDWR)) < 0) {
-        pa_log("open('%s'): %s", p, pa_cstrerror(errno));
+    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);
+
+    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->source)
+        pa_source_unref(u->source);
+
+    if (u->memchunk.memblock)
+        pa_memblock_unref(u->memchunk.memblock);
 
-    pa_source_disconnect(u->source);
-    pa_source_unref(u->source);
-    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->filename) {
+        unlink(u->filename);
+        pa_xfree(u->filename);
+    }
 
-    assert(u->filename);
-    unlink(u->filename);
-    pa_xfree(u->filename);
+    if (u->fd >= 0)
+        pa_assert_se(pa_close(u->fd) == 0);
 
     pa_xfree(u);
 }
index 5c8733fb49ffc95d28f028a8aaf5572924ef0b46..6bd7807972ca91a501141b226b3274654998ce9c 100644 (file)
@@ -29,7 +29,6 @@
 #include <string.h>
 #include <errno.h>
 #include <stdio.h>
-#include <assert.h>
 #include <unistd.h>
 #include <limits.h>
 
 #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>
   #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
 
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
new file mode 100644 (file)
index 0000000..e863c0c
--- /dev/null
@@ -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);
+}
index 25005f250377fdf5e73363fc39eeed53082d8f6b..5cabef762279ea98a060c12bb8cd5cfea3e4ac4b 100644 (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;
+
+        for (target = pa_idxset_first(c->sinks, &idx); target; target = pa_idxset_next(c->sinks, &idx))
+            if (target != sink)
+                break;
 
-    assert(target != sink);
+        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;
index 661455b3a9220d1fb5d1827c3368334bf688cb66..65b8ee7f80778fa6cb98ba1dc7890df45dbb92b0 100644 (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);
+
+    pa_assert(i);
     u = i->userdata;
+    pa_assert(u);
 
-    pa_sink_input_disconnect(u->sink_input);
+    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;
+
+    pa_assert(m);
 
-    if (!u)
+    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);
 }
 
index a50f1ecf8889183b6970b0eff5d87501735011a2..a8a947129a5fa718cbc542f30c0a79b729eb35ed 100644 (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) {
-    audio_info_t info;
+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;
-    size_t len;
-    ssize_t r;
+    audio_info_t info;
 
-    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);
+            if (u->memchunk.memblock)
+                r += pa_bytes_to_usec(u->memchunk.length, &PA_SINK(o)->sample_spec);
+        }
 
-    /* The sample counter can sometimes go backwards :( */
-    if (len > u->buffer_size)
-        len = 0;
+        *((pa_usec_t*) data) = r;
 
-    if (!u->sink_underflow && (len == u->buffer_size))
-        pa_log_debug("Solaris buffer underflow!");
+        return 0;
+    }
 
-    len -= len % u->frame_size;
+    case PA_SINK_MESSAGE_SET_VOLUME:
+        if (u->fd >= 0) {
+            AUDIO_INITINFO(&info);
+
+            info.play.gain = pa_cvolume_avg((pa_cvolume*)data) * 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));
+            } else {
+                return 0;
+            }
+        }
+        break;
 
-    if (len == 0)
-        return;
+    case PA_SINK_MESSAGE_GET_VOLUME:
+        if (u->fd >= 0) {
+            err = ioctl(u->fd, AUDIO_GETINFO, &info);
+            assert(err >= 0);
 
-    if (!u->memchunk.length) {
-        if (pa_sink_render(u->sink, len, &u->memchunk) < 0) {
-            u->sink_underflow = 1;
-            return;
-        }
-    }
+            pa_cvolume_set((pa_cvolume*) data, ((pa_cvolume*) data)->channels,
+                info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN);
 
-    u->sink_underflow = 0;
+            return 0;
+        }
+        break;
 
-    assert(u->memchunk.memblock);
-    assert(u->memchunk.memblock->data);
-    assert(u->memchunk.length);
+    case PA_SINK_MESSAGE_SET_MUTE:
+        if (u->fd >= 0) {
+            AUDIO_INITINFO(&info);
 
-    if (u->memchunk.length < len) {
-        len = u->memchunk.length;
-        len -= len % u->frame_size;
-        assert(len);
-    }
+            info.output_muted = !!PA_PTR_TO_UINT(data);
 
-    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;
-    }
+            if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0)
+                pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
+            else
+                return 0;
+        }
+        break;
 
-    assert(r % u->frame_size == 0);
+    case PA_SINK_MESSAGE_GET_MUTE:
+        if (u->fd >= 0) {
+            err = ioctl(u->fd, AUDIO_GETINFO, &info);
+            pa_assert(err >= 0);
 
-    u->memchunk.index += r;
-    u->memchunk.length -= r;
+            *(int*)data = !!info.output_muted;
 
-    if (u->memchunk.length <= 0) {
-        pa_memblock_unref(u->memchunk.memblock);
-        u->memchunk.memblock = NULL;
+            return 0;
+        }
+        break;
     }
 
-    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;
+        }
 
-    assert(r <= (ssize_t) memchunk.memblock->length);
-    memchunk.length = memchunk.memblock->length = r;
-    memchunk.index = 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;
 
-    pa_source_post(u->source, &memchunk);
-    pa_memblock_unref(memchunk.memblock);
+        case PA_SOURCE_MESSAGE_GET_VOLUME:
+            if (u->fd >= 0) {
+                err = ioctl(u->fd, AUDIO_GETINFO, &info);
+                pa_assert(err >= 0);
 
-    u->read_bytes += r;
-}
+                pa_cvolume_set((pa_cvolume*) data, ((pa_cvolume*) data)->channels,
+                    info.record.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN);
 
-static void io_callback(pa_iochannel *io, void*userdata) {
-    struct userdata *u = userdata;
-    assert(u);
-    do_write(u);
-    do_read(u);
-}
+                return 0;
+            }
+            break;
+    }
 
-static void timer_cb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) {
-    struct userdata *u = userdata;
-    struct timeval ntv;
+    return pa_source_process_msg(o, code, data, offset, chunk);
+}
 
-    assert(u);
+static void clear_underflow(struct userdata *u)
+{
+    audio_info_t info;
 
-    do_write(u);
+    AUDIO_INITINFO(&info);
 
-    pa_gettimeofday(&ntv);
-    pa_timeval_add(&ntv, u->poll_timeout);
+    info.play.error = 0;
 
-    a->time_restart(e, &ntv);
+    if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0)
+        pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
 }
 
-static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) {
-    struct userdata *u = userdata;
-    pa_cvolume old_vol;
+static void clear_overflow(struct userdata *u)
+{
+    audio_info_t info;
 
-    assert(u);
+    AUDIO_INITINFO(&info);
 
-    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);
-        }
-    }
+    info.record.error = 0;
 
-    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);
-        }
-    }
+    if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0)
+        pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
 }
 
-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);
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
+    unsigned short revents = 0;
+    int ret;
 
-    err = ioctl(u->fd, AUDIO_GETINFO, &info);
-    assert(err >= 0);
+    pa_assert(u);
 
-    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);
+    pa_log_debug("Thread starting up");
 
-    if (u->memchunk.memblock)
-        r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec);
+    if (u->core->high_priority)
+        pa_make_realtime();
 
-    return r;
-}
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
 
-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);
+    for (;;) {
+        /* Render some data and write it to the dsp */
 
-    err = ioctl(u->fd, AUDIO_GETINFO, &info);
-    assert(err >= 0);
+        if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state)) {
+            audio_info_t info;
+            int err;
+            size_t len;
 
-    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);
+            err = ioctl(u->fd, AUDIO_GETINFO, &info);
+            pa_assert(err >= 0);
 
-    return r;
-}
+            /*
+             * 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);
 
-static int sink_get_hw_volume_cb(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    audio_info_t info;
-    int err;
+            /* The sample counter can sometimes go backwards :( */
+            if (len > u->buffer_size)
+                len = 0;
 
-    err = ioctl(u->fd, AUDIO_GETINFO, &info);
-    assert(err >= 0);
+            if (info.play.error) {
+                pa_log_debug("Solaris buffer underflow!");
+                clear_underflow(u);
+            }
 
-    pa_cvolume_set(&s->hw_volume, s->hw_volume.channels,
-        info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN);
+            len -= len % u->frame_size;
 
-    return 0;
-}
+            while (len) {
+                void *p;
+                ssize_t r;
 
-static int sink_set_hw_volume_cb(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    audio_info_t info;
+                if (!u->memchunk.length)
+                    pa_sink_render(u->sink, len, &u->memchunk);
 
-    AUDIO_INITINFO(&info);
+                pa_assert(u->memchunk.length);
 
-    info.play.gain = pa_cvolume_avg(&s->hw_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM;
-    assert(info.play.gain <= AUDIO_MAX_GAIN);
+                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 (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;
-    }
+                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);
 
-    return 0;
-}
+                    u->memchunk.index += r;
+                    u->memchunk.length -= r;
 
-static int sink_get_hw_mute_cb(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    audio_info_t info;
-    int err;
+                    if (u->memchunk.length <= 0) {
+                        pa_memblock_unref(u->memchunk.memblock);
+                        pa_memchunk_reset(&u->memchunk);
+                    }
 
-    err = ioctl(u->fd, AUDIO_GETINFO, &info);
-    assert(err >= 0);
+                    len -= r;
+                    u->written_bytes += r;
+                }
+            }
+        }
 
-    s->hw_muted = !!info.output_muted;
+        /* 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;
+                }
+            }
+        }
 
-    return 0;
-}
+        if (u->fd >= 0) {
+            struct pollfd *pollfd;
 
-static int sink_set_hw_mute_cb(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    audio_info_t info;
+            pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+            pollfd->events =
+                ((u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) ? POLLIN : 0);
+        }
 
-    AUDIO_INITINFO(&info);
+        /* Hmm, nothing to do. Let's sleep */
+        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
+            goto fail;
 
-    info.output_muted = !!s->hw_muted;
+        if (ret == 0)
+            goto finish;
 
-    if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) {
-        pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
-        return -1;
-    }
+        if (u->fd >= 0) {
+            struct pollfd *pollfd;
 
-    return 0;
-}
+            pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
 
-static int source_get_hw_volume_cb(pa_source *s) {
-    struct userdata *u = s->userdata;
-    audio_info_t info;
-    int err;
+            if (pollfd->revents & ~(POLLOUT|POLLIN)) {
+                pa_log("DSP shutdown.");
+                goto fail;
+            }
 
-    err = ioctl(u->fd, AUDIO_GETINFO, &info);
-    assert(err >= 0);
+            revents = pollfd->revents;
+        } else
+            revents = 0;
+    }
 
-    pa_cvolume_set(&s->hw_volume, s->hw_volume.channels,
-        info.record.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN);
+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);
 
-    return 0;
+finish:
+    pa_log_debug("Thread shutting down");
 }
 
-static int source_set_hw_volume_cb(pa_source *s) {
-    struct userdata *u = s->userdata;
-    audio_info_t info;
-
-    AUDIO_INITINFO(&info);
+static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) {
+    struct userdata *u = userdata;
 
-    info.record.gain = pa_cvolume_avg(&s->hw_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM;
-    assert(info.record.gain <= AUDIO_MAX_GAIN);
+    assert(u);
 
-    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;
+    if (u->sink) {
+        pa_sink_get_volume(u->sink);
+        pa_sink_get_mute(u->sink);
     }
 
-    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);
+
+    u->rtpoll = pa_rtpoll_new();
+    pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
+
+    pa_rtpoll_set_timer_periodic(u->rtpoll, pa_bytes_to_usec(u->buffer_size / 10, &ss));
 
-    pa_gettimeofday(&tv);
-    pa_timeval_add(&tv, u->poll_timeout);
+    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;
 
-    u->timer = c->mainloop->time_new(c->mainloop, &tv, timer_cb, u);
-    assert(u->timer);
+    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)
-        pa_memblock_unref(u->memchunk.memblock);
+    if (u->sink)
+        pa_sink_unlink(u->sink);
 
-    if (u->sink) {
-        pa_sink_disconnect(u->sink);
-        pa_sink_unref(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);
     }
 
-    if (u->source) {
-        pa_source_disconnect(u->source);
+    pa_thread_mq_done(&u->thread_mq);
+
+    if (u->sink)
+        pa_sink_unref(u->sink);
+
+    if (u->source)
         pa_source_unref(u->source);
-    }
 
-    pa_iochannel_free(u->io);
+     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->fd >= 0)
+        close(u->fd);
+
     pa_xfree(u);
 }
diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
new file mode 100644 (file)
index 0000000..5a71139
--- /dev/null
@@ -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);
+}
index 288e049e89863bfacb9f3d056959e662fbc4b80d..b96d46b31302997c17ed68ff8b343ed67289a0d5 100644 (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);
index 61a17aefc05765ca154ea1a2e7002dc52a7e6104..77e6174f30b9ab059ef8760607f8ae4758ea94b8 100644 (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;
index b9c4ad499d13867b7cf6e01a6d90b9e86b81ac0d..4eacbb1e1f16ae6ad47e5beaf70377bec5ae26a1 100644 (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);
index fd1d532f53369b89fd8075fc2195525d8659af01..e0550e207f42a4b1864be276b90f2307f49c8350 100644 (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);
diff --git a/src/modules/module-x11-xsmp.c b/src/modules/module-x11-xsmp.c
new file mode 100644 (file)
index 0000000..3e353ca
--- /dev/null
@@ -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;
+    }
+}
index 69508ad0367298cb122c1487b8fec4a9a23e28dc..113686cfd54c7fa9659ad0f90c0c9fd8254b0cd6 100644 (file)
@@ -26,7 +26,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #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);
+
+    switch (state) {
+
+        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))));
 
-        t = avahi_alternative_service_name(s->service_name);
-        pa_xfree(s->service_name);
-        s->service_name = t;
+            avahi_entry_group_free(g);
+            s->entry_group = NULL;
 
-        publish_service(s->userdata, s);
+            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;
-    }
 
-    if (s->loaded.valid || s->autoload.valid) {
-        pa_namereg_type_t type;
+    txt = txt_record_server_data(s->userdata->core, txt);
 
-        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;
-            }
-        }
+    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));
 
-        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_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) {
 
-        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;
-        }
+        pa_log("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(s->userdata->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 */
-
-        if (s->entry_group)
-            avahi_entry_group_free(s->entry_group);
+    /* Remove this service */
+    if (r < 0)
+        service_free(s);
 
-        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;
+
+    pa_assert(u);
+    pa_object_assert_ref(device);
 
-    if ((s = pa_hashmap_get(u->services, name)))
+    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)));
-
-    pa_hashmap_put(u->services, s->name, s);
-
-    return s;
-}
-
-static int publish_sink(struct userdata *u, pa_sink *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_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;
+    s->device = device;
+
+    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;
+    }
 
-    pa_dynarray_put(u->source_dynarray, s->index, svc);
+    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);
 
-    if ((ret = publish_service(u, svc)) < 0)
-        return ret;
+    pa_hashmap_put(u->services, s->device, s);
 
-    pa_dynarray_put(u->sink_dynarray, s->index, svc);
-    return ret;
+    return s;
 }
 
-static int publish_autoload(struct userdata *u, pa_autoload_entry *s) {
-    struct service *svc;
-    int ret;
+static void service_free(struct service *s) {
+    pa_assert(s);
 
-    assert(u && s);
+    pa_hashmap_remove(s->userdata->services, s->device);
 
-    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;
+    if (s->entry_group) {
+        pa_log_debug("Removing entry group for %s.", s->service_name);
+        avahi_entry_group_free(s->entry_group);
+    }
 
-    pa_dynarray_put(u->autoload_dynarray, s->index, svc);
-    return ret;
+    pa_xfree(s->service_name);
+    pa_xfree(s);
 }
 
-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;
+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);
 
-    svc->loaded.valid = 0;
-    pa_dynarray_put(u->sink_dynarray, idx, NULL);
+    publish_service(get_service(u, o));
 
-    return publish_service(u, svc);
+    return PA_HOOK_OK;
 }
 
-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;
+static pa_hook_result_t device_unlink_cb(pa_core *c, pa_object *o, struct userdata *u) {
+    struct service *s;
 
-    if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SOURCE)
-        return 0;
+    pa_assert(c);
+    pa_object_assert_ref(o);
 
-    svc->loaded.valid = 0;
-    pa_dynarray_put(u->source_dynarray, idx, NULL);
+    if ((s = pa_hashmap_get(u->services, o)))
+        service_free(s);
 
-    return publish_service(u, svc);
+    return PA_HOOK_OK;
 }
 
-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 int publish_main_service(struct userdata *u);
 
-static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
+static void main_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, 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;
-            }
+    pa_assert(u);
 
-            break;
+    switch (state) {
 
-        case PA_SUBSCRIPTION_EVENT_SOURCE:
+        case AVAHI_ENTRY_GROUP_ESTABLISHED:
+            pa_log_info("Successfully established main service.");
+            break;
 
-            if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
-                pa_source *source;
+        case AVAHI_ENTRY_GROUP_COLLISION: {
+            char *t;
 
-                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;
-            }
+            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 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;
-            }
+        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;
-    }
-
-    return;
-
-fail:
-    if (u->subscription) {
-        pa_subscription_free(u->subscription);
-        u->subscription = NULL;
-    }
-}
-
-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);
-
-    if (state == AVAHI_ENTRY_GROUP_COLLISION) {
-        char *t;
-
-        t = avahi_alternative_service_name(u->service_name);
-        pa_xfree(u->service_name);
-        u->service_name = t;
+        }
 
-        publish_main_service(u);
+        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 (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;
+    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)));
 
-    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);
 }
-
index fb531468aa6633970f9a7362d942fc8bf7dcb079..25e45a350c960afc2786e3b7f449840133d11e43 100644 (file)
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <sys/soundcard.h>
 #include <sys/ioctl.h>
 #include <stdio.h>
 #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;
+
+    if ((e = strrchr(p, '/')))
+        p = e+1;
 
-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 (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;
+}
index 087e0d220d8280fe987f7e6438824a20b93fa9d0..259a622a3e020137c4918010c8dfb923b75e57db 100644 (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
index 62ef561f1f01138fead240126b1c800b56516c20..6c0189312a20c1e079bfe1b6482e5fa8297de94d 100644 (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>
 #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) {
-    struct session *s;
-    assert(i);
-    s = i->userdata;
+/* 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;
 
-    return pa_memblockq_peek(s->memblockq, chunk);
+    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);
 }
 
-static void sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
+/* 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);
 
-    pa_memblockq_drop(s->memblockq, chunk, length);
+    return pa_memblockq_peek(s->memblockq, chunk);
 }
 
-static void sink_input_kill(pa_sink_input* i) {
+/* 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);
 
-    session_free(s, 1);
+    pa_memblockq_drop(s->memblockq, length);
 }
 
-static pa_usec_t sink_input_get_latency(pa_sink_input *i) {
+/* 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);
 
-    return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->sample_spec);
+    session_free(s);
 }
 
-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;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(s = i->userdata);
+
+    pa_assert(!s->rtpoll_item);
+    s->rtpoll_item = pa_rtpoll_item_new(i->sink->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);
+}
 
-    assert(m);
-    assert(t);
-    assert(tv);
-    assert(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);
 
-    session_free(s, 1);
+    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_rtp_context_init_recv(&s->rtp_context, fd, pa_frame_size(&s->sdp_info.sample_spec));
 
     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_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_sink_input_put(s->sink_input);
 
-    u->n_sessions++;
+    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->n_sessions = 0;
 
-    u->sap_event = c->mainloop->io_new(c->mainloop, fd, PA_IO_EVENT_INPUT, sap_event_cb, u);
+    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->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);
index 8c9e5f23cf7a47f359f76d380b4f571b3cca25f4..f36989bdd451abe340b034102845993134d3faf0 100644 (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);
 }
index 03a01412d301e8514f30af81bec35e13d8236ef4..997fcc3482a39fb0a01de8c81437b36af81c6bd8 100644 (file)
@@ -25,7 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 
 #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;
index 82421807248e1beff947fc905ffa7f76f4bff3f6..ed7eb0beb203c77b9bb8dcc2d30e5a78c6549e82 100644 (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;
     }
 
index 8b0bd5354da79a10c5a26d0dc718c1d40ebb0e89..50ac157a03ec1f6bfe3efbabd929a8c2eae77f7e 100644 (file)
@@ -25,7 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <time.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #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);
index ea2706e4243711c01d96b2cba3ead968dd828386..55e0b2cd59a5b8944895b4dfcd9c2c5e37a93135 100644 (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;
index 922ad2765b3a223f4e08c496cbb5b5dce779e200..e1f23d25e798861d08448cbac2e0f0e1d03d1c5c 100644 (file)
 
 #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
index d5b8f74377ef8b57fe3cf04edf3c2724f6b84839..2b8ef2b00dfdd2151ba1a31b489c977fbaf960c7 100644 (file)
 #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;
index f0c8f47521d30efcd0d9e35045446ebe3021a0fb..a05e19113c75ee9f892f4c66dfce3ea7621e6566 100644 (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
 
index e8de955308c504734710c01c00c018511ce13f09..e240ba88848d9078bd2328521821b60995cdf41e 100644 (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;
index bb9123359d1be920e49d4d8cc1679908d9879324..abd277a69de2799915a1604d362b1828efc9c682 100644 (file)
 #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>
 
 #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;
 
index 58a5a8794fa3476b076b44af17f54b49e0108d86..805cd44ee19018862cf9c1ba2e821dbea53289f4 100644 (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);
index 5b399aa2bba113334c64f41c3519d90139f53f9a..b7a7537a011631db1052b487b892991eb1cc21ed 100644 (file)
@@ -25,8 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
-
 #include <pulse/xmalloc.h>
 #include <pulse/timeval.h>
 
index 52354fdcbd3f302874759129e50cef2de4efb8b4..95593adb05e865640303e4b5526e4779fbc944c5 100644 (file)
 #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;
 
index 7f6406cf84210da3502cd3ec5000703e3c1156ef..6610a724040c47b10fed4849c7fa8ecec374de69 100644 (file)
 #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;
+}
index 43e430b20ea66784e9e6d54dde673311db3201db..c148ee5eca62c7b2b7205fdaa47ed897d0bb188f 100644 (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
index 001ff314bd940c4dcf06c28d5b068f3d281bea7e..b2ed34342d6899b729d3831d4861aa3c46cefc5b 100644 (file)
 #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);
 }
 
index 28ddec492d144daa5e92ac3eb96304ae9832cd6e..7d3017e2ea5aa0c416a9610c1829ee6a709c22e0 100644 (file)
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <signal.h>
 #include <errno.h>
 #include <stdlib.h>
 #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;
 }
index 43cbb19ff3f172ac33a87a92fd0400fd28fcd5d2..ad4e4e97df5473fa19281294a4416882a25c8170 100644 (file)
 #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;
index f23def50c24158e51f55c9d04824449c0d32234c..ed5eb4aa1bf6021a868e0bf4d46e509bb3926ea0 100644 (file)
 #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;
 }
index ffdeedf75d91294f40e6d21780e2ff61f7dc2452..ae2a0b9f0a703787529c64d14382d8467656a30c 100644 (file)
 #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;
index 683167cc5f3a0ffba0127a00b89845b1cffe9486..b307621e4b8dbd7e1c64ac982d7f383dc6ba01c4 100644 (file)
@@ -155,31 +155,31 @@ typedef struct pa_sample_spec {
 typedef uint64_t pa_usec_t;
 
 /** Return the amount of bytes playback of a second of audio with the specified sample type takes */
-size_t pa_bytes_per_second(const pa_sample_spec *spec);
+size_t pa_bytes_per_second(const pa_sample_spec *spec) PA_GCC_PURE;
 
 /** Return the size of a frame with the specific sample type */
-size_t pa_frame_size(const pa_sample_spec *spec);
+size_t pa_frame_size(const pa_sample_spec *spec) PA_GCC_PURE;
 
 /** Return the size of a sample with the specific sample type */
-size_t pa_sample_size(const pa_sample_spec *spec);
+size_t pa_sample_size(const pa_sample_spec *spec) PA_GCC_PURE;
 
 /** Calculate the time the specified bytes take to play with the specified sample type */
-pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec);
+pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) PA_GCC_PURE;
 
 /** Calculates the number of bytes that are required for the specified time. \since 0.9 */
-size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec);
+size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) PA_GCC_PURE;
 
 /** Return non-zero when the sample type specification is valid */
-int pa_sample_spec_valid(const pa_sample_spec *spec);
+int pa_sample_spec_valid(const pa_sample_spec *spec) PA_GCC_PURE;
 
 /** Return non-zero when the two sample type specifications match */
-int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b);
+int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b) PA_GCC_PURE;
 
 /** Return a descriptive string for the specified sample format. \since 0.8 */
-const char *pa_sample_format_to_string(pa_sample_format_t f);
+const char *pa_sample_format_to_string(pa_sample_format_t f) PA_GCC_PURE;
 
 /** Parse a sample format text. Inverse of pa_sample_format_to_string() */
-pa_sample_format_t pa_parse_sample_format(const char *format);
+pa_sample_format_t pa_parse_sample_format(const char *format) PA_GCC_PURE;
 
 /** Maximum required string length for pa_sample_spec_snprint() */
 #define PA_SAMPLE_SPEC_SNPRINT_MAX 32
index 09bc1078d9ab79f3a17cf08acfe16f85f3f19a0e..186b0a3e698e9aa5630270efebe4ce52c1a9b454 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 
 #include <pulsecore/pstream-util.h>
+#include <pulsecore/macro.h>
 
 #include "internal.h"
 
@@ -40,7 +40,8 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) {
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(s);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY(s->context, length > 0, PA_ERR_INVALID);
@@ -66,7 +67,9 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) {
 int pa_stream_finish_upload(pa_stream *s) {
     pa_tagstruct *t;
     uint32_t tag;
-    assert(s);
+
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY(s->context, s->channel_valid, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -87,8 +90,8 @@ pa_operation *pa_context_play_sample(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);
@@ -115,8 +118,8 @@ pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_conte
     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);
index 3cf862d28bca58bee0126bb57d8ca17885d3dab0..1072fb4d60a943ab3f7628edc5287698a26755f2 100644 (file)
@@ -1,3 +1,4 @@
+
 /* $Id$ */
 
 /***
@@ -27,7 +28,6 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 #include <stdlib.h>
 
 #include <pulse/pulseaudio.h>
@@ -36,6 +36,7 @@
 
 #include <pulsecore/native-common.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "simple.h"
 
@@ -83,8 +84,8 @@ if (!(p)->context || pa_context_get_state((p)->context) != PA_CONTEXT_READY || \
 
 static void context_state_cb(pa_context *c, void *userdata) {
     pa_simple *p = userdata;
-    assert(c);
-    assert(p);
+    pa_assert(c);
+    pa_assert(p);
 
     switch (pa_context_get_state(c)) {
         case PA_CONTEXT_READY:
@@ -103,8 +104,8 @@ static void context_state_cb(pa_context *c, void *userdata) {
 
 static void stream_state_cb(pa_stream *s, void * userdata) {
     pa_simple *p = userdata;
-    assert(s);
-    assert(p);
+    pa_assert(s);
+    pa_assert(p);
 
     switch (pa_stream_get_state(s)) {
 
@@ -122,7 +123,7 @@ static void stream_state_cb(pa_stream *s, void * userdata) {
 
 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
     pa_simple *p = userdata;
-    assert(p);
+    pa_assert(p);
 
     pa_threaded_mainloop_signal(p->mainloop, 0);
 }
@@ -130,21 +131,21 @@ static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
 static void stream_latency_update_cb(pa_stream *s, void *userdata) {
     pa_simple *p = userdata;
 
-    assert(p);
+    pa_assert(p);
 
     pa_threaded_mainloop_signal(p->mainloop, 0);
 }
 
 pa_simple* pa_simple_new(
-    const char *server,
-    const char *name,
-    pa_stream_direction_t dir,
-    const char *dev,
-    const char *stream_name,
-    const pa_sample_spec *ss,
-    const pa_channel_map *map,
-    const pa_buffer_attr *attr,
-    int *rerror) {
+        const char *server,
+        const char *name,
+        pa_stream_direction_t dir,
+        const char *dev,
+        const char *stream_name,
+        const pa_sample_spec *ss,
+        const pa_channel_map *map,
+        const pa_buffer_attr *attr,
+        int *rerror) {
 
     pa_simple *p;
     int error = PA_ERR_INTERNAL, r;
@@ -232,7 +233,7 @@ fail:
 }
 
 void pa_simple_free(pa_simple *s) {
-    assert(s);
+    pa_assert(s);
 
     if (s->mainloop)
         pa_threaded_mainloop_stop(s->mainloop);
@@ -250,7 +251,7 @@ void pa_simple_free(pa_simple *s) {
 }
 
 int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) {
-    assert(p);
+    pa_assert(p);
 
     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
     CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1);
@@ -289,7 +290,7 @@ unlock_and_fail:
 }
 
 int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) {
-    assert(p);
+    pa_assert(p);
 
     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, -1);
     CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1);
@@ -346,8 +347,8 @@ unlock_and_fail:
 static void success_cb(pa_stream *s, int success, void *userdata) {
     pa_simple *p = userdata;
 
-    assert(s);
-    assert(p);
+    pa_assert(s);
+    pa_assert(p);
 
     p->operation_success = success;
     pa_threaded_mainloop_signal(p->mainloop, 0);
@@ -356,7 +357,7 @@ static void success_cb(pa_stream *s, int success, void *userdata) {
 int pa_simple_drain(pa_simple *p, int *rerror) {
     pa_operation *o = NULL;
 
-    assert(p);
+    pa_assert(p);
 
     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
 
@@ -392,7 +393,7 @@ unlock_and_fail:
 int pa_simple_flush(pa_simple *p, int *rerror) {
     pa_operation *o = NULL;
 
-    assert(p);
+    pa_assert(p);
 
     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
 
@@ -429,7 +430,7 @@ pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) {
     pa_usec_t t;
     int negative;
 
-    assert(p);
+    pa_assert(p);
 
     pa_threaded_mainloop_lock(p->mainloop);
 
index 128d271604b954e6f4bb9baa4cb51df6d4886c5a..f76c1d67b8bc93f6421861389a56bf31d4bf72b2 100644 (file)
@@ -51,7 +51,7 @@
  * pa_simple *s;
  * pa_sample_spec ss;
  *
- * ss.format = PA_SAMPLE_S16_NE;
+ * ss.format = PA_SAMPLE_S16NE;
  * ss.channels = 2;
  * ss.rate = 44100;
  *
index f20c17aefea68cfc057718a3b5f98126a71aadaf..47906a5cf6bd54742c03dd7bc456ad3fa23c1f3d 100644 (file)
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 #include <string.h>
@@ -38,6 +37,7 @@
 #include <pulsecore/pstream-util.h>
 #include <pulsecore/log.h>
 #include <pulsecore/hashmap.h>
+#include <pulsecore/macro.h>
 
 #include "internal.h"
 
@@ -47,13 +47,14 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *
     pa_stream *s;
     int i;
 
-    assert(c);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID);
     PA_CHECK_VALIDITY_RETURN_NULL(c, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID);
 
     s = pa_xnew(pa_stream, 1);
-    s->ref = 1;
+    PA_REFCNT_INIT(s);
     s->context = c;
     s->mainloop = c->mainloop;
 
@@ -91,6 +92,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *
     s->peek_memchunk.index = 0;
     s->peek_memchunk.length = 0;
     s->peek_memchunk.memblock = NULL;
+    s->peek_data = NULL;
 
     s->record_memblockq = NULL;
 
@@ -118,15 +120,20 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *
 }
 
 static void stream_free(pa_stream *s) {
-    assert(s && !s->context && !s->channel_valid);
+    pa_assert(s);
+    pa_assert(!s->context);
+    pa_assert(!s->channel_valid);
 
     if (s->auto_timing_update_event) {
-        assert(s->mainloop);
+        pa_assert(s->mainloop);
         s->mainloop->time_free(s->auto_timing_update_event);
     }
 
-    if (s->peek_memchunk.memblock)
+    if (s->peek_memchunk.memblock) {
+        if (s->peek_data)
+            pa_memblock_release(s->peek_memchunk.memblock);
         pa_memblock_unref(s->peek_memchunk.memblock);
+    }
 
     if (s->record_memblockq)
         pa_memblockq_free(s->record_memblockq);
@@ -136,38 +143,38 @@ static void stream_free(pa_stream *s) {
 }
 
 void pa_stream_unref(pa_stream *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
-    if (--(s->ref) == 0)
+    if (PA_REFCNT_DEC(s) <= 0)
         stream_free(s);
 }
 
 pa_stream* pa_stream_ref(pa_stream *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
-    s->ref++;
+    PA_REFCNT_INC(s);
     return s;
 }
 
 pa_stream_state_t pa_stream_get_state(pa_stream *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     return s->state;
 }
 
 pa_context* pa_stream_get_context(pa_stream *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     return s->context;
 }
 
 uint32_t pa_stream_get_index(pa_stream *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
 
@@ -175,8 +182,8 @@ uint32_t pa_stream_get_index(pa_stream *s) {
 }
 
 void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     if (s->state == st)
         return;
@@ -214,6 +221,13 @@ void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) {
         s->channel_valid = 0;
 
         s->context = NULL;
+
+        s->read_callback = NULL;
+        s->write_callback = NULL;
+        s->state_callback = NULL;
+        s->overflow_callback = NULL;
+        s->underflow_callback = NULL;
+        s->latency_update_callback = NULL;
     }
 
     pa_stream_unref(s);
@@ -224,10 +238,11 @@ void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
     pa_stream *s;
     uint32_t channel;
 
-    assert(pd);
-    assert(command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED);
-    assert(t);
-    assert(c);
+    pa_assert(pd);
+    pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED);
+    pa_assert(t);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     pa_context_ref(c);
 
@@ -252,10 +267,11 @@ void pa_command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32
     pa_context *c = userdata;
     uint32_t bytes, channel;
 
-    assert(pd);
-    assert(command == PA_COMMAND_REQUEST);
-    assert(t);
-    assert(c);
+    pa_assert(pd);
+    pa_assert(command == PA_COMMAND_REQUEST);
+    pa_assert(t);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     pa_context_ref(c);
 
@@ -285,10 +301,11 @@ void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, PA_GCC
     pa_context *c = userdata;
     uint32_t channel;
 
-    assert(pd);
-    assert(command == PA_COMMAND_OVERFLOW || command == PA_COMMAND_UNDERFLOW);
-    assert(t);
-    assert(c);
+    pa_assert(pd);
+    pa_assert(command == PA_COMMAND_OVERFLOW || command == PA_COMMAND_UNDERFLOW);
+    pa_assert(t);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     pa_context_ref(c);
 
@@ -317,8 +334,8 @@ void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, PA_GCC
 }
 
 static void request_auto_timing_update(pa_stream *s, int force) {
-    struct timeval next;
-    assert(s);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     if (!(s->flags & PA_STREAM_AUTO_TIMING_UPDATE))
         return;
@@ -335,13 +352,17 @@ static void request_auto_timing_update(pa_stream *s, int force) {
         }
     }
 
-    pa_gettimeofday(&next);
-    pa_timeval_add(&next, LATENCY_IPOL_INTERVAL_USEC);
-    s->mainloop->time_restart(s->auto_timing_update_event, &next);
+    if (s->auto_timing_update_event) {
+        struct timeval next;
+        pa_gettimeofday(&next);
+        pa_timeval_add(&next, LATENCY_IPOL_INTERVAL_USEC);
+        s->mainloop->time_restart(s->auto_timing_update_event, &next);
+    }
 }
 
 static void invalidate_indexes(pa_stream *s, int r, int w) {
-    assert(s);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
 /*     pa_log("invalidate r:%u w:%u tag:%u", r, w, s->context->ctag); */
 
@@ -376,6 +397,9 @@ static void invalidate_indexes(pa_stream *s, int r, int w) {
 static void auto_timing_update_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC_UNUSED pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) {
     pa_stream *s = userdata;
 
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+
 /*     pa_log("time event");    */
 
     pa_stream_ref(s);
@@ -383,12 +407,32 @@ static void auto_timing_update_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC
     pa_stream_unref(s);
 }
 
+static void create_stream_complete(pa_stream *s) {
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(s->state == PA_STREAM_CREATING);
+
+    pa_stream_set_state(s, PA_STREAM_READY);
+
+    if (s->requested_bytes > 0 && s->write_callback)
+        s->write_callback(s, s->requested_bytes, s->write_userdata);
+
+    if (s->flags & PA_STREAM_AUTO_TIMING_UPDATE) {
+        struct timeval tv;
+        pa_gettimeofday(&tv);
+        tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */
+        pa_assert(!s->auto_timing_update_event);
+        s->auto_timing_update_event = s->mainloop->time_new(s->mainloop, &tv, &auto_timing_update_callback, s);
+    }
+}
+
 void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
     pa_stream *s = userdata;
 
-    assert(pd);
-    assert(s);
-    assert(s->state == PA_STREAM_CREATING);
+    pa_assert(pd);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(s->state == PA_STREAM_CREATING);
 
     pa_stream_ref(s);
 
@@ -431,7 +475,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
     }
 
     if (s->direction == PA_STREAM_RECORD) {
-        assert(!s->record_memblockq);
+        pa_assert(!s->record_memblockq);
 
         s->record_memblockq = pa_memblockq_new(
                 0,
@@ -446,23 +490,16 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
     s->channel_valid = 1;
     pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
 
-    pa_stream_set_state(s, PA_STREAM_READY);
-
-    if (s->direction != PA_STREAM_UPLOAD &&
-        s->flags & PA_STREAM_AUTO_TIMING_UPDATE) {
-        struct timeval tv;
-
-        pa_gettimeofday(&tv);
-        tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */
-
-        assert(!s->auto_timing_update_event);
-        s->auto_timing_update_event = s->mainloop->time_new(s->mainloop, &tv, &auto_timing_update_callback, s);
-
+    if (s->direction != PA_STREAM_UPLOAD && s->flags & PA_STREAM_AUTO_TIMING_UPDATE) {
+        /* If automatic timing updates are active, we wait for the
+         * first timing update before going to PA_STREAM_READY
+         * state */
+        s->state = PA_STREAM_READY;
         request_auto_timing_update(s, 1);
-    }
+        s->state = PA_STREAM_CREATING;
 
-    if (s->requested_bytes > 0 && s->ref > 1 && s->write_callback)
-        s->write_callback(s, s->requested_bytes, s->write_userdata);
+    } else
+        create_stream_complete(s);
 
 finish:
     pa_stream_unref(s);
@@ -480,8 +517,8 @@ static int create_stream(
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY(s->context, !(flags & ~((direction != PA_STREAM_UPLOAD ?
@@ -503,12 +540,12 @@ static int create_stream(
     if (attr)
         s->buffer_attr = *attr;
     else {
-        /* half a second */
+        /* half a second, with minimum request of 10 ms */
         s->buffer_attr.tlength = pa_bytes_per_second(&s->sample_spec)/2;
         s->buffer_attr.maxlength = (s->buffer_attr.tlength*3)/2;
-        s->buffer_attr.minreq = s->buffer_attr.tlength/100;
+        s->buffer_attr.minreq = s->buffer_attr.tlength/50;
         s->buffer_attr.prebuf = s->buffer_attr.tlength - s->buffer_attr.minreq;
-        s->buffer_attr.fragsize = s->buffer_attr.tlength/100;
+        s->buffer_attr.fragsize = s->buffer_attr.tlength/50;
     }
 
     if (!dev)
@@ -565,8 +602,8 @@ int pa_stream_connect_playback(
         pa_cvolume *volume,
         pa_stream *sync_stream) {
 
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     return create_stream(PA_STREAM_PLAYBACK, s, dev, attr, flags, volume, sync_stream);
 }
@@ -577,8 +614,8 @@ int pa_stream_connect_record(
         const pa_buffer_attr *attr,
         pa_stream_flags_t flags) {
 
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     return create_stream(PA_STREAM_RECORD, s, dev, attr, flags, NULL, NULL);
 }
@@ -593,9 +630,9 @@ int pa_stream_write(
 
     pa_memchunk chunk;
 
-    assert(s);
-    assert(s->ref >= 1);
-    assert(data);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(data);
 
     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK || s->direction == PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
@@ -608,8 +645,11 @@ int pa_stream_write(
     if (free_cb)
         chunk.memblock = pa_memblock_new_user(s->context->mempool, (void*) data, length, free_cb, 1);
     else {
+        void *tdata;
         chunk.memblock = pa_memblock_new(s->context->mempool, length);
-        memcpy(chunk.memblock->data, data, length);
+        tdata = pa_memblock_acquire(chunk.memblock);
+        memcpy(tdata, data, length);
+        pa_memblock_release(chunk.memblock);
     }
 
     chunk.index = 0;
@@ -660,10 +700,10 @@ int pa_stream_write(
 }
 
 int pa_stream_peek(pa_stream *s, const void **data, size_t *length) {
-    assert(s);
-    assert(s->ref >= 1);
-    assert(data);
-    assert(length);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(data);
+    pa_assert(length);
 
     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE);
@@ -675,27 +715,32 @@ int pa_stream_peek(pa_stream *s, const void **data, size_t *length) {
             *length = 0;
             return 0;
         }
+
+        s->peek_data = pa_memblock_acquire(s->peek_memchunk.memblock);
     }
 
-    *data = (const char*) s->peek_memchunk.memblock->data + s->peek_memchunk.index;
+    pa_assert(s->peek_data);
+    *data = (uint8_t*) s->peek_data + s->peek_memchunk.index;
     *length = s->peek_memchunk.length;
     return 0;
 }
 
 int pa_stream_drop(pa_stream *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY(s->context, s->peek_memchunk.memblock, PA_ERR_BADSTATE);
 
-    pa_memblockq_drop(s->record_memblockq, &s->peek_memchunk, s->peek_memchunk.length);
+    pa_memblockq_drop(s->record_memblockq, s->peek_memchunk.length);
 
     /* Fix the simulated local read index */
     if (s->timing_info_valid && !s->timing_info.read_index_corrupt)
         s->timing_info.read_index += s->peek_memchunk.length;
 
+    pa_assert(s->peek_data);
+    pa_memblock_release(s->peek_memchunk.memblock);
     pa_memblock_unref(s->peek_memchunk.memblock);
     s->peek_memchunk.length = 0;
     s->peek_memchunk.index = 0;
@@ -705,8 +750,8 @@ int pa_stream_drop(pa_stream *s) {
 }
 
 size_t pa_stream_writable_size(pa_stream *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (size_t) -1);
     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_RECORD, PA_ERR_BADSTATE, (size_t) -1);
@@ -715,8 +760,8 @@ size_t pa_stream_writable_size(pa_stream *s) {
 }
 
 size_t pa_stream_readable_size(pa_stream *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (size_t) -1);
     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, (size_t) -1);
@@ -729,8 +774,8 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
@@ -750,8 +795,9 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
     struct timeval local, remote, now;
     pa_timing_info *i;
 
-    assert(pd);
-    assert(o);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context || !o->stream)
         goto finish;
@@ -874,6 +920,10 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
         }
     }
 
+    /* First, let's complete the initialization, if necessary. */
+    if (o->stream->state == PA_STREAM_CREATING)
+        create_stream_complete(o->stream);
+
     if (o->stream->latency_update_callback)
         o->stream->latency_update_callback(o->stream, o->stream->latency_update_userdata);
 
@@ -895,8 +945,8 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t
     struct timeval now;
     int cidx = 0;
 
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
@@ -938,9 +988,9 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t
 void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
     pa_stream *s = userdata;
 
-    assert(pd);
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(pd);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     pa_stream_ref(s);
 
@@ -965,8 +1015,8 @@ int pa_stream_disconnect(pa_stream *s) {
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY(s->context, s->channel_valid, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -987,48 +1037,48 @@ int pa_stream_disconnect(pa_stream *s) {
 }
 
 void pa_stream_set_read_callback(pa_stream *s, pa_stream_request_cb_t cb, void *userdata) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->read_callback = cb;
     s->read_userdata = userdata;
 }
 
 void pa_stream_set_write_callback(pa_stream *s, pa_stream_request_cb_t cb, void *userdata) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->write_callback = cb;
     s->write_userdata = userdata;
 }
 
 void pa_stream_set_state_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->state_callback = cb;
     s->state_userdata = userdata;
 }
 
 void pa_stream_set_overflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->overflow_callback = cb;
     s->overflow_userdata = userdata;
 }
 
 void pa_stream_set_underflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->underflow_callback = cb;
     s->underflow_userdata = userdata;
 }
 
 void pa_stream_set_latency_update_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->latency_update_callback = cb;
     s->latency_update_userdata = userdata;
@@ -1038,9 +1088,9 @@ void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN
     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;
@@ -1070,8 +1120,8 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
@@ -1100,8 +1150,8 @@ static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command,
     pa_operation *o;
     uint32_t tag;
 
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
 
@@ -1118,6 +1168,9 @@ static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command,
 pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) {
     pa_operation *o;
 
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
 
     if ((o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata))) {
@@ -1143,6 +1196,9 @@ pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *use
 pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) {
     pa_operation *o;
 
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE);
 
@@ -1155,6 +1211,9 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us
 pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) {
     pa_operation *o;
 
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE);
 
@@ -1169,9 +1228,9 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(s);
-    assert(s->ref >= 1);
-    assert(name);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(name);
 
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
@@ -1193,8 +1252,8 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe
 int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) {
     pa_usec_t usec = 0;
 
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
@@ -1277,8 +1336,8 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) {
 }
 
 static pa_usec_t time_counter_diff(pa_stream *s, pa_usec_t a, pa_usec_t b, int *negative) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     if (negative)
         *negative = 0;
@@ -1299,9 +1358,9 @@ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) {
     int r;
     int64_t cindex;
 
-    assert(s);
-    assert(s->ref >= 1);
-    assert(r_usec);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(r_usec);
 
     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
@@ -1331,8 +1390,8 @@ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) {
 }
 
 const pa_timing_info* pa_stream_get_timing_info(pa_stream *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
@@ -1342,22 +1401,22 @@ const pa_timing_info* pa_stream_get_timing_info(pa_stream *s) {
 }
 
 const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     return &s->sample_spec;
 }
 
 const pa_channel_map* pa_stream_get_channel_map(pa_stream *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     return &s->channel_map;
 }
 
 const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
index 5d8f12523187a4b4edcdcd8ff6c15d724e9d3608..580038cc7e8f7ad82c9c9ebef786e0d38c639878 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdio.h>
 
 #include <pulsecore/gccmacro.h>
+#include <pulsecore/macro.h>
 #include <pulsecore/pstream-util.h>
 
 #include "internal.h"
@@ -40,10 +40,11 @@ void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSE
     pa_subscription_event_type_t e;
     uint32_t idx;
 
-    assert(pd);
-    assert(command == PA_COMMAND_SUBSCRIBE_EVENT);
-    assert(t);
-    assert(c);
+    pa_assert(pd);
+    pa_assert(command == PA_COMMAND_SUBSCRIBE_EVENT);
+    pa_assert(t);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     pa_context_ref(c);
 
@@ -67,8 +68,8 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_c
     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);
 
@@ -83,8 +84,8 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_c
 }
 
 void pa_context_set_subscribe_callback(pa_context *c, pa_context_subscribe_cb_t cb, void *userdata) {
-    assert(c);
-    assert(c->ref >= 1);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     c->subscribe_callback = cb;
     c->subscribe_userdata = userdata;
index 4f3cacc9a12df2ec63af554771fded4bd118de9e..9dd47ae327a8f2511b2517089d8d15768ee48d19 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <signal.h>
 #include <stdio.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 <pulse/xmalloc.h>
+#include <pulse/mainloop.h>
 
 #include <pulsecore/log.h>
 #include <pulsecore/hashmap.h>
 #include <pulsecore/thread.h>
 #include <pulsecore/mutex.h>
+#include <pulsecore/macro.h>
 
-#include "mainloop.h"
 #include "thread-mainloop.h"
 
 struct pa_threaded_mainloop {
@@ -63,7 +63,7 @@ static int poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void
     pa_mutex *mutex = userdata;
     int r;
 
-    assert(mutex);
+    pa_assert(mutex);
 
     /* Before entering poll() we unlock the mutex, so that
      * avahi_simple_poll_quit() can succeed from another thread. */
@@ -103,7 +103,7 @@ pa_threaded_mainloop *pa_threaded_mainloop_new(void) {
         return NULL;
     }
 
-    m->mutex = pa_mutex_new(1);
+    m->mutex = pa_mutex_new(TRUE, FALSE);
     m->cond = pa_cond_new();
     m->accept_cond = pa_cond_new();
     m->thread = NULL;
@@ -116,10 +116,10 @@ pa_threaded_mainloop *pa_threaded_mainloop_new(void) {
 }
 
 void pa_threaded_mainloop_free(pa_threaded_mainloop* m) {
-    assert(m);
+    pa_assert(m);
 
     /* Make sure that this function is not called from the helper thread */
-    assert((m->thread && !pa_thread_is_running(m->thread)) || !in_worker(m));
+    pa_assert((m->thread && !pa_thread_is_running(m->thread)) || !in_worker(m));
 
     pa_threaded_mainloop_stop(m);
 
@@ -136,9 +136,9 @@ void pa_threaded_mainloop_free(pa_threaded_mainloop* m) {
 }
 
 int pa_threaded_mainloop_start(pa_threaded_mainloop *m) {
-    assert(m);
+    pa_assert(m);
 
-    assert(!m->thread || !pa_thread_is_running(m->thread));
+    pa_assert(!m->thread || !pa_thread_is_running(m->thread));
 
     if (!(m->thread = pa_thread_new(thread, m)))
         return -1;
@@ -147,13 +147,13 @@ int pa_threaded_mainloop_start(pa_threaded_mainloop *m) {
 }
 
 void pa_threaded_mainloop_stop(pa_threaded_mainloop *m) {
-    assert(m);
+    pa_assert(m);
 
     if (!m->thread || !pa_thread_is_running(m->thread))
         return;
 
     /* Make sure that this function is not called from the helper thread */
-    assert(!in_worker(m));
+    pa_assert(!in_worker(m));
 
     pa_mutex_lock(m->mutex);
     pa_mainloop_quit(m->real_mainloop, 0);
@@ -163,25 +163,25 @@ void pa_threaded_mainloop_stop(pa_threaded_mainloop *m) {
 }
 
 void pa_threaded_mainloop_lock(pa_threaded_mainloop *m) {
-    assert(m);
+    pa_assert(m);
 
     /* Make sure that this function is not called from the helper thread */
-    assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
+    pa_assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
 
     pa_mutex_lock(m->mutex);
 }
 
 void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) {
-    assert(m);
+    pa_assert(m);
 
     /* Make sure that this function is not called from the helper thread */
-    assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
+    pa_assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
 
     pa_mutex_unlock(m->mutex);
 }
 
 void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) {
-    assert(m);
+    pa_assert(m);
 
     pa_cond_signal(m->cond, 1);
 
@@ -190,36 +190,42 @@ void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) {
 }
 
 void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) {
-    assert(m);
+    pa_assert(m);
 
     /* Make sure that this function is not called from the helper thread */
-    assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
+    pa_assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
 
     m->n_waiting ++;
 
     pa_cond_wait(m->cond, m->mutex);
 
-    assert(m->n_waiting > 0);
+    pa_assert(m->n_waiting > 0);
     m->n_waiting --;
 }
 
 void pa_threaded_mainloop_accept(pa_threaded_mainloop *m) {
-    assert(m);
+    pa_assert(m);
 
     /* Make sure that this function is not called from the helper thread */
-    assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
+    pa_assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
 
     pa_cond_signal(m->accept_cond, 0);
 }
 
 int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) {
-    assert(m);
+    pa_assert(m);
 
     return pa_mainloop_get_retval(m->real_mainloop);
 }
 
 pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m) {
-    assert(m);
+    pa_assert(m);
 
     return pa_mainloop_get_api(m->real_mainloop);
 }
+
+int pa_threaded_mainloop_in_thread(pa_threaded_mainloop *m) {
+    pa_assert(m);
+
+    return m->thread && pa_thread_self() == m->thread;
+}
index b78c1583f3913ffeea274180988c58dc1cb9577c..ea08f72ac7b3ece3c2f113eb4baeb73dc8c314c7 100644 (file)
@@ -297,6 +297,9 @@ int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m);
 /** Return the abstract main loop abstraction layer vtable for this main loop. */
 pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m);
 
+/** Returns non-zero when called from withing the event loop thread. \since 0.9.7 */
+int pa_threaded_mainloop_in_thread(pa_threaded_mainloop *m);
+
 PA_C_DECL_END
 
 #endif
index 78ece0616468c36e82944cdd39c9f6217e3b1c62..70ceb71e58477cbb029d7795f9f1d6e9e3bbae0e 100644 (file)
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stddef.h>
 #include <sys/time.h>
 
 #include <windows.h>
 #endif
 
-#include "../pulsecore/winsock.h"
+#include <pulsecore/winsock.h>
+#include <pulsecore/macro.h>
 
 #include "timeval.h"
 
 struct timeval *pa_gettimeofday(struct timeval *tv) {
 #ifdef HAVE_GETTIMEOFDAY
-    assert(tv);
+    pa_assert(tv);
 
-    return gettimeofday(tv, NULL) < 0 ? NULL : tv;
+    pa_assert_se(gettimeofday(tv, NULL) == 0);
+    return tv;
 #elif defined(OS_IS_WIN32)
     /*
      * Copied from implementation by Steven Edwards (LGPL).
@@ -59,7 +60,7 @@ struct timeval *pa_gettimeofday(struct timeval *tv) {
     LARGE_INTEGER   li;
     __int64         t;
 
-    assert(tv);
+    pa_assert(tv);
 
     GetSystemTimeAsFileTime(&ft);
     li.LowPart  = ft.dwLowDateTime;
@@ -67,8 +68,8 @@ struct timeval *pa_gettimeofday(struct timeval *tv) {
     t  = li.QuadPart;       /* In 100-nanosecond intervals */
     t -= EPOCHFILETIME;     /* Offset to the Epoch time */
     t /= 10;                /* In microseconds */
-    tv->tv_sec  = (long)(t / 1000000);
-    tv->tv_usec = (long)(t % 1000000);
+    tv->tv_sec  = (time_t) (t / PA_USEC_PER_SEC);
+    tv->tv_usec = (suseconds_t) (t % PA_USEC_PER_SEC);
 
     return tv;
 #else
@@ -78,9 +79,11 @@ struct timeval *pa_gettimeofday(struct timeval *tv) {
 
 pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
     pa_usec_t r;
-    assert(a && b);
 
-    /* Check which whan is the earlier time and swap the two arguments if reuqired. */
+    pa_assert(a);
+    pa_assert(b);
+
+    /* Check which whan is the earlier time and swap the two arguments if required. */
     if (pa_timeval_cmp(a, b) < 0) {
         const struct timeval *c;
         c = a;
@@ -89,7 +92,7 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
     }
 
     /* Calculate the second difference*/
-    r = ((pa_usec_t) a->tv_sec - b->tv_sec)* 1000000;
+    r = ((pa_usec_t) a->tv_sec - b->tv_sec) * PA_USEC_PER_SEC;
 
     /* Calculate the microsecond difference */
     if (a->tv_usec > b->tv_usec)
@@ -101,7 +104,8 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
 }
 
 int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) {
-    assert(a && b);
+    pa_assert(a);
+    pa_assert(b);
 
     if (a->tv_sec < b->tv_sec)
         return -1;
@@ -120,26 +124,43 @@ int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) {
 
 pa_usec_t pa_timeval_age(const struct timeval *tv) {
     struct timeval now;
-    assert(tv);
+    pa_assert(tv);
 
     return pa_timeval_diff(pa_gettimeofday(&now), tv);
 }
 
 struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
     unsigned long secs;
-    assert(tv);
+    pa_assert(tv);
 
-    secs = (v/1000000);
-    tv->tv_sec += (unsigned long) secs;
-    v -= secs*1000000;
+    secs = (unsigned long) (v/PA_USEC_PER_SEC);
+    tv->tv_sec += secs;
+    v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
 
-    tv->tv_usec += v;
+    tv->tv_usec += (suseconds_t) v;
 
     /* Normalize */
-    while (tv->tv_usec >= 1000000) {
+    while (tv->tv_usec >= PA_USEC_PER_SEC) {
         tv->tv_sec++;
-        tv->tv_usec -= 1000000;
+        tv->tv_usec -= PA_USEC_PER_SEC;
     }
 
     return tv;
 }
+
+struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
+    pa_assert(tv);
+
+    tv->tv_sec = v / PA_USEC_PER_SEC;
+    tv->tv_usec = v % PA_USEC_PER_SEC;
+
+    return tv;
+}
+
+pa_usec_t pa_timeval_load(const struct timeval *tv) {
+    pa_assert(tv);
+
+    return
+        (pa_usec_t) tv->tv_sec * PA_USEC_PER_SEC +
+        (pa_usec_t) tv->tv_usec;
+}
index 1e5627e33da2d454090d40d53ea58f6c1d7bb8ea..65a0e51330e82cbfe2a1cdc9e5631c873f140147 100644 (file)
 
 PA_C_DECL_BEGIN
 
+#define PA_MSEC_PER_SEC 1000
+#define PA_USEC_PER_SEC 1000000
+#define PA_NSEC_PER_SEC 1000000000
+#define PA_USEC_PER_MSEC 1000
+
 struct timeval;
 
 /** Return the current timestamp, just like UNIX gettimeofday() */
@@ -40,16 +45,22 @@ struct timeval *pa_gettimeofday(struct timeval *tv);
 
 /** Calculate the difference between the two specified timeval
  * structs. */
-pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b);
+pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) PA_GCC_PURE;
 
 /** Compare the two timeval structs and return 0 when equal, negative when a < b, positive otherwse */
-int pa_timeval_cmp(const struct timeval *a, const struct timeval *b);
+int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) PA_GCC_PURE;
 
 /** Return the time difference between now and the specified timestamp */
 pa_usec_t pa_timeval_age(const struct timeval *tv);
 
 /** Add the specified time inmicroseconds to the specified timeval structure */
-struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v);
+struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) PA_GCC_PURE;
+
+/** Store the specified uec value in the timeval struct. \since 0.9.7 */
+struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v);
+
+/** Load the specified tv value and return it in usec. \since 0.9.7 */
+pa_usec_t pa_timeval_load(const struct timeval *tv);
 
 PA_C_DECL_END
 
index 2ac2d10635e2f68a950a6ec61f111a3e3094836b..b2f6c3bd74c527a605cc0754d2f3f6a33ad31878 100644 (file)
@@ -37,7 +37,7 @@
  *
  * 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
+ * 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
@@ -50,7 +50,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <inttypes.h>
 #include <iconv.h>
 #endif
 
+#include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
+
 #include "utf8.h"
-#include "xmalloc.h"
 
 #define FILTER_CHAR '_'
 
 static inline int is_unicode_valid(uint32_t ch) {
+
     if (ch >= 0x110000) /* End of unicode space */
         return 0;
     if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */
@@ -74,6 +76,7 @@ static inline int is_unicode_valid(uint32_t ch) {
         return 0;
     if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */
         return 0;
+
     return 1;
 }
 
@@ -95,6 +98,8 @@ static char* utf8_validate(const char *str, char *output) {
     int size;
     uint8_t *o;
 
+    pa_assert(str);
+
     o = (uint8_t*) output;
     for (p = (const uint8_t*) str; *p; p++) {
         if (*p < 128) {
@@ -178,15 +183,15 @@ failure:
     return NULL;
 }
 
-const char* pa_utf8_valid (const char *str) {
+char* pa_utf8_valid (const char *str) {
     return utf8_validate(str, NULL);
 }
 
 char* pa_utf8_filter (const char *str) {
     char *new_str;
 
+    pa_assert(str);
     new_str = pa_xnew(char, strlen(str) + 1);
-
     return utf8_validate(str, new_str);
 }
 
@@ -195,22 +200,24 @@ char* pa_utf8_filter (const char *str) {
 static char* iconv_simple(const char *str, const char *to, const char *from) {
     char *new_str;
     size_t len, inlen;
-
     iconv_t cd;
     ICONV_CONST char *inbuf;
     char *outbuf;
     size_t res, inbytes, outbytes;
 
+    pa_assert(str);
+    pa_assert(to);
+    pa_assert(from);
+
     cd = iconv_open(to, from);
     if (cd == (iconv_t)-1)
         return NULL;
 
     inlen = len = strlen(str) + 1;
-    new_str = pa_xmalloc(len);
-    assert(new_str);
+    new_str = pa_xnew(char, len);
 
-    while (1) {
-        inbuf = (ICONV_CONST char*)str; /* Brain dead prototype for iconv() */
+    for (;;) {
+        inbuf = (ICONV_CONST char*) str; /* Brain dead prototype for iconv() */
         inbytes = inlen;
         outbuf = new_str;
         outbytes = len;
@@ -226,11 +233,10 @@ static char* iconv_simple(const char *str, const char *to, const char *from) {
             break;
         }
 
-        assert(inbytes != 0);
+        pa_assert(inbytes != 0);
 
         len += inbytes;
         new_str = pa_xrealloc(new_str, len);
-        assert(new_str);
     }
 
     iconv_close(cd);
@@ -249,10 +255,12 @@ char* pa_locale_to_utf8 (const char *str) {
 #else
 
 char* pa_utf8_to_locale (const char *str) {
+    pa_assert(str);
     return NULL;
 }
 
 char* pa_locale_to_utf8 (const char *str) {
+    pa_assert(str);
     return NULL;
 }
 
index ff8dc215bc4ac147f9ec79dcf36a63567b4aca33..1e08047c6a8e8dd3c5834c0da3d1a8fe9382d70f 100644 (file)
@@ -34,7 +34,7 @@
 PA_C_DECL_BEGIN
 
 /** Test if the specified strings qualifies as valid UTF8. Return the string if so, otherwise NULL */
-const char *pa_utf8_valid(const char *str);
+char *pa_utf8_valid(const char *str) PA_GCC_PURE;
 
 /** Filter all invalid UTF8 characters from the specified string, returning a new fully UTF8 valid string. Don't forget to free the returned string with pa_xfree() */
 char *pa_utf8_filter(const char *str);
index d561329cb70e9d25ccd628ddf41485df5e4268bd..5dbb670bcd12f5cdeaf2a720294c3e6c68dd5932 100644 (file)
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
 #include <sys/prctl.h>
 #endif
 
-#include "../pulsecore/winsock.h"
-
+#include <pulsecore/winsock.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/log.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
 
 #include "util.h"
 
-#ifndef OS_IS_WIN32
-#define PATH_SEP '/'
-#else
-#define PATH_SEP '\\'
-#endif
-
 char *pa_get_user_name(char *s, size_t l) {
     char *p;
     char buf[1024];
@@ -78,7 +71,8 @@ char *pa_get_user_name(char *s, size_t l) {
     struct passwd pw, *r;
 #endif
 
-    assert(s && l > 0);
+    pa_assert(s);
+    pa_assert(l > 0);
 
     if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) {
 #ifdef HAVE_PWD_H
@@ -90,7 +84,7 @@ char *pa_get_user_name(char *s, size_t l) {
             * that do not support getpwuid_r. */
         if ((r = getpwuid(getuid())) == NULL) {
 #endif
-            snprintf(s, l, "%lu", (unsigned long) getuid());
+            pa_snprintf(s, l, "%lu", (unsigned long) getuid());
             return s;
         }
 
@@ -113,11 +107,15 @@ char *pa_get_user_name(char *s, size_t l) {
 }
 
 char *pa_get_host_name(char *s, size_t l) {
-    assert(s && l > 0);
+
+    pa_assert(s);
+    pa_assert(l > 0);
+
     if (gethostname(s, l) < 0) {
         pa_log("gethostname(): %s", pa_cstrerror(errno));
         return NULL;
     }
+
     s[l-1] = 0;
     return s;
 }
@@ -130,7 +128,8 @@ char *pa_get_home_dir(char *s, size_t l) {
     struct passwd pw, *r;
 #endif
 
-    assert(s && l);
+    pa_assert(s);
+    pa_assert(l > 0);
 
     if ((e = getenv("HOME")))
         return pa_strlcpy(s, e, l);
@@ -159,8 +158,8 @@ char *pa_get_home_dir(char *s, size_t l) {
 
 char *pa_get_binary_name(char *s, size_t l) {
 
-    assert(s);
-    assert(l);
+    pa_assert(s);
+    pa_assert(l > 0);
 
 #if defined(OS_IS_WIN32)
     {
@@ -171,7 +170,7 @@ char *pa_get_binary_name(char *s, size_t l) {
     }
 #endif
 
-#ifdef HAVE_READLINK
+#ifdef __linux__
     {
         int i;
         char path[PATH_MAX];
@@ -206,13 +205,15 @@ char *pa_get_binary_name(char *s, size_t l) {
     return NULL;
 }
 
-const char *pa_path_get_filename(const char *p) {
+char *pa_path_get_filename(const char *p) {
     char *fn;
 
-    if ((fn = strrchr(p, PATH_SEP)))
+    pa_assert(p);
+
+    if ((fn = strrchr(p, PA_PATH_SEP_CHAR)))
         return fn+1;
 
-    return (const char*) p;
+    return (char*) p;
 }
 
 char *pa_get_fqdn(char *s, size_t l) {
@@ -221,6 +222,9 @@ char *pa_get_fqdn(char *s, size_t l) {
     struct addrinfo *a, hints;
 #endif
 
+    pa_assert(s);
+    pa_assert(l > 0);
+
     if (!pa_get_host_name(hn, sizeof(hn)))
         return NULL;
 
index 95bd86f36320f9e50f46adf9638a0ef1a2cf3d07..764678e5caafc2258298e5de67f6d3a91984e8ae 100644 (file)
@@ -52,7 +52,7 @@ char *pa_get_binary_name(char *s, size_t l);
 
 /** Return a pointer to the filename inside a path (which is the last
  * component). */
-const char *pa_path_get_filename(const char *p);
+char *pa_path_get_filename(const char *p);
 
 /** Wait t milliseconds */
 int pa_msleep(unsigned long t);
index feb33f078b9340b584bdbe28dd2ea5e63be9b741..3688b847c68aa3cda66fd47b7d902819096bf997 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 
+#include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
+
 #include "volume.h"
 
 int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) {
     int i;
-    assert(a);
-    assert(b);
+    pa_assert(a);
+    pa_assert(b);
 
     if (a->channels != b->channels)
         return 0;
@@ -49,9 +51,9 @@ int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) {
 pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) {
     int i;
 
-    assert(a);
-    assert(channels > 0);
-    assert(channels <= PA_CHANNELS_MAX);
+    pa_assert(a);
+    pa_assert(channels > 0);
+    pa_assert(channels <= PA_CHANNELS_MAX);
 
     a->channels = channels;
 
@@ -64,7 +66,7 @@ pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) {
 pa_volume_t pa_cvolume_avg(const pa_cvolume *a) {
     uint64_t sum = 0;
     int i;
-    assert(a);
+    pa_assert(a);
 
     for (i = 0; i < a->channels; i++)
         sum += a->values[i];
@@ -118,14 +120,14 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
     int first = 1;
     char *e;
 
-    assert(s);
-    assert(l > 0);
-    assert(c);
+    pa_assert(s);
+    pa_assert(l > 0);
+    pa_assert(c);
 
     *(e = s) = 0;
 
     for (channel = 0; channel < c->channels && l > 1; channel++) {
-        l -= snprintf(e, l, "%s%u: %3u%%",
+        l -= pa_snprintf(e, l, "%s%u: %3u%%",
                       first ? "" : " ",
                       channel,
                       (c->values[channel]*100)/PA_VOLUME_NORM);
@@ -140,7 +142,7 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
 /** Return non-zero if the volume of all channels is equal to the specified value */
 int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) {
     unsigned c;
-    assert(a);
+    pa_assert(a);
 
     for (c = 0; c < a->channels; c++)
         if (a->values[c] != v)
@@ -152,9 +154,9 @@ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) {
 pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
     unsigned i;
 
-    assert(dest);
-    assert(a);
-    assert(b);
+    pa_assert(dest);
+    pa_assert(a);
+    pa_assert(b);
 
     for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++) {
 
@@ -169,7 +171,7 @@ pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const
 }
 
 int pa_cvolume_valid(const pa_cvolume *v) {
-    assert(v);
+    pa_assert(v);
 
     if (v->channels <= 0 || v->channels > PA_CHANNELS_MAX)
         return 0;
index a928ff711cac38dbc48509db592de316cf73b0ca..22e5b8a4eaf897a16b20103238c2351afc0ab785 100644 (file)
@@ -113,7 +113,7 @@ typedef struct pa_cvolume {
 } pa_cvolume;
 
 /** Return non-zero when *a == *b */
-int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b);
+int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) PA_GCC_PURE;
 
 /** Set the volume of all channels to PA_VOLUME_NORM */
 #define pa_cvolume_reset(a, n) pa_cvolume_set((a), (n), PA_VOLUME_NORM)
@@ -131,13 +131,13 @@ pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v);
 char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c);
 
 /** Return the average volume of all channels */
-pa_volume_t pa_cvolume_avg(const pa_cvolume *a);
+pa_volume_t pa_cvolume_avg(const pa_cvolume *a) PA_GCC_PURE;
 
 /** Return TRUE when the passed cvolume structure is valid, FALSE otherwise */
-int pa_cvolume_valid(const pa_cvolume *v);
+int pa_cvolume_valid(const pa_cvolume *v) PA_GCC_PURE;
 
 /** Return non-zero if the volume of all channels is equal to the specified value */
-int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v);
+int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) PA_GCC_PURE;
 
 /** Return 1 if the specified volume has all channels muted */
 #define pa_cvolume_is_muted(a) pa_cvolume_channels_equal_to((a), PA_VOLUME_MUTED)
@@ -146,22 +146,22 @@ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v);
 #define pa_cvolume_is_norm(a) pa_cvolume_channels_equal_to((a), PA_VOLUME_NORM)
 
 /** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. This is only valid for software volumes! */
-pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b);
+pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) PA_GCC_CONST;
 
 /** Multiply to per-channel volumes and return the result in *dest. This is only valid for software volumes! */
-pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b);
+pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) PA_GCC_PURE;
 
 /** Convert a decibel value to a volume. This is only valid for software volumes! \since 0.4 */
-pa_volume_t pa_sw_volume_from_dB(double f);
+pa_volume_t pa_sw_volume_from_dB(double f) PA_GCC_CONST;
 
 /** Convert a volume to a decibel value. This is only valid for software volumes! \since 0.4 */
-double pa_sw_volume_to_dB(pa_volume_t v);
+double pa_sw_volume_to_dB(pa_volume_t v) PA_GCC_CONST;
 
 /** Convert a linear factor to a volume. This is only valid for software volumes! \since 0.8 */
-pa_volume_t pa_sw_volume_from_linear(double v);
+pa_volume_t pa_sw_volume_from_linear(double v) PA_GCC_CONST;
 
 /** Convert a volume to a linear factor. This is only valid for software volumes! \since 0.8 */
-double pa_sw_volume_to_linear(pa_volume_t v);
+double pa_sw_volume_to_linear(pa_volume_t v) PA_GCC_CONST;
 
 #ifdef INFINITY
 #define PA_DECIBEL_MININFTY (-INFINITY)
index 1f0734c242c127bdc06e9632904462ef8c738969..5348dda412c3037b0a4365e0b07fadc28909fe67 100644 (file)
 
 #include <stdlib.h>
 #include <signal.h>
-#include <assert.h>
 #include <unistd.h>
 #include <string.h>
 
 #include <pulsecore/core-util.h>
 #include <pulsecore/gccmacro.h>
+#include <pulsecore/macro.h>
 
 #include "xmalloc.h"
 
@@ -60,8 +60,8 @@ static void oom(void) {
 
 void* pa_xmalloc(size_t size) {
     void *p;
-    assert(size > 0);
-    assert(size < MAX_ALLOC_SIZE);
+    pa_assert(size > 0);
+    pa_assert(size < MAX_ALLOC_SIZE);
 
     if (!(p = malloc(size)))
         oom();
@@ -71,8 +71,8 @@ void* pa_xmalloc(size_t size) {
 
 void* pa_xmalloc0(size_t size) {
     void *p;
-    assert(size > 0);
-    assert(size < MAX_ALLOC_SIZE);
+    pa_assert(size > 0);
+    pa_assert(size < MAX_ALLOC_SIZE);
 
     if (!(p = calloc(1, size)))
         oom();
@@ -82,8 +82,8 @@ void* pa_xmalloc0(size_t size) {
 
 void *pa_xrealloc(void *ptr, size_t size) {
     void *p;
-    assert(size > 0);
-    assert(size < MAX_ALLOC_SIZE);
+    pa_assert(size > 0);
+    pa_assert(size < MAX_ALLOC_SIZE);
 
     if (!(p = realloc(ptr, size)))
         oom();
index 2f6399c580bcde9043c39033356577f1c0450728..62a450dc17fed7179a4b491affc86abdddbd22f4 100644 (file)
@@ -75,6 +75,15 @@ static inline void* pa_xnew0_internal(unsigned n, size_t k) {
 /** Same as pa_xnew() but set the memory to zero */
 #define pa_xnew0(type, n) ((type*) pa_xnew0_internal((n), sizeof(type)))
 
+/** Internal helper for pa_xnew0() */
+static inline void* pa_xnewdup_internal(const void *p, unsigned n, size_t k) {
+    assert(n < INT_MAX/k);
+    return pa_xmemdup(p, n*k);
+}
+
+/** Same as pa_xnew() but set the memory to zero */
+#define pa_xnewdup(type, p, n) ((type*) pa_xnewdup_internal((p), (n), sizeof(type)))
+
 PA_C_DECL_END
 
 #endif
diff --git a/src/pulsecore/anotify.c b/src/pulsecore/anotify.c
deleted file mode 100644 (file)
index 25c5fe7..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/* $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.1 of the
-  License, or (at your option) any later version.
-
-  PulseAudio is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with PulseAudio; if not, 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 <assert.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <pulse/xmalloc.h>
-
-#include "anotify.h"
-
-#define EVENTS_MAX 16
-
-struct pa_anotify {
-    pa_mainloop_api *api;
-    pa_anotify_cb_t callback;
-    void *userdata;
-    int fds[2];
-    pa_io_event *io_event;
-    pa_defer_event *defer_event;
-
-    uint8_t queued_events[EVENTS_MAX];
-    unsigned n_queued_events, queue_index;
-};
-
-static void dispatch_event(pa_anotify *a) {
-    assert(a);
-    assert(a->queue_index < a->n_queued_events);
-
-    a->callback(a->queued_events[a->queue_index++], a->userdata);
-
-    if (a->queue_index >= a->n_queued_events) {
-        a->n_queued_events = 0;
-        a->queue_index = 0;
-
-        a->api->io_enable(a->io_event, PA_IO_EVENT_INPUT);
-        a->api->defer_enable(a->defer_event, 0);
-    } else {
-        a->api->io_enable(a->io_event, 0);
-        a->api->defer_enable(a->defer_event, 1);
-    }
-}
-
-static void io_callback(
-        pa_mainloop_api *api,
-        pa_io_event *e,
-        int fd,
-        pa_io_event_flags_t events,
-        void *userdata) {
-
-    pa_anotify *a = userdata;
-    ssize_t r;
-
-    assert(a);
-    assert(events == PA_IO_EVENT_INPUT);
-    assert(a->n_queued_events == 0);
-
-    r = read(fd, a->queued_events, sizeof(a->queued_events));
-    assert(r > 0);
-
-    a->n_queued_events = (unsigned) r;
-    a->queue_index = 0;
-
-    /* Only dispatch a single event */
-    dispatch_event(a);
-}
-
-static void defer_callback(pa_mainloop_api *api, pa_defer_event *e, void *userdata) {
-    pa_anotify *a = userdata;
-    assert(a);
-
-    dispatch_event(a);
-}
-
-pa_anotify *pa_anotify_new(pa_mainloop_api*api, pa_anotify_cb_t cb, void *userdata) {
-    pa_anotify *a;
-
-    assert(api);
-    assert(cb);
-
-    a = pa_xnew(pa_anotify, 1);
-
-    if (pipe(a->fds) < 0) {
-        pa_xfree(a);
-        return NULL;
-    }
-
-    a->api = api;
-    a->callback = cb;
-    a->userdata = userdata;
-
-    a->io_event = api->io_new(api, a->fds[0], PA_IO_EVENT_INPUT, io_callback, a);
-    a->defer_event = api->defer_new(api, defer_callback, a);
-    a->api->defer_enable(a->defer_event, 0);
-
-    a->n_queued_events = 0;
-
-    return a;
-}
-
-void pa_anotify_free(pa_anotify *a) {
-    assert(a);
-
-    a->api->io_free(a->io_event);
-    a->api->defer_free(a->defer_event);
-
-    if (a->fds[0] >= 0)
-        close(a->fds[0]);
-    if (a->fds[1] >= 0)
-        close(a->fds[1]);
-
-    pa_xfree(a);
-}
-
-int pa_anotify_signal(pa_anotify *a, uint8_t event) {
-    ssize_t r;
-    assert(a);
-
-    r = write(a->fds[1], &event, 1);
-    return r != 1 ? -1 : 0;
-}
diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
new file mode 100644 (file)
index 0000000..96b43a7
--- /dev/null
@@ -0,0 +1,303 @@
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, 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 <unistd.h>
+#include <errno.h>
+
+#include <pulsecore/atomic.h>
+#include <pulsecore/log.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/semaphore.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/flist.h>
+#include <pulse/xmalloc.h>
+
+#include "asyncmsgq.h"
+
+PA_STATIC_FLIST_DECLARE(asyncmsgq, 0, pa_xfree);
+PA_STATIC_FLIST_DECLARE(semaphores, 0, (void(*)(void*)) pa_semaphore_free);
+
+struct asyncmsgq_item {
+    int code;
+    pa_msgobject *object;
+    void *userdata;
+    pa_free_cb_t free_cb;
+    int64_t offset;
+    pa_memchunk memchunk;
+    pa_semaphore *semaphore;
+    int ret;
+};
+
+struct pa_asyncmsgq {
+    PA_REFCNT_DECLARE;
+    pa_asyncq *asyncq;
+    pa_mutex *mutex; /* only for the writer side */
+
+    struct asyncmsgq_item *current;
+};
+
+pa_asyncmsgq *pa_asyncmsgq_new(unsigned size) {
+    pa_asyncmsgq *a;
+
+    a = pa_xnew(pa_asyncmsgq, 1);
+
+    PA_REFCNT_INIT(a);
+    pa_assert_se(a->asyncq = pa_asyncq_new(size));
+    pa_assert_se(a->mutex = pa_mutex_new(FALSE, TRUE));
+    a->current = NULL;
+
+    return a;
+}
+
+static void asyncmsgq_free(pa_asyncmsgq *a) {
+    struct asyncmsgq_item *i;
+    pa_assert(a);
+
+    while ((i = pa_asyncq_pop(a->asyncq, 0))) {
+
+        pa_assert(!i->semaphore);
+
+        if (i->object)
+            pa_msgobject_unref(i->object);
+
+        if (i->memchunk.memblock)
+            pa_memblock_unref(i->memchunk.memblock);
+
+        if (i->free_cb)
+            i->free_cb(i->userdata);
+
+        if (pa_flist_push(PA_STATIC_FLIST_GET(asyncmsgq), i) < 0)
+            pa_xfree(i);
+    }
+
+    pa_asyncq_free(a->asyncq, NULL);
+    pa_mutex_free(a->mutex);
+    pa_xfree(a);
+}
+
+pa_asyncmsgq* pa_asyncmsgq_ref(pa_asyncmsgq *q) {
+    pa_assert(PA_REFCNT_VALUE(q) > 0);
+
+    PA_REFCNT_INC(q);
+    return q;
+}
+
+void pa_asyncmsgq_unref(pa_asyncmsgq* q) {
+    pa_assert(PA_REFCNT_VALUE(q) > 0);
+
+    if (PA_REFCNT_DEC(q) <= 0)
+        asyncmsgq_free(q);
+}
+
+void pa_asyncmsgq_post(pa_asyncmsgq *a, pa_msgobject *object, int code, const void *userdata, int64_t offset, const pa_memchunk *chunk, pa_free_cb_t free_cb) {
+    struct asyncmsgq_item *i;
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
+
+    if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(asyncmsgq))))
+        i = pa_xnew(struct asyncmsgq_item, 1);
+
+    i->code = code;
+    i->object = object ? pa_msgobject_ref(object) : NULL;
+    i->userdata = (void*) userdata;
+    i->free_cb = free_cb;
+    i->offset = offset;
+    if (chunk) {
+        pa_assert(chunk->memblock);
+        i->memchunk = *chunk;
+        pa_memblock_ref(i->memchunk.memblock);
+    } else
+        pa_memchunk_reset(&i->memchunk);
+    i->semaphore = NULL;
+
+    /* This mutex makes the queue multiple-writer safe. This lock is only used on the writing side */
+    pa_mutex_lock(a->mutex);
+    pa_assert_se(pa_asyncq_push(a->asyncq, i, 1) == 0);
+    pa_mutex_unlock(a->mutex);
+}
+
+int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const void *userdata, int64_t offset, const pa_memchunk *chunk) {
+    struct asyncmsgq_item i;
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
+
+    i.code = code;
+    i.object = object;
+    i.userdata = (void*) userdata;
+    i.free_cb = NULL;
+    i.ret = -1;
+    i.offset = offset;
+    if (chunk) {
+        pa_assert(chunk->memblock);
+        i.memchunk = *chunk;
+    } else
+        pa_memchunk_reset(&i.memchunk);
+
+    if (!(i.semaphore = pa_flist_pop(PA_STATIC_FLIST_GET(semaphores))))
+        i.semaphore = pa_semaphore_new(0);
+
+    pa_assert_se(i.semaphore);
+
+    /* Thus mutex makes the queue multiple-writer safe. This lock is only used on the writing side */
+    pa_mutex_lock(a->mutex);
+    pa_assert_se(pa_asyncq_push(a->asyncq, &i, 1) == 0);
+    pa_mutex_unlock(a->mutex);
+
+    pa_semaphore_wait(i.semaphore);
+
+    if (pa_flist_push(PA_STATIC_FLIST_GET(semaphores), i.semaphore) < 0)
+        pa_semaphore_free(i.semaphore);
+
+    return i.ret;
+}
+
+int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **userdata, int64_t *offset, pa_memchunk *chunk, int wait) {
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
+    pa_assert(!a->current);
+
+    if (!(a->current = pa_asyncq_pop(a->asyncq, wait))) {
+/*         pa_log("failure"); */
+        return -1;
+    }
+
+/*     pa_log("success"); */
+
+    if (code)
+        *code = a->current->code;
+    if (userdata)
+        *userdata = a->current->userdata;
+    if (offset)
+        *offset = a->current->offset;
+    if (object) {
+        if ((*object = a->current->object))
+            pa_msgobject_assert_ref(*object);
+    }
+    if (chunk)
+        *chunk = a->current->memchunk;
+
+/*     pa_log_debug("Get q=%p object=%p (%s) code=%i data=%p chunk.length=%lu", (void*) a, (void*) a->current->object, a->current->object ? a->current->object->parent.type_name : NULL, a->current->code, (void*) a->current->userdata, (unsigned long) a->current->memchunk.length); */
+
+    return 0;
+}
+
+void pa_asyncmsgq_done(pa_asyncmsgq *a, int ret) {
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
+    pa_assert(a);
+    pa_assert(a->current);
+
+    if (a->current->semaphore) {
+        a->current->ret = ret;
+        pa_semaphore_post(a->current->semaphore);
+    } else {
+
+        if (a->current->free_cb)
+            a->current->free_cb(a->current->userdata);
+
+        if (a->current->object)
+            pa_msgobject_unref(a->current->object);
+
+        if (a->current->memchunk.memblock)
+            pa_memblock_unref(a->current->memchunk.memblock);
+
+        if (pa_flist_push(PA_STATIC_FLIST_GET(asyncmsgq), a->current) < 0)
+            pa_xfree(a->current);
+    }
+
+    a->current = NULL;
+}
+
+int pa_asyncmsgq_wait_for(pa_asyncmsgq *a, int code) {
+    int c;
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
+
+    pa_asyncmsgq_ref(a);
+
+    do {
+        pa_msgobject *o;
+        void *data;
+        int64_t offset;
+        pa_memchunk chunk;
+        int ret;
+
+        if (pa_asyncmsgq_get(a, &o, &c, &data, &offset, &chunk, 1) < 0)
+            return -1;
+
+        ret = pa_asyncmsgq_dispatch(o, c, data, offset, &chunk);
+        pa_asyncmsgq_done(a, ret);
+
+    } while (c != code);
+
+    pa_asyncmsgq_unref(a);
+
+    return 0;
+}
+
+int pa_asyncmsgq_process_one(pa_asyncmsgq *a) {
+    pa_msgobject *object;
+    int code;
+    void *data;
+    pa_memchunk chunk;
+    int64_t offset;
+    int ret;
+
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
+
+    if (pa_asyncmsgq_get(a, &object, &code, &data, &offset, &chunk, 0) < 0)
+        return 0;
+
+    pa_asyncmsgq_ref(a);
+    ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
+    pa_asyncmsgq_done(a, ret);
+    pa_asyncmsgq_unref(a);
+
+    return 1;
+}
+
+int pa_asyncmsgq_get_fd(pa_asyncmsgq *a) {
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
+
+    return pa_asyncq_get_fd(a->asyncq);
+}
+
+int pa_asyncmsgq_before_poll(pa_asyncmsgq *a) {
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
+
+    return pa_asyncq_before_poll(a->asyncq);
+}
+
+void pa_asyncmsgq_after_poll(pa_asyncmsgq *a) {
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
+
+    pa_asyncq_after_poll(a->asyncq);
+}
+
+int pa_asyncmsgq_dispatch(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *memchunk) {
+
+    if (object)
+        return object->process_msg(object, code, userdata, offset, memchunk);
+
+    return 0;
+}
diff --git a/src/pulsecore/asyncmsgq.h b/src/pulsecore/asyncmsgq.h
new file mode 100644 (file)
index 0000000..5d3867b
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef foopulseasyncmsgqhfoo
+#define foopulseasyncmsgqhfoo
+
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#include <sys/types.h>
+
+#include <pulsecore/asyncq.h>
+#include <pulsecore/memchunk.h>
+#include <pulsecore/msgobject.h>
+
+/* A simple asynchronous message queue, based on pa_asyncq. In
+ * contrast to pa_asyncq this one is multiple-writer safe, though
+ * still not multiple-reader safe. This queue is intended to be used
+ * for controlling real-time threads from normal-priority
+ * threads. Multiple-writer-safety is accomplished by using a mutex on
+ * the writer side. This queue is thus not useful for communication
+ * between several real-time threads.
+ *
+ * The queue takes messages consisting of:
+ *    "Object" for which this messages is intended (may be NULL)
+ *    A numeric message code
+ *    Arbitrary userdata pointer (may be NULL)
+ *    A memchunk (may be NULL)
+ *
+ * There are two functions for submitting messages: _post and
+ * _send. The former just enqueues the message asynchronously, the
+ * latter waits for completion, synchronously. */
+
+enum {
+    PA_MESSAGE_SHUTDOWN = -1/* A generic message to inform the handler of this queue to quit */
+};
+
+typedef struct pa_asyncmsgq pa_asyncmsgq;
+
+pa_asyncmsgq* pa_asyncmsgq_new(unsigned size);
+pa_asyncmsgq* pa_asyncmsgq_ref(pa_asyncmsgq *q);
+void pa_asyncmsgq_unref(pa_asyncmsgq* q);
+
+void pa_asyncmsgq_post(pa_asyncmsgq *q, pa_msgobject *object, int code, const void *userdata, int64_t offset, const pa_memchunk *memchunk, pa_free_cb_t userdata_free_cb);
+int pa_asyncmsgq_send(pa_asyncmsgq *q, pa_msgobject *object, int code, const void *userdata, int64_t offset, const pa_memchunk *memchunk);
+
+int pa_asyncmsgq_get(pa_asyncmsgq *q, pa_msgobject **object, int *code, void **userdata, int64_t *offset, pa_memchunk *memchunk, int wait);
+int pa_asyncmsgq_dispatch(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *memchunk);
+void pa_asyncmsgq_done(pa_asyncmsgq *q, int ret);
+int pa_asyncmsgq_wait_for(pa_asyncmsgq *a, int code);
+int pa_asyncmsgq_process_one(pa_asyncmsgq *a);
+
+/* Just for the reading side */
+int pa_asyncmsgq_get_fd(pa_asyncmsgq *q);
+int pa_asyncmsgq_before_poll(pa_asyncmsgq *a);
+void pa_asyncmsgq_after_poll(pa_asyncmsgq *a);
+
+#endif
diff --git a/src/pulsecore/asyncq.c b/src/pulsecore/asyncq.c
new file mode 100644 (file)
index 0000000..75b15c0
--- /dev/null
@@ -0,0 +1,213 @@
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, 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 <unistd.h>
+#include <errno.h>
+
+#include <pulsecore/atomic.h>
+#include <pulsecore/log.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
+#include <pulse/xmalloc.h>
+
+#include "asyncq.h"
+#include "fdsem.h"
+
+#define ASYNCQ_SIZE 128
+
+/* For debugging purposes we can define _Y to put and extra thread
+ * yield between each operation. */
+
+/* #define PROFILE */
+
+#ifdef PROFILE
+#define _Y pa_thread_yield()
+#else
+#define _Y do { } while(0)
+#endif
+
+struct pa_asyncq {
+    unsigned size;
+    unsigned read_idx;
+    unsigned write_idx;
+    pa_fdsem *read_fdsem, *write_fdsem;
+};
+
+#define PA_ASYNCQ_CELLS(x) ((pa_atomic_ptr_t*) ((uint8_t*) (x) + PA_ALIGN(sizeof(struct pa_asyncq))))
+
+static int is_power_of_two(unsigned size) {
+    return !(size & (size - 1));
+}
+
+static int reduce(pa_asyncq *l, int value) {
+    return value & (unsigned) (l->size - 1);
+}
+
+pa_asyncq *pa_asyncq_new(unsigned size) {
+    pa_asyncq *l;
+
+    if (!size)
+        size = ASYNCQ_SIZE;
+
+    pa_assert(is_power_of_two(size));
+
+    l = pa_xmalloc0(PA_ALIGN(sizeof(pa_asyncq)) + (sizeof(pa_atomic_ptr_t) * size));
+
+    l->size = size;
+
+    if (!(l->read_fdsem = pa_fdsem_new())) {
+        pa_xfree(l);
+        return NULL;
+    }
+
+    if (!(l->write_fdsem = pa_fdsem_new())) {
+        pa_fdsem_free(l->read_fdsem);
+        pa_xfree(l);
+        return NULL;
+    }
+
+    return l;
+}
+
+void pa_asyncq_free(pa_asyncq *l, pa_free_cb_t free_cb) {
+    pa_assert(l);
+
+    if (free_cb) {
+        void *p;
+
+        while ((p = pa_asyncq_pop(l, 0)))
+            free_cb(p);
+    }
+
+    pa_fdsem_free(l->read_fdsem);
+    pa_fdsem_free(l->write_fdsem);
+    pa_xfree(l);
+}
+
+int pa_asyncq_push(pa_asyncq*l, void *p, int wait) {
+    int idx;
+    pa_atomic_ptr_t *cells;
+
+    pa_assert(l);
+    pa_assert(p);
+
+    cells = PA_ASYNCQ_CELLS(l);
+
+    _Y;
+    idx = reduce(l, l->write_idx);
+
+    if (!pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)) {
+
+        if (!wait)
+            return -1;
+
+/*         pa_log("sleeping on push"); */
+
+        do {
+            pa_fdsem_wait(l->read_fdsem);
+        } while (!pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p));
+    }
+
+    _Y;
+    l->write_idx++;
+
+    pa_fdsem_post(l->write_fdsem);
+
+    return 0;
+}
+
+void* pa_asyncq_pop(pa_asyncq*l, int wait) {
+    int idx;
+    void *ret;
+    pa_atomic_ptr_t *cells;
+
+    pa_assert(l);
+
+    cells = PA_ASYNCQ_CELLS(l);
+
+    _Y;
+    idx = reduce(l, l->read_idx);
+
+    if (!(ret = pa_atomic_ptr_load(&cells[idx]))) {
+
+        if (!wait)
+            return NULL;
+
+/*         pa_log("sleeping on pop"); */
+
+        do {
+            pa_fdsem_wait(l->write_fdsem);
+        } while (!(ret = pa_atomic_ptr_load(&cells[idx])));
+    }
+
+    pa_assert(ret);
+
+    /* Guaranteed to succeed if we only have a single reader */
+    pa_assert_se(pa_atomic_ptr_cmpxchg(&cells[idx], ret, NULL));
+
+    _Y;
+    l->read_idx++;
+
+    pa_fdsem_post(l->read_fdsem);
+
+    return ret;
+}
+
+int pa_asyncq_get_fd(pa_asyncq *q) {
+    pa_assert(q);
+
+    return pa_fdsem_get(q->write_fdsem);
+}
+
+int pa_asyncq_before_poll(pa_asyncq *l) {
+    int idx;
+    pa_atomic_ptr_t *cells;
+
+    pa_assert(l);
+
+    cells = PA_ASYNCQ_CELLS(l);
+
+    _Y;
+    idx = reduce(l, l->read_idx);
+
+    for (;;) {
+        if (pa_atomic_ptr_load(&cells[idx]))
+            return -1;
+
+        if (pa_fdsem_before_poll(l->write_fdsem) >= 0)
+            return 0;
+    }
+
+    return 0;
+}
+
+void pa_asyncq_after_poll(pa_asyncq *l) {
+    pa_assert(l);
+
+    pa_fdsem_after_poll(l->write_fdsem);
+}
diff --git a/src/pulsecore/asyncq.h b/src/pulsecore/asyncq.h
new file mode 100644 (file)
index 0000000..53d4586
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef foopulseasyncqhfoo
+#define foopulseasyncqhfoo
+
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#include <sys/types.h>
+#include <pulse/def.h>
+
+/* A simple, asynchronous, lock-free (if requested also wait-free)
+ * queue. Not multiple-reader/multiple-writer safe. If that is
+ * required both sides can be protected by a mutex each. --- Which is
+ * not a bad thing in most cases, since this queue is intended for
+ * communication between a normal thread and a single real-time
+ * thread. Only the real-time side needs to be lock-free/wait-free.
+ *
+ * If the queue is full and another entry shall be pushed, or when the
+ * queue is empty and another entry shall be popped and the "wait"
+ * argument is non-zero, the queue will block on a UNIX FIFO object --
+ * that will probably require locking on the kernel side -- which
+ * however is probably not problematic, because we do it only on
+ * starvation or overload in which case we have to block anyway.  */
+
+typedef struct pa_asyncq pa_asyncq;
+
+pa_asyncq* pa_asyncq_new(unsigned size);
+void pa_asyncq_free(pa_asyncq* q, pa_free_cb_t free_cb);
+
+void* pa_asyncq_pop(pa_asyncq *q, int wait);
+int pa_asyncq_push(pa_asyncq *q, void *p, int wait);
+
+int pa_asyncq_get_fd(pa_asyncq *q);
+int pa_asyncq_before_poll(pa_asyncq *a);
+void pa_asyncq_after_poll(pa_asyncq *a);
+
+#endif
index 013e8c205c083eddb89390e6033892fbb1bdec51..c2c99888bf2134b356bcb2dc38f3fa39fc037e84 100644 (file)
   USA.
 ***/
 
-#include <atomic_ops.h>
-
-/* atomic_ops guarantees us that sizeof(AO_t) == sizeof(void*).
+/*
+ * atomic_ops guarantees us that sizeof(AO_t) == sizeof(void*).  It is
+ * not guaranteed however, that sizeof(AO_t) == sizeof(size_t).
+ * however very likely.
+ *
+ * For now we do only full memory barriers. Eventually we might want
+ * to support more elaborate memory barriers, in which case we will add
+ * suffixes to the function names.
  *
- * It is not guaranteed however, that sizeof(AO_t) == sizeof(size_t).
- * however very likely. */
+ * On gcc >= 4.1 we use the builtin atomic functions. otherwise we use
+ * libatomic_ops
+ */
 
-typedef struct pa_atomic_int {
-    volatile AO_t value;
-} pa_atomic_int_t;
+#ifndef PACKAGE
+#error "Please include config.h before including this file!"
+#endif
+
+#ifdef HAVE_ATOMIC_BUILTINS
+
+/* __sync based implementation */
+
+typedef struct pa_atomic {
+    volatile int value;
+} pa_atomic_t;
 
 #define PA_ATOMIC_INIT(v) { .value = (v) }
 
-/* For now we do only full memory barriers. Eventually we might want
- * to support more elaborate memory barriers, in which case we will add
- * suffixes to the function names */
+static inline int pa_atomic_load(const pa_atomic_t *a) {
+    __sync_synchronize();
+    return a->value;
+}
+
+static inline void pa_atomic_store(pa_atomic_t *a, int i) {
+    a->value = i;
+    __sync_synchronize();
+}
+
+/* Returns the previously set value */
+static inline int pa_atomic_add(pa_atomic_t *a, int i) {
+    return __sync_fetch_and_add(&a->value, i);
+}
+
+/* Returns the previously set value */
+static inline int pa_atomic_sub(pa_atomic_t *a, int i) {
+    return __sync_fetch_and_sub(&a->value, i);
+}
+
+/* Returns the previously set value */
+static inline int pa_atomic_inc(pa_atomic_t *a) {
+    return pa_atomic_add(a, 1);
+}
+
+/* Returns the previously set value */
+static inline int pa_atomic_dec(pa_atomic_t *a) {
+    return pa_atomic_sub(a, 1);
+}
+
+/* Returns non-zero when the operation was successful. */
+static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) {
+    return __sync_bool_compare_and_swap(&a->value, old_i, new_i);
+}
+
+typedef struct pa_atomic_ptr {
+    volatile unsigned long value;
+} pa_atomic_ptr_t;
+
+#define PA_ATOMIC_PTR_INIT(v) { .value = (long) (v) }
+
+static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) {
+    __sync_synchronize();
+    return (void*) a->value;
+}
+
+static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) {
+    a->value = (unsigned long) p;
+    __sync_synchronize();
+}
+
+static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) {
+    return __sync_bool_compare_and_swap(&a->value, (long) old_p, (long) new_p);
+}
+
+#elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__))
+
+#error "The native atomic operations implementation for AMD64 has not been tested. libatomic_ops is known to not work properly on AMD64 and your gcc version is too old for the gcc-builtin atomic ops support. You have three options now: make the native atomic operations implementation for AMD64 work, fix libatomic_ops, or upgrade your GCC."
+
+/* Addapted from glibc */
+
+typedef struct pa_atomic {
+    volatile int value;
+} pa_atomic_t;
+
+#define PA_ATOMIC_INIT(v) { .value = (v) }
+
+static inline int pa_atomic_load(const pa_atomic_t *a) {
+    return a->value;
+}
+
+static inline void pa_atomic_store(pa_atomic_t *a, int i) {
+    a->value = i;
+}
+
+static inline int pa_atomic_add(pa_atomic_t *a, int i) {
+    int result;
+
+    __asm __volatile ("lock; xaddl %0, %1"
+                      : "=r" (result), "=m" (a->value)
+                      : "0" (i), "m" (a->value));
+
+    return result;
+}
+
+static inline int pa_atomic_sub(pa_atomic_t *a, int i) {
+    return pa_atomic_add(a, -i);
+}
+
+static inline int pa_atomic_inc(pa_atomic_t *a) {
+    return pa_atomic_add(a, 1);
+}
 
-static inline int pa_atomic_load(const pa_atomic_int_t *a) {
+static inline int pa_atomic_dec(pa_atomic_t *a) {
+    return pa_atomic_sub(a, 1);
+}
+
+static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) {
+    int result;
+
+    __asm__ __volatile__ ("lock; cmpxchgl %2, %1"
+                          : "=a" (result), "=m" (a->value)
+                          : "r" (new_i), "m" (a->value), "0" (old_i));
+
+    return result == oldval;
+}
+
+typedef struct pa_atomic_ptr {
+    volatile unsigned long value;
+} pa_atomic_ptr_t;
+
+#define PA_ATOMIC_PTR_INIT(v) { .value = (long) (v) }
+
+static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) {
+    return (void*) a->value;
+}
+
+static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) {
+    a->value = (unsigned long) p;
+}
+
+static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) {
+    void *result;
+
+    __asm__ __volatile__ ("lock; cmpxchgq %q2, %1"
+                          : "=a" (result), "=m" (a->value)
+                          : "r" (new_p), "m" (a->value), "0" (old_p));
+
+    return result;
+}
+
+#else
+
+/* libatomic_ops based implementation */
+
+#include <atomic_ops.h>
+
+typedef struct pa_atomic {
+    volatile AO_t value;
+} pa_atomic_t;
+
+#define PA_ATOMIC_INIT(v) { .value = (v) }
+
+static inline int pa_atomic_load(const pa_atomic_t *a) {
     return (int) AO_load_full((AO_t*) &a->value);
 }
 
-static inline void pa_atomic_store(pa_atomic_int_t *a, int i) {
+static inline void pa_atomic_store(pa_atomic_t *a, int i) {
     AO_store_full(&a->value, (AO_t) i);
 }
 
-static inline int pa_atomic_add(pa_atomic_int_t *a, int i) {
+static inline int pa_atomic_add(pa_atomic_t *a, int i) {
     return AO_fetch_and_add_full(&a->value, (AO_t) i);
 }
 
-static inline int pa_atomic_sub(pa_atomic_int_t *a, int i) {
+static inline int pa_atomic_sub(pa_atomic_t *a, int i) {
     return AO_fetch_and_add_full(&a->value, (AO_t) -i);
 }
 
-static inline int pa_atomic_inc(pa_atomic_int_t *a) {
+static inline int pa_atomic_inc(pa_atomic_t *a) {
     return AO_fetch_and_add1_full(&a->value);
 }
 
-static inline int pa_atomic_dec(pa_atomic_int_t *a) {
+static inline int pa_atomic_dec(pa_atomic_t *a) {
     return AO_fetch_and_sub1_full(&a->value);
 }
 
-static inline int pa_atomic_cmpxchg(pa_atomic_int_t *a, int old_i, int new_i) {
+static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) {
     return AO_compare_and_swap_full(&a->value, old_i, new_i);
 }
 
@@ -73,6 +226,8 @@ typedef struct pa_atomic_ptr {
     volatile AO_t value;
 } pa_atomic_ptr_t;
 
+#define PA_ATOMIC_PTR_INIT(v) { .value = (AO_t) (v) }
+
 static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) {
     return (void*) AO_load_full((AO_t*) &a->value);
 }
@@ -86,3 +241,5 @@ static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* n
 }
 
 #endif
+
+#endif
index 3b8304b2382b158e0c59e808731add739e996a38..541545003a362292ef227aa2a372116198999ed1 100644 (file)
   USA.
 ***/
 
-#include <assert.h>
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <string.h>
 
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/props.h>
+#include <pulsecore/macro.h>
 #include <pulsecore/log.h>
+#include <pulsecore/refcnt.h>
 
 #include "authkey-prop.h"
 
 struct authkey_data {
-    int ref;
+    PA_REFCNT_DECLARE;
     size_t length;
 };
 
 int pa_authkey_prop_get(pa_core *c, const char *name, void *data, size_t len) {
     struct authkey_data *a;
-    assert(c && name && data && len > 0);
+
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(data);
+    pa_assert(len > 0);
 
     if (!(a = pa_property_get(c, name)))
         return -1;
 
-    assert(a->length == len);
-    memcpy(data, a+1, len);
+    pa_assert(a->length == len);
+    memcpy(data, (uint8_t*) a + PA_ALIGN(sizeof(struct authkey_data)), len);
+
     return 0;
 }
 
 int pa_authkey_prop_put(pa_core *c, const char *name, const void *data, size_t len) {
     struct authkey_data *a;
-    assert(c && name);
+
+    pa_assert(c);
+    pa_assert(name);
 
     if (pa_property_get(c, name))
         return -1;
 
-    a = pa_xmalloc(sizeof(struct authkey_data) + len);
-    a->ref = 1;
+    a = pa_xmalloc(PA_ALIGN(sizeof(struct authkey_data)) + len);
+    PA_REFCNT_INIT(a);
     a->length = len;
-    memcpy(a+1, data, len);
+    memcpy((uint8_t*) a + PA_ALIGN(sizeof(struct authkey_data)), data, len);
 
     pa_property_set(c, name, a);
 
@@ -67,22 +79,27 @@ int pa_authkey_prop_put(pa_core *c, const char *name, const void *data, size_t l
 
 void pa_authkey_prop_ref(pa_core *c, const char *name) {
     struct authkey_data *a;
-    assert(c && name);
 
-    a = pa_property_get(c, name);
-    assert(a && a->ref >= 1);
+    pa_assert(c);
+    pa_assert(name);
 
-    a->ref++;
+    a = pa_property_get(c, name);
+    pa_assert(a);
+    pa_assert(PA_REFCNT_VALUE(a) >= 1);
+    PA_REFCNT_INC(a);
 }
 
 void pa_authkey_prop_unref(pa_core *c, const char *name) {
     struct authkey_data *a;
-    assert(c && name);
+
+    pa_assert(c);
+    pa_assert(name);
 
     a = pa_property_get(c, name);
-    assert(a && a->ref >= 1);
+    pa_assert(a);
+    pa_assert(PA_REFCNT_VALUE(a) >= 1);
 
-    if (!(--a->ref)) {
+    if (PA_REFCNT_DEC(a) <= 0) {
         pa_property_remove(c, name);
         pa_xfree(a);
     }
index a6150d0e0a5d7280c629581e68480c5847a65a2a..80bc85765e3e2386e9eda7eaa964b05c0b549031 100644 (file)
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <string.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
 #include <pulsecore/random.h>
+#include <pulsecore/macro.h>
 
 #include "authkey.h"
 
 /* Generate a new authorization key, store it in file fd and return it in *data  */
 static int generate(int fd, void *ret_data, size_t length) {
     ssize_t r;
-    assert(fd >= 0 && ret_data && length);
+
+    pa_assert(fd >= 0);
+    pa_assert(ret_data);
+    pa_assert(length > 0);
 
     pa_random(ret_data, length);
 
     lseek(fd, 0, SEEK_SET);
-    ftruncate(fd, 0);
+    (void) ftruncate(fd, 0);
 
     if ((r = pa_loop_write(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) {
-        pa_log("failed to write cookie file: %s", pa_cstrerror(errno));
+        pa_log("Failed to write cookie file: %s", pa_cstrerror(errno));
         return -1;
     }
 
@@ -68,6 +71,10 @@ static int generate(int fd, void *ret_data, size_t length) {
 #define O_BINARY 0
 #endif
 
+#ifndef O_NOCTTY
+#define O_NOCTTY 0
+#endif
+
 /* Load an euthorization cookie from file fn and store it in data. If
  * the cookie file doesn't exist, create it */
 static int load(const char *fn, void *data, size_t length) {
@@ -75,11 +82,15 @@ static int load(const char *fn, void *data, size_t length) {
     int writable = 1;
     int unlock = 0, ret = -1;
     ssize_t r;
-    assert(fn && data && length);
 
-    if ((fd = open(fn, O_RDWR|O_CREAT|O_BINARY, S_IRUSR|S_IWUSR)) < 0) {
-        if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY)) < 0) {
-            pa_log("failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
+    pa_assert(fn);
+    pa_assert(data);
+    pa_assert(length > 0);
+
+    if ((fd = open(fn, O_RDWR|O_CREAT|O_BINARY|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) {
+
+        if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY|O_NOCTTY)) < 0) {
+            pa_log("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
             goto finish;
         } else
             writable = 0;
@@ -88,15 +99,15 @@ static int load(const char *fn, void *data, size_t length) {
     unlock = pa_lock_fd(fd, 1) >= 0;
 
     if ((r = pa_loop_read(fd, data, length, NULL)) < 0) {
-        pa_log("failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
+        pa_log("Failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
         goto finish;
     }
 
     if ((size_t) r != length) {
-        pa_log_debug("got %d bytes from cookie file '%s', expected %d", (int)r, fn, (int)length);
+        pa_log_debug("Got %d bytes from cookie file '%s', expected %d", (int) r, fn, (int) length);
 
         if (!writable) {
-            pa_log("unable to write cookie to read only file");
+            pa_log("Unable to write cookie to read only file");
             goto finish;
         }
 
@@ -113,7 +124,10 @@ finish:
         if (unlock)
             pa_lock_fd(fd, 0);
 
-        close(fd);
+        if (pa_close(fd) < 0) {
+            pa_log_warn("Failed to close cookie file: %s", pa_cstrerror(errno));
+            ret = -1;
+        }
     }
 
     return ret;
@@ -123,13 +137,12 @@ finish:
 int pa_authkey_load(const char *path, void *data, size_t length) {
     int ret;
 
-    assert(path && data && length);
+    pa_assert(path);
+    pa_assert(data);
+    pa_assert(length > 0);
 
-    ret = load(path, data, length);
-
-    if (ret < 0)
-        pa_log("Failed to load authorization key '%s': %s", path,
-               (ret == -1) ? pa_cstrerror(errno) : "file corrupt");
+    if ((ret = load(path, data, length)) < 0)
+        pa_log("Failed to load authorization key '%s': %s", path, (ret < 0) ? pa_cstrerror(errno) : "File corrupt");
 
     return ret;
 }
@@ -137,7 +150,10 @@ int pa_authkey_load(const char *path, void *data, size_t length) {
 /* If the specified file path starts with / return it, otherwise
  * return path prepended with home directory */
 static const char *normalize_path(const char *fn, char *s, size_t l) {
-    assert(fn && s && l > 0);
+
+    pa_assert(fn);
+    pa_assert(s);
+    pa_assert(l > 0);
 
 #ifndef OS_IS_WIN32
     if (fn[0] != '/') {
@@ -145,13 +161,14 @@ static const char *normalize_path(const char *fn, char *s, size_t l) {
     if (strlen(fn) < 3 || !isalpha(fn[0]) || fn[1] != ':' || fn[2] != '\\') {
 #endif
         char homedir[PATH_MAX];
+
         if (!pa_get_home_dir(homedir, sizeof(homedir)))
             return NULL;
 
 #ifndef OS_IS_WIN32
-        snprintf(s, l, "%s/%s", homedir, fn);
+        pa_snprintf(s, l, "%s/%s", homedir, fn);
 #else
-        snprintf(s, l, "%s\\%s", homedir, fn);
+        pa_snprintf(s, l, "%s\\%s", homedir, fn);
 #endif
         return s;
     }
@@ -164,7 +181,10 @@ static const char *normalize_path(const char *fn, char *s, size_t l) {
 int pa_authkey_load_auto(const char *fn, void *data, size_t length) {
     char path[PATH_MAX];
     const char *p;
-    assert(fn && data && length);
+
+    pa_assert(fn);
+    pa_assert(data);
+    pa_assert(length > 0);
 
     if (!(p = normalize_path(fn, path, sizeof(path))))
         return -2;
@@ -179,20 +199,23 @@ int pa_authkey_save(const char *fn, const void *data, size_t length) {
     ssize_t r;
     char path[PATH_MAX];
     const char *p;
-    assert(fn && data && length);
+
+    pa_assert(fn);
+    pa_assert(data);
+    pa_assert(length > 0);
 
     if (!(p = normalize_path(fn, path, sizeof(path))))
         return -2;
 
-    if ((fd = open(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
-        pa_log("failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
+    if ((fd = open(p, O_RDWR|O_CREAT|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) {
+        pa_log("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
         goto finish;
     }
 
     unlock = pa_lock_fd(fd, 1) >= 0;
 
     if ((r = pa_loop_write(fd, data, length, NULL)) < 0 || (size_t) r != length) {
-        pa_log("failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
+        pa_log("Failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
         goto finish;
     }
 
@@ -205,7 +228,10 @@ finish:
         if (unlock)
             pa_lock_fd(fd, 0);
 
-        close(fd);
+        if (pa_close(fd) < 0) {
+            pa_log_warn("Failed to close cookie file: %s", pa_cstrerror(errno));
+            ret = -1;
+        }
     }
 
     return ret;
index 6f888526c815479dcc5e3cbabbf9ed9309f3bbfc..a1d3e02d50feb12eec421dbaa9b8986a8346a75d 100644 (file)
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include <pulsecore/memchunk.h>
 #include <pulsecore/sound-file.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 #include <pulsecore/core-scache.h>
 #include <pulsecore/core-subscribe.h>
 
 #include "autoload.h"
 
 static void entry_free(pa_autoload_entry *e) {
-    assert(e);
+    pa_assert(e);
     pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_REMOVE, PA_INVALID_INDEX);
     pa_xfree(e->name);
     pa_xfree(e->module);
@@ -51,7 +51,8 @@ static void entry_free(pa_autoload_entry *e) {
 }
 
 static void entry_remove_and_free(pa_autoload_entry *e) {
-    assert(e && e->core);
+    pa_assert(e);
+    pa_assert(e->core);
 
     pa_idxset_remove_by_data(e->core->autoload_idxset, e, NULL);
     pa_hashmap_remove(e->core->autoload_hashmap, e->name);
@@ -60,12 +61,14 @@ static void entry_remove_and_free(pa_autoload_entry *e) {
 
 static pa_autoload_entry* entry_new(pa_core *c, const char *name) {
     pa_autoload_entry *e = NULL;
-    assert(c && name);
+
+    pa_core_assert_ref(c);
+    pa_assert(name);
 
     if (c->autoload_hashmap && (e = pa_hashmap_get(c->autoload_hashmap, name)))
         return NULL;
 
-    e = pa_xmalloc(sizeof(pa_autoload_entry));
+    e = pa_xnew(pa_autoload_entry, 1);
     e->core = c;
     e->name = pa_xstrdup(name);
     e->module = e->argument = NULL;
@@ -73,7 +76,7 @@ static pa_autoload_entry* entry_new(pa_core *c, const char *name) {
 
     if (!c->autoload_hashmap)
         c->autoload_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-    assert(c->autoload_hashmap);
+    pa_assert(c->autoload_hashmap);
 
     pa_hashmap_put(c->autoload_hashmap, e->name, e);
 
@@ -88,7 +91,11 @@ static pa_autoload_entry* entry_new(pa_core *c, const char *name) {
 
 int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type_t type, const char*module, const char *argument, uint32_t *idx) {
     pa_autoload_entry *e = NULL;
-    assert(c && name && module && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE));
+
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(module);
+    pa_assert(type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE);
 
     if (!(e = entry_new(c, name)))
         return -1;
@@ -105,7 +112,10 @@ int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type_t type, const c
 
 int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type_t type) {
     pa_autoload_entry *e;
-    assert(c && name && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE));
+
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE);
 
     if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type)
         return -1;
@@ -116,7 +126,9 @@ int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type_t ty
 
 int pa_autoload_remove_by_index(pa_core *c, uint32_t idx) {
     pa_autoload_entry *e;
-    assert(c && idx != PA_IDXSET_INVALID);
+
+    pa_assert(c);
+    pa_assert(idx != PA_IDXSET_INVALID);
 
     if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, idx)))
         return -1;
@@ -128,7 +140,9 @@ int pa_autoload_remove_by_index(pa_core *c, uint32_t idx) {
 void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type_t type) {
     pa_autoload_entry *e;
     pa_module *m;
-    assert(c && name);
+
+    pa_assert(c);
+    pa_assert(name);
 
     if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || (e->type != type))
         return;
@@ -153,6 +167,7 @@ static void free_func(void *p, PA_GCC_UNUSED void *userdata) {
 }
 
 void pa_autoload_free(pa_core *c) {
+
     if (c->autoload_hashmap) {
         pa_hashmap_free(c->autoload_hashmap, free_func, NULL);
         c->autoload_hashmap = NULL;
@@ -166,7 +181,9 @@ void pa_autoload_free(pa_core *c) {
 
 const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type_t type) {
     pa_autoload_entry *e;
-    assert(c && name);
+
+    pa_core_assert_ref(c);
+    pa_assert(name);
 
     if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type)
         return NULL;
@@ -176,7 +193,9 @@ const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa
 
 const pa_autoload_entry* pa_autoload_get_by_index(pa_core *c, uint32_t idx) {
     pa_autoload_entry *e;
-    assert(c && idx != PA_IDXSET_INVALID);
+
+    pa_core_assert_ref(c);
+    pa_assert(idx != PA_IDXSET_INVALID);
 
     if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, idx)))
         return NULL;
index 855ed5671c854497617102c581eb087157b4e59d..fae54810a1662be305564ea92353ddc2e1fbf75d 100644 (file)
   USA.
 ***/
 
-#include <assert.h>
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
 
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "avahi-wrap.h"
 
@@ -61,9 +64,9 @@ static pa_io_event_flags_t translate_io_flags(AvahiWatchEvent e) {
 static void watch_callback(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
     AvahiWatch *w = userdata;
 
-    assert(a);
-    assert(e);
-    assert(w);
+    pa_assert(a);
+    pa_assert(e);
+    pa_assert(w);
 
     w->current_event = translate_io_flags_back(events);
     w->callback(w, fd, w->current_event, w->userdata);
@@ -74,12 +77,10 @@ static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event
     pa_avahi_poll *p;
     AvahiWatch *w;
 
-    assert(api);
-    assert(fd >= 0);
-    assert(callback);
-
-    p = api->userdata;
-    assert(p);
+    pa_assert(api);
+    pa_assert(fd >= 0);
+    pa_assert(callback);
+    pa_assert_se(p = api->userdata);
 
     w = pa_xnew(AvahiWatch, 1);
     w->avahi_poll = p;
@@ -92,19 +93,19 @@ static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event
 }
 
 static void watch_update(AvahiWatch *w, AvahiWatchEvent event) {
-    assert(w);
+    pa_assert(w);
 
     w->avahi_poll->mainloop->io_enable(w->io_event, translate_io_flags(event));
 }
 
 static AvahiWatchEvent watch_get_events(AvahiWatch *w) {
-    assert(w);
+    pa_assert(w);
 
     return w->current_event;
 }
 
 static void watch_free(AvahiWatch *w) {
-    assert(w);
+    pa_assert(w);
 
     w->avahi_poll->mainloop->io_free(w->io_event);
     pa_xfree(w);
@@ -120,9 +121,9 @@ struct AvahiTimeout {
 static void timeout_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) {
     AvahiTimeout *t = userdata;
 
-    assert(a);
-    assert(e);
-    assert(t);
+    pa_assert(a);
+    pa_assert(e);
+    pa_assert(t);
 
     t->callback(t, t->userdata);
 }
@@ -131,11 +132,9 @@ static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv,
     pa_avahi_poll *p;
     AvahiTimeout *t;
 
-    assert(api);
-    assert(callback);
-
-    p = api->userdata;
-    assert(p);
+    pa_assert(api);
+    pa_assert(callback);
+    pa_assert_se(p = api->userdata);
 
     t = pa_xnew(AvahiTimeout, 1);
     t->avahi_poll = p;
@@ -148,7 +147,7 @@ static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv,
 }
 
 static void timeout_update(AvahiTimeout *t, const struct timeval *tv) {
-    assert(t);
+    pa_assert(t);
 
     if (t->time_event && tv)
         t->avahi_poll->mainloop->time_restart(t->time_event, tv);
@@ -161,7 +160,7 @@ static void timeout_update(AvahiTimeout *t, const struct timeval *tv) {
 }
 
 static void timeout_free(AvahiTimeout *t) {
-    assert(t);
+    pa_assert(t);
 
     if (t->time_event)
         t->avahi_poll->mainloop->time_free(t->time_event);
@@ -171,7 +170,7 @@ static void timeout_free(AvahiTimeout *t) {
 AvahiPoll* pa_avahi_poll_new(pa_mainloop_api *m) {
     pa_avahi_poll *p;
 
-    assert(m);
+    pa_assert(m);
 
     p = pa_xnew(pa_avahi_poll, 1);
 
@@ -190,9 +189,8 @@ AvahiPoll* pa_avahi_poll_new(pa_mainloop_api *m) {
 
 void pa_avahi_poll_free(AvahiPoll *api) {
     pa_avahi_poll *p;
-    assert(api);
-    p = api->userdata;
-    assert(p);
+    pa_assert(api);
+    pa_assert_se(p = api->userdata);
 
     pa_xfree(p);
 }
index 6989069d365369ea9487a8e4f9eae5768db95df7..539fd34ddd860f71522f15f4dedfe1a3feed37db 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
@@ -95,6 +94,7 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb
 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail);
 static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail);
 static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail);
+static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail);
 static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail);
 static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail);
 static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail);
@@ -114,6 +114,9 @@ static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf
 static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail);
 static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail);
 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail);
+static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail);
+static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail);
+static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail);
 
 /* A method table for all available commands */
 
@@ -130,13 +133,14 @@ static const struct command commands[] = {
     { "info",                    pa_cli_command_info,               "Show comprehensive status",    1 },
     { "ls",                      pa_cli_command_info,               NULL,                           1 },
     { "list",                    pa_cli_command_info,               NULL,                           1 },
-    { "load-module",             pa_cli_command_load,               "Load a module (args: name, arguments)",                     3},
-    { "unload-module",           pa_cli_command_unload,             "Unload a module (args: index)",                             2},
-    { "set-sink-volume",         pa_cli_command_sink_volume,        "Set the volume of a sink (args: index|name, volume)",             3},
-    { "set-sink-input-volume",   pa_cli_command_sink_input_volume,  "Set the volume of a sink input (args: index|name, volume)", 3},
+    { "load-module",             pa_cli_command_load,               "Load a module (args: name, arguments)", 3},
+    { "unload-module",           pa_cli_command_unload,             "Unload a module (args: index)", 2},
+    { "set-sink-volume",         pa_cli_command_sink_volume,        "Set the volume of a sink (args: index|name, volume)", 3},
+    { "set-sink-input-volume",   pa_cli_command_sink_input_volume,  "Set the volume of a sink input (args: index, volume)", 3},
     { "set-source-volume",       pa_cli_command_source_volume,      "Set the volume of a source (args: index|name, volume)", 3},
-    { "set-sink-mute",           pa_cli_command_sink_mute,          "Set the mute switch of a sink (args: index|name, mute)", 3},
-    { "set-source-mute",         pa_cli_command_source_mute,        "Set the mute switch of a source (args: index|name, mute)", 3},
+    { "set-sink-mute",           pa_cli_command_sink_mute,          "Set the mute switch of a sink (args: index|name, bool)", 3},
+    { "set-sink-input-mute",     pa_cli_command_sink_input_mute,    "Set the mute switch of a sink input (args: index, bool)", 3},
+    { "set-source-mute",         pa_cli_command_source_mute,        "Set the mute switch of a source (args: index|name, bool)", 3},
     { "set-default-sink",        pa_cli_command_sink_default,       "Set the default sink (args: index|name)", 2},
     { "set-default-source",      pa_cli_command_source_default,     "Set the default source (args: index|name)", 2},
     { "kill-client",             pa_cli_command_kill_client,        "Kill a client (args: index)", 2},
@@ -159,6 +163,9 @@ static const struct command commands[] = {
     { "move-sink-input",         pa_cli_command_move_sink_input,    "Move sink input to another sink (args: index, sink)", 3},
     { "move-source-output",      pa_cli_command_move_source_output, "Move source output to another source (args: index, source)", 3},
     { "vacuum",                  pa_cli_command_vacuum,             NULL, 1},
+    { "suspend-sink",            pa_cli_command_suspend_sink,       "Suspend sink (args: index|name, bool)", 3},
+    { "suspend-source",          pa_cli_command_suspend_source,     "Suspend source (args: index|name, bool)", 3},
+    { "suspend",                 pa_cli_command_suspend,            "Suspend all sinks and all sources (args: bool)", 2},
     { NULL, NULL, NULL, 0 }
 };
 
@@ -174,15 +181,23 @@ static uint32_t parse_index(const char *n) {
     return idx;
 }
 
-static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, PA_GCC_UNUSED pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
-    assert(c && c->mainloop && t);
+static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
     c->mainloop->quit(c->mainloop, 0);
     return 0;
 }
 
-static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const struct command*command;
-    assert(c && t && buf);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     pa_strbuf_puts(buf, "Available commands:\n");
 
@@ -192,67 +207,91 @@ static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
     return 0;
 }
 
-static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     char *s;
-    assert(c && t);
-    s = pa_module_list_to_string(c);
-    assert(s);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
+    pa_assert_se(s = pa_module_list_to_string(c));
     pa_strbuf_puts(buf, s);
     pa_xfree(s);
     return 0;
 }
 
-static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     char *s;
-    assert(c && t);
-    s = pa_client_list_to_string(c);
-    assert(s);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
+    pa_assert_se(s = pa_client_list_to_string(c));
     pa_strbuf_puts(buf, s);
     pa_xfree(s);
     return 0;
 }
 
-static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     char *s;
-    assert(c && t);
-    s = pa_sink_list_to_string(c);
-    assert(s);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
+    pa_assert_se(s = pa_sink_list_to_string(c));
     pa_strbuf_puts(buf, s);
     pa_xfree(s);
     return 0;
 }
 
-static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     char *s;
-    assert(c && t);
-    s = pa_source_list_to_string(c);
-    assert(s);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
+    pa_assert_se(s = pa_source_list_to_string(c));
     pa_strbuf_puts(buf, s);
     pa_xfree(s);
     return 0;
 }
 
-static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     char *s;
-    assert(c && t);
-    s = pa_sink_input_list_to_string(c);
-    assert(s);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
+    pa_assert_se(s = pa_sink_input_list_to_string(c));
     pa_strbuf_puts(buf, s);
     pa_xfree(s);
     return 0;
 }
 
-static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     char *s;
-    assert(c && t);
-    s = pa_source_output_list_to_string(c);
-    assert(s);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
+    pa_assert_se(s = pa_source_output_list_to_string(c));
     pa_strbuf_puts(buf, s);
     pa_xfree(s);
     return 0;
 }
 
-static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     char s[256];
     const pa_mempool_stat *stat;
     unsigned k;
@@ -267,8 +306,10 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
         [PA_MEMBLOCK_IMPORTED] = "IMPORTED",
     };
 
-    assert(c);
-    assert(t);
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     stat = pa_mempool_get_stat(c->mempool);
 
@@ -312,7 +353,11 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
 }
 
 static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
-    assert(c && t);
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
     pa_cli_command_stat(c, t, buf, fail);
     pa_cli_command_modules(c, t, buf, fail);
     pa_cli_command_sinks(c, t, buf, fail);
@@ -325,10 +370,14 @@ static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int
     return 0;
 }
 
-static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     pa_module *m;
     const char *name;
-    assert(c && t);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(name = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify the module name and optionally arguments.\n");
@@ -343,12 +392,16 @@ static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
     return 0;
 }
 
-static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     pa_module *m;
     uint32_t idx;
     const char *i;
     char *e;
-    assert(c && t);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(i = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify the module index.\n");
@@ -365,12 +418,17 @@ static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA
     return 0;
 }
 
-static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *n, *v;
     pa_sink *sink;
     uint32_t volume;
     pa_cvolume cvolume;
 
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
     if (!(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
         return -1;
@@ -392,17 +450,22 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
     }
 
     pa_cvolume_set(&cvolume, sink->sample_spec.channels, volume);
-    pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &cvolume);
+    pa_sink_set_volume(sink, &cvolume);
     return 0;
 }
 
-static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *n, *v;
     pa_sink_input *si;
     pa_volume_t volume;
     pa_cvolume cvolume;
     uint32_t idx;
 
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
     if (!(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
         return -1;
@@ -433,12 +496,17 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb
     return 0;
 }
 
-static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *n, *v;
     pa_source *source;
     uint32_t volume;
     pa_cvolume cvolume;
 
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
     if (!(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
         return -1;
@@ -460,15 +528,20 @@ static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *
     }
 
     pa_cvolume_set(&cvolume, source->sample_spec.channels, volume);
-    pa_source_set_volume(source, PA_MIXER_HARDWARE, &cvolume);
+    pa_source_set_volume(source, &cvolume);
     return 0;
 }
 
-static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *n, *m;
     pa_sink *sink;
     int mute;
 
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
     if (!(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
         return -1;
@@ -489,15 +562,20 @@ static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf,
         return -1;
     }
 
-    pa_sink_set_mute(sink, PA_MIXER_HARDWARE, mute);
+    pa_sink_set_mute(sink, mute);
     return 0;
 }
 
-static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *n, *m;
     pa_source *source;
     int mute;
 
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
     if (!(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
         return -1;
@@ -518,13 +596,57 @@ static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
         return -1;
     }
 
-    pa_source_set_mute(source, PA_MIXER_HARDWARE, mute);
+    pa_source_set_mute(source, mute);
     return 0;
 }
 
-static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
+    const char *n, *v;
+    pa_sink_input *si;
+    uint32_t idx;
+    int mute;
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
+    if (!(n = pa_tokenizer_get(t, 1))) {
+        pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
+        return -1;
+    }
+
+    if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
+        pa_strbuf_puts(buf, "Failed to parse index.\n");
+        return -1;
+    }
+
+    if (!(v = pa_tokenizer_get(t, 2))) {
+        pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n");
+        return -1;
+    }
+
+    if (pa_atoi(v, &mute) < 0) {
+        pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
+        return -1;
+    }
+
+    if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
+        pa_strbuf_puts(buf, "No sink input found with this index.\n");
+        return -1;
+    }
+
+    pa_sink_input_set_mute(si, mute);
+    return 0;
+}
+
+static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *n;
-    assert(c && t);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
@@ -535,9 +657,13 @@ static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *b
     return 0;
 }
 
-static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *n;
-    assert(c && t);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
@@ -548,11 +674,15 @@ static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf
     return 0;
 }
 
-static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *n;
     pa_client *client;
     uint32_t idx;
-    assert(c && t);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a client by its index.\n");
@@ -573,11 +703,15 @@ static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
     return 0;
 }
 
-static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *n;
     pa_sink_input *sink_input;
     uint32_t idx;
-    assert(c && t);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
@@ -598,11 +732,15 @@ static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf
     return 0;
 }
 
-static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *n;
     pa_source_output *source_output;
     uint32_t idx;
-    assert(c && t);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
@@ -623,20 +761,29 @@ static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_str
     return 0;
 }
 
-static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     char *s;
-    assert(c && t);
-    s = pa_scache_list_to_string(c);
-    assert(s);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
+    pa_assert_se(s = pa_scache_list_to_string(c));
     pa_strbuf_puts(buf, s);
     pa_xfree(s);
+
     return 0;
 }
 
 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *n, *sink_name;
     pa_sink *sink;
-    assert(c && t && buf && fail);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(n = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
         pa_strbuf_puts(buf, "You need to specify a sample name and a sink name.\n");
@@ -658,7 +805,11 @@ static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
 
 static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *n;
-    assert(c && t && buf && fail);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a sample name.\n");
@@ -676,7 +827,11 @@ static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *
 static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *fname, *n;
     int r;
-    assert(c && t && buf && fail);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(fname = pa_tokenizer_get(t, 2)) || !(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a file name and a sample name.\n");
@@ -696,7 +851,11 @@ static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
 
 static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *pname;
-    assert(c && t && buf && fail);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(pname = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a path name.\n");
@@ -714,7 +873,11 @@ static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf
 static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *fname, *sink_name;
     pa_sink *sink;
-    assert(c && t && buf && fail);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(fname = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
         pa_strbuf_puts(buf, "You need to specify a file name and a sink name.\n");
@@ -732,7 +895,11 @@ static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf,
 
 static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *a, *b;
-    assert(c && t && buf && fail);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(a = pa_tokenizer_get(t, 1)) || !(b = pa_tokenizer_get(t, 2))) {
         pa_strbuf_puts(buf, "You need to specify a device name, a filename or a module name and optionally module arguments\n");
@@ -746,7 +913,11 @@ static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *b
 
 static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *name;
-    assert(c && t && buf && fail);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     if (!(name = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a device name\n");
@@ -761,25 +932,36 @@ static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf
     return 0;
 }
 
-static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     char *s;
-    assert(c && t);
-    s = pa_autoload_list_to_string(c);
-    assert(s);
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
+    pa_assert_se(s = pa_autoload_list_to_string(c));
     pa_strbuf_puts(buf, s);
     pa_xfree(s);
+
     return 0;
 }
 
-static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
-    assert(c && t);
+static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
     pa_property_dump(c, buf);
     return 0;
 }
 
 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
-    assert(c);
-    assert(t);
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     pa_mempool_vacuum(c->mempool);
 
@@ -792,6 +974,11 @@ static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf
     pa_sink *sink;
     uint32_t idx;
 
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
     if (!(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
         return -1;
@@ -830,6 +1017,11 @@ static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_str
     pa_source *source;
     uint32_t idx;
 
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
     if (!(n = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
         return -1;
@@ -862,7 +1054,105 @@ static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_str
     return 0;
 }
 
-static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
+    const char *n, *m;
+    pa_sink *sink;
+    int suspend;
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
+    if (!(n = pa_tokenizer_get(t, 1))) {
+        pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
+        return -1;
+    }
+
+    if (!(m = pa_tokenizer_get(t, 2))) {
+        pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
+        return -1;
+    }
+
+    if (pa_atoi(m, &suspend) < 0) {
+        pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
+        return -1;
+    }
+
+    if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK, 1))) {
+        pa_strbuf_puts(buf, "No sink found by this name or index.\n");
+        return -1;
+    }
+
+    pa_sink_suspend(sink, suspend);
+    return 0;
+}
+
+static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
+    const char *n, *m;
+    pa_source *source;
+    int suspend;
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
+    if (!(n = pa_tokenizer_get(t, 1))) {
+        pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
+        return -1;
+    }
+
+    if (!(m = pa_tokenizer_get(t, 2))) {
+        pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
+        return -1;
+    }
+
+    if (pa_atoi(m, &suspend) < 0) {
+        pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
+        return -1;
+    }
+
+    if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE, 1))) {
+        pa_strbuf_puts(buf, "No source found by this name or index.\n");
+        return -1;
+    }
+
+    pa_source_suspend(source, suspend);
+    return 0;
+}
+
+static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
+    const char *m;
+    int suspend;
+    int ret;
+
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
+
+    if (!(m = pa_tokenizer_get(t, 1))) {
+        pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
+        return -1;
+    }
+
+    if (pa_atoi(m, &suspend) < 0) {
+        pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
+        return -1;
+    }
+
+    ret = - (pa_sink_suspend_all(c, suspend) < 0);
+    if (pa_source_suspend_all(c, suspend) < 0)
+        ret = -1;
+
+    if (ret < 0)
+        pa_strbuf_puts(buf, "Failed to resume/suspend all sinks/sources.\n");
+
+    return 0;
+}
+
+static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     pa_module *m;
     pa_sink *sink;
     pa_source *source;
@@ -874,7 +1164,10 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
     void *i;
     pa_autoload_entry *a;
 
-    assert(c && t);
+    pa_core_assert_ref(c);
+    pa_assert(t);
+    pa_assert(buf);
+    pa_assert(fail);
 
     time(&now);
 
@@ -884,7 +1177,6 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
     pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
 #endif
 
-
     for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) {
         if (m->auto_unload)
             continue;
@@ -900,7 +1192,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
     nl = 0;
 
     for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) {
-        if (sink->owner && sink->owner->auto_unload)
+        if (sink->module && sink->module->auto_unload)
             continue;
 
         if (!nl) {
@@ -908,12 +1200,12 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
             nl = 1;
         }
 
-        pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink, PA_MIXER_HARDWARE)));
-        pa_strbuf_printf(buf, "set-sink-mute %s %d\n", sink->name, pa_sink_get_mute(sink, PA_MIXER_HARDWARE));
+        pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink)));
+        pa_strbuf_printf(buf, "set-sink-mute %s %d\n", sink->name, pa_sink_get_mute(sink));
     }
 
     for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) {
-        if (source->owner && source->owner->auto_unload)
+        if (source->module && source->module->auto_unload)
             continue;
 
         if (!nl) {
@@ -921,8 +1213,8 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
             nl = 1;
         }
 
-        pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_avg(pa_source_get_volume(source, PA_MIXER_HARDWARE)));
-        pa_strbuf_printf(buf, "set-source-mute %s %d\n", source->name, pa_source_get_mute(source, PA_MIXER_HARDWARE));
+        pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_avg(pa_source_get_volume(source)));
+        pa_strbuf_printf(buf, "set-source-mute %s %d\n", source->name, pa_source_get_mute(source));
     }
 
 
@@ -972,6 +1264,10 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
 int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, int *fail, int *ifstate) {
     const char *cs;
 
+    pa_assert(c);
+    pa_assert(s);
+    pa_assert(buf);
+
     cs = s+strspn(s, whitespace);
 
     if (*cs == '#' || !*cs)
@@ -1006,9 +1302,9 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b
 
             if (l == sizeof(META_INCLUDE)-1 && !strncmp(cs, META_INCLUDE, l)) {
                 const char *filename = cs+l+strspn(cs+l, whitespace);
-
                 if (pa_cli_command_execute_file(c, filename, buf, fail) < 0)
-                    if (*fail) return -1;
+                    if (*fail)
+                        return -1;
             } else if (l == sizeof(META_IFEXISTS)-1 && !strncmp(cs, META_IFEXISTS, l)) {
                 if (!ifstate) {
                     pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
@@ -1020,6 +1316,7 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b
                     const char *filename = cs+l+strspn(cs+l, whitespace);
 
                     *ifstate = access(filename, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
+                    pa_log_debug("Checking for existance of '%s': %s", filename, *ifstate == IFSTATE_TRUE ? "success" : "failure");
                 }
             } else {
                 pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs);
@@ -1034,14 +1331,13 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b
         if (ifstate && *ifstate == IFSTATE_FALSE)
              return 0;
 
-
         l = strcspn(cs, whitespace);
 
         for (command = commands; command->name; command++)
             if (strlen(command->name) == l && !strncmp(cs, command->name, l)) {
                 int ret;
                 pa_tokenizer *t = pa_tokenizer_new(cs, command->args);
-                assert(t);
+                pa_assert(t);
                 ret = command->proc(c, t, buf, fail);
                 pa_tokenizer_free(t);
                 unknown = 0;
@@ -1072,9 +1368,9 @@ int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, int
     int ifstate = IFSTATE_NONE;
     int ret = -1;
 
-    assert(c);
-    assert(fn);
-    assert(buf);
+    pa_assert(c);
+    pa_assert(fn);
+    pa_assert(buf);
 
     if (!(f = fopen(fn, "r"))) {
         pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, pa_cstrerror(errno));
@@ -1104,9 +1400,9 @@ int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail)
     const char *p;
     int ifstate = IFSTATE_NONE;
 
-    assert(c);
-    assert(s);
-    assert(buf);
+    pa_assert(c);
+    pa_assert(s);
+    pa_assert(buf);
 
     p = s;
     while (*p) {
@@ -1125,3 +1421,4 @@ int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail)
 
     return 0;
 }
+
index 413f93340c5b688371a29229caa386466d0cdec1..6683e6973388e3460371674a26a1b2c18ac9779a 100644 (file)
@@ -25,7 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <string.h>
 
 #include <pulse/volume.h>
@@ -41,6 +40,7 @@
 #include <pulsecore/sample-util.h>
 #include <pulsecore/core-scache.h>
 #include <pulsecore/autoload.h>
+#include <pulsecore/macro.h>
 
 #include "cli-text.h"
 
@@ -48,10 +48,9 @@ char *pa_module_list_to_string(pa_core *c) {
     pa_strbuf *s;
     pa_module *m;
     uint32_t idx = PA_IDXSET_INVALID;
-    assert(c);
+    pa_assert(c);
 
     s = pa_strbuf_new();
-    assert(s);
 
     pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_size(c->modules));
 
@@ -72,10 +71,9 @@ char *pa_client_list_to_string(pa_core *c) {
     pa_strbuf *s;
     pa_client *client;
     uint32_t idx = PA_IDXSET_INVALID;
-    assert(c);
+    pa_assert(c);
 
     s = pa_strbuf_new();
-    assert(s);
 
     pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_size(c->clients));
 
@@ -93,10 +91,15 @@ char *pa_sink_list_to_string(pa_core *c) {
     pa_strbuf *s;
     pa_sink *sink;
     uint32_t idx = PA_IDXSET_INVALID;
-    assert(c);
+    static const char* const state_table[] = {
+        [PA_SINK_RUNNING] = "RUNNING",
+        [PA_SINK_SUSPENDED] = "SUSPENDED",
+        [PA_SINK_IDLE] = "IDLE",
+        [PA_SINK_UNLINKED] = "UNLINKED"
+    };
+    pa_assert(c);
 
     s = pa_strbuf_new();
-    assert(s);
 
     pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_size(c->sinks));
 
@@ -108,22 +111,35 @@ char *pa_sink_list_to_string(pa_core *c) {
             "  %c index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
+            "\tflags: %s%s%s\n"
+            "\tstate: %s\n"
             "\tvolume: <%s>\n"
+            "\tmute: <%i>\n"
             "\tlatency: <%0.0f usec>\n"
-            "\tmonitor_source: <%u>\n"
+            "\tmonitor source: <%u>\n"
             "\tsample spec: <%s>\n"
-            "\tchannel map: <%s>\n",
+            "\tchannel map: <%s>\n"
+            "\tused by: <%u>\n"
+            "\tlinked by: <%u>\n",
             c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ',
-            sink->index, sink->name,
+            sink->index,
+            sink->name,
             sink->driver,
-            pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, PA_MIXER_HARDWARE)),
+            sink->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
+            sink->flags & PA_SINK_LATENCY ? "LATENCY " : "",
+            sink->flags & PA_SINK_HARDWARE ? "HARDWARE " : "",
+            state_table[pa_sink_get_state(sink)],
+            pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink)),
+            !!pa_sink_get_mute(sink),
             (double) pa_sink_get_latency(sink),
             sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
             pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec),
-            pa_channel_map_snprint(cm, sizeof(cm), &sink->channel_map));
+            pa_channel_map_snprint(cm, sizeof(cm), &sink->channel_map),
+            pa_sink_used_by(sink),
+            pa_sink_linked_by(sink));
 
-        if (sink->owner)
-            pa_strbuf_printf(s, "\towner module: <%u>\n", sink->owner->index);
+        if (sink->module)
+            pa_strbuf_printf(s, "\tmodule: <%u>\n", sink->module->index);
         if (sink->description)
             pa_strbuf_printf(s, "\tdescription: <%s>\n", sink->description);
     }
@@ -135,15 +151,20 @@ char *pa_source_list_to_string(pa_core *c) {
     pa_strbuf *s;
     pa_source *source;
     uint32_t idx = PA_IDXSET_INVALID;
-    assert(c);
+    static const char* const state_table[] = {
+        [PA_SOURCE_RUNNING] = "RUNNING",
+        [PA_SOURCE_SUSPENDED] = "SUSPENDED",
+        [PA_SOURCE_IDLE] = "IDLE",
+        [PA_SOURCE_UNLINKED] = "UNLINKED"
+    };
+    pa_assert(c);
 
     s = pa_strbuf_new();
-    assert(s);
 
     pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_size(c->sources));
 
     for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) {
-        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX];
 
 
         pa_strbuf_printf(
@@ -151,21 +172,35 @@ char *pa_source_list_to_string(pa_core *c) {
             "  %c index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
+            "\tflags: %s%s%s\n"
+            "\tstate: %s\n"
+            "\tvolume: <%s>\n"
+            "\tmute: <%u>\n"
             "\tlatency: <%0.0f usec>\n"
             "\tsample spec: <%s>\n"
-            "\tchannel map: <%s>\n",
+            "\tchannel map: <%s>\n"
+            "\tused by: <%u>\n"
+            "\tlinked by: <%u>\n",
             c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ',
             source->index,
             source->name,
             source->driver,
+            source->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
+            source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
+            source->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "",
+            state_table[pa_source_get_state(source)],
+            pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source)),
+            !!pa_source_get_mute(source),
             (double) pa_source_get_latency(source),
             pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec),
-            pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map));
+            pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map),
+            pa_source_used_by(source),
+            pa_source_linked_by(source));
 
         if (source->monitor_of)
             pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->index);
-        if (source->owner)
-            pa_strbuf_printf(s, "\towner module: <%u>\n", source->owner->index);
+        if (source->module)
+            pa_strbuf_printf(s, "\tmodule: <%u>\n", source->module->index);
         if (source->description)
             pa_strbuf_printf(s, "\tdescription: <%s>\n", source->description);
     }
@@ -179,37 +214,41 @@ char *pa_source_output_list_to_string(pa_core *c) {
     pa_source_output *o;
     uint32_t idx = PA_IDXSET_INVALID;
     static const char* const state_table[] = {
-        "RUNNING",
-        "CORKED",
-        "DISCONNECTED"
+        [PA_SOURCE_OUTPUT_RUNNING] = "RUNNING",
+        [PA_SOURCE_OUTPUT_CORKED] = "CORKED",
+        [PA_SOURCE_OUTPUT_UNLINKED] = "UNLINKED"
     };
-    assert(c);
+    pa_assert(c);
 
     s = pa_strbuf_new();
-    assert(s);
 
     pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_size(c->source_outputs));
 
     for (o = pa_idxset_first(c->source_outputs, &idx); o; o = pa_idxset_next(c->source_outputs, &idx)) {
         char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
 
-        assert(o->source);
+        pa_assert(o->source);
 
         pa_strbuf_printf(
             s,
             "    index: %u\n"
             "\tname: '%s'\n"
             "\tdriver: <%s>\n"
+            "\tflags: %s%s\n"
             "\tstate: %s\n"
             "\tsource: <%u> '%s'\n"
+            "\tlatency: <%0.0f usec>\n"
             "\tsample spec: <%s>\n"
             "\tchannel map: <%s>\n"
             "\tresample method: %s\n",
             o->index,
             o->name,
             o->driver,
-            state_table[o->state],
+            o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "",
+            o->flags & PA_SOURCE_OUTPUT_DONT_MOVE ? "DONT_MOVE " : "",
+            state_table[pa_source_output_get_state(o)],
             o->source->index, o->source->name,
+            (double) pa_source_output_get_latency(o),
             pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec),
             pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map),
             pa_resample_method_to_string(pa_source_output_get_resample_method(o)));
@@ -227,30 +266,32 @@ char *pa_sink_input_list_to_string(pa_core *c) {
     pa_sink_input *i;
     uint32_t idx = PA_IDXSET_INVALID;
     static const char* const state_table[] = {
-        "RUNNING",
-        "CORKED",
-        "DISCONNECTED"
+        [PA_SINK_INPUT_RUNNING] = "RUNNING",
+        [PA_SINK_INPUT_DRAINED] = "DRAINED",
+        [PA_SINK_INPUT_CORKED] = "CORKED",
+        [PA_SINK_INPUT_UNLINKED] = "UNLINKED"
     };
 
-    assert(c);
+    pa_assert(c);
     s = pa_strbuf_new();
-    assert(s);
 
     pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_size(c->sink_inputs));
 
     for (i = pa_idxset_first(c->sink_inputs, &idx); i; i = pa_idxset_next(c->sink_inputs, &idx)) {
         char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
 
-        assert(i->sink);
+        pa_assert(i->sink);
 
         pa_strbuf_printf(
             s,
             "    index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
+            "\tflags: %s%s\n"
             "\tstate: %s\n"
             "\tsink: <%u> '%s'\n"
             "\tvolume: <%s>\n"
+            "\tmute: <%i>\n"
             "\tlatency: <%0.0f usec>\n"
             "\tsample spec: <%s>\n"
             "\tchannel map: <%s>\n"
@@ -258,16 +299,19 @@ char *pa_sink_input_list_to_string(pa_core *c) {
             i->index,
             i->name,
             i->driver,
-            state_table[i->state],
+            i->flags & PA_SINK_INPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "",
+            i->flags & PA_SINK_INPUT_DONT_MOVE ? "DONT_MOVE " : "",
+            state_table[pa_sink_input_get_state(i)],
             i->sink->index, i->sink->name,
             pa_cvolume_snprint(cv, sizeof(cv), pa_sink_input_get_volume(i)),
+            !!pa_sink_input_get_mute(i),
             (double) pa_sink_input_get_latency(i),
             pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec),
             pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
             pa_resample_method_to_string(pa_sink_input_get_resample_method(i)));
 
         if (i->module)
-            pa_strbuf_printf(s, "\towner module: <%u>\n", i->module->index);
+            pa_strbuf_printf(s, "\tmodule: <%u>\n", i->module->index);
         if (i->client)
             pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", i->client->index, i->client->name);
     }
@@ -277,10 +321,9 @@ char *pa_sink_input_list_to_string(pa_core *c) {
 
 char *pa_scache_list_to_string(pa_core *c) {
     pa_strbuf *s;
-    assert(c);
+    pa_assert(c);
 
     s = pa_strbuf_new();
-    assert(s);
 
     pa_strbuf_printf(s, "%u cache entries available.\n", c->scache ? pa_idxset_size(c->scache) : 0);
 
@@ -326,10 +369,9 @@ char *pa_scache_list_to_string(pa_core *c) {
 
 char *pa_autoload_list_to_string(pa_core *c) {
     pa_strbuf *s;
-    assert(c);
+    pa_assert(c);
 
     s = pa_strbuf_new();
-    assert(s);
 
     pa_strbuf_printf(s, "%u autoload entries available.\n", c->autoload_hashmap ? pa_hashmap_size(c->autoload_hashmap) : 0);
 
index ee05d7f9520f96c42c5ecfe73f4e6fe8c913e68e..3f3c9cde7834b9448935dfabe6e71383e94c17cb 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 #include <stdlib.h>
 
 #include <pulse/xmalloc.h>
@@ -45,6 +44,7 @@
 #include <pulsecore/cli-text.h>
 #include <pulsecore/cli-command.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "cli.h"
 
@@ -68,19 +68,17 @@ static void client_kill(pa_client *c);
 pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) {
     char cname[256];
     pa_cli *c;
-    assert(io);
+    pa_assert(io);
 
-    c = pa_xmalloc(sizeof(pa_cli));
+    c = pa_xnew(pa_cli, 1);
     c->core = core;
-    c->line = pa_ioline_new(io);
-    assert(c->line);
+    pa_assert_se(c->line = pa_ioline_new(io));
 
     c->userdata = NULL;
     c->eof_callback = NULL;
 
     pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
-    c->client = pa_client_new(core, __FILE__, cname);
-    assert(c->client);
+    pa_assert_se(c->client = pa_client_new(core, __FILE__, cname));
     c->client->kill = client_kill;
     c->client->userdata = c;
     c->client->owner = m;
@@ -94,7 +92,8 @@ pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) {
 }
 
 void pa_cli_free(pa_cli *c) {
-    assert(c);
+    pa_assert(c);
+
     pa_ioline_close(c->line);
     pa_ioline_unref(c->line);
     pa_client_free(c->client);
@@ -103,8 +102,9 @@ void pa_cli_free(pa_cli *c) {
 
 static void client_kill(pa_client *client) {
     pa_cli *c;
-    assert(client && client->userdata);
-    c = client->userdata;
+
+    pa_assert(client);
+    pa_assert_se(c = client->userdata);
 
     pa_log_debug("CLI client killed.");
     if (c->defer_kill)
@@ -119,7 +119,9 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) {
     pa_strbuf *buf;
     pa_cli *c = userdata;
     char *p;
-    assert(line && c);
+
+    pa_assert(line);
+    pa_assert(c);
 
     if (!s) {
         pa_log_debug("CLI got EOF from user.");
@@ -129,8 +131,7 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) {
         return;
     }
 
-    buf = pa_strbuf_new();
-    assert(buf);
+    pa_assert_se(buf = pa_strbuf_new());
     c->defer_kill++;
     pa_cli_command_execute_line(c->core, s, buf, &c->fail);
     c->defer_kill--;
@@ -145,7 +146,8 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) {
 }
 
 void pa_cli_set_eof_callback(pa_cli *c, void (*cb)(pa_cli*c, void *userdata), void *userdata) {
-    assert(c);
+    pa_assert(c);
+
     c->eof_callback = cb;
     c->userdata = userdata;
 }
index 0d792bb45cb7778bd6daddce9e78a4ac14406f1c..319b8387d2e08ea9a1fbe54098d854349cf61384 100644 (file)
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
 
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "client.h"
 
 pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) {
     pa_client *c;
-    int r;
-    assert(core);
 
-    c = pa_xmalloc(sizeof(pa_client));
+    pa_core_assert_ref(core);
+
+    c = pa_xnew(pa_client, 1);
     c->name = pa_xstrdup(name);
     c->driver = pa_xstrdup(driver);
     c->owner = NULL;
@@ -52,10 +52,9 @@ pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) {
     c->kill = NULL;
     c->userdata = NULL;
 
-    r = pa_idxset_put(core->clients, c, &c->index);
-    assert(c->index != PA_IDXSET_INVALID && r >= 0);
+    pa_assert_se(pa_idxset_put(core->clients, c, &c->index) >= 0);
 
-    pa_log_info("created %u \"%s\"", c->index, c->name);
+    pa_log_info("Created %u \"%s\"", c->index, c->name);
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index);
 
     pa_core_check_quit(core);
@@ -64,13 +63,14 @@ pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) {
 }
 
 void pa_client_free(pa_client *c) {
-    assert(c && c->core);
+    pa_assert(c);
+    pa_assert(c->core);
 
     pa_idxset_remove_by_data(c->core->clients, c, NULL);
 
     pa_core_check_quit(c->core);
 
-    pa_log_info("freed %u \"%s\"", c->index, c->name);
+    pa_log_info("Freed %u \"%s\"", c->index, c->name);
     pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index);
     pa_xfree(c->name);
     pa_xfree(c->driver);
@@ -78,7 +78,8 @@ void pa_client_free(pa_client *c) {
 }
 
 void pa_client_kill(pa_client *c) {
-    assert(c);
+    pa_assert(c);
+
     if (!c->kill) {
         pa_log_warn("kill() operation not implemented for client %u", c->index);
         return;
@@ -88,9 +89,9 @@ void pa_client_kill(pa_client *c) {
 }
 
 void pa_client_set_name(pa_client *c, const char *name) {
-    assert(c);
+    pa_assert(c);
 
-    pa_log_info("client %u changed name from \"%s\" to \"%s\"", c->index, c->name, name);
+    pa_log_info("Client %u changed name from \"%s\" to \"%s\"", c->index, c->name, name);
 
     pa_xfree(c->name);
     c->name = pa_xstrdup(name);
index 12efbd2c43c14c9ab58ed7d5c08091eb23f460e5..0e0ba95a9a2e4326061a2b6d5a557e803c852ea4 100644 (file)
@@ -25,7 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 #include <errno.h>
@@ -35,6 +34,7 @@
 #include <pulsecore/core-error.h>
 #include <pulsecore/log.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
 
 #include "conf-parser.h"
 
 
 /* Run the user supplied parser for an assignment */
 static int next_assignment(const char *filename, unsigned line, const pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) {
-    assert(filename && t && lvalue && rvalue);
+    pa_assert(filename);
+    pa_assert(t);
+    pa_assert(lvalue);
+    pa_assert(rvalue);
 
     for (; t->parse; t++)
         if (!strcmp(lvalue, t->lvalue))
@@ -56,7 +59,7 @@ static int next_assignment(const char *filename, unsigned line, const pa_config_
 
 /* Returns non-zero when c is contained in s */
 static int in_string(char c, const char *s) {
-    assert(s);
+    pa_assert(s);
 
     for (; *s; s++)
         if (*s == c)
@@ -107,7 +110,9 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void
     int r = -1;
     unsigned line = 0;
     int do_close = !f;
-    assert(filename && t);
+
+    pa_assert(filename);
+    pa_assert(t);
 
     if (!f && !(f = fopen(filename, "r"))) {
         if (errno == ENOENT) {
@@ -115,7 +120,7 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void
             goto finish;
         }
 
-        pa_log_warn("WARNING: failed to open configuration file '%s': %s",
+        pa_log_warn("Failed to open configuration file '%s': %s",
             filename, pa_cstrerror(errno));
         goto finish;
     }
@@ -126,7 +131,7 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void
             if (feof(f))
                 break;
 
-            pa_log_warn("WARNING: failed to read configuration file '%s': %s",
+            pa_log_warn("Failed to read configuration file '%s': %s",
                 filename, pa_cstrerror(errno));
             goto finish;
         }
@@ -148,7 +153,11 @@ finish:
 int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
     int *i = data;
     int32_t k;
-    assert(filename && lvalue && rvalue && data);
+
+    pa_assert(filename);
+    pa_assert(lvalue);
+    pa_assert(rvalue);
+    pa_assert(data);
 
     if (pa_atoi(rvalue, &k) < 0) {
         pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
@@ -161,7 +170,11 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue,
 
 int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
     int *b = data, k;
-    assert(filename && lvalue && rvalue && data);
+
+    pa_assert(filename);
+    pa_assert(lvalue);
+    pa_assert(rvalue);
+    pa_assert(data);
 
     if ((k = pa_parse_boolean(rvalue)) < 0) {
         pa_log("[%s:%u] Failed to parse boolean value: %s", filename, line, rvalue);
@@ -175,7 +188,11 @@ int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue
 
 int pa_config_parse_string(const char *filename, PA_GCC_UNUSED unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
     char **s = data;
-    assert(filename && lvalue && rvalue && data);
+
+    pa_assert(filename);
+    pa_assert(lvalue);
+    pa_assert(rvalue);
+    pa_assert(data);
 
     pa_xfree(*s);
     *s = *rvalue ? pa_xstrdup(rvalue) : NULL;
index 10a3be428ddb0a5e0e510d86ee53b3fd31739985..4bc051375c59ee9954358424f0ece199f951cb69 100644 (file)
@@ -24,9 +24,6 @@
   USA.
 ***/
 
-typedef enum pa_mixer {
-    PA_MIXER_SOFTWARE,
-    PA_MIXER_HARDWARE
-} pa_mixer_t;
+/* FIXME: Remove this shit */
 
 #endif
index 044bea124039463fa1e924587be9257eaccd5d84..8a61e7264cdc559def8ac1369de5545423e100b6 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
-#ifdef HAVE_PTHREAD
-#include <pthread.h>
-#endif
-
-#ifdef HAVE_WINDOWS_H
-#include <windows.h>
-#endif
-
 #include <pulse/utf8.h>
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/core-util.h>
 #include <pulsecore/native-common.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/log.h>
 
 #include "core-error.h"
 
-#ifdef HAVE_PTHREAD
-
-static pthread_once_t cstrerror_once = PTHREAD_ONCE_INIT;
-static pthread_key_t tlsstr_key;
-
-static void inittls(void) {
-    int ret;
-
-    ret = pthread_key_create(&tlsstr_key, pa_xfree);
-    if (ret) {
-        fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", errno);
-        exit(-1);
-    }
-}
-
-#elif HAVE_WINDOWS_H
-
-static DWORD tlsstr_key = TLS_OUT_OF_INDEXES;
-static DWORD monitor_key = TLS_OUT_OF_INDEXES;
-
-static void inittls(void) {
-    HANDLE mutex;
-    char name[64];
-
-    sprintf(name, "pulse%d", (int)GetCurrentProcessId());
-
-    mutex = CreateMutex(NULL, FALSE, name);
-    if (!mutex) {
-        fprintf(stderr, __FILE__ ": CRITICAL: Unable to create named mutex (%d)\n", (int)GetLastError());
-        exit(-1);
-    }
-
-    WaitForSingleObject(mutex, INFINITE);
-
-    if (tlsstr_key == TLS_OUT_OF_INDEXES) {
-        tlsstr_key = TlsAlloc();
-        monitor_key = TlsAlloc();
-        if ((tlsstr_key == TLS_OUT_OF_INDEXES) || (monitor_key == TLS_OUT_OF_INDEXES)) {
-            fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", (int)GetLastError());
-            exit(-1);
-        }
-    }
-
-    ReleaseMutex(mutex);
-
-    CloseHandle(mutex);
-}
-
-/*
- * This is incredibly brain dead, but this is necessary when dealing with
- * the hell that is Win32.
- */
-struct monitor_data {
-    HANDLE thread;
-    void *data;
-};
-
-static DWORD WINAPI monitor_thread(LPVOID param) {
-    struct monitor_data *data;
-
-    data = (struct monitor_data*)param;
-    assert(data);
-
-    WaitForSingleObject(data->thread, INFINITE);
-
-    CloseHandle(data->thread);
-    pa_xfree(data->data);
-    pa_xfree(data);
-
-    return 0;
-}
-
-static void start_monitor(void) {
-    HANDLE thread;
-    struct monitor_data *data;
-
-    data = pa_xnew(struct monitor_data, 1);
-    assert(data);
-
-    DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
-        GetCurrentProcess(), &data->thread, 0, FALSE, DUPLICATE_SAME_ACCESS);
-
-    thread = CreateThread(NULL, 0, monitor_thread, data, 0, NULL);
-    assert(thread);
-
-    TlsSetValue(monitor_key, data);
-
-    CloseHandle(thread);
-}
-
-#else
-
-/* Unsafe, but we have no choice */
-static char *tlsstr;
-
-#endif
+PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
 
 const char* pa_cstrerror(int errnum) {
-    const char *origbuf;
-
-#ifdef HAVE_STRERROR_R
+    const char *original = NULL;
+    char *translated, *t;
     char errbuf[128];
-#endif
 
-#ifdef HAVE_PTHREAD
-    char *tlsstr;
+    if ((t = PA_STATIC_TLS_GET(cstrerror)))
+        pa_xfree(t);
 
-    pthread_once(&cstrerror_once, inittls);
-
-    tlsstr = pthread_getspecific(tlsstr_key);
-#elif defined(HAVE_WINDOWS_H)
-    char *tlsstr;
-    struct monitor_data *data;
-
-    inittls();
-
-    tlsstr = TlsGetValue(tlsstr_key);
-    if (!tlsstr)
-        start_monitor();
-    data = TlsGetValue(monitor_key);
-#endif
-
-    if (tlsstr)
-        pa_xfree(tlsstr);
-
-#ifdef HAVE_STRERROR_R
-
-#ifdef __GLIBC__
-    origbuf = strerror_r(errnum, errbuf, sizeof(errbuf));
-    if (origbuf == NULL)
-        origbuf = "";
-#else
+#if defined(HAVE_STRERROR_R) && defined(__GLIBC__)
+    original = strerror_r(errnum, errbuf, sizeof(errbuf));
+#elif defined(HAVE_STRERROR_R)
     if (strerror_r(errnum, errbuf, sizeof(errbuf)) == 0) {
-        origbuf = errbuf;
-        errbuf[sizeof(errbuf) - 1] = '\0';
-    } else
-        origbuf = "";
-#endif
-
+        errbuf[sizeof(errbuf) - 1] = 0;
+        original = errbuf;
+    }
 #else
     /* This might not be thread safe, but we hope for the best */
-    origbuf = strerror(errnum);
+    original = strerror(errnum);
 #endif
 
-    tlsstr = pa_locale_to_utf8(origbuf);
-    if (!tlsstr) {
-        fprintf(stderr, "Unable to convert, filtering\n");
-        tlsstr = pa_utf8_filter(origbuf);
+    if (!original) {
+        pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
+        original = errbuf;
     }
 
-#ifdef HAVE_PTHREAD
-    pthread_setspecific(tlsstr_key, tlsstr);
-#elif defined(HAVE_WINDOWS_H)
-    TlsSetValue(tlsstr_key, tlsstr);
-    data->data = tlsstr;
-#endif
+    if (!(translated = pa_locale_to_utf8(original))) {
+        pa_log_warn("Unable to convert error string to locale, filtering.");
+        translated = pa_utf8_filter(original);
+    }
+
+    PA_STATIC_TLS_SET(cstrerror, translated);
 
-    return tlsstr;
+    return translated;
 }
index cb2727845dff287e003bc42f74ef6ff8fd268165..732d90dd23e7d4e4c56d1e97ca6b3f754cce5b6a 100644 (file)
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -60,6 +59,7 @@
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
 #include <pulsecore/core-error.h>
+#include <pulsecore/macro.h>
 
 #include "core-scache.h"
 
 static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) {
     pa_core *c = userdata;
     struct timeval ntv;
-    assert(c && c->mainloop == m && c->scache_auto_unload_event == e);
+
+    pa_assert(c);
+    pa_assert(c->mainloop == m);
+    pa_assert(c->scache_auto_unload_event == e);
 
     pa_scache_unload_unused(c);
 
@@ -78,7 +81,8 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED
 }
 
 static void free_entry(pa_scache_entry *e) {
-    assert(e);
+    pa_assert(e);
+
     pa_namereg_unregister(e->core, e->name);
     pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_REMOVE, e->index);
     pa_xfree(e->name);
@@ -90,7 +94,9 @@ static void free_entry(pa_scache_entry *e) {
 
 static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
     pa_scache_entry *e;
-    assert(c && name);
+
+    pa_assert(c);
+    pa_assert(name);
 
     if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) {
         if (e->memchunk.memblock)
@@ -98,11 +104,11 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
 
         pa_xfree(e->filename);
 
-        assert(e->core == c);
+        pa_assert(e->core == c);
 
         pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index);
     } else {
-        e = pa_xmalloc(sizeof(pa_scache_entry));
+        e = pa_xnew(pa_scache_entry, 1);
 
         if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, 1)) {
             pa_xfree(e);
@@ -114,7 +120,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
 
         if (!c->scache) {
             c->scache = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
-            assert(c->scache);
+            pa_assert(c->scache);
         }
 
         pa_idxset_put(c->scache, e, &e->index);
@@ -139,7 +145,9 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
 int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map, const pa_memchunk *chunk, uint32_t *idx) {
     pa_scache_entry *e;
     char st[PA_SAMPLE_SPEC_SNPRINT_MAX];
-    assert(c && name);
+
+    pa_assert(c);
+    pa_assert(name);
 
     if (chunk && chunk->length > PA_SCACHE_ENTRY_SIZE_MAX)
         return -1;
@@ -164,9 +172,9 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c
     if (idx)
         *idx = e->index;
 
-    pa_log_debug("created sample \"%s\" (#%d), %d bytes with sample spec %s",
-        name, e->index, e->memchunk.length,
-        pa_sample_spec_snprint(st, sizeof(st), &e->sample_spec));
+    pa_log_debug("Created sample \"%s\" (#%d), %lu bytes with sample spec %s",
+                 name, e->index, (unsigned long) e->memchunk.length,
+                 pa_sample_spec_snprint(st, sizeof(st), &e->sample_spec));
 
     return 0;
 }
@@ -184,6 +192,10 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3
         filename = buf;
 #endif
 
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(filename);
+
     if (pa_sound_file_load(c->mempool, filename, &ss, &map, &chunk) < 0)
         return -1;
 
@@ -203,7 +215,9 @@ int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename,
         filename = buf;
 #endif
 
-    assert(c && name);
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(filename);
 
     if (!(e = scache_add_item(c, name)))
         return -1;
@@ -226,15 +240,17 @@ int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename,
 
 int pa_scache_remove_item(pa_core *c, const char *name) {
     pa_scache_entry *e;
-    assert(c && name);
+
+    pa_assert(c);
+    pa_assert(name);
 
     if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0)))
         return -1;
 
     if (pa_idxset_remove_by_data(c->scache, e, NULL) != e)
-        assert(0);
+        pa_assert(0);
 
-    pa_log_debug("removed sample \"%s\"", name);
+    pa_log_debug("Removed sample \"%s\"", name);
 
     free_entry(e);
 
@@ -243,12 +259,13 @@ int pa_scache_remove_item(pa_core *c, const char *name) {
 
 static void free_cb(void *p, PA_GCC_UNUSED void *userdata) {
     pa_scache_entry *e = p;
-    assert(e);
+    pa_assert(e);
+
     free_entry(e);
 }
 
 void pa_scache_free(pa_core *c) {
-    assert(c);
+    pa_assert(c);
 
     if (c->scache) {
         pa_idxset_free(c->scache, free_cb, NULL);
@@ -264,9 +281,9 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t
     char *t;
     pa_cvolume r;
 
-    assert(c);
-    assert(name);
-    assert(sink);
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(sink);
 
     if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1)))
         return -1;
@@ -284,7 +301,7 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t
     if (!e->memchunk.memblock)
         return -1;
 
-    pa_log_debug("playing sample \"%s\" on \"%s\"", name, sink->name);
+    pa_log_debug("Playing sample \"%s\" on \"%s\"", name, sink->name);
 
     t = pa_sprintf_malloc("sample:%s", name);
 
@@ -304,9 +321,23 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t
     return 0;
 }
 
+int pa_scache_play_item_by_name(pa_core *c, const char *name, const char*sink_name, pa_volume_t volume, int autoload) {
+    pa_sink *sink;
+
+    pa_assert(c);
+    pa_assert(name);
+
+    if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK, autoload)))
+        return -1;
+
+    return pa_scache_play_item(c, name, sink, volume);
+}
+
 const char * pa_scache_get_name_by_id(pa_core *c, uint32_t id) {
     pa_scache_entry *e;
-    assert(c && id != PA_IDXSET_INVALID);
+
+    pa_assert(c);
+    pa_assert(id != PA_IDXSET_INVALID);
 
     if (!c->scache || !(e = pa_idxset_get_by_index(c->scache, id)))
         return NULL;
@@ -316,7 +347,9 @@ const char * pa_scache_get_name_by_id(pa_core *c, uint32_t id) {
 
 uint32_t pa_scache_get_id_by_name(pa_core *c, const char *name) {
     pa_scache_entry *e;
-    assert(c && name);
+
+    pa_assert(c);
+    pa_assert(name);
 
     if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0)))
         return PA_IDXSET_INVALID;
@@ -327,7 +360,8 @@ uint32_t pa_scache_get_id_by_name(pa_core *c, const char *name) {
 uint32_t pa_scache_total_size(pa_core *c) {
     pa_scache_entry *e;
     uint32_t idx, sum = 0;
-    assert(c);
+
+    pa_assert(c);
 
     if (!c->scache || !pa_idxset_size(c->scache))
         return 0;
@@ -343,7 +377,8 @@ void pa_scache_unload_unused(pa_core *c) {
     pa_scache_entry *e;
     time_t now;
     uint32_t idx;
-    assert(c);
+
+    pa_assert(c);
 
     if (!c->scache || !pa_idxset_size(c->scache))
         return;
@@ -370,6 +405,9 @@ static void add_file(pa_core *c, const char *pathname) {
     struct stat st;
     const char *e;
 
+    pa_core_assert_ref(c);
+    pa_assert(pathname);
+
     e = pa_path_get_filename(pathname);
 
     if (stat(pathname, &st) < 0) {
@@ -385,7 +423,9 @@ static void add_file(pa_core *c, const char *pathname) {
 
 int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) {
     DIR *dir;
-    assert(c && pathname);
+
+    pa_core_assert_ref(c);
+    pa_assert(pathname);
 
     /* First try to open this as directory */
     if (!(dir = opendir(pathname))) {
@@ -415,7 +455,7 @@ int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) {
             if (e->d_name[0] == '.')
                 continue;
 
-            snprintf(p, sizeof(p), "%s/%s", pathname, e->d_name);
+            pa_snprintf(p, sizeof(p), "%s/%s", pathname, e->d_name);
             add_file(c, p);
         }
     }
index bbf13f156379a21cd8c4cf35ba44f1f6c44cced2..ab7ec0ef338d4f78dbb22b000b2c01326627b08f 100644 (file)
@@ -55,6 +55,7 @@ int pa_scache_add_directory_lazy(pa_core *c, const char *pathname);
 
 int pa_scache_remove_item(pa_core *c, const char *name);
 int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t volume);
+int pa_scache_play_item_by_name(pa_core *c, const char *name, const char*sink_name, pa_volume_t volume, int autoload);
 void pa_scache_free(pa_core *c);
 
 const char *pa_scache_get_name_by_id(pa_core *c, uint32_t id);
index 6608d57a424c324c6f26e00dac25b51161bbb329..06c5a4ad3c973bb8027e02f597e9b608251ccebd 100644 (file)
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/queue.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "core-subscribe.h"
 
@@ -68,9 +68,9 @@ static void sched_event(pa_core *c);
 pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, pa_subscription_cb_t callback, void *userdata) {
     pa_subscription *s;
 
-    assert(c);
-    assert(m);
-    assert(callback);
+    pa_assert(c);
+    pa_assert(m);
+    pa_assert(callback);
 
     s = pa_xnew(pa_subscription, 1);
     s->core = c;
@@ -85,24 +85,24 @@ pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, pa_su
 
 /* Free a subscription object, effectively marking it for deletion */
 void pa_subscription_free(pa_subscription*s) {
-    assert(s);
-    assert(!s->dead);
+    pa_assert(s);
+    pa_assert(!s->dead);
 
     s->dead = 1;
     sched_event(s->core);
 }
 
 static void free_subscription(pa_subscription *s) {
-    assert(s);
-    assert(s->core);
+    pa_assert(s);
+    pa_assert(s->core);
 
     PA_LLIST_REMOVE(pa_subscription, s->core->subscriptions, s);
     pa_xfree(s);
 }
 
 static void free_event(pa_subscription_event *s) {
-    assert(s);
-    assert(s->core);
+    pa_assert(s);
+    pa_assert(s->core);
 
     if (!s->next)
         s->core->subscription_event_last = s->prev;
@@ -113,7 +113,7 @@ static void free_event(pa_subscription_event *s) {
 
 /* Free all subscription objects */
 void pa_subscription_free_all(pa_core *c) {
-    assert(c);
+    pa_assert(c);
 
     while (c->subscriptions)
         free_subscription(c->subscriptions);
@@ -160,9 +160,9 @@ static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) {
     pa_core *c = userdata;
     pa_subscription *s;
 
-    assert(c->mainloop == m);
-    assert(c);
-    assert(c->subscription_defer_event == de);
+    pa_assert(c->mainloop == m);
+    pa_assert(c);
+    pa_assert(c->subscription_defer_event == de);
 
     c->mainloop->defer_enable(c->subscription_defer_event, 0);
 
@@ -196,20 +196,20 @@ static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) {
 
 /* Schedule an mainloop event so that a pending subscription event is dispatched */
 static void sched_event(pa_core *c) {
-    assert(c);
+    pa_assert(c);
 
     if (!c->subscription_defer_event) {
         c->subscription_defer_event = c->mainloop->defer_new(c->mainloop, defer_cb, c);
-        assert(c->subscription_defer_event);
+        pa_assert(c->subscription_defer_event);
     }
 
     c->mainloop->defer_enable(c->subscription_defer_event, 1);
 }
 
 /* Append a new subscription event to the subscription event queue and schedule a main loop event */
-void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t index) {
+void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t idx) {
     pa_subscription_event *e;
-    assert(c);
+    pa_assert(c);
 
     /* No need for queuing subscriptions of noone is listening */
     if (!c->subscriptions)
@@ -227,7 +227,7 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i
                 continue;
 
             /* not the same object */
-            if (i->index != index)
+            if (i->index != idx)
                 continue;
 
             if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
@@ -253,7 +253,7 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i
     e = pa_xnew(pa_subscription_event, 1);
     e->core = c;
     e->type = t;
-    e->index = index;
+    e->index = idx;
 
     PA_LLIST_INSERT_AFTER(pa_subscription_event, c->subscription_event_queue, c->subscription_event_last, e);
     c->subscription_event_last = e;
index e5766b2fa7abd826cae0c95b1413bec0cb4d6ce0..a644b6642c87ba093d8cc7725377aeebcfb4921c 100644 (file)
@@ -31,7 +31,6 @@
 #include <stdlib.h>
 #include <signal.h>
 #include <errno.h>
-#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 
+#ifdef HAVE_STRTOF_L
+#include <locale.h>
+#endif
+
 #ifdef HAVE_SCHED_H
 #include <sched.h>
 #endif
 #include <sys/capability.h>
 #endif
 
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
 #ifdef HAVE_PTHREAD
 #include <pthread.h>
 #endif
 #include <grp.h>
 #endif
 
+#ifdef HAVE_LIBSAMPLERATE
 #include <samplerate.h>
+#endif
 
 #include <pulse/xmalloc.h>
 #include <pulse/util.h>
+#include <pulse/utf8.h>
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/winsock.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/thread.h>
 
 #include "core-util.h"
 
 
 #ifndef OS_IS_WIN32
 #define PA_USER_RUNTIME_PATH_PREFIX "/tmp/pulse-"
-#define PATH_SEP '/'
 #else
 #define PA_USER_RUNTIME_PATH_PREFIX "%TEMP%\\pulse-"
-#define PATH_SEP '\\'
 #endif
 
 #ifdef OS_IS_WIN32
@@ -111,7 +121,7 @@ int pa_set_root(HANDLE handle) {
     if (!GetModuleFileName(handle, library_path + sizeof(PULSE_ROOTENV), MAX_PATH))
         return 0;
 
-    sep = strrchr(library_path, '\\');
+    sep = strrchr(library_path, PA_PATH_SEP_CHAR);
     if (sep)
         *sep = '\0';
 
@@ -124,23 +134,42 @@ int pa_set_root(HANDLE handle) {
 #endif
 
 /** Make a file descriptor nonblock. Doesn't do any error checking */
-void pa_make_nonblock_fd(int fd) {
+void pa_make_fd_nonblock(int fd) {
+
 #ifdef O_NONBLOCK
     int v;
-    assert(fd >= 0);
+    pa_assert(fd >= 0);
+
+    pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
+
+    if (!(v & O_NONBLOCK))
+        pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
 
-    if ((v = fcntl(fd, F_GETFL)) >= 0)
-        if (!(v & O_NONBLOCK))
-            fcntl(fd, F_SETFL, v|O_NONBLOCK);
 #elif defined(OS_IS_WIN32)
     u_long arg = 1;
     if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
-        if (WSAGetLastError() == WSAENOTSOCK)
-            pa_log_warn("WARNING: Only sockets can be made non-blocking!");
+        pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
+        pa_log_warn("Only sockets can be made non-blocking!");
     }
 #else
-    pa_log_warn("WARNING: Non-blocking I/O not supported.!");
+    pa_log_warn("Non-blocking I/O not supported.!");
 #endif
+
+}
+
+/* Set the FD_CLOEXEC flag for a fd */
+void pa_make_fd_cloexec(int fd) {
+
+#ifdef FD_CLOEXEC
+    int v;
+    pa_assert(fd >= 0);
+
+    pa_assert_se((v = fcntl(fd, F_GETFD, 0)) >= 0);
+
+    if (!(v & FD_CLOEXEC))
+        pa_assert_se(fcntl(fd, F_SETFD, v|FD_CLOEXEC) >= 0);
+#endif
+
 }
 
 /** Creates a directory securely */
@@ -148,7 +177,7 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
     struct stat st;
     int r;
 
-    assert(dir);
+    pa_assert(dir);
 
 #ifdef OS_IS_WIN32
     r = mkdir(dir);
@@ -169,7 +198,7 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
         uid = getuid();
     if (gid == (gid_t)-1)
         gid = getgid();
-    chown(dir, uid, gid);
+    (void) chown(dir, uid, gid);
 #endif
 
 #ifdef HAVE_CHMOD
@@ -295,9 +324,9 @@ ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
     ssize_t ret = 0;
     int _type;
 
-    assert(fd >= 0);
-    assert(data);
-    assert(size);
+    pa_assert(fd >= 0);
+    pa_assert(data);
+    pa_assert(size);
 
     if (!type) {
         _type = 0;
@@ -326,9 +355,9 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
     ssize_t ret = 0;
     int _type;
 
-    assert(fd >= 0);
-    assert(data);
-    assert(size);
+    pa_assert(fd >= 0);
+    pa_assert(data);
+    pa_assert(size);
 
     if (!type) {
         _type = 0;
@@ -354,13 +383,12 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
 
 /** Platform independent read function. Necessary since not all
  * systems treat all file descriptors equal. */
-int pa_close(int fd)
-{
+int pa_close(int fd) {
+
 #ifdef OS_IS_WIN32
     int ret;
 
-    ret = closesocket(fd);
-    if (ret == 0)
+    if ((ret = closesocket(fd)) == 0)
         return 0;
 
     if (WSAGetLastError() != WSAENOTSOCK) {
@@ -407,9 +435,9 @@ void pa_check_signal_is_blocked(int sig) {
     if (sa.sa_handler != SIG_DFL)
         return;
 
-    pa_log("WARNING: %s is not trapped. This might cause malfunction!", pa_strsignal(sig));
+    pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig));
 #else /* HAVE_SIGACTION */
-    pa_log("WARNING: %s might not be trapped. This might cause malfunction!", pa_strsignal(sig));
+    pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig));
 #endif
 }
 
@@ -419,7 +447,7 @@ char *pa_sprintf_malloc(const char *format, ...) {
     int  size = 100;
     char *c = NULL;
 
-    assert(format);
+    pa_assert(format);
 
     for(;;) {
         int r;
@@ -431,6 +459,8 @@ char *pa_sprintf_malloc(const char *format, ...) {
         r = vsnprintf(c, size, format, ap);
         va_end(ap);
 
+        c[size-1] = 0;
+
         if (r > -1 && r < size)
             return c;
 
@@ -447,19 +477,20 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) {
     int  size = 100;
     char *c = NULL;
 
-    assert(format);
+    pa_assert(format);
 
     for(;;) {
         int r;
         va_list aq;
 
-        va_copy(aq, ap);
-
         c = pa_xrealloc(c, size);
-        r = vsnprintf(c, size, format, aq);
 
+        va_copy(aq, ap);
+        r = vsnprintf(c, size, format, aq);
         va_end(aq);
 
+        c[size-1] = 0;
+
         if (r > -1 && r < size)
             return c;
 
@@ -472,36 +503,47 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) {
 
 /* Similar to OpenBSD's strlcpy() function */
 char *pa_strlcpy(char *b, const char *s, size_t l) {
-    assert(b && s && l > 0);
+    pa_assert(b);
+    pa_assert(s);
+    pa_assert(l > 0);
 
     strncpy(b, s, l);
     b[l-1] = 0;
     return b;
 }
 
-#define NICE_LEVEL (-15)
+/* Make the current thread a realtime thread*/
+void pa_make_realtime(void) {
 
-/* Raise the priority of the current process as much as possible and
-sensible: set the nice level to -15 and enable realtime scheduling if
-supported.*/
-void pa_raise_priority(void) {
-#if defined(HAVE_SYS_CAPABILITY_H)
-    cap_t caps;
-
-    /* Temporarily acquire CAP_SYS_NICE in the effective set */
-    if ((caps = cap_get_proc())) {
-        cap_t caps_new;
-        cap_value_t nice_cap = CAP_SYS_NICE;
-
-        if ((caps_new = cap_dup(caps))) {
-            cap_set_flag(caps_new, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET);
-            cap_set_flag(caps_new, CAP_PERMITTED, 1, &nice_cap, CAP_SET);
-            cap_set_proc(caps_new);
-            cap_free(caps_new);
-        }
+#ifdef _POSIX_PRIORITY_SCHEDULING
+    struct sched_param sp;
+    int r, policy;
+
+    memset(&sp, 0, sizeof(sp));
+    policy = 0;
+
+    if ((r = pthread_getschedparam(pthread_self(), &policy, &sp)) != 0) {
+        pa_log("pthread_getschedgetparam(): %s", pa_cstrerror(r));
+        return;
+    }
+
+    sp.sched_priority = 1;
+    if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) != 0) {
+        pa_log_warn("pthread_setschedparam(): %s", pa_cstrerror(r));
+        return;
     }
+
+    pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread.");
 #endif
 
+}
+
+#define NICE_LEVEL (-11)
+
+/* Raise the priority of the current process as much as possible and
+sensible: set the nice level to -15.*/
+void pa_raise_priority(void) {
+
 #ifdef HAVE_SYS_RESOURCE_H
     if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0)
         pa_log_warn("setpriority(): %s", pa_cstrerror(errno));
@@ -509,86 +551,26 @@ void pa_raise_priority(void) {
         pa_log_info("Successfully gained nice level %i.", NICE_LEVEL);
 #endif
 
-#ifdef _POSIX_PRIORITY_SCHEDULING
-    {
-        struct sched_param sp;
-
-        if (sched_getparam(0, &sp) < 0) {
-            pa_log("sched_getparam(): %s", pa_cstrerror(errno));
-            goto fail;
-        }
-
-        sp.sched_priority = 1;
-        if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) {
-            pa_log_warn("sched_setscheduler(): %s", pa_cstrerror(errno));
-            goto fail;
-        }
-
-        pa_log_info("Successfully enabled SCHED_FIFO scheduling.");
-    }
-#endif
-
 #ifdef OS_IS_WIN32
     if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS))
         pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
     else
         pa_log_info("Successfully gained high priority class.");
 #endif
-
-fail:
-
-#if defined(HAVE_SYS_CAPABILITY_H)
-    if (caps) {
-        /* Restore original caps */
-        cap_set_proc(caps);
-        cap_free(caps);
-    }
-#endif
-
-    ; /* We put this here to get the code to compile when
-       * HAVE_SYS_CAPABILITY_H is not defined. Don't remove unless you
-       * know what you do */
 }
 
-/* Reset the priority to normal, inverting the changes made by pa_raise_priority() */
+/* Reset the priority to normal, inverting the changes made by
+ * pa_raise_priority() */
 void pa_reset_priority(void) {
 #ifdef OS_IS_WIN32
     SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
 #endif
 
-#ifdef _POSIX_PRIORITY_SCHEDULING
-    {
-        struct sched_param sp;
-        sched_getparam(0, &sp);
-        sp.sched_priority = 0;
-        sched_setscheduler(0, SCHED_OTHER, &sp);
-    }
-#endif
-
 #ifdef HAVE_SYS_RESOURCE_H
     setpriority(PRIO_PROCESS, 0, 0);
 #endif
 }
 
-/* Set the FD_CLOEXEC flag for a fd */
-int pa_fd_set_cloexec(int fd, int b) {
-
-#ifdef FD_CLOEXEC
-    int v;
-    assert(fd >= 0);
-
-    if ((v = fcntl(fd, F_GETFD, 0)) < 0)
-        return -1;
-
-    v = (v & ~FD_CLOEXEC) | (b ? FD_CLOEXEC : 0);
-
-    if (fcntl(fd, F_SETFD, v) < 0)
-        return -1;
-#endif
-
-    return 0;
-}
-
 /* Try to parse a boolean string value.*/
 int pa_parse_boolean(const char *v) {
 
@@ -639,31 +621,134 @@ char *pa_split_spaces(const char *c, const char **state) {
     return pa_xstrndup(current, l);
 }
 
-/* Return the name of an UNIX signal. Similar to GNU's strsignal() */
-const char *pa_strsignal(int sig) {
+PA_STATIC_TLS_DECLARE(signame, pa_xfree);
+
+/* Return the name of an UNIX signal. Similar to Solaris sig2str() */
+const char *pa_sig2str(int sig) {
+    char *t;
+
+    if (sig <= 0)
+        goto fail;
+
+#ifdef NSIG
+    if (sig >= NSIG)
+        goto fail;
+#endif
+
+#ifdef HAVE_SIG2STR
+    {
+        char buf[SIG2STR_MAX];
+
+        if (sig2str(sig, buf) == 0) {
+            pa_xfree(PA_STATIC_TLS_GET(signame));
+            t = pa_sprintf_malloc("SIG%s", buf);
+            PA_STATIC_TLS_SET(signame, t);
+            return t;
+        }
+    }
+#else
+
     switch(sig) {
-        case SIGINT: return "SIGINT";
-        case SIGTERM: return "SIGTERM";
+#ifdef SIGHUP
+        case SIGHUP:    return "SIGHUP";
+#endif
+        case SIGINT:    return "SIGINT";
+#ifdef SIGQUIT
+        case SIGQUIT:   return "SIGQUIT";
+#endif
+        case SIGILL:    return "SIGULL";
+#ifdef SIGTRAP
+        case SIGTRAP:   return "SIGTRAP";
+#endif
+        case SIGABRT:   return "SIGABRT";
+#ifdef SIGBUS
+        case SIGBUS:    return "SIGBUS";
+#endif
+        case SIGFPE:    return "SIGFPE";
+#ifdef SIGKILL
+        case SIGKILL:   return "SIGKILL";
+#endif
 #ifdef SIGUSR1
-        case SIGUSR1: return "SIGUSR1";
+        case SIGUSR1:   return "SIGUSR1";
 #endif
+        case SIGSEGV:   return "SIGSEGV";
 #ifdef SIGUSR2
-        case SIGUSR2: return "SIGUSR2";
-#endif
-#ifdef SIGXCPU
-        case SIGXCPU: return "SIGXCPU";
+        case SIGUSR2:   return "SIGUSR2";
 #endif
 #ifdef SIGPIPE
-        case SIGPIPE: return "SIGPIPE";
+        case SIGPIPE:   return "SIGPIPE";
+#endif
+#ifdef SIGALRM
+        case SIGALRM:   return "SIGALRM";
+#endif
+        case SIGTERM:   return "SIGTERM";
+#ifdef SIGSTKFLT
+        case SIGSTKFLT: return "SIGSTKFLT";
 #endif
 #ifdef SIGCHLD
-        case SIGCHLD: return "SIGCHLD";
+        case SIGCHLD:   return "SIGCHLD";
 #endif
-#ifdef SIGHUP
-        case SIGHUP: return "SIGHUP";
+#ifdef SIGCONT
+        case SIGCONT:   return "SIGCONT";
+#endif
+#ifdef SIGSTOP
+        case SIGSTOP:   return "SIGSTOP";
+#endif
+#ifdef SIGTSTP
+        case SIGTSTP:   return "SIGTSTP";
+#endif
+#ifdef SIGTTIN
+        case SIGTTIN:   return "SIGTTIN";
+#endif
+#ifdef SIGTTOU
+        case SIGTTOU:   return "SIGTTOU";
+#endif
+#ifdef SIGURG
+        case SIGURG:    return "SIGURG";
+#endif
+#ifdef SIGXCPU
+        case SIGXCPU:   return "SIGXCPU";
+#endif
+#ifdef SIGXFSZ
+        case SIGXFSZ:   return "SIGXFSZ";
 #endif
-        default: return "UNKNOWN SIGNAL";
+#ifdef SIGVTALRM
+        case SIGVTALRM: return "SIGVTALRM";
+#endif
+#ifdef SIGPROF
+        case SIGPROF:   return "SIGPROF";
+#endif
+#ifdef SIGWINCH
+        case SIGWINCH:  return "SIGWINCH";
+#endif
+#ifdef SIGIO
+        case SIGIO:     return "SIGIO";
+#endif
+#ifdef SIGPWR
+        case SIGPWR:    return "SIGPWR";
+#endif
+#ifdef SIGSYS
+        case SIGSYS:    return "SIGSYS";
+#endif
+    }
+
+#ifdef SIGRTMIN
+    if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
+        pa_xfree(PA_STATIC_TLS_GET(signame));
+        t = pa_sprintf_malloc("SIGRTMIN+%i", sig - SIGRTMIN);
+        PA_STATIC_TLS_SET(signame, t);
+        return t;
     }
+#endif
+
+#endif
+
+fail:
+
+    pa_xfree(PA_STATIC_TLS_GET(signame));
+    t = pa_sprintf_malloc("SIG%i", sig);
+    PA_STATIC_TLS_SET(signame, t);
+    return t;
 }
 
 #ifdef HAVE_GRP_H
@@ -715,7 +800,7 @@ int pa_own_uid_in_group(const char *name, gid_t *gid) {
     int n = sysconf(_SC_NGROUPS_MAX);
     int r = -1, i;
 
-    assert(n > 0);
+    pa_assert(n > 0);
 
     gids = pa_xmalloc(sizeof(GETGROUPS_T)*n);
 
@@ -861,8 +946,7 @@ int pa_lock_fd(int fd, int b) {
             return 0;
     }
 
-    pa_log("%slock: %s", !b? "un" : "",
-        pa_cstrerror(errno));
+    pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno));
 #endif
 
 #ifdef OS_IS_WIN32
@@ -881,7 +965,7 @@ int pa_lock_fd(int fd, int b) {
 
 /* Remove trailing newlines from a string */
 char* pa_strip_nl(char *s) {
-    assert(s);
+    pa_assert(s);
 
     s[strcspn(s, "\r\n")] = 0;
     return s;
@@ -890,38 +974,46 @@ char* pa_strip_nl(char *s) {
 /* Create a temporary lock file and lock it. */
 int pa_lock_lockfile(const char *fn) {
     int fd = -1;
-    assert(fn);
+    pa_assert(fn);
 
     for (;;) {
         struct stat st;
 
-        if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) {
-            pa_log("failed to create lock file '%s': %s", fn,
-                pa_cstrerror(errno));
+        if ((fd = open(fn, O_CREAT|O_RDWR
+#ifdef O_NOCTTY
+                       |O_NOCTTY
+#endif
+#ifdef O_NOFOLLOW
+                       |O_NOFOLLOW
+#endif
+                       , S_IRUSR|S_IWUSR)) < 0) {
+            pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
             goto fail;
         }
 
         if (pa_lock_fd(fd, 1) < 0) {
-            pa_log("failed to lock file '%s'.", fn);
+            pa_log_warn("Failed to lock file '%s'.", fn);
             goto fail;
         }
 
         if (fstat(fd, &st) < 0) {
-            pa_log("failed to fstat() file '%s'.", fn);
+            pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
             goto fail;
         }
 
-        /* Check wheter the file has been removed meanwhile. When yes, restart this loop, otherwise, we're done */
+        /* Check wheter the file has been removed meanwhile. When yes,
+         * restart this loop, otherwise, we're done */
         if (st.st_nlink >= 1)
             break;
 
         if (pa_lock_fd(fd, 0) < 0) {
-            pa_log("failed to unlock file '%s'.", fn);
+            pa_log_warn("Failed to unlock file '%s'.", fn);
             goto fail;
         }
 
-        if (close(fd) < 0) {
-            pa_log("failed to close file '%s'.", fn);
+        if (pa_close(fd) < 0) {
+            pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
+            fd = -1;
             goto fail;
         }
 
@@ -933,7 +1025,7 @@ int pa_lock_lockfile(const char *fn) {
 fail:
 
     if (fd >= 0)
-        close(fd);
+        pa_close(fd);
 
     return -1;
 }
@@ -941,22 +1033,21 @@ fail:
 /* Unlock a temporary lcok file */
 int pa_unlock_lockfile(const char *fn, int fd) {
     int r = 0;
-    assert(fn && fd >= 0);
+    pa_assert(fn);
+    pa_assert(fd >= 0);
 
     if (unlink(fn) < 0) {
-        pa_log_warn("WARNING: unable to remove lock file '%s': %s",
-            fn, pa_cstrerror(errno));
+        pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
         r = -1;
     }
 
     if (pa_lock_fd(fd, 0) < 0) {
-        pa_log_warn("WARNING: failed to unlock file '%s'.", fn);
+        pa_log_warn("Failed to unlock file '%s'.", fn);
         r = -1;
     }
 
-    if (close(fd) < 0) {
-        pa_log_warn("WARNING: failed to close lock file '%s': %s",
-            fn, pa_cstrerror(errno));
+    if (pa_close(fd) < 0) {
+        pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
         r = -1;
     }
 
@@ -1019,10 +1110,8 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
                 return f;
             }
 
-            if (errno != ENOENT) {
-                pa_log_warn("WARNING: failed to open configuration file '%s': %s",
-                    lfn, pa_cstrerror(errno));
-            }
+            if (errno != ENOENT)
+                pa_log_warn("Failed to open configuration file '%s': %s", lfn, pa_cstrerror(errno));
 
             pa_xfree(lfn);
         }
@@ -1051,7 +1140,10 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
     size_t i = 0, j = 0;
     const char hex[] = "0123456789abcdef";
-    assert(d && s && slength > 0);
+
+    pa_assert(d);
+    pa_assert(s);
+    pa_assert(slength > 0);
 
     while (i < dlength && j+3 <= slength) {
         s[j++] = hex[*d >> 4];
@@ -1082,7 +1174,9 @@ static int hexc(char c) {
 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
     size_t j = 0;
-    assert(p && d);
+
+    pa_assert(p);
+    pa_assert(d);
 
     while (j < dlength && *p) {
         int b;
@@ -1109,8 +1203,8 @@ size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
 int pa_startswith(const char *s, const char *pfx) {
     size_t l;
 
-    assert(s);
-    assert(pfx);
+    pa_assert(s);
+    pa_assert(pfx);
 
     l = strlen(pfx);
 
@@ -1121,8 +1215,8 @@ int pa_startswith(const char *s, const char *pfx) {
 int pa_endswith(const char *s, const char *sfx) {
     size_t l1, l2;
 
-    assert(s);
-    assert(sfx);
+    pa_assert(s);
+    pa_assert(sfx);
 
     l1 = strlen(s);
     l2 = strlen(sfx);
@@ -1146,17 +1240,17 @@ char *pa_runtime_path(const char *fn, char *s, size_t l) {
     if ((e = getenv("PULSE_RUNTIME_PATH"))) {
 
         if (fn)
-            snprintf(s, l, "%s%c%s", e, PATH_SEP, fn);
+            pa_snprintf(s, l, "%s%c%s", e, PA_PATH_SEP_CHAR, fn);
         else
-            snprintf(s, l, "%s", e);
+            pa_snprintf(s, l, "%s", e);
 
     } else {
         char u[256];
 
         if (fn)
-            snprintf(s, l, "%s%s%c%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn);
+            pa_snprintf(s, l, "%s%s%c%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PA_PATH_SEP_CHAR, fn);
         else
-            snprintf(s, l, "%s%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)));
+            pa_snprintf(s, l, "%s%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)));
     }
 
 
@@ -1175,11 +1269,17 @@ char *pa_runtime_path(const char *fn, char *s, size_t l) {
 int pa_atoi(const char *s, int32_t *ret_i) {
     char *x = NULL;
     long l;
-    assert(s && ret_i);
 
+    pa_assert(s);
+    pa_assert(ret_i);
+
+    errno = 0;
     l = strtol(s, &x, 0);
 
-    if (!x || *x)
+    if (!x || *x || errno != 0)
+        return -1;
+
+    if ((int32_t) l != l)
         return -1;
 
     *ret_i = (int32_t) l;
@@ -1191,14 +1291,219 @@ int pa_atoi(const char *s, int32_t *ret_i) {
 int pa_atou(const char *s, uint32_t *ret_u) {
     char *x = NULL;
     unsigned long l;
-    assert(s && ret_u);
 
+    pa_assert(s);
+    pa_assert(ret_u);
+
+    errno = 0;
     l = strtoul(s, &x, 0);
 
-    if (!x || *x)
+    if (!x || *x || errno != 0)
+        return -1;
+
+    if ((uint32_t) l != l)
         return -1;
 
     *ret_u = (uint32_t) l;
 
     return 0;
 }
+
+#ifdef HAVE_STRTOF_L
+static locale_t c_locale = NULL;
+
+static void c_locale_destroy(void) {
+    freelocale(c_locale);
+}
+#endif
+
+int pa_atof(const char *s, float *ret_f) {
+    char *x = NULL;
+    float f;
+    int r = 0;
+
+    pa_assert(s);
+    pa_assert(ret_f);
+
+    /* This should be locale independent */
+
+#ifdef HAVE_STRTOF_L
+
+    PA_ONCE_BEGIN {
+
+        if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
+            atexit(c_locale_destroy);
+
+    } PA_ONCE_END;
+
+    if (c_locale) {
+        errno = 0;
+        f = strtof_l(s, &x, c_locale);
+    } else
+#endif
+    {
+        errno = 0;
+#ifdef HAVE_STRTOF
+        f = strtof(s, &x);
+#else
+        f = strtod(s, &x);
+#endif
+    }
+
+    if (!x || *x || errno != 0)
+        r =  -1;
+    else
+        *ret_f = f;
+
+    return r;
+}
+
+/* Same as snprintf, but guarantees NUL-termination on every platform */
+int pa_snprintf(char *str, size_t size, const char *format, ...) {
+    int ret;
+    va_list ap;
+
+    pa_assert(str);
+    pa_assert(size > 0);
+    pa_assert(format);
+
+    va_start(ap, format);
+    ret = vsnprintf(str, size, format, ap);
+    va_end(ap);
+
+    str[size-1] = 0;
+
+    return ret;
+}
+
+/* Truncate the specified string, but guarantee that the string
+ * returned still validates as UTF8 */
+char *pa_truncate_utf8(char *c, size_t l) {
+    pa_assert(c);
+    pa_assert(pa_utf8_valid(c));
+
+    if (strlen(c) <= l)
+        return c;
+
+    c[l] = 0;
+
+    while (l > 0 && !pa_utf8_valid(c))
+        c[--l] = 0;
+
+    return c;
+}
+
+char *pa_getcwd(void) {
+    size_t l = 128;
+
+    for (;;) {
+        char *p = pa_xnew(char, l);
+        if (getcwd(p, l))
+            return p;
+
+        if (errno != ERANGE)
+            return NULL;
+
+        pa_xfree(p);
+        l *= 2;
+    }
+}
+
+char *pa_make_path_absolute(const char *p) {
+    char *r;
+    char *cwd;
+
+    pa_assert(p);
+
+    if (p[0] == '/')
+        return pa_xstrdup(p);
+
+    if (!(cwd = pa_getcwd()))
+        return pa_xstrdup(p);
+
+    r = pa_sprintf_malloc("%s/%s", cwd, p);
+    pa_xfree(cwd);
+    return r;
+}
+
+void *pa_will_need(const void *p, size_t l) {
+#ifdef RLIMIT_MEMLOCK
+    struct rlimit rlim;
+#endif
+    const void *a;
+    size_t size;
+    int r;
+    size_t bs;
+
+    pa_assert(p);
+    pa_assert(l > 0);
+
+    a = PA_PAGE_ALIGN_PTR(p);
+    size = (const uint8_t*) p + l - (const uint8_t*) a;
+
+#ifdef HAVE_POSIX_MADVISE
+    if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
+        pa_log_debug("posix_madvise() worked fine!");
+        return (void*) p;
+    }
+#endif
+
+    /* Most likely the memory was not mmap()ed from a file and thus
+     * madvise() didn't work, so let's misuse mlock() do page this
+     * stuff back into RAM. Yeah, let's fuck with the MM!  It's so
+     * inviting, the man page of mlock() tells us: "All pages that
+     * contain a part of the specified address range are guaranteed to
+     * be resident in RAM when the call returns successfully." */
+
+#ifdef RLIMIT_MEMLOCK
+    pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
+
+    if (rlim.rlim_cur < PA_PAGE_SIZE) {
+        pa_log_debug("posix_madvise() failed (or doesn't exist), resource limits don't allow mlock(), can't page in data: %s", pa_cstrerror(r));
+        return (void*) p;
+    }
+
+    bs = PA_PAGE_ALIGN(rlim.rlim_cur);
+#else
+    bs = PA_PAGE_SIZE*4;
+#endif
+
+    pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
+
+#ifdef HAVE_MLOCK
+    while (size > 0 && bs > 0) {
+
+        if (bs > size)
+            bs = size;
+
+        if (mlock(a, bs) < 0) {
+            bs = PA_PAGE_ALIGN(bs / 2);
+            continue;
+        }
+
+        pa_assert_se(munlock(a, bs) == 0);
+
+        a = (const uint8_t*) a + bs;
+        size -= bs;
+    }
+#endif
+
+    if (bs <= 0)
+        pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
+    else
+        pa_log_debug("mlock() worked fine!");
+
+    return (void*) p;
+}
+
+void pa_close_pipe(int fds[2]) {
+    pa_assert(fds);
+
+    if (fds[0] >= 0)
+        pa_assert_se(pa_close(fds[0]) == 0);
+
+    if (fds[1] >= 0)
+        pa_assert_se(pa_close(fds[1]) == 0);
+
+    fds[0] = fds[1] = -1;
+}
index 1d921e036c982566880543f1fe3f4c5d750067d0..0fe865ec41eb0ad53e8a3d636c2bfe8fff77852a 100644 (file)
@@ -34,7 +34,8 @@
 
 struct timeval;
 
-void pa_make_nonblock_fd(int fd);
+void pa_make_fd_nonblock(int fd);
+void pa_make_fd_cloexec(int fd);
 
 int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid);
 int pa_make_secure_parent_dir(const char *fn, mode_t, uid_t uid, gid_t gid);
@@ -55,19 +56,18 @@ char *pa_strlcpy(char *b, const char *s, size_t l);
 
 char *pa_parent_dir(const char *fn);
 
+void pa_make_realtime(void);
 void pa_raise_priority(void);
 void pa_reset_priority(void);
 
-int pa_fd_set_cloexec(int fd, int b);
-
-int pa_parse_boolean(const char *s);
+int pa_parse_boolean(const char *s) PA_GCC_PURE;
 
 char *pa_split(const char *c, const char*delimiters, const char **state);
 char *pa_split_spaces(const char *c, const char **state);
 
 char *pa_strip_nl(char *s);
 
-const char *pa_strsignal(int sig);
+const char *pa_sig2str(int sig) PA_GCC_PURE;
 
 int pa_own_uid_in_group(const char *name, gid_t *gid);
 int pa_uid_in_group(uid_t uid, const char *name);
@@ -84,12 +84,42 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength);
 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength);
 
-int pa_startswith(const char *s, const char *pfx);
-int pa_endswith(const char *s, const char *sfx);
+int pa_startswith(const char *s, const char *pfx) PA_GCC_PURE;
+int pa_endswith(const char *s, const char *sfx) PA_GCC_PURE;
 
 char *pa_runtime_path(const char *fn, char *s, size_t l);
 
 int pa_atoi(const char *s, int32_t *ret_i);
 int pa_atou(const char *s, uint32_t *ret_u);
+int pa_atof(const char *s, float *ret_f);
+
+int pa_snprintf(char *str, size_t size, const char *format, ...);
+
+char *pa_truncate_utf8(char *c, size_t l);
+
+char *pa_getcwd(void);
+char *pa_make_path_absolute(const char *p);
+
+void *pa_will_need(const void *p, size_t l);
+
+static inline int pa_is_power_of_two(unsigned n) {
+    return !(n & (n - 1));
+}
+
+static inline unsigned pa_make_power_of_two(unsigned n) {
+    unsigned j = n;
+
+    if (pa_is_power_of_two(n))
+        return n;
+
+    while (j) {
+        j = j >> 1;
+        n = n | j;
+    }
+
+    return n + 1;
+}
+
+void pa_close_pipe(int fds[2]);
 
 #endif
index 31b6c18816de648a39ad05019134e4680314e468..e9008833d2a6ab43217187b67fe199804b1c21c1 100644 (file)
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <stdio.h>
 #include <signal.h>
 
 #include <pulsecore/props.h>
 #include <pulsecore/random.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "core.h"
 
+static PA_DEFINE_CHECK_TYPE(pa_core, pa_msgobject);
+
+static int core_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
+    pa_core *c = PA_CORE(o);
+
+    pa_core_assert_ref(c);
+
+    switch (code) {
+
+        case PA_CORE_MESSAGE_UNLOAD_MODULE:
+            pa_module_unload(c, userdata);
+            return 0;
+
+        default:
+            return -1;
+    }
+}
+
+static void core_free(pa_object *o);
+
 pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
     pa_core* c;
     pa_mempool *pool;
+    int j;
+
+    pa_assert(m);
 
     if (shared) {
         if (!(pool = pa_mempool_new(shared))) {
@@ -66,7 +89,9 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
         }
     }
 
-    c = pa_xnew(pa_core, 1);
+    c = pa_msgobject_new(pa_core);
+    c->parent.parent.free = core_free;
+    c->parent.process_msg = core_process_msg;
 
     c->mainloop = m;
     c->clients = pa_idxset_new(NULL, NULL);
@@ -87,6 +112,8 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
     c->default_sample_spec.format = PA_SAMPLE_S16NE;
     c->default_sample_spec.rate = 44100;
     c->default_sample_spec.channels = 2;
+    c->default_n_fragments = 4;
+    c->default_fragment_size_msec = 25;
 
     c->module_auto_unload_event = NULL;
     c->module_defer_unload_event = NULL;
@@ -99,22 +126,21 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
 
     c->mempool = pool;
 
-    c->disallow_module_loading = 0;
-
     c->quit_event = NULL;
 
     c->exit_idle_time = -1;
     c->module_idle_time = 20;
     c->scache_idle_time = 20;
 
-    c->resample_method = PA_RESAMPLER_SRC_SINC_FASTEST;
+    c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE;
 
     c->is_system_instance = 0;
+    c->disallow_module_loading = 0;
+    c->high_priority = 0;
+
 
-    pa_hook_init(&c->hook_sink_input_new, c);
-    pa_hook_init(&c->hook_sink_disconnect, c);
-    pa_hook_init(&c->hook_source_output_new, c);
-    pa_hook_init(&c->hook_source_disconnect, c);
+    for (j = 0; j < PA_CORE_HOOK_MAX; j++)
+        pa_hook_init(&c->hooks[j], c);
 
     pa_property_init(c);
 
@@ -123,28 +149,31 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
 #ifdef SIGPIPE
     pa_check_signal_is_blocked(SIGPIPE);
 #endif
+
     return c;
 }
 
-void pa_core_free(pa_core *c) {
-    assert(c);
+static void core_free(pa_object *o) {
+    pa_core *c = PA_CORE(o);
+    int j;
+    pa_assert(c);
 
     pa_module_unload_all(c);
-    assert(!c->modules);
+    pa_assert(!c->modules);
 
-    assert(pa_idxset_isempty(c->clients));
+    pa_assert(pa_idxset_isempty(c->clients));
     pa_idxset_free(c->clients, NULL, NULL);
 
-    assert(pa_idxset_isempty(c->sinks));
+    pa_assert(pa_idxset_isempty(c->sinks));
     pa_idxset_free(c->sinks, NULL, NULL);
 
-    assert(pa_idxset_isempty(c->sources));
+    pa_assert(pa_idxset_isempty(c->sources));
     pa_idxset_free(c->sources, NULL, NULL);
 
-    assert(pa_idxset_isempty(c->source_outputs));
+    pa_assert(pa_idxset_isempty(c->source_outputs));
     pa_idxset_free(c->source_outputs, NULL, NULL);
 
-    assert(pa_idxset_isempty(c->sink_inputs));
+    pa_assert(pa_idxset_isempty(c->sink_inputs));
     pa_idxset_free(c->sink_inputs, NULL, NULL);
 
     pa_scache_free(c);
@@ -162,23 +191,21 @@ void pa_core_free(pa_core *c) {
 
     pa_property_cleanup(c);
 
-    pa_hook_free(&c->hook_sink_input_new);
-    pa_hook_free(&c->hook_sink_disconnect);
-    pa_hook_free(&c->hook_source_output_new);
-    pa_hook_free(&c->hook_source_disconnect);
+    for (j = 0; j < PA_CORE_HOOK_MAX; j++)
+        pa_hook_free(&c->hooks[j]);
 
     pa_xfree(c);
 }
 
 static void quit_callback(pa_mainloop_api*m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) {
     pa_core *c = userdata;
-    assert(c->quit_event = e);
+    pa_assert(c->quit_event == e);
 
     m->quit(m, 0);
 }
 
 void pa_core_check_quit(pa_core *c) {
-    assert(c);
+    pa_assert(c);
 
     if (!c->quit_event && c->exit_idle_time >= 0 && pa_idxset_size(c->clients) == 0) {
         struct timeval tv;
index 51a18b62e9aadad8fcd3bc31281e51e731f4163d..dfa80f8d6191816e03f3b325acc7a21939ce8575 100644 (file)
 #include <pulsecore/queue.h>
 #include <pulsecore/llist.h>
 #include <pulsecore/hook-list.h>
+#include <pulsecore/asyncmsgq.h>
 
 typedef struct pa_core pa_core;
 
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/sink-input.h>
+#include <pulsecore/msgobject.h>
+
+typedef enum pa_core_hook {
+    PA_CORE_HOOK_SINK_NEW_POST,
+    PA_CORE_HOOK_SINK_UNLINK,
+    PA_CORE_HOOK_SINK_UNLINK_POST,
+    PA_CORE_HOOK_SINK_STATE_CHANGED,
+    PA_CORE_HOOK_SINK_DESCRIPTION_CHANGED,
+    PA_CORE_HOOK_SOURCE_NEW_POST,
+    PA_CORE_HOOK_SOURCE_UNLINK,
+    PA_CORE_HOOK_SOURCE_UNLINK_POST,
+    PA_CORE_HOOK_SOURCE_STATE_CHANGED,
+    PA_CORE_HOOK_SOURCE_DESCRIPTION_CHANGED,
+    PA_CORE_HOOK_SINK_INPUT_NEW,
+    PA_CORE_HOOK_SINK_INPUT_PUT,
+    PA_CORE_HOOK_SINK_INPUT_UNLINK,
+    PA_CORE_HOOK_SINK_INPUT_UNLINK_POST,
+    PA_CORE_HOOK_SINK_INPUT_MOVE,
+    PA_CORE_HOOK_SINK_INPUT_MOVE_POST,
+    PA_CORE_HOOK_SINK_INPUT_NAME_CHANGED,
+    PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED,
+    PA_CORE_HOOK_SOURCE_OUTPUT_NEW,
+    PA_CORE_HOOK_SOURCE_OUTPUT_PUT,
+    PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK,
+    PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST,
+    PA_CORE_HOOK_SOURCE_OUTPUT_MOVE,
+    PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST,
+    PA_CORE_HOOK_SOURCE_OUTPUT_NAME_CHANGED,
+    PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED,
+    PA_CORE_HOOK_MAX
+} pa_core_hook_t;
 
 /* The core structure of PulseAudio. Every PulseAudio daemon contains
  * exactly one of these. It is used for storing kind of global
  * variables for the daemon. */
 
 struct pa_core {
+    pa_msgobject parent;
+
     /* A random value which may be used to identify this instance of
      * PulseAudio. Not cryptographically secure in any way. */
     uint32_t cookie;
@@ -61,6 +95,8 @@ struct pa_core {
     char *default_source_name, *default_sink_name;
 
     pa_sample_spec default_sample_spec;
+    unsigned default_n_fragments, default_fragment_size_msec;
+
     pa_time_event *module_auto_unload_event;
     pa_defer_event *module_defer_unload_event;
 
@@ -71,27 +107,30 @@ struct pa_core {
 
     pa_mempool *mempool;
 
-    int disallow_module_loading, running_as_daemon;
     int exit_idle_time, module_idle_time, scache_idle_time;
 
     pa_time_event *quit_event;
 
     pa_time_event *scache_auto_unload_event;
 
+    int disallow_module_loading, running_as_daemon;
     pa_resample_method_t resample_method;
-
     int is_system_instance;
+    int high_priority;
 
     /* hooks */
-    pa_hook
-        hook_sink_input_new,
-        hook_sink_disconnect,
-        hook_source_output_new,
-        hook_source_disconnect;
+    pa_hook hooks[PA_CORE_HOOK_MAX];
+};
+
+PA_DECLARE_CLASS(pa_core);
+#define PA_CORE(o) pa_core_cast(o)
+
+enum {
+    PA_CORE_MESSAGE_UNLOAD_MODULE,
+    PA_CORE_MESSAGE_MAX
 };
 
 pa_core* pa_core_new(pa_mainloop_api *m, int shared);
-void pa_core_free(pa_core*c);
 
 /* Check whether noone is connected to this core */
 void pa_core_check_quit(pa_core *c);
index e0a025bd0b88fb76b34b547fb42fddddad74c24c..51dfc33d5ef7b0fc774cef3d3e7c99e0b0a9c8e7 100644 (file)
@@ -26,7 +26,9 @@
 
 #include <sys/types.h>
 
-/* config.h must be included before this file */
+#ifndef PACKAGE
+#error "Please include config.h before including this file!"
+#endif
 
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
index 944e35707bf085c9aaa3b00aae95b05353eab1e5..8bdb46fa8cf2517a441ebdabdfdbb3f17deb3895 100644 (file)
 #endif
 
 #include <string.h>
-#include <assert.h>
 #include <stdlib.h>
 
 #include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
 
 #include "dynarray.h"
 
@@ -52,7 +52,7 @@ pa_dynarray* pa_dynarray_new(void) {
 
 void pa_dynarray_free(pa_dynarray* a, void (*func)(void *p, void *userdata), void *userdata) {
     unsigned i;
-    assert(a);
+    pa_assert(a);
 
     if (func)
         for (i = 0; i < a->n_entries; i++)
@@ -64,7 +64,7 @@ void pa_dynarray_free(pa_dynarray* a, void (*func)(void *p, void *userdata), voi
 }
 
 void pa_dynarray_put(pa_dynarray*a, unsigned i, void *p) {
-    assert(a);
+    pa_assert(a);
 
     if (i >= a->n_allocated) {
         unsigned n;
@@ -85,21 +85,27 @@ void pa_dynarray_put(pa_dynarray*a, unsigned i, void *p) {
 }
 
 unsigned pa_dynarray_append(pa_dynarray*a, void *p) {
-    unsigned i = a->n_entries;
+    unsigned i;
+
+    pa_assert(a);
+
+    i = a->n_entries;
     pa_dynarray_put(a, i, p);
     return i;
 }
 
 void *pa_dynarray_get(pa_dynarray*a, unsigned i) {
-    assert(a);
+    pa_assert(a);
+
     if (i >= a->n_entries)
         return NULL;
 
-    assert(a->data);
+    pa_assert(a->data);
     return a->data[i];
 }
 
 unsigned pa_dynarray_size(pa_dynarray*a) {
-    assert(a);
+    pa_assert(a);
+
     return a->n_entries;
 }
index c0c3a6d8c042bde9c50259a77aa0dc73475e916d..8f7cfade31f34de9d91d17df418b68eeebe66d62 100644 (file)
 
 #include <inttypes.h>
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
+#ifndef PACKAGE
+#error "Please include config.h before including this file!"
 #endif
 
-#define INT16_SWAP(x) ( (int16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) )
-#define UINT16_SWAP(x) ( (uint16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) )
-#define INT32_SWAP(x) ( (int32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) )
-#define UINT32_SWAP(x) ( (uint32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) )
+#ifdef HAVE_BYTESWAP_H
+#include <byteswap.h>
+#endif
+
+#ifdef HAVE_BYTESWAP_H
+#define PA_INT16_SWAP(x) ((int16_t) bswap_16((uint16_t) x))
+#define PA_UINT16_SWAP(x) ((uint16_t) bswap_16((uint16_t) x))
+#define PA_INT32_SWAP(x) ((int32_t) bswap_32((uint32_t) x))
+#define PA_UINT32_SWAP(x) ((uint32_t) bswap_32((uint32_t) x))
+#else
+#define PA_INT16_SWAP(x) ( (int16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) )
+#define PA_UINT16_SWAP(x) ( (uint16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) )
+#define PA_INT32_SWAP(x) ( (int32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) )
+#define PA_UINT32_SWAP(x) ( (uint32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) )
+#endif
+
+#define PA_MAYBE_INT16_SWAP(c,x) ((c) ? PA_INT32_SWAP(x) : x)
+#define PA_MAYBE_UINT16_SWAP(c,x) ((c) ? PA_UINT32_SWAP(x) : x)
 
-#define MAYBE_INT32_SWAP(c,x) ((c) ? INT32_SWAP(x) : x)
-#define MAYBE_UINT32_SWAP(c,x) ((c) ? UINT32_SWAP(x) : x)
+#define PA_MAYBE_INT32_SWAP(c,x) ((c) ? PA_INT32_SWAP(x) : x)
+#define PA_MAYBE_UINT32_SWAP(c,x) ((c) ? PA_UINT32_SWAP(x) : x)
 
 #ifdef WORDS_BIGENDIAN
- #define INT16_FROM_LE(x) INT16_SWAP(x)
- #define INT16_FROM_BE(x) ((int16_t)(x))
+ #define PA_INT16_FROM_LE(x) PA_INT16_SWAP(x)
+ #define PA_INT16_FROM_BE(x) ((int16_t)(x))
 
- #define INT16_TO_LE(x) INT16_SWAP(x)
- #define INT16_TO_BE(x) ((int16_t)(x))
+ #define PA_INT16_TO_LE(x) PA_INT16_SWAP(x)
+ #define PA_INT16_TO_BE(x) ((int16_t)(x))
 
- #define UINT16_FROM_LE(x) UINT16_SWAP(x)
- #define UINT16_FROM_BE(x) ((uint16_t)(x))
+ #define PA_UINT16_FROM_LE(x) PA_UINT16_SWAP(x)
+ #define PA_UINT16_FROM_BE(x) ((uint16_t)(x))
 
- #define INT32_FROM_LE(x) INT32_SWAP(x)
- #define INT32_FROM_BE(x) ((int32_t)(x))
+ #define PA_INT32_FROM_LE(x) PA_INT32_SWAP(x)
+ #define PA_INT32_FROM_BE(x) ((int32_t)(x))
 
- #define UINT32_FROM_LE(x) UINT32_SWAP(x)
- #define UINT32_FROM_BE(x) ((uint32_t)(x))
+ #define PA_UINT32_FROM_LE(x) PA_UINT32_SWAP(x)
+ #define PA_UINT32_FROM_BE(x) ((uint32_t)(x))
 
- #define UINT32_TO_LE(x) UINT32_SWAP(x)
- #define UINT32_TO_BE(x) ((uint32_t)(x))
+ #define PA_UINT32_TO_LE(x) PA_UINT32_SWAP(x)
+ #define PA_UINT32_TO_BE(x) ((uint32_t)(x))
 #else
- #define INT16_FROM_LE(x) ((int16_t)(x))
- #define INT16_FROM_BE(x) INT16_SWAP(x)
+ #define PA_INT16_FROM_LE(x) ((int16_t)(x))
+ #define PA_INT16_FROM_BE(x) PA_INT16_SWAP(x)
 
- #define INT16_TO_LE(x) ((int16_t)(x))
- #define INT16_TO_BE(x) INT16_SWAP(x)
+ #define PA_INT16_TO_LE(x) ((int16_t)(x))
+ #define PA_INT16_TO_BE(x) PA_INT16_SWAP(x)
 
- #define UINT16_FROM_LE(x) ((uint16_t)(x))
- #define UINT16_FROM_BE(x) UINT16_SWAP(x)
+ #define PA_UINT16_FROM_LE(x) ((uint16_t)(x))
+ #define PA_UINT16_FROM_BE(x) PA_UINT16_SWAP(x)
 
- #define INT32_FROM_LE(x) ((int32_t)(x))
- #define INT32_FROM_BE(x) INT32_SWAP(x)
+ #define PA_INT32_FROM_LE(x) ((int32_t)(x))
+ #define PA_INT32_FROM_BE(x) PA_INT32_SWAP(x)
 
- #define UINT32_FROM_LE(x) ((uint32_t)(x))
- #define UINT32_FROM_BE(x) UINT32_SWAP(x)
+ #define PA_UINT32_FROM_LE(x) ((uint32_t)(x))
+ #define PA_UINT32_FROM_BE(x) PA_UINT32_SWAP(x)
 
- #define UINT32_TO_LE(x) ((uint32_t)(x))
- #define UINT32_TO_BE(x) UINT32_SWAP(x)
+ #define PA_UINT32_TO_LE(x) ((uint32_t)(x))
+ #define PA_UINT32_TO_BE(x) PA_UINT32_SWAP(x)
 #endif
 
 #endif
index 3778a535f608e062ad8530b421f74b85c6fe3578..ea6a566505b1c8cddfd7125c96b82eacb625e799 100644 (file)
@@ -205,7 +205,7 @@ typedef int esd_client_state_t;
 /* the endian key is transferred in binary, if it's read into int, */
 /* and matches ESD_ENDIAN_KEY (ENDN), then the endianness of the */
 /* server and the client match; if it's SWAP_ENDIAN_KEY, swap data */
-#define ESD_SWAP_ENDIAN_KEY (UINT32_SWAP(ESD_ENDIAN_KEY))
+#define ESD_SWAP_ENDIAN_KEY (PA_UINT32_SWAP(ESD_ENDIAN_KEY))
 
 
 #endif
diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c
new file mode 100644 (file)
index 0000000..927bf00
--- /dev/null
@@ -0,0 +1,276 @@
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, 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
+
+#ifdef HAVE_SYS_SYSCALL_H
+#include <sys/syscall.h>
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <pulsecore/atomic.h>
+#include <pulsecore/log.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
+#include <pulse/xmalloc.h>
+
+#ifndef HAVE_PIPE
+#include <pulsecore/pipe.h>
+#endif
+
+#ifdef __linux__
+
+#if !defined(__NR_eventfd) && defined(__i386__)
+#define __NR_eventfd 323
+#endif
+
+#if !defined(__NR_eventfd) && defined(__x86_64__)
+#define __NR_eventfd 284
+#endif
+
+#if !defined(SYS_eventfd) && defined(__NR_eventfd)
+#define SYS_eventfd __NR_eventfd
+#endif
+
+#ifdef SYS_eventfd
+#define HAVE_EVENTFD
+
+static inline long eventfd(unsigned count) {
+    return syscall(SYS_eventfd, count);
+}
+
+#endif
+#endif
+
+#include "fdsem.h"
+
+struct pa_fdsem {
+    int fds[2];
+#ifdef HAVE_EVENTFD
+    int efd;
+#endif
+    pa_atomic_t waiting;
+    pa_atomic_t signalled;
+    pa_atomic_t in_pipe;
+};
+
+pa_fdsem *pa_fdsem_new(void) {
+    pa_fdsem *f;
+
+    f = pa_xnew(pa_fdsem, 1);
+
+#ifdef HAVE_EVENTFD
+    if ((f->efd = eventfd(0)) >= 0) {
+        pa_make_fd_cloexec(f->efd);
+        f->fds[0] = f->fds[1] = -1;
+
+    } else
+#endif
+    {
+        if (pipe(f->fds) < 0) {
+            pa_xfree(f);
+            return NULL;
+        }
+
+        pa_make_fd_cloexec(f->fds[0]);
+        pa_make_fd_cloexec(f->fds[1]);
+    }
+
+    pa_atomic_store(&f->waiting, 0);
+    pa_atomic_store(&f->signalled, 0);
+    pa_atomic_store(&f->in_pipe, 0);
+
+    return f;
+}
+
+void pa_fdsem_free(pa_fdsem *f) {
+    pa_assert(f);
+
+#ifdef HAVE_EVENTFD
+    if (f->efd >= 0)
+        pa_close(f->efd);
+#endif
+    pa_close_pipe(f->fds);
+
+    pa_xfree(f);
+}
+
+static void flush(pa_fdsem *f) {
+    ssize_t r;
+    pa_assert(f);
+
+    if (pa_atomic_load(&f->in_pipe) <= 0)
+        return;
+
+    do {
+        char x[10];
+
+#ifdef HAVE_EVENTFD
+        if (f->efd >= 0) {
+            uint64_t u;
+
+            if ((r = read(f->efd, &u, sizeof(u))) != sizeof(u)) {
+                pa_assert(r < 0 && errno == EINTR);
+                continue;
+            }
+            r = (ssize_t) u;
+        } else
+#endif
+
+        if ((r = read(f->fds[0], &x, sizeof(x))) <= 0) {
+            pa_assert(r < 0 && errno == EINTR);
+            continue;
+        }
+
+    } while (pa_atomic_sub(&f->in_pipe, r) > r);
+}
+
+void pa_fdsem_post(pa_fdsem *f) {
+    pa_assert(f);
+
+    if (pa_atomic_cmpxchg(&f->signalled, 0, 1)) {
+
+        if (pa_atomic_load(&f->waiting)) {
+            ssize_t r;
+            char x = 'x';
+
+            pa_atomic_inc(&f->in_pipe);
+
+            for (;;) {
+
+#ifdef HAVE_EVENTFD
+                if (f->efd >= 0) {
+                    uint64_t u = 1;
+
+                    if ((r = write(f->efd, &u, sizeof(u))) != sizeof(u)) {
+                        pa_assert(r < 0 && errno == EINTR);
+                        continue;
+                    }
+                } else
+#endif
+
+                if ((r = write(f->fds[1], &x, 1)) != 1) {
+                    pa_assert(r < 0 && errno == EINTR);
+                    continue;
+                }
+
+                break;
+            }
+        }
+    }
+}
+
+void pa_fdsem_wait(pa_fdsem *f) {
+    pa_assert(f);
+
+    flush(f);
+
+    if (pa_atomic_cmpxchg(&f->signalled, 1, 0))
+        return;
+
+    pa_atomic_inc(&f->waiting);
+
+    while (!pa_atomic_cmpxchg(&f->signalled, 1, 0)) {
+        char x[10];
+        ssize_t r;
+
+#ifdef HAVE_EVENTFD
+        if (f->efd >= 0) {
+            uint64_t u;
+
+            if ((r = read(f->efd, &u, sizeof(u))) != sizeof(u)) {
+                pa_assert(r < 0 && errno == EINTR);
+                continue;
+            }
+
+            r = (ssize_t) u;
+        } else
+#endif
+
+        if ((r = read(f->fds[0], &x, sizeof(x))) <= 0) {
+            pa_assert(r < 0 && errno == EINTR);
+            continue;
+        }
+
+        pa_atomic_sub(&f->in_pipe, r);
+    }
+
+    pa_assert_se(pa_atomic_dec(&f->waiting) >= 1);
+}
+
+int pa_fdsem_try(pa_fdsem *f) {
+    pa_assert(f);
+
+    flush(f);
+
+    if (pa_atomic_cmpxchg(&f->signalled, 1, 0))
+        return 1;
+
+    return 0;
+}
+
+int pa_fdsem_get(pa_fdsem *f) {
+    pa_assert(f);
+
+#ifdef HAVE_EVENTFD
+    if (f->efd >= 0)
+        return f->efd;
+#endif
+
+    return f->fds[0];
+}
+
+int pa_fdsem_before_poll(pa_fdsem *f) {
+    pa_assert(f);
+
+    flush(f);
+
+    if (pa_atomic_cmpxchg(&f->signalled, 1, 0))
+        return -1;
+
+    pa_atomic_inc(&f->waiting);
+
+    if (pa_atomic_cmpxchg(&f->signalled, 1, 0)) {
+        pa_assert_se(pa_atomic_dec(&f->waiting) >= 1);
+        return -1;
+    }
+    return 0;
+}
+
+int pa_fdsem_after_poll(pa_fdsem *f) {
+    pa_assert(f);
+
+    pa_assert_se(pa_atomic_dec(&f->waiting) >= 1);
+
+    flush(f);
+
+    if (pa_atomic_cmpxchg(&f->signalled, 1, 0))
+        return 1;
+
+    return 0;
+}
diff --git a/src/pulsecore/fdsem.h b/src/pulsecore/fdsem.h
new file mode 100644 (file)
index 0000000..f38ef20
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef foopulsefdsemhfoo
+#define foopulsefdsemhfoo
+
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#include <sys/types.h>
+#include <pulse/def.h>
+
+/* A simple, asynchronous semaphore which uses fds for sleeping. In
+ * the best case all functions are lock-free unless sleeping is
+ * required.  */
+
+typedef struct pa_fdsem pa_fdsem;
+
+pa_fdsem *pa_fdsem_new(void);
+void pa_fdsem_free(pa_fdsem *f);
+
+void pa_fdsem_post(pa_fdsem *f);
+void pa_fdsem_wait(pa_fdsem *f);
+int pa_fdsem_try(pa_fdsem *f);
+
+int pa_fdsem_get(pa_fdsem *f);
+
+int pa_fdsem_before_poll(pa_fdsem *f);
+int pa_fdsem_after_poll(pa_fdsem *f);
+
+
+#endif
diff --git a/src/pulsecore/ffmpeg/Makefile b/src/pulsecore/ffmpeg/Makefile
new file mode 100644 (file)
index 0000000..316beb7
--- /dev/null
@@ -0,0 +1,13 @@
+# This is a dirty trick just to ease compilation with emacs
+#
+# This file is not intended to be distributed or anything
+#
+# So: don't touch it, even better ignore it!
+
+all:
+       $(MAKE) -C ../..
+
+clean:
+       $(MAKE) -C ../.. clean
+
+.PHONY: all clean
diff --git a/src/pulsecore/ffmpeg/avcodec.h b/src/pulsecore/ffmpeg/avcodec.h
new file mode 100644 (file)
index 0000000..696fc98
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * copyright (c) 2001 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_H
+#define AVCODEC_H
+
+/* Just a heavily bastardized version of the original file from
+ * ffmpeg, just enough to get resample2.c to compile without
+ * modification -- Lennart */
+
+#if !defined(PACKAGE) && defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#define av_mallocz(l) calloc(1, (l))
+#define av_malloc(l) malloc(l)
+#define av_realloc(p,l) realloc((p),(l))
+#define av_free(p) free(p)
+
+static inline void av_freep(void *k) {
+    void **p = k;
+
+    if (p) {
+        free(*p);
+        *p = NULL;
+    }
+}
+
+static inline int av_clip(int a, int amin, int amax)
+{
+    if (a < amin)      return amin;
+    else if (a > amax) return amax;
+    else               return a;
+}
+
+#define av_log(a,b,c)
+
+#define FFABS(a) ((a) >= 0 ? (a) : (-(a)))
+#define FFSIGN(a) ((a) > 0 ? 1 : -1)
+
+#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
+#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
+
+struct AVResampleContext;
+struct AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_length, int log2_phase_count, int linear, double cutoff);
+int av_resample(struct AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx);
+void av_resample_compensate(struct AVResampleContext *c, int sample_delta, int compensation_distance);
+void av_resample_close(struct AVResampleContext *c);
+void av_build_filter(int16_t *filter, double factor, int tap_count, int phase_count, int scale, int type);
+
+/*
+ * crude lrintf for non-C99 systems.
+ */
+#ifndef HAVE_LRINTF
+#define lrintf(x) ((long int)(x))
+#endif
+
+#endif /* AVCODEC_H */
diff --git a/src/pulsecore/ffmpeg/dsputil.h b/src/pulsecore/ffmpeg/dsputil.h
new file mode 100644 (file)
index 0000000..8da742d
--- /dev/null
@@ -0,0 +1 @@
+/* empty file, just here to allow us to compile an unmodified resampler2.c */
diff --git a/src/pulsecore/ffmpeg/resample2.c b/src/pulsecore/ffmpeg/resample2.c
new file mode 100644 (file)
index 0000000..da1443d
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * audio resampling
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file resample2.c
+ * audio resampling
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#include "avcodec.h"
+#include "dsputil.h"
+
+#ifndef CONFIG_RESAMPLE_HP
+#define FILTER_SHIFT 15
+
+#define FELEM int16_t
+#define FELEM2 int32_t
+#define FELEML int64_t
+#define FELEM_MAX INT16_MAX
+#define FELEM_MIN INT16_MIN
+#define WINDOW_TYPE 9
+#elif !defined(CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE)
+#define FILTER_SHIFT 30
+
+#define FELEM int32_t
+#define FELEM2 int64_t
+#define FELEML int64_t
+#define FELEM_MAX INT32_MAX
+#define FELEM_MIN INT32_MIN
+#define WINDOW_TYPE 12
+#else
+#define FILTER_SHIFT 0
+
+#define FELEM double
+#define FELEM2 double
+#define FELEML double
+#define WINDOW_TYPE 24
+#endif
+
+
+typedef struct AVResampleContext{
+    FELEM *filter_bank;
+    int filter_length;
+    int ideal_dst_incr;
+    int dst_incr;
+    int index;
+    int frac;
+    int src_incr;
+    int compensation_distance;
+    int phase_shift;
+    int phase_mask;
+    int linear;
+}AVResampleContext;
+
+/**
+ * 0th order modified bessel function of the first kind.
+ */
+static double bessel(double x){
+    double v=1;
+    double t=1;
+    int i;
+
+    x= x*x/4;
+    for(i=1; i<50; i++){
+        t *= x/(i*i);
+        v += t;
+    }
+    return v;
+}
+
+/**
+ * builds a polyphase filterbank.
+ * @param factor resampling factor
+ * @param scale wanted sum of coefficients for each filter
+ * @param type 0->cubic, 1->blackman nuttall windowed sinc, 2..16->kaiser windowed sinc beta=2..16
+ */
+void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_count, int scale, int type){
+    int ph, i;
+    double x, y, w, tab[tap_count];
+    const int center= (tap_count-1)/2;
+
+    /* if upsampling, only need to interpolate, no filter */
+    if (factor > 1.0)
+        factor = 1.0;
+
+    for(ph=0;ph<phase_count;ph++) {
+        double norm = 0;
+        for(i=0;i<tap_count;i++) {
+            x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor;
+            if (x == 0) y = 1.0;
+            else        y = sin(x) / x;
+            switch(type){
+            case 0:{
+                const float d= -0.5; //first order derivative = -0.5
+                x = fabs(((double)(i - center) - (double)ph / phase_count) * factor);
+                if(x<1.0) y= 1 - 3*x*x + 2*x*x*x + d*(            -x*x + x*x*x);
+                else      y=                       d*(-4 + 8*x - 5*x*x + x*x*x);
+                break;}
+            case 1:
+                w = 2.0*x / (factor*tap_count) + M_PI;
+                y *= 0.3635819 - 0.4891775 * cos(w) + 0.1365995 * cos(2*w) - 0.0106411 * cos(3*w);
+                break;
+            default:
+                w = 2.0*x / (factor*tap_count*M_PI);
+                y *= bessel(type*sqrt(FFMAX(1-w*w, 0)));
+                break;
+            }
+
+            tab[i] = y;
+            norm += y;
+        }
+
+        /* normalize so that an uniform color remains the same */
+        for(i=0;i<tap_count;i++) {
+#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE
+            filter[ph * tap_count + i] = tab[i] / norm;
+#else
+            filter[ph * tap_count + i] = av_clip(lrintf(tab[i] * scale / norm), FELEM_MIN, FELEM_MAX);
+#endif
+        }
+    }
+#if 0
+    {
+#define LEN 1024
+        int j,k;
+        double sine[LEN + tap_count];
+        double filtered[LEN];
+        double maxff=-2, minff=2, maxsf=-2, minsf=2;
+        for(i=0; i<LEN; i++){
+            double ss=0, sf=0, ff=0;
+            for(j=0; j<LEN+tap_count; j++)
+                sine[j]= cos(i*j*M_PI/LEN);
+            for(j=0; j<LEN; j++){
+                double sum=0;
+                ph=0;
+                for(k=0; k<tap_count; k++)
+                    sum += filter[ph * tap_count + k] * sine[k+j];
+                filtered[j]= sum / (1<<FILTER_SHIFT);
+                ss+= sine[j + center] * sine[j + center];
+                ff+= filtered[j] * filtered[j];
+                sf+= sine[j + center] * filtered[j];
+            }
+            ss= sqrt(2*ss/LEN);
+            ff= sqrt(2*ff/LEN);
+            sf= 2*sf/LEN;
+            maxff= FFMAX(maxff, ff);
+            minff= FFMIN(minff, ff);
+            maxsf= FFMAX(maxsf, sf);
+            minsf= FFMIN(minsf, sf);
+            if(i%11==0){
+                av_log(NULL, AV_LOG_ERROR, "i:%4d ss:%f ff:%13.6e-%13.6e sf:%13.6e-%13.6e\n", i, ss, maxff, minff, maxsf, minsf);
+                minff=minsf= 2;
+                maxff=maxsf= -2;
+            }
+        }
+    }
+#endif
+}
+
+/**
+ * Initializes an audio resampler.
+ * Note, if either rate is not an integer then simply scale both rates up so they are.
+ */
+AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff){
+    AVResampleContext *c= av_mallocz(sizeof(AVResampleContext));
+    double factor= FFMIN(out_rate * cutoff / in_rate, 1.0);
+    int phase_count= 1<<phase_shift;
+
+    c->phase_shift= phase_shift;
+    c->phase_mask= phase_count-1;
+    c->linear= linear;
+
+    c->filter_length= FFMAX((int)ceil(filter_size/factor), 1);
+    c->filter_bank= av_mallocz(c->filter_length*(phase_count+1)*sizeof(FELEM));
+    av_build_filter(c->filter_bank, factor, c->filter_length, phase_count, 1<<FILTER_SHIFT, WINDOW_TYPE);
+    memcpy(&c->filter_bank[c->filter_length*phase_count+1], c->filter_bank, (c->filter_length-1)*sizeof(FELEM));
+    c->filter_bank[c->filter_length*phase_count]= c->filter_bank[c->filter_length - 1];
+
+    c->src_incr= out_rate;
+    c->ideal_dst_incr= c->dst_incr= in_rate * phase_count;
+    c->index= -phase_count*((c->filter_length-1)/2);
+
+    return c;
+}
+
+void av_resample_close(AVResampleContext *c){
+    av_freep(&c->filter_bank);
+    av_freep(&c);
+}
+
+/**
+ * Compensates samplerate/timestamp drift. The compensation is done by changing
+ * the resampler parameters, so no audible clicks or similar distortions ocur
+ * @param compensation_distance distance in output samples over which the compensation should be performed
+ * @param sample_delta number of output samples which should be output less
+ *
+ * example: av_resample_compensate(c, 10, 500)
+ * here instead of 510 samples only 500 samples would be output
+ *
+ * note, due to rounding the actual compensation might be slightly different,
+ * especially if the compensation_distance is large and the in_rate used during init is small
+ */
+void av_resample_compensate(AVResampleContext *c, int sample_delta, int compensation_distance){
+//    sample_delta += (c->ideal_dst_incr - c->dst_incr)*(int64_t)c->compensation_distance / c->ideal_dst_incr;
+    c->compensation_distance= compensation_distance;
+    c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance;
+}
+
+/**
+ * resamples.
+ * @param src an array of unconsumed samples
+ * @param consumed the number of samples of src which have been consumed are returned here
+ * @param src_size the number of unconsumed samples available
+ * @param dst_size the amount of space in samples available in dst
+ * @param update_ctx if this is 0 then the context wont be modified, that way several channels can be resampled with the same context
+ * @return the number of samples written in dst or -1 if an error occured
+ */
+int av_resample(AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx){
+    int dst_index, i;
+    int index= c->index;
+    int frac= c->frac;
+    int dst_incr_frac= c->dst_incr % c->src_incr;
+    int dst_incr=      c->dst_incr / c->src_incr;
+    int compensation_distance= c->compensation_distance;
+
+  if(compensation_distance == 0 && c->filter_length == 1 && c->phase_shift==0){
+        int64_t index2= ((int64_t)index)<<32;
+        int64_t incr= (1LL<<32) * c->dst_incr / c->src_incr;
+        dst_size= FFMIN(dst_size, (src_size-1-index) * (int64_t)c->src_incr / c->dst_incr);
+
+        for(dst_index=0; dst_index < dst_size; dst_index++){
+            dst[dst_index] = src[index2>>32];
+            index2 += incr;
+        }
+        frac += dst_index * dst_incr_frac;
+        index += dst_index * dst_incr;
+        index += frac / c->src_incr;
+        frac %= c->src_incr;
+  }else{
+    for(dst_index=0; dst_index < dst_size; dst_index++){
+        FELEM *filter= c->filter_bank + c->filter_length*(index & c->phase_mask);
+        int sample_index= index >> c->phase_shift;
+        FELEM2 val=0;
+
+        if(sample_index < 0){
+            for(i=0; i<c->filter_length; i++)
+                val += src[FFABS(sample_index + i) % src_size] * filter[i];
+        }else if(sample_index + c->filter_length > src_size){
+            break;
+        }else if(c->linear){
+            FELEM2 v2=0;
+            for(i=0; i<c->filter_length; i++){
+                val += src[sample_index + i] * (FELEM2)filter[i];
+                v2  += src[sample_index + i] * (FELEM2)filter[i + c->filter_length];
+            }
+            val+=(v2-val)*(FELEML)frac / c->src_incr;
+        }else{
+            for(i=0; i<c->filter_length; i++){
+                val += src[sample_index + i] * (FELEM2)filter[i];
+            }
+        }
+
+#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE
+        dst[dst_index] = av_clip_int16(lrintf(val));
+#else
+        val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;
+        dst[dst_index] = (unsigned)(val + 32768) > 65535 ? (val>>31) ^ 32767 : val;
+#endif
+
+        frac += dst_incr_frac;
+        index += dst_incr;
+        if(frac >= c->src_incr){
+            frac -= c->src_incr;
+            index++;
+        }
+
+        if(dst_index + 1 == compensation_distance){
+            compensation_distance= 0;
+            dst_incr_frac= c->ideal_dst_incr % c->src_incr;
+            dst_incr=      c->ideal_dst_incr / c->src_incr;
+        }
+    }
+  }
+    *consumed= FFMAX(index, 0) >> c->phase_shift;
+    if(index>=0) index &= c->phase_mask;
+
+    if(compensation_distance){
+        compensation_distance -= dst_index;
+        assert(compensation_distance > 0);
+    }
+    if(update_ctx){
+        c->frac= frac;
+        c->index= index;
+        c->dst_incr= dst_incr_frac + c->src_incr*dst_incr;
+        c->compensation_distance= compensation_distance;
+    }
+#if 0
+    if(update_ctx && !c->compensation_distance){
+#undef rand
+        av_resample_compensate(c, rand() % (8000*2) - 8000, 8000*2);
+av_log(NULL, AV_LOG_DEBUG, "%d %d %d\n", c->dst_incr, c->ideal_dst_incr, c->compensation_distance);
+    }
+#endif
+
+    return dst_index;
+}
index 00567ab32dc53765fd781fff7bec8a9ceb2a8db4..d9740777138b4e9808173c3c679ee584ad535e07 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
+#include <pulse/xmalloc.h>
 
 #include <pulsecore/atomic.h>
 #include <pulsecore/log.h>
 #include <pulsecore/thread.h>
-#include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
 
 #include "flist.h"
 
@@ -90,21 +92,18 @@ enum {
 };
 
 struct cell {
-    pa_atomic_int_t state;
+    pa_atomic_t state;
     void *data;
 };
 
 struct pa_flist {
-    struct cell *cells;
     unsigned size;
-    pa_atomic_int_t length;
-    pa_atomic_int_t read_idx;
-    pa_atomic_int_t write_idx;
+    pa_atomic_t length;
+    pa_atomic_t read_idx;
+    pa_atomic_t write_idx;
 };
 
-static int is_power_of_two(unsigned size) {
-    return !(size & (size - 1));
-}
+#define PA_FLIST_CELLS(x) ((struct cell*) ((uint8_t*) (x) + PA_ALIGN(sizeof(struct pa_flist))))
 
 pa_flist *pa_flist_new(unsigned size) {
     pa_flist *l;
@@ -112,12 +111,11 @@ pa_flist *pa_flist_new(unsigned size) {
     if (!size)
         size = FLIST_SIZE;
 
-    assert(is_power_of_two(size));
+    pa_assert(pa_is_power_of_two(size));
 
-    l = pa_xnew(pa_flist, 1);
+    l = pa_xmalloc0(PA_ALIGN(sizeof(pa_flist)) + (sizeof(struct cell) * size));
 
     l->size = size;
-    l->cells = pa_xnew0(struct cell, size);
 
     pa_atomic_store(&l->read_idx, 0);
     pa_atomic_store(&l->write_idx, 0);
@@ -131,32 +129,37 @@ static int reduce(pa_flist *l, int value) {
 }
 
 void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb) {
-    assert(l);
+    pa_assert(l);
 
     if (free_cb) {
+        struct cell *cells;
         int len, idx;
 
+        cells = PA_FLIST_CELLS(l);
+
         idx = reduce(l, pa_atomic_load(&l->read_idx));
         len = pa_atomic_load(&l->length);
 
         for (; len > 0; len--) {
 
-            if (pa_atomic_load(&l->cells[idx].state) == STATE_USED)
-                free_cb(l->cells[idx].data);
+            if (pa_atomic_load(&cells[idx].state) == STATE_USED)
+                free_cb(cells[idx].data);
 
             idx = reduce(l, idx + 1);
         }
     }
 
-    pa_xfree(l->cells);
     pa_xfree(l);
 }
 
 int pa_flist_push(pa_flist*l, void *p) {
     int idx, len, n;
+    struct cell *cells;
+
+    pa_assert(l);
+    pa_assert(p);
 
-    assert(l);
-    assert(p);
+    cells = PA_FLIST_CELLS(l);
 
     n = len = (int) l->size - pa_atomic_load(&l->length) + N_EXTRA_SCAN;
     _Y;
@@ -165,13 +168,13 @@ int pa_flist_push(pa_flist*l, void *p) {
     for (; n > 0 ; n--) {
         _Y;
 
-        if (pa_atomic_cmpxchg(&l->cells[idx].state, STATE_UNUSED, STATE_BUSY)) {
+        if (pa_atomic_cmpxchg(&cells[idx].state, STATE_UNUSED, STATE_BUSY)) {
             _Y;
             pa_atomic_inc(&l->write_idx);
             _Y;
-            l->cells[idx].data = p;
+            cells[idx].data = p;
             _Y;
-            pa_atomic_store(&l->cells[idx].state, STATE_USED);
+            pa_atomic_store(&cells[idx].state, STATE_USED);
             _Y;
             pa_atomic_inc(&l->length);
             return 0;
@@ -183,7 +186,7 @@ int pa_flist_push(pa_flist*l, void *p) {
 
 #ifdef PROFILE
     if (len > N_EXTRA_SCAN)
-        pa_log("WARNING: Didn't  find free cell after %u iterations.", len);
+        pa_log_warn("Didn't  find free cell after %u iterations.", len);
 #endif
 
     return -1;
@@ -191,8 +194,11 @@ int pa_flist_push(pa_flist*l, void *p) {
 
 void* pa_flist_pop(pa_flist*l) {
     int idx, len, n;
+    struct cell *cells;
+
+    pa_assert(l);
 
-    assert(l);
+    cells = PA_FLIST_CELLS(l);
 
     n = len = pa_atomic_load(&l->length) + N_EXTRA_SCAN;
     _Y;
@@ -201,14 +207,14 @@ void* pa_flist_pop(pa_flist*l) {
     for (; n > 0 ; n--) {
         _Y;
 
-        if (pa_atomic_cmpxchg(&l->cells[idx].state, STATE_USED, STATE_BUSY)) {
+        if (pa_atomic_cmpxchg(&cells[idx].state, STATE_USED, STATE_BUSY)) {
             void *p;
             _Y;
             pa_atomic_inc(&l->read_idx);
             _Y;
-            p = l->cells[idx].data;
+            p = cells[idx].data;
             _Y;
-            pa_atomic_store(&l->cells[idx].state, STATE_UNUSED);
+            pa_atomic_store(&cells[idx].state, STATE_UNUSED);
             _Y;
 
             pa_atomic_dec(&l->length);
@@ -221,7 +227,7 @@ void* pa_flist_pop(pa_flist*l) {
 
 #ifdef PROFILE
     if (len > N_EXTRA_SCAN)
-        pa_log("WARNING: Didn't find used cell after %u iterations.", len);
+        pa_log_warn("Didn't find used cell after %u iterations.", len);
 #endif
 
     return NULL;
index bf702bf33ef1fe7618420fca0380819cf2691e68..daf0fec417ec8e2abbf91d653d643c8920ea52fb 100644 (file)
@@ -26,6 +26,9 @@
 
 #include <pulse/def.h>
 
+#include <pulsecore/once.h>
+#include <pulsecore/gccmacro.h>
+
 /* A multiple-reader multipler-write lock-free free list implementation */
 
 typedef struct pa_flist pa_flist;
@@ -38,4 +41,28 @@ void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb);
 int pa_flist_push(pa_flist*l, void *p);
 void* pa_flist_pop(pa_flist*l);
 
+/* Please not that the destructor stuff is not really necesary, we do
+ * this just to make valgrind output more useful. */
+
+#define PA_STATIC_FLIST_DECLARE(name, size, free_cb)                    \
+    static struct {                                                     \
+        pa_flist *flist;                                                \
+        pa_once once;                                                   \
+    } name##_flist = { NULL, PA_ONCE_INIT };                            \
+    static void name##_flist_init(void) {                               \
+        name##_flist.flist = pa_flist_new(size);                        \
+    }                                                                   \
+    static inline pa_flist* name##_flist_get(void) {                    \
+        pa_run_once(&name##_flist.once, name##_flist_init);             \
+        return name##_flist.flist;                                      \
+    }                                                                   \
+    static void name##_flist_destructor(void) PA_GCC_DESTRUCTOR;        \
+    static void name##_flist_destructor(void) {                         \
+        if (name##_flist.flist)                                         \
+            pa_flist_free(name##_flist.flist, (free_cb));               \
+    }                                                                   \
+    struct __stupid_useless_struct_to_allow_trailing_semicolon
+
+#define PA_STATIC_FLIST_GET(name) (name##_flist_get())
+
 #endif
index 8c2bbf0084acfb86f0beead9f05a187426587822..aa2d703a8e29326f341eb10989e71158b9962272 100644 (file)
 
 #include "g711.h"
 
-#define        SIGN_BIT        (0x80)          /* Sign bit for a A-law byte. */
-#define        QUANT_MASK      (0xf)           /* Quantization field mask. */
-#define        NSEGS           (8)             /* Number of A-law segments. */
-#define        SEG_SHIFT       (4)             /* Left shift for segment number. */
-#define        SEG_MASK        (0x70)          /* Segment field mask. */
+#define        SIGN_BIT        (0x80)                /* Sign bit for a A-law byte. */
+#define        QUANT_MASK        (0xf)                /* Quantization field mask. */
+#define        NSEGS                (8)                /* Number of A-law segments. */
+#define        SEG_SHIFT        (4)                /* Left shift for segment number. */
+#define        SEG_MASK        (0x70)                /* Segment field mask. */
 
 #if !defined(FAST_ALAW_CONVERSION) || !defined(FAST_ULAW_CONVERSION)
 static int16_t seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF,
-                             0x1FF, 0x3FF, 0x7FF, 0xFFF};
+                              0x1FF, 0x3FF, 0x7FF, 0xFFF};
 static int16_t seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
-                             0x3FF, 0x7FF, 0xFFF, 0x1FFF};
+                              0x3FF, 0x7FF, 0xFFF, 0x1FFF};
 
 static int16_t search(
-       int16_t val,
-       int16_t *table,
-       int size)
+        int16_t        val,
+        int16_t *table,
+        int size)
 {
-       int i;
+        int i;
 
-       for (i = 0; i < size; i++) {
-               if (val <= *table++)
-                       return (i);
-       }
-       return (size);
+        for (i = 0; i < size; i++) {
+                if (val <= *table++)
+                        return (i);
+        }
+        return (size);
 }
 #endif /* !FAST_*_CONVERSION */
 
@@ -77,55 +77,55 @@ static int16_t search(
  * the data shifted such that it only contains information in the lower
  * 13-bits.
  *
- *             Linear Input Code       Compressed Code
- *     ------------------------        ---------------
- *     0000000wxyza                    000wxyz
- *     0000001wxyza                    001wxyz
- *     000001wxyzab                    010wxyz
- *     00001wxyzabc                    011wxyz
- *     0001wxyzabcd                    100wxyz
- *     001wxyzabcde                    101wxyz
- *     01wxyzabcdef                    110wxyz
- *     1wxyzabcdefg                    111wxyz
+ *                Linear Input Code        Compressed Code
+ *        ------------------------        ---------------
+ *        0000000wxyza                        000wxyz
+ *        0000001wxyza                        001wxyz
+ *        000001wxyzab                        010wxyz
+ *        00001wxyzabc                        011wxyz
+ *        0001wxyzabcd                        100wxyz
+ *        001wxyzabcde                        101wxyz
+ *        01wxyzabcdef                        110wxyz
+ *        1wxyzabcdefg                        111wxyz
  *
  * For further information see John C. Bellamy's Digital Telephony, 1982,
  * John Wiley & Sons, pps 98-111 and 472-476.
  */
 unsigned char st_13linear2alaw(
-       int16_t         pcm_val)        /* 2's complement (13-bit range) */
+        int16_t                pcm_val)        /* 2's complement (13-bit range) */
 {
-       int16_t         mask;
-       short           seg;
-       unsigned char   aval;
+        int16_t                mask;
+        short                seg;
+        unsigned char        aval;
 
-       /* Have calling software do it since its already doing a shift
-        * from 32-bits down to 16-bits.
-        */
-       /* pcm_val = pcm_val >> 3; */
+        /* Have calling software do it since its already doing a shift
+         * from 32-bits down to 16-bits.
+         */
+        /* pcm_val = pcm_val >> 3; */
 
-       /* A-law using even bit inversion */
-       if (pcm_val >= 0) {
-               mask = 0xD5;            /* sign (7th) bit = 1 */
-       } else {
-               mask = 0x55;            /* sign bit = 0 */
-               pcm_val = -pcm_val - 1;
-       }
+        /* A-law using even bit inversion */
+        if (pcm_val >= 0) {
+                mask = 0xD5;                /* sign (7th) bit = 1 */
+        } else {
+                mask = 0x55;                /* sign bit = 0 */
+                pcm_val = -pcm_val - 1;
+        }
 
-       /* Convert the scaled magnitude to segment number. */
-       seg = search(pcm_val, seg_aend, 8);
+        /* Convert the scaled magnitude to segment number. */
+        seg = search(pcm_val, seg_aend, 8);
 
-       /* Combine the sign, segment, and quantization bits. */
+        /* Combine the sign, segment, and quantization bits. */
 
-       if (seg >= 8)           /* out of range, return maximum value. */
-               return (unsigned char) (0x7F ^ mask);
-       else {
-               aval = (unsigned char) seg << SEG_SHIFT;
-               if (seg < 2)
-                       aval |= (pcm_val >> 1) & QUANT_MASK;
-               else
-                       aval |= (pcm_val >> seg) & QUANT_MASK;
-               return (aval ^ mask);
-       }
+        if (seg >= 8)                /* out of range, return maximum value. */
+                return (unsigned char) (0x7F ^ mask);
+        else {
+                aval = (unsigned char) seg << SEG_SHIFT;
+                if (seg < 2)
+                        aval |= (pcm_val >> 1) & QUANT_MASK;
+                else
+                        aval |= (pcm_val >> seg) & QUANT_MASK;
+                return (aval ^ mask);
+        }
 }
 
 /*
@@ -133,31 +133,31 @@ unsigned char st_13linear2alaw(
  *
  */
 int16_t st_alaw2linear16(
-       unsigned char   a_val)
+        unsigned char        a_val)
 {
-       int16_t t;
-       int16_t seg;
+        int16_t t;
+        int16_t seg;
 
-       a_val ^= 0x55;
+        a_val ^= 0x55;
 
-       t = (a_val & QUANT_MASK) << 4;
-       seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
-       switch (seg) {
-       case 0:
-               t += 8;
-               break;
-       case 1:
-               t += 0x108;
-               break;
-       default:
-               t += 0x108;
-               t <<= seg - 1;
-       }
-       return ((a_val & SIGN_BIT) ? t : -t);
+        t = (a_val & QUANT_MASK) << 4;
+        seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
+        switch (seg) {
+        case 0:
+                t += 8;
+                break;
+        case 1:
+                t += 0x108;
+                break;
+        default:
+                t += 0x108;
+                t <<= seg - 1;
+        }
+        return ((a_val & SIGN_BIT) ? t : -t);
 }
 #endif /* !FAST_ALAW_CONVERSION */
 
-#define        BIAS            (0x84)          /* Bias for linear code. */
+#define        BIAS                (0x84)                /* Bias for linear code. */
 #define CLIP            8159
 
 #ifndef FAST_ULAW_CONVERSION
@@ -171,16 +171,16 @@ int16_t st_alaw2linear16(
  * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
  * (33 - 8191). The result can be seen in the following encoding table:
  *
- *     Biased Linear Input Code        Compressed Code
- *     ------------------------        ---------------
- *     00000001wxyza                   000wxyz
- *     0000001wxyzab                   001wxyz
- *     000001wxyzabc                   010wxyz
- *     00001wxyzabcd                   011wxyz
- *     0001wxyzabcde                   100wxyz
- *     001wxyzabcdef                   101wxyz
- *     01wxyzabcdefg                   110wxyz
- *     1wxyzabcdefgh                   111wxyz
+ *        Biased Linear Input Code        Compressed Code
+ *        ------------------------        ---------------
+ *        00000001wxyza                        000wxyz
+ *        0000001wxyzab                        001wxyz
+ *        000001wxyzabc                        010wxyz
+ *        00001wxyzabcd                        011wxyz
+ *        0001wxyzabcde                        100wxyz
+ *        001wxyzabcdef                        101wxyz
+ *        01wxyzabcdefg                        110wxyz
+ *        1wxyzabcdefgh                        111wxyz
  *
  * Each biased linear code has a leading 1 which identifies the segment
  * number. The value of the segment number is equal to 7 minus the number
@@ -194,41 +194,41 @@ int16_t st_alaw2linear16(
  * John Wiley & Sons, pps 98-111 and 472-476.
  */
 unsigned char st_14linear2ulaw(
-       int16_t         pcm_val)        /* 2's complement (14-bit range) */
+        int16_t                pcm_val)        /* 2's complement (14-bit range) */
 {
-       int16_t         mask;
-       int16_t         seg;
-       unsigned char   uval;
+        int16_t                mask;
+        int16_t                seg;
+        unsigned char        uval;
 
-       /* Have calling software do it since its already doing a shift
-        * from 32-bits down to 16-bits.
-        */
-       /* pcm_val = pcm_val >> 2; */
+        /* Have calling software do it since its already doing a shift
+         * from 32-bits down to 16-bits.
+         */
+        /* pcm_val = pcm_val >> 2; */
 
-       /* u-law inverts all bits */
-       /* Get the sign and the magnitude of the value. */
-       if (pcm_val < 0) {
-               pcm_val = -pcm_val;
-               mask = 0x7F;
-       } else {
-               mask = 0xFF;
-       }
-        if ( pcm_val > CLIP ) pcm_val = CLIP;          /* clip the magnitude */
-       pcm_val += (BIAS >> 2);
+        /* u-law inverts all bits */
+        /* Get the sign and the magnitude of the value. */
+        if (pcm_val < 0) {
+                pcm_val = -pcm_val;
+                mask = 0x7F;
+        } else {
+                mask = 0xFF;
+        }
+        if ( pcm_val > CLIP ) pcm_val = CLIP;                /* clip the magnitude */
+        pcm_val += (BIAS >> 2);
 
-       /* Convert the scaled magnitude to segment number. */
-       seg = search(pcm_val, seg_uend, 8);
+        /* Convert the scaled magnitude to segment number. */
+        seg = search(pcm_val, seg_uend, 8);
 
-       /*
-        * Combine the sign, segment, quantization bits;
-        * and complement the code word.
-        */
-       if (seg >= 8)           /* out of range, return maximum value. */
-               return (unsigned char) (0x7F ^ mask);
-       else {
-               uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
-               return (uval ^ mask);
-       }
+        /*
+         * Combine the sign, segment, quantization bits;
+         * and complement the code word.
+         */
+        if (seg >= 8)                /* out of range, return maximum value. */
+                return (unsigned char) (0x7F ^ mask);
+        else {
+                uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
+                return (uval ^ mask);
+        }
 
 }
 
@@ -242,21 +242,21 @@ unsigned char st_14linear2ulaw(
  * original code word. This is in keeping with ISDN conventions.
  */
 int16_t st_ulaw2linear16(
-       unsigned char   u_val)
+        unsigned char        u_val)
 {
-       int16_t         t;
+        int16_t                t;
 
-       /* Complement to obtain normal u-law value. */
-       u_val = ~u_val;
+        /* Complement to obtain normal u-law value. */
+        u_val = ~u_val;
 
-       /*
-        * Extract and bias the quantization bits. Then
-        * shift up by the segment number and subtract out the bias.
-        */
-       t = ((u_val & QUANT_MASK) << 3) + BIAS;
-       t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
+        /*
+         * Extract and bias the quantization bits. Then
+         * shift up by the segment number and subtract out the bias.
+         */
+        t = ((u_val & QUANT_MASK) << 3) + BIAS;
+        t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
 
-       return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
+        return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
 }
 #endif /* !FAST_ULAW_CONVERSION */
 
@@ -2413,52 +2413,52 @@ int main()
     printf("int16_t _st_alaw2linear16[256] = {\n  ");
     for (x = 0; x < 256; x++)
     {
-       printf("%8d,", st_alaw2linear16(x));
-       y++;
-       if (y == 7)
-       {
-           y = 0;
-           printf("\n  ");
-       }
+        printf("%8d,", st_alaw2linear16(x));
+        y++;
+        if (y == 7)
+        {
+            y = 0;
+            printf("\n  ");
+        }
     }
 
     printf("\n};\n\nuint8_t _st_13linear2alaw[0x2000] = {\n  ");
     y = 0;
     for (x = 0; x < 0x2000; x++)
     {
-       printf(" 0x%02x,", st_13linear2alaw((-0x1000)+x));
-       y++;
-       if (y == 12)
-       {
-           y = 0;
-           printf("\n  ");
-       }
+        printf(" 0x%02x,", st_13linear2alaw((-0x1000)+x));
+        y++;
+        if (y == 12)
+        {
+            y = 0;
+            printf("\n  ");
+        }
     }
 
     printf("\n};\n\nint16_t _st_ulaw2linear16[256] = {\n  ");
     y = 0;
     for (x = 0; x < 256; x++)
     {
-       printf("%8d,", st_ulaw2linear16(x));
-       y++;
-       if (y == 7)
-       {
-           y = 0;
-           printf("\n  ");
-       }
+        printf("%8d,", st_ulaw2linear16(x));
+        y++;
+        if (y == 7)
+        {
+            y = 0;
+            printf("\n  ");
+        }
     }
 
     printf("\n};\n\nuint8_t _st_14linear2ulaw[0x4000] = {\n  ");
     y = 0;
     for (x = 0; x < 0x4000; x++)
     {
-       printf(" 0x%02x,", st_14linear2ulaw((-0x2000)+x));
-       y++;
-       if (y == 12)
-       {
-           y = 0;
-           printf("\n  ");
-       }
+        printf(" 0x%02x,", st_14linear2ulaw((-0x2000)+x));
+        y++;
+        if (y == 12)
+        {
+            y = 0;
+            printf("\n  ");
+        }
     }
     printf("\n};\n");
 
@@ -2468,64 +2468,64 @@ int main()
 /* The following is not used by SoX but kept for reference */
 #if 0
 /* copy from CCITT G.711 specifications */
-unsigned char _u2a[128] = {                    /* u- to A-law conversions */
-       1,      1,      2,      2,      3,      3,      4,      4,
-       5,      5,      6,      6,      7,      7,      8,      8,
-       9,      10,     11,     12,     13,     14,     15,     16,
-       17,     18,     19,     20,     21,     22,     23,     24,
-       25,     27,     29,     31,     33,     34,     35,     36,
-       37,     38,     39,     40,     41,     42,     43,     44,
-       46,     48,     49,     50,     51,     52,     53,     54,
-       55,     56,     57,     58,     59,     60,     61,     62,
-       64,     65,     66,     67,     68,     69,     70,     71,
-       72,     73,     74,     75,     76,     77,     78,     79,
+unsigned char _u2a[128] = {                        /* u- to A-law conversions */
+        1,        1,        2,        2,        3,        3,        4,        4,
+        5,        5,        6,        6,        7,        7,        8,        8,
+        9,        10,        11,        12,        13,        14,        15,        16,
+        17,        18,        19,        20,        21,        22,        23,        24,
+        25,        27,        29,        31,        33,        34,        35,        36,
+        37,        38,        39,        40,        41,        42,        43,        44,
+        46,        48,        49,        50,        51,        52,        53,        54,
+        55,        56,        57,        58,        59,        60,        61,        62,
+        64,        65,        66,        67,        68,        69,        70,        71,
+        72,        73,        74,        75,        76,        77,        78,        79,
 /* corrected:
-       81,     82,     83,     84,     85,     86,     87,     88,
+        81,        82,        83,        84,        85,        86,        87,        88,
    should be: */
-       80,     82,     83,     84,     85,     86,     87,     88,
-       89,     90,     91,     92,     93,     94,     95,     96,
-       97,     98,     99,     100,    101,    102,    103,    104,
-       105,    106,    107,    108,    109,    110,    111,    112,
-       113,    114,    115,    116,    117,    118,    119,    120,
-       121,    122,    123,    124,    125,    126,    127,    128};
+        80,        82,        83,        84,        85,        86,        87,        88,
+        89,        90,        91,        92,        93,        94,        95,        96,
+        97,        98,        99,        100,        101,        102,        103,        104,
+        105,        106,        107,        108,        109,        110,        111,        112,
+        113,        114,        115,        116,        117,        118,        119,        120,
+        121,        122,        123,        124,        125,        126,        127,        128};
 
-unsigned char _a2u[128] = {                    /* A- to u-law conversions */
-       1,      3,      5,      7,      9,      11,     13,     15,
-       16,     17,     18,     19,     20,     21,     22,     23,
-       24,     25,     26,     27,     28,     29,     30,     31,
-       32,     32,     33,     33,     34,     34,     35,     35,
-       36,     37,     38,     39,     40,     41,     42,     43,
-       44,     45,     46,     47,     48,     48,     49,     49,
-       50,     51,     52,     53,     54,     55,     56,     57,
-       58,     59,     60,     61,     62,     63,     64,     64,
-       65,     66,     67,     68,     69,     70,     71,     72,
+unsigned char _a2u[128] = {                        /* A- to u-law conversions */
+        1,        3,        5,        7,        9,        11,        13,        15,
+        16,        17,        18,        19,        20,        21,        22,        23,
+        24,        25,        26,        27,        28,        29,        30,        31,
+        32,        32,        33,        33,        34,        34,        35,        35,
+        36,        37,        38,        39,        40,        41,        42,        43,
+        44,        45,        46,        47,        48,        48,        49,        49,
+        50,        51,        52,        53,        54,        55,        56,        57,
+        58,        59,        60,        61,        62,        63,        64,        64,
+        65,        66,        67,        68,        69,        70,        71,        72,
 /* corrected:
-       73,     74,     75,     76,     77,     78,     79,     79,
+        73,        74,        75,        76,        77,        78,        79,        79,
    should be: */
-       73,     74,     75,     76,     77,     78,     79,     80,
+        73,        74,        75,        76,        77,        78,        79,        80,
 
-       80,     81,     82,     83,     84,     85,     86,     87,
-       88,     89,     90,     91,     92,     93,     94,     95,
-       96,     97,     98,     99,     100,    101,    102,    103,
-       104,    105,    106,    107,    108,    109,    110,    111,
-       112,    113,    114,    115,    116,    117,    118,    119,
-       120,    121,    122,    123,    124,    125,    126,    127};
+        80,        81,        82,        83,        84,        85,        86,        87,
+        88,        89,        90,        91,        92,        93,        94,        95,
+        96,        97,        98,        99,        100,        101,        102,        103,
+        104,        105,        106,        107,        108,        109,        110,        111,
+        112,        113,        114,        115,        116,        117,        118,        119,
+        120,        121,        122,        123,        124,        125,        126,        127};
 
 /* A-law to u-law conversion */
 unsigned char st_alaw2ulaw(
-       unsigned char   aval)
+        unsigned char        aval)
 {
-       aval &= 0xff;
-       return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
-           (0x7F ^ _a2u[aval ^ 0x55]));
+        aval &= 0xff;
+        return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
+            (0x7F ^ _a2u[aval ^ 0x55]));
 }
 
 /* u-law to A-law conversion */
 unsigned char st_ulaw2alaw(
-       unsigned char   uval)
+        unsigned char        uval)
 {
-       uval &= 0xff;
-       return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
-           (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
+        uval &= 0xff;
+        return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
+            (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
 }
 #endif
index 57d28006484001c0abaed8930788dbe1e68285c2..e9f0d09395321a8f3518850b879808beca961a20 100644 (file)
 #define PA_GCC_UNUSED
 #endif
 
+#ifdef __GNUC__
+#define PA_GCC_DESTRUCTOR __attribute__ ((destructor))
+#else
+/** Call this function when process terminates */
+#define PA_GCC_DESTRUCTOR
+#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__ ((const))
+#else
+/** This function's return value depends only the arguments list (stricter version of PA_GCC_PURE) **/
+#define PA_GCC_CONST
+#endif
+#endif
+
 #endif
index 818e12bf785fa19d3d5487f6ef901ebb7614a001..f55896647f3914b0582cd46ad6352642463657f5 100644 (file)
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <string.h>
 
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/idxset.h>
 #include <pulsecore/log.h>
+#include <pulsecore/flist.h>
+#include <pulsecore/macro.h>
 
 #include "hashmap.h"
 
@@ -55,6 +56,8 @@ struct pa_hashmap {
     pa_compare_func_t compare_func;
 };
 
+PA_STATIC_FLIST_DECLARE(entries, 0, pa_xfree);
+
 pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) {
     pa_hashmap *h;
 
@@ -69,8 +72,8 @@ pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_f
 }
 
 static void remove(pa_hashmap *h, struct hashmap_entry *e) {
-    assert(h);
-    assert(e);
+    pa_assert(h);
+    pa_assert(e);
 
     if (e->next)
         e->next->previous = e->previous;
@@ -84,16 +87,18 @@ static void remove(pa_hashmap *h, struct hashmap_entry *e) {
     if (e->bucket_previous)
         e->bucket_previous->bucket_next = e->bucket_next;
     else {
-        assert(e->hash < h->size);
+        pa_assert(e->hash < h->size);
         h->data[e->hash] = e->bucket_next;
     }
 
-    pa_xfree(e);
+    if (pa_flist_push(PA_STATIC_FLIST_GET(entries), e) < 0)
+        pa_xfree(e);
+
     h->n_entries--;
 }
 
 void pa_hashmap_free(pa_hashmap*h, void (*free_func)(void *p, void *userdata), void *userdata) {
-    assert(h);
+    pa_assert(h);
 
     while (h->first_entry) {
         if (free_func)
@@ -107,8 +112,8 @@ void pa_hashmap_free(pa_hashmap*h, void (*free_func)(void *p, void *userdata), v
 
 static struct hashmap_entry *get(pa_hashmap *h, unsigned hash, const void *key) {
     struct hashmap_entry *e;
-    assert(h);
-    assert(hash < h->size);
+    pa_assert(h);
+    pa_assert(hash < h->size);
 
     for (e = h->data[hash]; e; e = e->bucket_next)
         if (h->compare_func(e->key, key) == 0)
@@ -120,14 +125,16 @@ static struct hashmap_entry *get(pa_hashmap *h, unsigned hash, const void *key)
 int pa_hashmap_put(pa_hashmap *h, const void *key, void *value) {
     struct hashmap_entry *e;
     unsigned hash;
-    assert(h);
+    pa_assert(h);
 
     hash = h->hash_func(key) % h->size;
 
     if ((e = get(h, hash, key)))
         return -1;
 
-    e = pa_xnew(struct hashmap_entry, 1);
+    if (!(e = pa_flist_pop(PA_STATIC_FLIST_GET(entries))))
+        e = pa_xnew(struct hashmap_entry, 1);
+
     e->hash = hash;
     e->key = key;
     e->value = value;
@@ -152,7 +159,7 @@ void* pa_hashmap_get(pa_hashmap *h, const void *key) {
     unsigned hash;
     struct hashmap_entry *e;
 
-    assert(h);
+    pa_assert(h);
 
     hash = h->hash_func(key) % h->size;
 
@@ -167,7 +174,7 @@ void* pa_hashmap_remove(pa_hashmap *h, const void *key) {
     unsigned hash;
     void *data;
 
-    assert(h);
+    pa_assert(h);
 
     hash = h->hash_func(key) % h->size;
 
@@ -184,8 +191,8 @@ unsigned pa_hashmap_size(pa_hashmap *h) {
 }
 
 void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void **key) {
-    assert(h);
-    assert(state);
+    pa_assert(h);
+    pa_assert(state);
 
     if (!*state)
         *state = h->first_entry;
@@ -207,7 +214,7 @@ void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void **key) {
 void* pa_hashmap_steal_first(pa_hashmap *h) {
     void *data;
 
-    assert(h);
+    pa_assert(h);
 
     if (!h->first_entry)
         return NULL;
@@ -218,7 +225,7 @@ void* pa_hashmap_steal_first(pa_hashmap *h) {
 }
 
 void *pa_hashmap_get_first(pa_hashmap *h) {
-    assert(h);
+    pa_assert(h);
 
     if (!h->first_entry)
         return NULL;
index 3ca2a4795aaf9d5e4878f98917a65154d6a9a601..98df45021301c0c9bf3e06b464a077bf93ed908a 100644 (file)
 
 typedef struct pa_hashmap pa_hashmap;
 
+typedef void (*pa_free2_cb_t)(void *p, void *userdata);
+
 /* Create a new hashmap. Use the specified functions for hashing and comparing objects in the map */
 pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func);
 
 /* Free the hash table. Calls the specified function for every value in the table. The function may be NULL */
-void pa_hashmap_free(pa_hashmap*, void (*free_func)(void *p, void *userdata), void *userdata);
+void pa_hashmap_free(pa_hashmap*, pa_free2_cb_t free_cb, void *userdata);
 
 /* Returns non-zero when the entry already exists */
 int pa_hashmap_put(pa_hashmap *h, const void *key, void *value);
index 4f8841876e44be5bdf550d6afbfc1eb79fe6a577..3a6874c47cf5375d8d99f42a49a6e5dbb52471d2 100644 (file)
   USA.
 ***/
 
-#include <pulsecore/hook-list.h>
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulsecore/macro.h>
+
+#include "hook-list.h"
 
 void pa_hook_init(pa_hook *hook, void *data) {
-    assert(hook);
+    pa_assert(hook);
 
     PA_LLIST_HEAD_INIT(pa_hook_slot, hook->slots);
     hook->last = NULL;
@@ -33,8 +39,8 @@ void pa_hook_init(pa_hook *hook, void *data) {
 }
 
 static void slot_free(pa_hook *hook, pa_hook_slot *slot) {
-    assert(hook);
-    assert(slot);
+    pa_assert(hook);
+    pa_assert(slot);
 
     if (hook->last == slot)
         hook->last = slot->prev;
@@ -45,8 +51,8 @@ static void slot_free(pa_hook *hook, pa_hook_slot *slot) {
 }
 
 void pa_hook_free(pa_hook *hook) {
-    assert(hook);
-    assert(!hook->firing);
+    pa_assert(hook);
+    pa_assert(!hook->firing);
 
     while (hook->slots)
         slot_free(hook, hook->slots);
@@ -57,7 +63,7 @@ void pa_hook_free(pa_hook *hook) {
 pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t cb, void *data) {
     pa_hook_slot *slot;
 
-    assert(cb);
+    pa_assert(cb);
 
     slot = pa_xnew(pa_hook_slot, 1);
     slot->hook = hook;
@@ -72,8 +78,8 @@ pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t cb, void *data) {
 }
 
 void pa_hook_slot_free(pa_hook_slot *slot) {
-    assert(slot);
-    assert(!slot->dead);
+    pa_assert(slot);
+    pa_assert(!slot->dead);
 
     if (slot->hook->firing > 0) {
         slot->dead = 1;
@@ -86,7 +92,7 @@ pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data) {
     pa_hook_slot *slot, *next;
     pa_hook_result_t result = PA_HOOK_OK;
 
-    assert(hook);
+    pa_assert(hook);
 
     hook->firing ++;
 
index 70ef7ba70b5ba8c44e76baa91fe5816ab4b62588..8a88471f216abca6974bffd5b52c82dd545fac8e 100644 (file)
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/flist.h>
 
 #include "idxset.h"
 
-typedef struct idxset_entry {
+struct idxset_entry {
     void *data;
     uint32_t index;
     unsigned hash_value;
 
     struct idxset_entry *hash_prev, *hash_next;
     struct idxset_entry* iterate_prev, *iterate_next;
-} idxset_entry;
+};
 
 struct pa_idxset {
     pa_hash_func_t hash_func;
     pa_compare_func_t compare_func;
 
     unsigned hash_table_size, n_entries;
-    idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail;
+    struct idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail;
     uint32_t index, start_index, array_size;
 };
 
+PA_STATIC_FLIST_DECLARE(entries, 0, pa_xfree);
+
 unsigned pa_idxset_string_hash_func(const void *p) {
     unsigned hash = 0;
     const char *c;
@@ -82,7 +85,7 @@ pa_idxset* pa_idxset_new(pa_hash_func_t hash_func, pa_compare_func_t compare_fun
     s->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func;
     s->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func;
     s->hash_table_size = 127;
-    s->hash_table = pa_xnew0(idxset_entry*, s->hash_table_size);
+    s->hash_table = pa_xnew0(struct idxset_entry*, s->hash_table_size);
     s->array = NULL;
     s->array_size = 0;
     s->index = 0;
@@ -95,15 +98,17 @@ pa_idxset* pa_idxset_new(pa_hash_func_t hash_func, pa_compare_func_t compare_fun
 }
 
 void pa_idxset_free(pa_idxset *s, void (*free_func) (void *p, void *userdata), void *userdata) {
-    assert(s);
+    pa_assert(s);
 
     while (s->iterate_list_head) {
-        idxset_entry *e = s->iterate_list_head;
+        struct idxset_entry *e = s->iterate_list_head;
         s->iterate_list_head = s->iterate_list_head->iterate_next;
 
         if (free_func)
             free_func(e->data, userdata);
-        pa_xfree(e);
+
+        if (pa_flist_push(PA_STATIC_FLIST_GET(entries), e) < 0)
+            pa_xfree(e);
     }
 
     pa_xfree(s->hash_table);
@@ -111,10 +116,10 @@ void pa_idxset_free(pa_idxset *s, void (*free_func) (void *p, void *userdata), v
     pa_xfree(s);
 }
 
-static idxset_entry* hash_scan(pa_idxset *s, idxset_entry* e, const void *p) {
-    assert(p);
+static struct idxset_entry* hash_scan(pa_idxset *s, struct idxset_entry* e, const void *p) {
+    pa_assert(p);
 
-    assert(s->compare_func);
+    pa_assert(s->compare_func);
     for (; e; e = e->hash_next)
         if (s->compare_func(e->data, p) == 0)
             return e;
@@ -124,8 +129,10 @@ static idxset_entry* hash_scan(pa_idxset *s, idxset_entry* e, const void *p) {
 
 static void extend_array(pa_idxset *s, uint32_t idx) {
     uint32_t i, j, l;
-    idxset_entry** n;
-    assert(idx >= s->start_index);
+    struct idxset_entry** n;
+
+    pa_assert(s);
+    pa_assert(idx >= s->start_index);
 
     if (idx < s->start_index + s->array_size)
         return;
@@ -135,7 +142,7 @@ static void extend_array(pa_idxset *s, uint32_t idx) {
             break;
 
     l = idx - s->start_index - i + 100;
-    n = pa_xnew0(idxset_entry*, l);
+    n = pa_xnew0(struct idxset_entry*, l);
 
     for (j = 0; j < s->array_size-i; j++)
         n[j] = s->array[i+j];
@@ -147,7 +154,9 @@ static void extend_array(pa_idxset *s, uint32_t idx) {
     s->start_index += i;
 }
 
-static idxset_entry** array_index(pa_idxset*s, uint32_t idx) {
+static struct idxset_entry** array_index(pa_idxset*s, uint32_t idx) {
+    pa_assert(s);
+
     if (idx >= s->start_index + s->array_size)
         return NULL;
 
@@ -159,15 +168,15 @@ static idxset_entry** array_index(pa_idxset*s, uint32_t idx) {
 
 int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) {
     unsigned h;
-    idxset_entry *e, **a;
+    struct idxset_entry *e, **a;
 
-    assert(s);
-    assert(p);
+    pa_assert(s);
+    pa_assert(p);
 
-    assert(s->hash_func);
+    pa_assert(s->hash_func);
     h = s->hash_func(p) % s->hash_table_size;
 
-    assert(s->hash_table);
+    pa_assert(s->hash_table);
     if ((e = hash_scan(s, s->hash_table[h], p))) {
         if (idx)
             *idx = e->index;
@@ -175,7 +184,8 @@ int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) {
         return -1;
     }
 
-    e = pa_xmalloc(sizeof(idxset_entry));
+    if (!(e = pa_flist_pop(PA_STATIC_FLIST_GET(entries))))
+        e = pa_xnew(struct idxset_entry, 1);
     e->data = p;
     e->index = s->index++;
     e->hash_value = h;
@@ -190,23 +200,23 @@ int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) {
     /* Insert into array */
     extend_array(s, e->index);
     a = array_index(s, e->index);
-    assert(a && !*a);
+    pa_assert(a && !*a);
     *a = e;
 
     /* Insert into linked list */
     e->iterate_next = NULL;
     e->iterate_prev = s->iterate_list_tail;
     if (s->iterate_list_tail) {
-        assert(s->iterate_list_head);
+        pa_assert(s->iterate_list_head);
         s->iterate_list_tail->iterate_next = e;
     } else {
-        assert(!s->iterate_list_head);
+        pa_assert(!s->iterate_list_head);
         s->iterate_list_head = e;
     }
     s->iterate_list_tail = e;
 
     s->n_entries++;
-    assert(s->n_entries >= 1);
+    pa_assert(s->n_entries >= 1);
 
     if (idx)
         *idx = e->index;
@@ -215,8 +225,8 @@ int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) {
 }
 
 void* pa_idxset_get_by_index(pa_idxset*s, uint32_t idx) {
-    idxset_entry **a;
-    assert(s);
+    struct idxset_entry **a;
+    pa_assert(s);
 
     if (!(a = array_index(s, idx)))
         return NULL;
@@ -229,13 +239,15 @@ void* pa_idxset_get_by_index(pa_idxset*s, uint32_t idx) {
 
 void* pa_idxset_get_by_data(pa_idxset*s, const void *p, uint32_t *idx) {
     unsigned h;
-    idxset_entry *e;
-    assert(s && p);
+    struct idxset_entry *e;
 
-    assert(s->hash_func);
+    pa_assert(s);
+    pa_assert(p);
+
+    pa_assert(s->hash_func);
     h = s->hash_func(p) % s->hash_table_size;
 
-    assert(s->hash_table);
+    pa_assert(s->hash_table);
     if (!(e = hash_scan(s, s->hash_table[h], p)))
         return NULL;
 
@@ -245,13 +257,15 @@ void* pa_idxset_get_by_data(pa_idxset*s, const void *p, uint32_t *idx) {
     return e->data;
 }
 
-static void remove_entry(pa_idxset *s, idxset_entry *e) {
-    idxset_entry **a;
-    assert(s && e);
+static void remove_entry(pa_idxset *s, struct idxset_entry *e) {
+    struct idxset_entry **a;
+
+    pa_assert(s);
+    pa_assert(e);
 
     /* Remove from array */
     a = array_index(s, e->index);
-    assert(a && *a && *a == e);
+    pa_assert(a && *a && *a == e);
     *a = NULL;
 
     /* Remove from linked list */
@@ -274,17 +288,18 @@ static void remove_entry(pa_idxset *s, idxset_entry *e) {
     else
         s->hash_table[e->hash_value] = e->hash_next;
 
-    pa_xfree(e);
+    if (pa_flist_push(PA_STATIC_FLIST_GET(entries), e) < 0)
+        pa_xfree(e);
 
-    assert(s->n_entries >= 1);
+    pa_assert(s->n_entries >= 1);
     s->n_entries--;
 }
 
 void* pa_idxset_remove_by_index(pa_idxset*s, uint32_t idx) {
-    idxset_entry **a;
+    struct idxset_entry **a;
     void *data;
 
-    assert(s);
+    pa_assert(s);
 
     if (!(a = array_index(s, idx)))
         return NULL;
@@ -299,14 +314,16 @@ void* pa_idxset_remove_by_index(pa_idxset*s, uint32_t idx) {
 }
 
 void* pa_idxset_remove_by_data(pa_idxset*s, const void *data, uint32_t *idx) {
-    idxset_entry *e;
+    struct idxset_entry *e;
     unsigned h;
     void *r;
 
-    assert(s->hash_func);
+    pa_assert(s);
+
+    pa_assert(s->hash_func);
     h = s->hash_func(data) % s->hash_table_size;
 
-    assert(s->hash_table);
+    pa_assert(s->hash_table);
     if (!(e = hash_scan(s, s->hash_table[h], data)))
         return NULL;
 
@@ -320,8 +337,10 @@ void* pa_idxset_remove_by_data(pa_idxset*s, const void *data, uint32_t *idx) {
 }
 
 void* pa_idxset_rrobin(pa_idxset *s, uint32_t *idx) {
-    idxset_entry **a, *e = NULL;
-    assert(s && idx);
+    struct idxset_entry **a, *e = NULL;
+
+    pa_assert(s);
+    pa_assert(idx);
 
     if ((a = array_index(s, *idx)) && *a)
         e = (*a)->iterate_next;
@@ -337,7 +356,7 @@ void* pa_idxset_rrobin(pa_idxset *s, uint32_t *idx) {
 }
 
 void* pa_idxset_first(pa_idxset *s, uint32_t *idx) {
-    assert(s);
+    pa_assert(s);
 
     if (!s->iterate_list_head)
         return NULL;
@@ -348,9 +367,10 @@ void* pa_idxset_first(pa_idxset *s, uint32_t *idx) {
 }
 
 void *pa_idxset_next(pa_idxset *s, uint32_t *idx) {
-    idxset_entry **a, *e = NULL;
-    assert(s);
-    assert(idx);
+    struct idxset_entry **a, *e = NULL;
+
+    pa_assert(s);
+    pa_assert(idx);
 
     if ((a = array_index(s, *idx)) && *a)
         e = (*a)->iterate_next;
@@ -365,13 +385,15 @@ void *pa_idxset_next(pa_idxset *s, uint32_t *idx) {
 }
 
 int pa_idxset_foreach(pa_idxset*s, int (*func)(void *p, uint32_t idx, int *del, void*userdata), void *userdata) {
-    idxset_entry *e;
-    assert(s && func);
+    struct idxset_entry *e;
+
+    pa_assert(s);
+    pa_assert(func);
 
     e = s->iterate_list_head;
     while (e) {
         int del = 0, r;
-        idxset_entry *n = e->iterate_next;
+        struct idxset_entry *n = e->iterate_next;
 
         r = func(e->data, e->index, &del, userdata);
 
@@ -388,12 +410,14 @@ int pa_idxset_foreach(pa_idxset*s, int (*func)(void *p, uint32_t idx, int *del,
 }
 
 unsigned pa_idxset_size(pa_idxset*s) {
-    assert(s);
+    pa_assert(s);
+
     return s->n_entries;
 }
 
 int pa_idxset_isempty(pa_idxset *s) {
-    assert(s);
+    pa_assert(s);
+
     return s->n_entries == 0;
 }
 
index 17a70f4ff3c340e7209e26ad1d942dd02dcd5efe..5b55cec205ea1f1e790958e8b759bf70ceb8b5bf 100644 (file)
@@ -44,11 +44,6 @@ int pa_idxset_trivial_compare_func(const void *a, const void *b);
 unsigned pa_idxset_string_hash_func(const void *p);
 int pa_idxset_string_compare_func(const void *a, const void *b);
 
-#define PA_PTR_TO_UINT(p) ((unsigned int) (unsigned long) (p))
-#define PA_UINT_TO_PTR(u) ((void*) (unsigned long) (u))
-#define PA_PTR_TO_UINT32(p) ((uint32_t) PA_PTR_TO_UINT(p))
-#define PA_UINT32_TO_PTR(u) PA_UINT_TO_PTR(u)
-
 typedef unsigned (*pa_hash_func_t)(const void *p);
 typedef int (*pa_compare_func_t)(const void *a, const void *b);
 
index 302369f78cb89736c43a9bdbef0997ee299149f8..041bc09bc38ef747b4aaaeea6f3c28489b7c8897 100644 (file)
@@ -47,7 +47,7 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) {
 
     switch (af) {
     case AF_INET:
-        snprintf(dst, cnt, "%d.%d.%d.%d",
+        pa_snprintf(dst, cnt, "%d.%d.%d.%d",
 #ifdef WORDS_BIGENDIAN
             (int)(in->s_addr >> 24) & 0xff,
             (int)(in->s_addr >> 16) & 0xff,
@@ -61,7 +61,7 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) {
 #endif
         break;
     case AF_INET6:
-        snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x",
+        pa_snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x",
             in6->s6_addr[ 0] << 8 | in6->s6_addr[ 1],
             in6->s6_addr[ 2] << 8 | in6->s6_addr[ 3],
             in6->s6_addr[ 4] << 8 | in6->s6_addr[ 5],
index 6f58ae755ac4639212fb9a47e414fa021733964e..01f17ab32db3d8bb48a20679b919f6da45c5f728 100644 (file)
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
@@ -47,6 +46,7 @@
 #include <pulsecore/core-util.h>
 #include <pulsecore/socket-util.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "iochannel.h"
 
@@ -58,21 +58,21 @@ struct pa_iochannel {
     pa_iochannel_cb_t callback;
     void*userdata;
 
-    int readable;
-    int writable;
-    int hungup;
+    pa_bool_t readable;
+    pa_bool_t writable;
+    pa_bool_t hungup;
 
-    int no_close;
+    pa_bool_t no_close;
 
     pa_io_event* input_event, *output_event;
 };
 
 static void enable_mainloop_sources(pa_iochannel *io) {
-    assert(io);
+    pa_assert(io);
 
     if (io->input_event == io->output_event && io->input_event) {
         pa_io_event_flags_t f = PA_IO_EVENT_NULL;
-        assert(io->input_event);
+        pa_assert(io->input_event);
 
         if (!io->readable)
             f |= PA_IO_EVENT_INPUT;
@@ -90,28 +90,28 @@ static void enable_mainloop_sources(pa_iochannel *io) {
 
 static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
     pa_iochannel *io = userdata;
-    int changed = 0;
+    pa_bool_t changed = FALSE;
 
-    assert(m);
-    assert(e);
-    assert(fd >= 0);
-    assert(userdata);
+    pa_assert(m);
+    pa_assert(e);
+    pa_assert(fd >= 0);
+    pa_assert(userdata);
 
     if ((f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) && !io->hungup) {
-        io->hungup = 1;
-        changed = 1;
+        io->hungup = TRUE;
+        changed = TRUE;
     }
 
     if ((f & PA_IO_EVENT_INPUT) && !io->readable) {
-        io->readable = 1;
-        changed = 1;
-        assert(e == io->input_event);
+        io->readable = TRUE;
+        changed = TRUE;
+        pa_assert(e == io->input_event);
     }
 
     if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) {
-        io->writable = 1;
-        changed = 1;
-        assert(e == io->output_event);
+        io->writable = TRUE;
+        changed = TRUE;
+        pa_assert(e == io->output_event);
     }
 
     if (changed) {
@@ -125,8 +125,8 @@ static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_fla
 pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) {
     pa_iochannel *io;
 
-    assert(m);
-    assert(ifd >= 0 || ofd >= 0);
+    pa_assert(m);
+    pa_assert(ifd >= 0 || ofd >= 0);
 
     io = pa_xnew(pa_iochannel, 1);
     io->ifd = ifd;
@@ -136,26 +136,26 @@ pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) {
 
     io->userdata = NULL;
     io->callback = NULL;
-    io->readable = 0;
-    io->writable = 0;
-    io->hungup = 0;
-    io->no_close = 0;
+    io->readable = FALSE;
+    io->writable = FALSE;
+    io->hungup = FALSE;
+    io->no_close = FALSE;
 
     io->input_event = io->output_event = NULL;
 
     if (ifd == ofd) {
-        assert(ifd >= 0);
-        pa_make_nonblock_fd(io->ifd);
+        pa_assert(ifd >= 0);
+        pa_make_fd_nonblock(io->ifd);
         io->input_event = io->output_event = m->io_new(m, ifd, PA_IO_EVENT_INPUT|PA_IO_EVENT_OUTPUT, callback, io);
     } else {
 
         if (ifd >= 0) {
-            pa_make_nonblock_fd(io->ifd);
+            pa_make_fd_nonblock(io->ifd);
             io->input_event = m->io_new(m, ifd, PA_IO_EVENT_INPUT, callback, io);
         }
 
         if (ofd >= 0) {
-            pa_make_nonblock_fd(io->ofd);
+            pa_make_fd_nonblock(io->ofd);
             io->output_event = m->io_new(m, ofd, PA_IO_EVENT_OUTPUT, callback, io);
         }
     }
@@ -164,7 +164,7 @@ pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) {
 }
 
 void pa_iochannel_free(pa_iochannel*io) {
-    assert(io);
+    pa_assert(io);
 
     if (io->input_event)
         io->mainloop->io_free(io->input_event);
@@ -182,20 +182,20 @@ void pa_iochannel_free(pa_iochannel*io) {
     pa_xfree(io);
 }
 
-int pa_iochannel_is_readable(pa_iochannel*io) {
-    assert(io);
+pa_bool_t pa_iochannel_is_readable(pa_iochannel*io) {
+    pa_assert(io);
 
     return io->readable || io->hungup;
 }
 
-int pa_iochannel_is_writable(pa_iochannel*io) {
-    assert(io);
+pa_bool_t pa_iochannel_is_writable(pa_iochannel*io) {
+    pa_assert(io);
 
     return io->writable && !io->hungup;
 }
 
-int pa_iochannel_is_hungup(pa_iochannel*io) {
-    assert(io);
+pa_bool_t pa_iochannel_is_hungup(pa_iochannel*io) {
+    pa_assert(io);
 
     return io->hungup;
 }
@@ -203,14 +203,13 @@ int pa_iochannel_is_hungup(pa_iochannel*io) {
 ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) {
     ssize_t r;
 
-    assert(io);
-    assert(data);
-    assert(l);
-    assert(io->ofd >= 0);
+    pa_assert(io);
+    pa_assert(data);
+    pa_assert(l);
+    pa_assert(io->ofd >= 0);
 
-    r = pa_write(io->ofd, data, l, &io->ofd_type);
-    if (r >= 0) {
-        io->writable = 0;
+    if ((r = pa_write(io->ofd, data, l, &io->ofd_type)) >= 0) {
+        io->writable = FALSE;
         enable_mainloop_sources(io);
     }
 
@@ -220,13 +219,12 @@ ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) {
 ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) {
     ssize_t r;
 
-    assert(io);
-    assert(data);
-    assert(io->ifd >= 0);
+    pa_assert(io);
+    pa_assert(data);
+    pa_assert(io->ifd >= 0);
 
-    r = pa_read(io->ifd, data, l, &io->ifd_type);
-    if (r >= 0) {
-        io->readable = 0;
+    if ((r = pa_read(io->ifd, data, l, &io->ifd_type)) >= 0) {
+        io->readable = FALSE;
         enable_mainloop_sources(io);
     }
 
@@ -235,13 +233,13 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) {
 
 #ifdef HAVE_CREDS
 
-int pa_iochannel_creds_supported(pa_iochannel *io) {
+pa_bool_t pa_iochannel_creds_supported(pa_iochannel *io) {
     struct sockaddr_un sa;
     socklen_t l;
 
-    assert(io);
-    assert(io->ifd >= 0);
-    assert(io->ofd == io->ifd);
+    pa_assert(io);
+    pa_assert(io->ifd >= 0);
+    pa_assert(io->ofd == io->ifd);
 
     l = sizeof(sa);
 
@@ -254,8 +252,8 @@ int pa_iochannel_creds_supported(pa_iochannel *io) {
 int pa_iochannel_creds_enable(pa_iochannel *io) {
     int t = 1;
 
-    assert(io);
-    assert(io->ifd >= 0);
+    pa_assert(io);
+    pa_assert(io->ifd >= 0);
 
     if (setsockopt(io->ifd, SOL_SOCKET, SO_PASSCRED, &t, sizeof(t)) < 0) {
         pa_log_error("setsockopt(SOL_SOCKET, SO_PASSCRED): %s", pa_cstrerror(errno));
@@ -273,10 +271,10 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l
     struct ucred *u;
     struct cmsghdr *cmsg;
 
-    assert(io);
-    assert(data);
-    assert(l);
-    assert(io->ofd >= 0);
+    pa_assert(io);
+    pa_assert(data);
+    pa_assert(l);
+    pa_assert(io->ofd >= 0);
 
     memset(&iov, 0, sizeof(iov));
     iov.iov_base = (void*) data;
@@ -309,25 +307,25 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l
     mh.msg_flags = 0;
 
     if ((r = sendmsg(io->ofd, &mh, MSG_NOSIGNAL)) >= 0) {
-        io->writable = 0;
+        io->writable = FALSE;
         enable_mainloop_sources(io);
     }
 
     return r;
 }
 
-ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_creds *creds, int *creds_valid) {
+ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_creds *creds, pa_bool_t *creds_valid) {
     ssize_t r;
     struct msghdr mh;
     struct iovec iov;
     uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))];
 
-    assert(io);
-    assert(data);
-    assert(l);
-    assert(io->ifd >= 0);
-    assert(creds);
-    assert(creds_valid);
+    pa_assert(io);
+    pa_assert(data);
+    pa_assert(l);
+    pa_assert(io->ifd >= 0);
+    pa_assert(creds);
+    pa_assert(creds_valid);
 
     memset(&iov, 0, sizeof(iov));
     iov.iov_base = data;
@@ -353,17 +351,17 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr
 
             if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) {
                 struct ucred u;
-                assert(cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)));
+                pa_assert(cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)));
                 memcpy(&u, CMSG_DATA(cmsg), sizeof(struct ucred));
 
                 creds->gid = u.gid;
                 creds->uid = u.uid;
-                *creds_valid = 1;
+                *creds_valid = TRUE;
                 break;
             }
         }
 
-        io->readable = 0;
+        io->readable = FALSE;
         enable_mainloop_sources(io);
     }
 
@@ -373,46 +371,52 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr
 #endif /* HAVE_CREDS */
 
 void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_cb_t _callback, void *userdata) {
-    assert(io);
+    pa_assert(io);
 
     io->callback = _callback;
     io->userdata = userdata;
 }
 
-void pa_iochannel_set_noclose(pa_iochannel*io, int b) {
-    assert(io);
+void pa_iochannel_set_noclose(pa_iochannel*io, pa_bool_t b) {
+    pa_assert(io);
 
-    io->no_close = b;
+    io->no_close = !!b;
 }
 
 void pa_iochannel_socket_peer_to_string(pa_iochannel*io, char*s, size_t l) {
-    assert(io);
-    assert(s);
-    assert(l);
+    pa_assert(io);
+    pa_assert(s);
+    pa_assert(l);
 
     pa_socket_peer_to_string(io->ifd, s, l);
 }
 
 int pa_iochannel_socket_set_rcvbuf(pa_iochannel *io, size_t l) {
-    assert(io);
+    pa_assert(io);
 
     return pa_socket_set_rcvbuf(io->ifd, l);
 }
 
 int pa_iochannel_socket_set_sndbuf(pa_iochannel *io, size_t l) {
-    assert(io);
+    pa_assert(io);
 
     return pa_socket_set_sndbuf(io->ofd, l);
 }
 
 pa_mainloop_api* pa_iochannel_get_mainloop_api(pa_iochannel *io) {
-    assert(io);
+    pa_assert(io);
 
     return io->mainloop;
 }
 
 int pa_iochannel_get_recv_fd(pa_iochannel *io) {
-    assert(io);
+    pa_assert(io);
 
     return io->ifd;
 }
+
+int pa_iochannel_get_send_fd(pa_iochannel *io) {
+    pa_assert(io);
+
+    return io->ofd;
+}
index c22fefd302aad0592e0d8eac8e834990e0d50c3d..c9794d99610a872ba0b03b8f6af15dbca248ee2c 100644 (file)
   USA.
 ***/
 
+#ifndef PACKAGE
+#error "Please include config.h before including this file!"
+#endif
+
 #include <sys/types.h>
 
 #include <pulse/mainloop-api.h>
 #include <pulsecore/creds.h>
+#include <pulsecore/macro.h>
 
 /* A wrapper around UNIX file descriptors for attaching them to the a
    main event loop. Everytime new data may be read or be written to
@@ -54,20 +59,20 @@ ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l);
 ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l);
 
 #ifdef HAVE_CREDS
-int pa_iochannel_creds_supported(pa_iochannel *io);
+pa_bool_t pa_iochannel_creds_supported(pa_iochannel *io);
 int pa_iochannel_creds_enable(pa_iochannel *io);
 
 ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const pa_creds *ucred);
-ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_creds *ucred, int *creds_valid);
+ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_creds *ucred, pa_bool_t *creds_valid);
 #endif
 
-int pa_iochannel_is_readable(pa_iochannel*io);
-int pa_iochannel_is_writable(pa_iochannel*io);
-int pa_iochannel_is_hungup(pa_iochannel*io);
+pa_bool_t pa_iochannel_is_readable(pa_iochannel*io);
+pa_bool_t pa_iochannel_is_writable(pa_iochannel*io);
+pa_bool_t pa_iochannel_is_hungup(pa_iochannel*io);
 
 /* Don't close the file descirptors when the io channel is freed. By
  * default the file descriptors are closed. */
-void pa_iochannel_set_noclose(pa_iochannel*io, int b);
+void pa_iochannel_set_noclose(pa_iochannel*io, pa_bool_t b);
 
 /* Set the callback function that is called whenever data becomes available for read or write */
 typedef void (*pa_iochannel_cb_t)(pa_iochannel*io, void *userdata);
@@ -83,5 +88,6 @@ int pa_iochannel_socket_set_sndbuf(pa_iochannel*io, size_t l);
 pa_mainloop_api* pa_iochannel_get_mainloop_api(pa_iochannel *io);
 
 int pa_iochannel_get_recv_fd(pa_iochannel *io);
+int pa_iochannel_get_send_fd(pa_iochannel *io);
 
 #endif
index 07b60bee31777dd0ea9900f32fb785fb292ce697..5fd2189b32969abc765c798396bd67a4fa7b476e 100644 (file)
 
 #include <errno.h>
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/winsock.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/refcnt.h>
 
 #include "ioline.h"
 
 #define READ_SIZE (1024)
 
 struct pa_ioline {
+    PA_REFCNT_DECLARE;
+
     pa_iochannel *io;
     pa_defer_event *defer_event;
     pa_mainloop_api *mainloop;
-    int ref;
     int dead;
 
     char *wbuf;
@@ -65,9 +68,10 @@ static void defer_callback(pa_mainloop_api*m, pa_defer_event*e, void *userdata);
 
 pa_ioline* pa_ioline_new(pa_iochannel *io) {
     pa_ioline *l;
-    assert(io);
+    pa_assert(io);
 
     l = pa_xnew(pa_ioline, 1);
+    PA_REFCNT_INIT(l);
     l->io = io;
     l->dead = 0;
 
@@ -79,7 +83,6 @@ pa_ioline* pa_ioline_new(pa_iochannel *io) {
 
     l->callback = NULL;
     l->userdata = NULL;
-    l->ref = 1;
 
     l->mainloop = pa_iochannel_get_mainloop_api(io);
 
@@ -94,7 +97,7 @@ pa_ioline* pa_ioline_new(pa_iochannel *io) {
 }
 
 static void ioline_free(pa_ioline *l) {
-    assert(l);
+    pa_assert(l);
 
     if (l->io)
         pa_iochannel_free(l->io);
@@ -108,24 +111,24 @@ static void ioline_free(pa_ioline *l) {
 }
 
 void pa_ioline_unref(pa_ioline *l) {
-    assert(l);
-    assert(l->ref >= 1);
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
 
-    if ((--l->ref) <= 0)
+    if (PA_REFCNT_DEC(l) <= 0)
         ioline_free(l);
 }
 
 pa_ioline* pa_ioline_ref(pa_ioline *l) {
-    assert(l);
-    assert(l->ref >= 1);
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
 
-    l->ref++;
+    PA_REFCNT_INC(l);
     return l;
 }
 
 void pa_ioline_close(pa_ioline *l) {
-    assert(l);
-    assert(l->ref >= 1);
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
 
     l->dead = 1;
 
@@ -146,9 +149,9 @@ void pa_ioline_close(pa_ioline *l) {
 void pa_ioline_puts(pa_ioline *l, const char *c) {
     size_t len;
 
-    assert(l);
-    assert(l->ref >= 1);
-    assert(c);
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
+    pa_assert(c);
 
     if (l->dead)
         return;
@@ -158,7 +161,7 @@ void pa_ioline_puts(pa_ioline *l, const char *c) {
         len = BUFFER_LIMIT - l->wbuf_valid_length;
 
     if (len) {
-        assert(l->wbuf_length >= l->wbuf_valid_length);
+        pa_assert(l->wbuf_length >= l->wbuf_valid_length);
 
         /* In case the allocated buffer is too small, enlarge it. */
         if (l->wbuf_valid_length + len > l->wbuf_length) {
@@ -178,7 +181,7 @@ void pa_ioline_puts(pa_ioline *l, const char *c) {
             l->wbuf_index = 0;
         }
 
-        assert(l->wbuf_index + l->wbuf_valid_length + len <= l->wbuf_length);
+        pa_assert(l->wbuf_index + l->wbuf_valid_length + len <= l->wbuf_length);
 
         /* Append the new string */
         memcpy(l->wbuf + l->wbuf_index + l->wbuf_valid_length, c, len);
@@ -189,17 +192,17 @@ void pa_ioline_puts(pa_ioline *l, const char *c) {
 }
 
 void pa_ioline_set_callback(pa_ioline*l, void (*callback)(pa_ioline*io, const char *s, void *userdata), void *userdata) {
-    assert(l);
-    assert(l->ref >= 1);
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
 
     l->callback = callback;
     l->userdata = userdata;
 }
 
 static void failure(pa_ioline *l, int process_leftover) {
-    assert(l);
-    assert(l->ref >= 1);
-    assert(!l->dead);
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
+    pa_assert(!l->dead);
 
     if (process_leftover && l->rbuf_valid_length > 0) {
         /* Pass the last missing bit to the client */
@@ -220,7 +223,9 @@ static void failure(pa_ioline *l, int process_leftover) {
 }
 
 static void scan_for_lines(pa_ioline *l, size_t skip) {
-    assert(l && l->ref >= 1 && skip < l->rbuf_valid_length);
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
+    pa_assert(skip < l->rbuf_valid_length);
 
     while (!l->dead && l->rbuf_valid_length > skip) {
         char *e, *p;
@@ -255,7 +260,8 @@ static void scan_for_lines(pa_ioline *l, size_t skip) {
 static int do_write(pa_ioline *l);
 
 static int do_read(pa_ioline *l) {
-    assert(l && l->ref >= 1);
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
 
     while (!l->dead && pa_iochannel_is_readable(l->io)) {
         ssize_t r;
@@ -289,11 +295,11 @@ static int do_read(pa_ioline *l) {
 
         len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length;
 
-        assert(len >= READ_SIZE);
+        pa_assert(len >= READ_SIZE);
 
         /* Read some data */
         if ((r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) {
-            if (r < 0) {
+            if (r < 0 && errno != ECONNRESET) {
                 pa_log("read(): %s", pa_cstrerror(errno));
                 failure(l, 0);
             } else
@@ -314,13 +320,19 @@ static int do_read(pa_ioline *l) {
 /* Try to flush the buffer */
 static int do_write(pa_ioline *l) {
     ssize_t r;
-    assert(l && l->ref >= 1);
+
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
 
     while (!l->dead && pa_iochannel_is_writable(l->io) && l->wbuf_valid_length) {
 
-        if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) {
-            pa_log("write(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
+        if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) <= 0) {
+
+            if (r < 0 && errno != EPIPE)
+                pa_log("write(): %s", pa_cstrerror(errno));
+
             failure(l, 0);
+
             return -1;
         }
 
@@ -337,8 +349,8 @@ static int do_write(pa_ioline *l) {
 
 /* Try to flush read/write data */
 static void do_work(pa_ioline *l) {
-    assert(l);
-    assert(l->ref >= 1);
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
 
     pa_ioline_ref(l);
 
@@ -358,21 +370,28 @@ static void do_work(pa_ioline *l) {
 
 static void io_callback(pa_iochannel*io, void *userdata) {
     pa_ioline *l = userdata;
-    assert(io && l && l->ref >= 1);
+
+    pa_assert(io);
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
 
     do_work(l);
 }
 
 static void defer_callback(pa_mainloop_api*m, pa_defer_event*e, void *userdata) {
     pa_ioline *l = userdata;
-    assert(l && l->ref >= 1 && l->mainloop == m && l->defer_event == e);
+
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
+    pa_assert(l->mainloop == m);
+    pa_assert(l->defer_event == e);
 
     do_work(l);
 }
 
 void pa_ioline_defer_close(pa_ioline *l) {
-    assert(l);
-    assert(l->ref >= 1);
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
 
     l->defer_close = 1;
 
@@ -384,8 +403,8 @@ void pa_ioline_printf(pa_ioline *l, const char *format, ...) {
     char *t;
     va_list ap;
 
-    assert(l);
-    assert(l->ref >= 1);
+    pa_assert(l);
+    pa_assert(PA_REFCNT_VALUE(l) >= 1);
 
     va_start(ap, format);
     t = pa_vsprintf_malloc(format, ap);
index a240d2a0adc1bfe317fcbaa56ee2d3481c52018d..9b22e8f55b28192e01e7ade1cbe28b2aa9c2aedd 100644 (file)
 #include <arpa/inet.h>
 #endif
 
-#include "winsock.h"
-
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/core-util.h>
 #include <pulsecore/llist.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/winsock.h>
 
 #ifndef HAVE_INET_PTON
 #include "inet_pton.h"
@@ -77,7 +77,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) {
     char *a;
     pa_ip_acl *acl;
 
-    assert(s);
+    pa_assert(s);
 
     acl = pa_xnew(pa_ip_acl, 1);
     PA_LLIST_HEAD_INIT(struct acl_entry, acl->entries);
@@ -91,7 +91,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) {
             *slash = 0;
             slash++;
             if (pa_atou(slash, &bits) < 0) {
-                pa_log("failed to parse number of bits: %s", slash);
+                pa_log_warn("Failed to parse number of bits: %s", slash);
                 goto fail;
             }
         } else
@@ -102,21 +102,21 @@ pa_ip_acl* pa_ip_acl_new(const char *s) {
             e.bits = bits == (uint32_t) -1 ? 32 : (int) bits;
 
             if (e.bits > 32) {
-                pa_log("number of bits out of range: %i", e.bits);
+                pa_log_warn("Number of bits out of range: %i", e.bits);
                 goto fail;
             }
 
             e.family = AF_INET;
 
             if (e.bits < 32 && (uint32_t) (ntohl(e.address_ipv4.s_addr) << e.bits) != 0)
-                pa_log_warn("WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits);
+                pa_log_warn("Host part of ACL entry '%s/%u' is not zero!", a, e.bits);
 
         } else if (inet_pton(AF_INET6, a, &e.address_ipv6) > 0) {
 
             e.bits = bits == (uint32_t) -1 ? 128 : (int) bits;
 
             if (e.bits > 128) {
-                pa_log("number of bits out of range: %i", e.bits);
+                pa_log_warn("Number of bits out of range: %i", e.bits);
                 goto fail;
             }
             e.family = AF_INET6;
@@ -138,11 +138,11 @@ pa_ip_acl* pa_ip_acl_new(const char *s) {
                 }
 
                 if (t)
-                    pa_log_warn("WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits);
+                    pa_log_warn("Host part of ACL entry '%s/%u' is not zero!", a, e.bits);
             }
 
         } else {
-            pa_log("failed to parse address: %s", a);
+            pa_log_warn("Failed to parse address: %s", a);
             goto fail;
         }
 
@@ -162,7 +162,7 @@ fail:
 }
 
 void pa_ip_acl_free(pa_ip_acl *acl) {
-    assert(acl);
+    pa_assert(acl);
 
     while (acl->entries) {
         struct acl_entry *e = acl->entries;
@@ -178,8 +178,8 @@ int pa_ip_acl_check(pa_ip_acl *acl, int fd) {
     struct acl_entry *e;
     socklen_t  salen;
 
-    assert(acl);
-    assert(fd >= 0);
+    pa_assert(acl);
+    pa_assert(fd >= 0);
 
     salen = sizeof(sa);
     if (getpeername(fd, (struct sockaddr*) &sa, &salen) < 0)
index 8fc8e22b6491750d4b2e15986492950fefb7fe53..e62f15b400fb8b4d37b6afde30462b92eabac627 100644 (file)
   USA.
 ***/
 
-#include <assert.h>
+#include <pulsecore/macro.h>
 
 /* Some macros for maintaining doubly linked lists */
 
 /* The head of the linked list. Use this in the structure that shall
  * contain the head of the linked list */
-#define PA_LLIST_HEAD(t,name) t *name
+#define PA_LLIST_HEAD(t,name)                                           \
+    t *name
 
 /* The pointers in the linked list's items. Use this in the item structure */
-#define PA_LLIST_FIELDS(t) t *next, *prev
+#define PA_LLIST_FIELDS(t)                                              \
+    t *next, *prev
 
 /* Initialize the list's head */
-#define PA_LLIST_HEAD_INIT(t,item) do { (item) = (t*) NULL; } while(0)
+#define PA_LLIST_HEAD_INIT(t,item)                                      \
+    do {                                                                \
+        (item) = (t*) NULL; }                                           \
+    while(0)
 
 /* Initialize a list item */
-#define PA_LLIST_INIT(t,item) do { \
-                               t *_item = (item); \
-                               assert(_item); \
-                               _item->prev = _item->next = NULL; \
-                               } while(0)
+#define PA_LLIST_INIT(t,item)                                           \
+    do {                                                                \
+        t *_item = (item);                                              \
+        pa_assert(_item);                                               \
+        _item->prev = _item->next = NULL;                               \
+    } while(0)
 
 /* Prepend an item to the list */
-#define PA_LLIST_PREPEND(t,head,item) do { \
-                                        t **_head = &(head), *_item = (item); \
-                                        assert(_item); \
-                                        if ((_item->next = *_head)) \
-                                           _item->next->prev = _item; \
-                                        _item->prev = NULL; \
-                                        *_head = _item; \
-                                        } while (0)
+#define PA_LLIST_PREPEND(t,head,item)                                   \
+    do {                                                                \
+        t **_head = &(head), *_item = (item);                           \
+        pa_assert(_item);                                               \
+        if ((_item->next = *_head))                                     \
+            _item->next->prev = _item;                                  \
+        _item->prev = NULL;                                             \
+        *_head = _item;                                                 \
+    } while (0)
 
 /* Remove an item from the list */
-#define PA_LLIST_REMOVE(t,head,item) do { \
-                                    t **_head = &(head), *_item = (item); \
-                                    assert(_item); \
-                                    if (_item->next) \
-                                       _item->next->prev = _item->prev; \
-                                    if (_item->prev) \
-                                       _item->prev->next = _item->next; \
-                                    else {\
-                                       assert(*_head == _item); \
-                                       *_head = _item->next; \
-                                    } \
-                                    _item->next = _item->prev = NULL; \
-                                    } while(0)
-
-#define PA_LLIST_FIND_HEAD(t,item,head) \
-do { \
-    t **_head = (head), *_item = (item); \
-    *_head = _item; \
-    assert(_head); \
-    while ((*_head)->prev) \
-        *_head = (*_head)->prev; \
-} while (0)
-
-#define PA_LLIST_INSERT_AFTER(t,head,a,b) \
-do { \
-    t **_head = &(head), *_a = (a), *_b = (b); \
-    assert(_b); \
-    if (!_a) { \
-        if ((_b->next = *_head)) \
-            _b->next->prev = _b; \
-        _b->prev = NULL; \
-        *_head = _b; \
-    } else { \
-        if ((_b->next = _a->next)) \
-            _b->next->prev = _b; \
-        _b->prev = _a; \
-        _a->next = _b; \
-    } \
-} while (0)
-
+#define PA_LLIST_REMOVE(t,head,item)                                    \
+    do {                                                                \
+        t **_head = &(head), *_item = (item);                           \
+        pa_assert(_item);                                               \
+        if (_item->next)                                                \
+            _item->next->prev = _item->prev;                            \
+        if (_item->prev)                                                \
+            _item->prev->next = _item->next;                            \
+        else {                                                          \
+            pa_assert(*_head == _item);                                 \
+            *_head = _item->next;                                       \
+        }                                                               \
+        _item->next = _item->prev = NULL;                               \
+    } while(0)
+
+/* Find the head of the list */
+#define PA_LLIST_FIND_HEAD(t,item,head)                                 \
+    do {                                                                \
+        t **_head = (head), *_item = (item);                            \
+        *_head = _item;                                                 \
+        pa_assert(_head);                                               \
+        while ((*_head)->prev)                                          \
+            *_head = (*_head)->prev;                                    \
+    } while (0)
+
+/* Insert an item after another one (a = where, b = what) */
+#define PA_LLIST_INSERT_AFTER(t,head,a,b)                               \
+    do {                                                                \
+        t **_head = &(head), *_a = (a), *_b = (b);                      \
+        pa_assert(_b);                                                  \
+        if (!_a) {                                                      \
+            if ((_b->next = *_head))                                    \
+                _b->next->prev = _b;                                    \
+            _b->prev = NULL;                                            \
+            *_head = _b;                                                \
+        } else {                                                        \
+            if ((_b->next = _a->next))                                  \
+                _b->next->prev = _b;                                    \
+            _b->prev = _a;                                              \
+            _a->next = _b;                                              \
+        }                                                               \
+    } while (0)
 
 #endif
index 0033adb91ed52ad3e6c799de410d720b30210a92..c824e84d198f4d5f4edd2c80b47238a95f414e5b 100644 (file)
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -40,6 +39,7 @@
 #include <pulse/xmalloc.h>
 #include <pulse/util.h>
 
+#include <pulsecore/macro.h>
 #include <pulsecore/core-util.h>
 
 #include "log.h"
@@ -71,24 +71,30 @@ static const char level_to_char[] = {
 };
 
 void pa_log_set_ident(const char *p) {
-    if (log_ident)
-        pa_xfree(log_ident);
-    if (log_ident_local)
-        pa_xfree(log_ident_local);
+    pa_xfree(log_ident);
+    pa_xfree(log_ident_local);
 
     log_ident = pa_xstrdup(p);
-    log_ident_local = pa_utf8_to_locale(log_ident);
-    if (!log_ident_local)
+    if (!(log_ident_local = pa_utf8_to_locale(log_ident)))
         log_ident_local = pa_xstrdup(log_ident);
 }
 
+/* To make valgrind shut up. */
+static void ident_destructor(void) PA_GCC_DESTRUCTOR;
+static void ident_destructor(void) {
+    pa_xfree(log_ident);
+    pa_xfree(log_ident_local);
+}
+
 void pa_log_set_maximal_level(pa_log_level_t l) {
-    assert(l < PA_LOG_LEVEL_MAX);
+    pa_assert(l < PA_LOG_LEVEL_MAX);
+
     maximal_level = l;
 }
 
 void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t l, const char*s)) {
-    assert(t == PA_LOG_USER || !func);
+    pa_assert(t == PA_LOG_USER || !func);
+
     log_target = t;
     user_log_func = func;
 }
@@ -104,8 +110,8 @@ void pa_log_levelv_meta(
     const char *e;
     char *text, *t, *n, *location;
 
-    assert(level < PA_LOG_LEVEL_MAX);
-    assert(format);
+    pa_assert(level < PA_LOG_LEVEL_MAX);
+    pa_assert(format);
 
     if ((e = getenv(ENV_LOGLEVEL)))
         maximal_level = atoi(e);
@@ -221,6 +227,7 @@ void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) {
 
 void pa_log_level(pa_log_level_t level, const char *format, ...) {
     va_list ap;
+
     va_start(ap, format);
     pa_log_levelv_meta(level, NULL, 0, NULL, format, ap);
     va_end(ap);
diff --git a/src/pulsecore/ltdl-helper.c b/src/pulsecore/ltdl-helper.c
new file mode 100644 (file)
index 0000000..711396d
--- /dev/null
@@ -0,0 +1,64 @@
+/* $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 <stdlib.h>
+#include <ctype.h>
+
+#include <pulse/xmalloc.h>
+#include <pulse/util.h>
+
+#include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
+
+#include "ltdl-helper.h"
+
+pa_void_func_t pa_load_sym(lt_dlhandle handle, const char *module, const char *symbol) {
+    char *sn, *c;
+    pa_void_func_t f;
+
+    pa_assert(handle);
+    pa_assert(module);
+    pa_assert(symbol);
+
+    if ((f = ((pa_void_func_t) (long) lt_dlsym(handle, symbol))))
+        return f;
+
+    /* As the .la files might have been cleansed from the system, we should
+     * try with the ltdl prefix as well. */
+
+    sn = pa_sprintf_malloc("%s_LTX_%s", module, symbol);
+
+    for (c = sn; *c; c++)
+        if (!isalnum(*c))
+            *c = '_';
+
+    f = (pa_void_func_t) (long) lt_dlsym(handle, sn);
+    pa_xfree(sn);
+
+    return f;
+}
diff --git a/src/pulsecore/ltdl-helper.h b/src/pulsecore/ltdl-helper.h
new file mode 100644 (file)
index 0000000..5c7388a
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef foopulsecoreltdlhelperhfoo
+#define foopulsecoreltdlhelperhfoo
+
+/* $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.
+***/
+
+#include <ltdl.h>
+
+typedef void (*pa_void_func_t)(void);
+
+pa_void_func_t pa_load_sym(lt_dlhandle handle, const char*module, const char *symbol);
+
+#endif
+
diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
new file mode 100644 (file)
index 0000000..c6bba43
--- /dev/null
@@ -0,0 +1,149 @@
+#ifndef foopulsemacrohfoo
+#define foopulsemacrohfoo
+
+/* $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.
+***/
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include <pulsecore/log.h>
+
+#ifndef PACKAGE
+#error "Please include config.h before including this file!"
+#endif
+
+#if defined(PAGE_SIZE)
+#define PA_PAGE_SIZE ((size_t) PAGE_SIZE)
+#elif defined(PAGESIZE)
+#define PA_PAGE_SIZE ((size_t) PAGESIZE)
+#elif defined(HAVE_SYSCONF)
+#define PA_PAGE_SIZE ((size_t) (sysconf(_SC_PAGE_SIZE)))
+#else
+/* Let's hope it's like x86. */
+#define PA_PAGE_SIZE ((size_t) 4096)
+#endif
+
+static inline size_t pa_align(size_t l) {
+    return (((l + sizeof(void*) - 1) / sizeof(void*)) * sizeof(void*));
+}
+#define PA_ALIGN(x) (pa_align(x))
+
+static inline void* pa_page_align_ptr(const void *p) {
+    return (void*) (((size_t) p) & ~(PA_PAGE_SIZE-1));
+}
+#define PA_PAGE_ALIGN_PTR(x) (pa_page_align_ptr(x))
+
+static inline size_t pa_page_align(size_t l) {
+    return l & ~(PA_PAGE_SIZE-1);
+}
+#define PA_PAGE_ALIGN(x) (pa_page_align(x))
+
+#define PA_ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
+
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef CLAMP
+#define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
+#endif
+
+/* This type is not intended to be used in exported APIs! Use classic "int" there! */
+#ifdef HAVE_STD_BOOL
+typedef _Bool pa_bool_t;
+#else
+typedef int pa_bool_t;
+#endif
+
+#ifndef FALSE
+#define FALSE ((pa_bool_t) 0)
+#endif
+
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+#ifdef __GNUC__
+#define PA_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#else
+#define PA_PRETTY_FUNCTION ""
+#endif
+
+#define pa_return_if_fail(expr) \
+    do { \
+        if (!(expr)) { \
+            pa_log_debug("%s: Assertion <%s> failed.\n", PA_PRETTY_FUNCTION, #expr ); \
+            return; \
+        } \
+    } while(0)
+
+#define pa_return_val_if_fail(expr, val) \
+    do { \
+        if (!(expr)) { \
+            pa_log_debug("%s: Assertion <%s> failed.\n", PA_PRETTY_FUNCTION, #expr ); \
+            return (val); \
+        } \
+    } while(0)
+
+#define pa_return_null_if_fail(expr) pa_return_val_if_fail(expr, NULL)
+
+#define pa_assert assert
+
+#define pa_assert_not_reached() pa_assert(!"Should not be reached.")
+
+/* An assert which guarantees side effects of x */
+#ifdef NDEBUG
+#define pa_assert_se(x) x
+#else
+#define pa_assert_se(x) pa_assert(x)
+#endif
+
+#define PA_PTR_TO_UINT(p) ((unsigned int) (unsigned long) (p))
+#define PA_UINT_TO_PTR(u) ((void*) (unsigned long) (u))
+
+#define PA_PTR_TO_UINT32(p) ((uint32_t) PA_PTR_TO_UINT(p))
+#define PA_UINT32_TO_PTR(u) PA_UINT_TO_PTR((uint32_t) u)
+
+#define PA_PTR_TO_INT(p) ((int) PA_PTR_TO_UINT(p))
+#define PA_INT_TO_PTR(u) PA_UINT_TO_PTR((int) u)
+
+#define PA_PTR_TO_INT32(p) ((int32_t) PA_PTR_TO_UINT(p))
+#define PA_INT32_TO_PTR(u) PA_UINT_TO_PTR((int32_t) u)
+
+#ifdef OS_IS_WIN32
+#define PA_PATH_SEP "\\"
+#define PA_PATH_SEP_CHAR '\\'
+#else
+#define PA_PATH_SEP "/"
+#define PA_PATH_SEP_CHAR '/'
+#endif
+
+#endif
index dd1d71f3c39c2219dc32e90a96c4d4c617e62947..8ca7c962d1ad2c61cc3c75b4591f31e1e3b812df 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <assert.h>
 #include <string.h>
 
 #include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
 
 #include "mcalign.h"
 
@@ -41,7 +41,7 @@ struct pa_mcalign {
 
 pa_mcalign *pa_mcalign_new(size_t base) {
     pa_mcalign *m;
-    assert(base);
+    pa_assert(base);
 
     m = pa_xnew(pa_mcalign, 1);
 
@@ -53,7 +53,7 @@ pa_mcalign *pa_mcalign_new(size_t base) {
 }
 
 void pa_mcalign_free(pa_mcalign *m) {
-    assert(m);
+    pa_assert(m);
 
     if (m->leftover.memblock)
         pa_memblock_unref(m->leftover.memblock);
@@ -65,13 +65,13 @@ void pa_mcalign_free(pa_mcalign *m) {
 }
 
 void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) {
-    assert(m);
-    assert(c);
+    pa_assert(m);
+    pa_assert(c);
 
-    assert(c->memblock);
-    assert(c->length > 0);
+    pa_assert(c->memblock);
+    pa_assert(c->length > 0);
 
-    assert(!m->current.memblock);
+    pa_assert(!m->current.memblock);
 
     /* Append to the leftover memory block */
     if (m->leftover.memblock) {
@@ -91,9 +91,10 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) {
 
         } else {
             size_t l;
+            void *lo_data, *m_data;
 
             /* We have to copy */
-            assert(m->leftover.length < m->base);
+            pa_assert(m->leftover.length < m->base);
             l = m->base - m->leftover.length;
 
             if (l > c->length)
@@ -102,10 +103,15 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) {
             /* Can we use the current block? */
             pa_memchunk_make_writable(&m->leftover, m->base);
 
-            memcpy((uint8_t*) m->leftover.memblock->data + m->leftover.index + m->leftover.length, (uint8_t*) c->memblock->data + c->index, l);
+            lo_data = pa_memblock_acquire(m->leftover.memblock);
+            m_data = pa_memblock_acquire(c->memblock);
+            memcpy((uint8_t*) lo_data + m->leftover.index + m->leftover.length, (uint8_t*) m_data + c->index, l);
+            pa_memblock_release(m->leftover.memblock);
+            pa_memblock_release(c->memblock);
             m->leftover.length += l;
 
-            assert(m->leftover.length <= m->base && m->leftover.length <= m->leftover.memblock->length);
+            pa_assert(m->leftover.length <= m->base);
+            pa_assert(m->leftover.length <= pa_memblock_get_length(m->leftover.memblock));
 
             if (c->length > l) {
                 /* Save the remainder of the memory block */
@@ -128,12 +134,13 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) {
 }
 
 int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) {
-    assert(m);
-    assert(c);
+    pa_assert(m);
+    pa_assert(c);
 
     /* First test if there's a leftover memory block available */
     if (m->leftover.memblock) {
-        assert(m->leftover.length > 0 && m->leftover.length <= m->base);
+        pa_assert(m->leftover.length > 0);
+        pa_assert(m->leftover.length <= m->base);
 
         /* The leftover memory block is not yet complete */
         if (m->leftover.length < m->base)
@@ -155,13 +162,13 @@ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) {
     /* Now let's see if there is other data available */
     if (m->current.memblock) {
         size_t l;
-        assert(m->current.length >= m->base);
+        pa_assert(m->current.length >= m->base);
 
         /* The length of the returned memory block */
         l = m->current.length;
         l /= m->base;
         l *= m->base;
-        assert(l > 0);
+        pa_assert(l > 0);
 
         /* Prepare the returned block */
         *c = m->current;
@@ -169,7 +176,7 @@ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) {
         c->length = l;
 
         /* Drop that from the current memory block */
-        assert(l <= m->current.length);
+        pa_assert(l <= m->current.length);
         m->current.index += l;
         m->current.length -= l;
 
@@ -178,7 +185,7 @@ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) {
             pa_memblock_unref(m->current.memblock);
         else {
             /* Move the raimainder to leftover */
-            assert(m->current.length < m->base && !m->leftover.memblock);
+            pa_assert(m->current.length < m->base && !m->leftover.memblock);
 
             m->leftover = m->current;
         }
@@ -194,10 +201,10 @@ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) {
 }
 
 size_t pa_mcalign_csize(pa_mcalign *m, size_t l) {
-    assert(m);
-    assert(l > 0);
+    pa_assert(m);
+    pa_assert(l > 0);
 
-    assert(!m->current.memblock);
+    pa_assert(!m->current.memblock);
 
     if (m->leftover.memblock)
         l += m->leftover.length;
index 6f09a906ae49edb3846747b806be3fae2ee05a1c..99b5a13f080a0a1ff20559bb93a5a413580368d8 100644 (file)
@@ -14,7 +14,7 @@
   PulseAudio is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
+  Lesser General Public License for more details
 
   You should have received a copy of the GNU Lesser General Public
   License along with PulseAudio; if not, write to the Free Software
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <assert.h>
 #include <string.h>
 #include <unistd.h>
+#include <signal.h>
+#include <errno.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/def.h>
 
 #include <pulsecore/shm.h>
 #include <pulsecore/log.h>
 #include <pulsecore/hashmap.h>
+#include <pulsecore/semaphore.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/flist.h>
+#include <pulsecore/core-util.h>
 
 #include "memblock.h"
 
 #define PA_MEMIMPORT_SLOTS_MAX 128
 #define PA_MEMIMPORT_SEGMENTS_MAX 16
 
+struct pa_memblock {
+    PA_REFCNT_DECLARE; /* the reference counter */
+    pa_mempool *pool;
+
+    pa_memblock_type_t type;
+    int read_only; /* boolean */
+
+    pa_atomic_ptr_t data;
+    size_t length;
+
+    pa_atomic_t n_acquired;
+    pa_atomic_t please_signal;
+
+    union {
+        struct {
+            /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */
+            pa_free_cb_t free_cb;
+        } user;
+
+        struct  {
+            uint32_t id;
+            pa_memimport_segment *segment;
+        } imported;
+    } per_type;
+};
+
 struct pa_memimport_segment {
     pa_memimport *import;
     pa_shm memory;
@@ -55,6 +87,8 @@ struct pa_memimport_segment {
 };
 
 struct pa_memimport {
+    pa_mutex *mutex;
+
     pa_mempool *pool;
     pa_hashmap *segments;
     pa_hashmap *blocks;
@@ -73,9 +107,11 @@ struct memexport_slot {
 };
 
 struct pa_memexport {
+    pa_mutex *mutex;
     pa_mempool *pool;
 
     struct memexport_slot slots[PA_MEMEXPORT_SLOTS_MAX];
+
     PA_LLIST_HEAD(struct memexport_slot, free_slots);
     PA_LLIST_HEAD(struct memexport_slot, used_slots);
     unsigned n_init;
@@ -95,24 +131,32 @@ struct mempool_slot {
 };
 
 struct pa_mempool {
+    pa_semaphore *semaphore;
+    pa_mutex *mutex;
+
     pa_shm memory;
     size_t block_size;
-    unsigned n_blocks, n_init;
+    unsigned n_blocks;
+
+    pa_atomic_t n_init;
 
     PA_LLIST_HEAD(pa_memimport, imports);
     PA_LLIST_HEAD(pa_memexport, exports);
 
     /* A list of free slots that may be reused */
-    PA_LLIST_HEAD(struct mempool_slot, free_slots);
+    pa_flist *free_slots;
 
     pa_mempool_stat stat;
 };
 
 static void segment_detach(pa_memimport_segment *seg);
 
+PA_STATIC_FLIST_DECLARE(unused_memblocks, 0, pa_xfree);
+
+/* No lock necessary */
 static void stat_add(pa_memblock*b) {
-    assert(b);
-    assert(b->pool);
+    pa_assert(b);
+    pa_assert(b->pool);
 
     pa_atomic_inc(&b->pool->stat.n_allocated);
     pa_atomic_add(&b->pool->stat.allocated_size, b->length);
@@ -129,19 +173,20 @@ static void stat_add(pa_memblock*b) {
     pa_atomic_inc(&b->pool->stat.n_accumulated_by_type[b->type]);
 }
 
+/* No lock necessary */
 static void stat_remove(pa_memblock *b) {
-    assert(b);
-    assert(b->pool);
+    pa_assert(b);
+    pa_assert(b->pool);
 
-    assert(pa_atomic_load(&b->pool->stat.n_allocated) > 0);
-    assert(pa_atomic_load(&b->pool->stat.allocated_size) >= (int) b->length);
+    pa_assert(pa_atomic_load(&b->pool->stat.n_allocated) > 0);
+    pa_assert(pa_atomic_load(&b->pool->stat.allocated_size) >= (int) b->length);
 
     pa_atomic_dec(&b->pool->stat.n_allocated);
     pa_atomic_sub(&b->pool->stat.allocated_size,  b->length);
 
     if (b->type == PA_MEMBLOCK_IMPORTED) {
-        assert(pa_atomic_load(&b->pool->stat.n_imported) > 0);
-        assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length);
+        pa_assert(pa_atomic_load(&b->pool->stat.n_imported) > 0);
+        pa_assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length);
 
         pa_atomic_dec(&b->pool->stat.n_imported);
         pa_atomic_sub(&b->pool->stat.imported_size, b->length);
@@ -152,11 +197,12 @@ static void stat_remove(pa_memblock *b) {
 
 static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length);
 
+/* No lock necessary */
 pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) {
     pa_memblock *b;
 
-    assert(p);
-    assert(length > 0);
+    pa_assert(p);
+    pa_assert(length > 0);
 
     if (!(b = pa_memblock_new_pool(p, length)))
         b = memblock_new_appended(p, length);
@@ -164,56 +210,75 @@ pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) {
     return b;
 }
 
+/* No lock necessary */
 static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length) {
     pa_memblock *b;
 
-    assert(p);
-    assert(length > 0);
+    pa_assert(p);
+    pa_assert(length > 0);
 
-    b = pa_xmalloc(sizeof(pa_memblock) + length);
+    /* If -1 is passed as length we choose the size for the caller. */
+
+    if (length == (size_t) -1)
+        length = p->block_size - PA_ALIGN(sizeof(struct mempool_slot)) - PA_ALIGN(sizeof(pa_memblock));
+
+    b = pa_xmalloc(PA_ALIGN(sizeof(pa_memblock)) + length);
+    PA_REFCNT_INIT(b);
+    b->pool = p;
     b->type = PA_MEMBLOCK_APPENDED;
     b->read_only = 0;
-    PA_REFCNT_INIT(b);
+    pa_atomic_ptr_store(&b->data, (uint8_t*) b + PA_ALIGN(sizeof(pa_memblock)));
     b->length = length;
-    b->data = (uint8_t*) b + sizeof(pa_memblock);
-    b->pool = p;
+    pa_atomic_store(&b->n_acquired, 0);
+    pa_atomic_store(&b->please_signal, 0);
 
     stat_add(b);
     return b;
 }
 
+/* No lock necessary */
 static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) {
     struct mempool_slot *slot;
-    assert(p);
+    pa_assert(p);
 
-    if (p->free_slots) {
-        slot = p->free_slots;
-        PA_LLIST_REMOVE(struct mempool_slot, p->free_slots, slot);
-    } else if (p->n_init < p->n_blocks)
-        slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * p->n_init++));
-    else {
-        pa_log_debug("Pool full");
-        pa_atomic_inc(&p->stat.n_pool_full);
-        return NULL;
+    if (!(slot = pa_flist_pop(p->free_slots))) {
+        int idx;
+
+        /* The free list was empty, we have to allocate a new entry */
+
+        if ((unsigned) (idx = pa_atomic_inc(&p->n_init)) >= p->n_blocks)
+            pa_atomic_dec(&p->n_init);
+        else
+            slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * idx));
+
+        if (!slot) {
+            pa_log_debug("Pool full");
+            pa_atomic_inc(&p->stat.n_pool_full);
+            return NULL;
+        }
     }
 
     return slot;
 }
 
+/* No lock necessary */
 static void* mempool_slot_data(struct mempool_slot *slot) {
-    assert(slot);
+    pa_assert(slot);
 
-    return (uint8_t*) slot + sizeof(struct mempool_slot);
+    return (uint8_t*) slot + PA_ALIGN(sizeof(struct mempool_slot));
 }
 
+/* No lock necessary */
 static unsigned mempool_slot_idx(pa_mempool *p, void *ptr) {
-    assert(p);
-    assert((uint8_t*) ptr >= (uint8_t*) p->memory.ptr);
-    assert((uint8_t*) ptr < (uint8_t*) p->memory.ptr + p->memory.size);
+    pa_assert(p);
+
+    pa_assert((uint8_t*) ptr >= (uint8_t*) p->memory.ptr);
+    pa_assert((uint8_t*) ptr < (uint8_t*) p->memory.ptr + p->memory.size);
 
     return ((uint8_t*) ptr - (uint8_t*) p->memory.ptr) / p->block_size;
 }
 
+/* No lock necessary */
 static struct mempool_slot* mempool_slot_by_ptr(pa_mempool *p, void *ptr) {
     unsigned idx;
 
@@ -223,189 +288,321 @@ static struct mempool_slot* mempool_slot_by_ptr(pa_mempool *p, void *ptr) {
     return (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (idx * p->block_size));
 }
 
+/* No lock necessary */
 pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
     pa_memblock *b = NULL;
     struct mempool_slot *slot;
 
-    assert(p);
-    assert(length > 0);
+    pa_assert(p);
+    pa_assert(length > 0);
+
+    /* If -1 is passed as length we choose the size for the caller: we
+     * take the largest size that fits in one of our slots. */
 
-    if (p->block_size - sizeof(struct mempool_slot) >= sizeof(pa_memblock) + length) {
+    if (length == (size_t) -1)
+        length = pa_mempool_block_size_max(p);
+
+    if (p->block_size - PA_ALIGN(sizeof(struct mempool_slot)) >= PA_ALIGN(sizeof(pa_memblock)) + length) {
 
         if (!(slot = mempool_allocate_slot(p)))
             return NULL;
 
         b = mempool_slot_data(slot);
         b->type = PA_MEMBLOCK_POOL;
-        b->data = (uint8_t*) b + sizeof(pa_memblock);
+        pa_atomic_ptr_store(&b->data, (uint8_t*) b + PA_ALIGN(sizeof(pa_memblock)));
 
-    } else if (p->block_size - sizeof(struct mempool_slot) >= length) {
+    } else if (p->block_size - PA_ALIGN(sizeof(struct mempool_slot)) >= length) {
 
         if (!(slot = mempool_allocate_slot(p)))
             return NULL;
 
-        b = pa_xnew(pa_memblock, 1);
+        if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks))))
+            b = pa_xnew(pa_memblock, 1);
+
         b->type = PA_MEMBLOCK_POOL_EXTERNAL;
-        b->data = mempool_slot_data(slot);
+        pa_atomic_ptr_store(&b->data, mempool_slot_data(slot));
+
     } else {
-        pa_log_debug("Memory block too large for pool: %u > %u", length, p->block_size - sizeof(struct mempool_slot));
+        pa_log_debug("Memory block too large for pool: %lu > %lu", (unsigned long) length, (unsigned long) (p->block_size - PA_ALIGN(sizeof(struct mempool_slot))));
         pa_atomic_inc(&p->stat.n_too_large_for_pool);
         return NULL;
     }
 
-    b->length = length;
-    b->read_only = 0;
     PA_REFCNT_INIT(b);
     b->pool = p;
+    b->read_only = 0;
+    b->length = length;
+    pa_atomic_store(&b->n_acquired, 0);
+    pa_atomic_store(&b->please_signal, 0);
 
     stat_add(b);
     return b;
 }
 
+/* No lock necessary */
 pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int read_only) {
     pa_memblock *b;
 
-    assert(p);
-    assert(d);
-    assert(length > 0);
+    pa_assert(p);
+    pa_assert(d);
+    pa_assert(length != (size_t) -1);
+    pa_assert(length > 0);
 
-    b = pa_xnew(pa_memblock, 1);
+    if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks))))
+        b = pa_xnew(pa_memblock, 1);
+    PA_REFCNT_INIT(b);
+    b->pool = p;
     b->type = PA_MEMBLOCK_FIXED;
     b->read_only = read_only;
-    PA_REFCNT_INIT(b);
+    pa_atomic_ptr_store(&b->data, d);
     b->length = length;
-    b->data = d;
-    b->pool = p;
+    pa_atomic_store(&b->n_acquired, 0);
+    pa_atomic_store(&b->please_signal, 0);
 
     stat_add(b);
     return b;
 }
 
+/* No lock necessary */
 pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (*free_cb)(void *p), int read_only) {
     pa_memblock *b;
 
-    assert(p);
-    assert(d);
-    assert(length > 0);
-    assert(free_cb);
+    pa_assert(p);
+    pa_assert(d);
+    pa_assert(length > 0);
+    pa_assert(length != (size_t) -1);
+    pa_assert(free_cb);
 
-    b = pa_xnew(pa_memblock, 1);
+    if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks))))
+        b = pa_xnew(pa_memblock, 1);
+    PA_REFCNT_INIT(b);
+    b->pool = p;
     b->type = PA_MEMBLOCK_USER;
     b->read_only = read_only;
-    PA_REFCNT_INIT(b);
+    pa_atomic_ptr_store(&b->data, d);
     b->length = length;
-    b->data = d;
+    pa_atomic_store(&b->n_acquired, 0);
+    pa_atomic_store(&b->please_signal, 0);
+
     b->per_type.user.free_cb = free_cb;
-    b->pool = p;
 
     stat_add(b);
     return b;
 }
 
+/* No lock necessary */
+int pa_memblock_is_read_only(pa_memblock *b) {
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
+
+    return b->read_only && PA_REFCNT_VALUE(b) == 1;
+}
+
+/* No lock necessary */
+int pa_memblock_ref_is_one(pa_memblock *b) {
+    int r;
+
+    pa_assert(b);
+
+    r = PA_REFCNT_VALUE(b);
+    pa_assert(r > 0);
+
+    return r == 1;
+}
+
+/* No lock necessary */
+void* pa_memblock_acquire(pa_memblock *b) {
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
+
+    pa_atomic_inc(&b->n_acquired);
+
+    return pa_atomic_ptr_load(&b->data);
+}
+
+/* No lock necessary, in corner cases locks by its own */
+void pa_memblock_release(pa_memblock *b) {
+    int r;
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
+
+    r = pa_atomic_dec(&b->n_acquired);
+    pa_assert(r >= 1);
+
+    /* Signal a waiting thread that this memblock is no longer used */
+    if (r == 1 && pa_atomic_load(&b->please_signal))
+        pa_semaphore_post(b->pool->semaphore);
+}
+
+size_t pa_memblock_get_length(pa_memblock *b) {
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
+
+    return b->length;
+}
+
+pa_mempool* pa_memblock_get_pool(pa_memblock *b) {
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
+
+    return b->pool;
+}
+
+/* No lock necessary */
 pa_memblock* pa_memblock_ref(pa_memblock*b) {
-    assert(b);
-    assert(PA_REFCNT_VALUE(b) > 0);
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
 
     PA_REFCNT_INC(b);
     return b;
 }
 
-void pa_memblock_unref(pa_memblock*b) {
-    assert(b);
-    assert(PA_REFCNT_VALUE(b) > 0);
+static void memblock_free(pa_memblock *b) {
+    pa_assert(b);
 
-    if (PA_REFCNT_DEC(b) > 0)
-        return;
+    pa_assert(pa_atomic_load(&b->n_acquired) == 0);
 
     stat_remove(b);
 
     switch (b->type) {
         case PA_MEMBLOCK_USER :
-            assert(b->per_type.user.free_cb);
-            b->per_type.user.free_cb(b->data);
+            pa_assert(b->per_type.user.free_cb);
+            b->per_type.user.free_cb(pa_atomic_ptr_load(&b->data));
 
             /* Fall through */
 
         case PA_MEMBLOCK_FIXED:
         case PA_MEMBLOCK_APPENDED :
-            pa_xfree(b);
+            if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0)
+                pa_xfree(b);
+
             break;
 
         case PA_MEMBLOCK_IMPORTED : {
             pa_memimport_segment *segment;
+            pa_memimport *import;
 
-            segment = b->per_type.imported.segment;
-            assert(segment);
-            assert(segment->import);
+            /* FIXME! This should be implemented lock-free */
 
-            pa_hashmap_remove(segment->import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id));
-            segment->import->release_cb(segment->import, b->per_type.imported.id, segment->import->userdata);
+            segment = b->per_type.imported.segment;
+            pa_assert(segment);
+            import = segment->import;
+            pa_assert(import);
 
+            pa_mutex_lock(import->mutex);
+            pa_hashmap_remove(import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id));
             if (-- segment->n_blocks <= 0)
                 segment_detach(segment);
 
-            pa_xfree(b);
+            pa_mutex_unlock(import->mutex);
+
+            import->release_cb(import, b->per_type.imported.id, import->userdata);
+
+            if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0)
+                pa_xfree(b);
             break;
         }
 
         case PA_MEMBLOCK_POOL_EXTERNAL:
         case PA_MEMBLOCK_POOL: {
             struct mempool_slot *slot;
+            int call_free;
 
-            slot = mempool_slot_by_ptr(b->pool, b->data);
-            assert(slot);
+            slot = mempool_slot_by_ptr(b->pool, pa_atomic_ptr_load(&b->data));
+            pa_assert(slot);
 
-            PA_LLIST_PREPEND(struct mempool_slot, b->pool->free_slots, slot);
+            call_free = b->type == PA_MEMBLOCK_POOL_EXTERNAL;
 
-            if (b->type == PA_MEMBLOCK_POOL_EXTERNAL)
-                pa_xfree(b);
+            /* The free list dimensions should easily allow all slots
+             * to fit in, hence try harder if pushing this slot into
+             * the free list fails */
+            while (pa_flist_push(b->pool->free_slots, slot) < 0)
+                ;
+
+            if (call_free)
+                if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0)
+                    pa_xfree(b);
 
             break;
         }
 
         case PA_MEMBLOCK_TYPE_MAX:
         default:
-            abort();
+            pa_assert_not_reached();
     }
 }
 
+/* No lock necessary */
+void pa_memblock_unref(pa_memblock*b) {
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
+
+    if (PA_REFCNT_DEC(b) > 0)
+        return;
+
+    memblock_free(b);
+}
+
+/* Self locked */
+static void memblock_wait(pa_memblock *b) {
+    pa_assert(b);
+
+    if (pa_atomic_load(&b->n_acquired) > 0) {
+        /* We need to wait until all threads gave up access to the
+         * memory block before we can go on. Unfortunately this means
+         * that we have to lock and wait here. Sniff! */
+
+        pa_atomic_inc(&b->please_signal);
+
+        while (pa_atomic_load(&b->n_acquired) > 0)
+            pa_semaphore_wait(b->pool->semaphore);
+
+        pa_atomic_dec(&b->please_signal);
+    }
+}
+
+/* No lock necessary. This function is not multiple caller safe! */
 static void memblock_make_local(pa_memblock *b) {
-    assert(b);
+    pa_assert(b);
 
     pa_atomic_dec(&b->pool->stat.n_allocated_by_type[b->type]);
 
-    if (b->length <= b->pool->block_size - sizeof(struct mempool_slot)) {
+    if (b->length <= b->pool->block_size - PA_ALIGN(sizeof(struct mempool_slot))) {
         struct mempool_slot *slot;
 
         if ((slot = mempool_allocate_slot(b->pool))) {
             void *new_data;
             /* We can move it into a local pool, perfect! */
 
+            new_data = mempool_slot_data(slot);
+            memcpy(new_data, pa_atomic_ptr_load(&b->data), b->length);
+            pa_atomic_ptr_store(&b->data, new_data);
+
             b->type = PA_MEMBLOCK_POOL_EXTERNAL;
             b->read_only = 0;
 
-            new_data = mempool_slot_data(slot);
-            memcpy(new_data, b->data, b->length);
-            b->data = new_data;
             goto finish;
         }
     }
 
     /* Humm, not enough space in the pool, so lets allocate the memory with malloc() */
-    b->type = PA_MEMBLOCK_USER;
     b->per_type.user.free_cb = pa_xfree;
+    pa_atomic_ptr_store(&b->data, pa_xmemdup(pa_atomic_ptr_load(&b->data), b->length));
+
+    b->type = PA_MEMBLOCK_USER;
     b->read_only = 0;
-    b->data = pa_xmemdup(b->data, b->length);
 
 finish:
     pa_atomic_inc(&b->pool->stat.n_allocated_by_type[b->type]);
     pa_atomic_inc(&b->pool->stat.n_accumulated_by_type[b->type]);
+    memblock_wait(b);
 }
 
+/* No lock necessary. This function is not multiple caller safe*/
 void pa_memblock_unref_fixed(pa_memblock *b) {
-    assert(b);
-    assert(PA_REFCNT_VALUE(b) > 0);
-    assert(b->type == PA_MEMBLOCK_FIXED);
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
+    pa_assert(b->type == PA_MEMBLOCK_FIXED);
 
     if (PA_REFCNT_VALUE(b) > 1)
         memblock_make_local(b);
@@ -413,20 +610,37 @@ void pa_memblock_unref_fixed(pa_memblock *b) {
     pa_memblock_unref(b);
 }
 
+/* No lock necessary. */
+pa_memblock *pa_memblock_will_need(pa_memblock *b) {
+    void *p;
+
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
+
+    p = pa_memblock_acquire(b);
+    pa_will_need(p, b->length);
+    pa_memblock_release(b);
+
+    return b;
+}
+
+/* Self-locked. This function is not multiple-caller safe */
 static void memblock_replace_import(pa_memblock *b) {
     pa_memimport_segment *seg;
 
-    assert(b);
-    assert(b->type == PA_MEMBLOCK_IMPORTED);
+    pa_assert(b);
+    pa_assert(b->type == PA_MEMBLOCK_IMPORTED);
 
-    assert(pa_atomic_load(&b->pool->stat.n_imported) > 0);
-    assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length);
+    pa_assert(pa_atomic_load(&b->pool->stat.n_imported) > 0);
+    pa_assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length);
     pa_atomic_dec(&b->pool->stat.n_imported);
     pa_atomic_sub(&b->pool->stat.imported_size, b->length);
 
     seg = b->per_type.imported.segment;
-    assert(seg);
-    assert(seg->import);
+    pa_assert(seg);
+    pa_assert(seg->import);
+
+    pa_mutex_lock(seg->import->mutex);
 
     pa_hashmap_remove(
             seg->import->blocks,
@@ -434,51 +648,49 @@ static void memblock_replace_import(pa_memblock *b) {
 
     memblock_make_local(b);
 
-    if (-- seg->n_blocks <= 0)
+    if (-- seg->n_blocks <= 0) {
+        pa_mutex_unlock(seg->import->mutex);
         segment_detach(seg);
+    } else
+        pa_mutex_unlock(seg->import->mutex);
 }
 
 pa_mempool* pa_mempool_new(int shared) {
-    size_t ps;
     pa_mempool *p;
 
     p = pa_xnew(pa_mempool, 1);
 
-#ifdef HAVE_SYSCONF
-    ps = (size_t) sysconf(_SC_PAGESIZE);
-#elif defined(PAGE_SIZE)
-       ps = (size_t) PAGE_SIZE;
-#else
-       ps = 4096; /* Let's hope it's like x86. */
-#endif
-
-    p->block_size = (PA_MEMPOOL_SLOT_SIZE/ps)*ps;
+    p->mutex = pa_mutex_new(TRUE, TRUE);
+    p->semaphore = pa_semaphore_new(0);
 
-    if (p->block_size < ps)
-        p->block_size = ps;
+    p->block_size = PA_PAGE_ALIGN(PA_MEMPOOL_SLOT_SIZE);
+    if (p->block_size < PA_PAGE_SIZE)
+        p->block_size = PA_PAGE_SIZE;
 
     p->n_blocks = PA_MEMPOOL_SLOTS_MAX;
 
-    assert(p->block_size > sizeof(struct mempool_slot));
+    pa_assert(p->block_size > PA_ALIGN(sizeof(struct mempool_slot)));
 
     if (pa_shm_create_rw(&p->memory, p->n_blocks * p->block_size, shared, 0700) < 0) {
         pa_xfree(p);
         return NULL;
     }
 
-    p->n_init = 0;
+    memset(&p->stat, 0, sizeof(p->stat));
+    pa_atomic_store(&p->n_init, 0);
 
     PA_LLIST_HEAD_INIT(pa_memimport, p->imports);
     PA_LLIST_HEAD_INIT(pa_memexport, p->exports);
-    PA_LLIST_HEAD_INIT(struct mempool_slot, p->free_slots);
 
-    memset(&p->stat, 0, sizeof(p->stat));
+    p->free_slots = pa_flist_new(p->n_blocks*2);
 
     return p;
 }
 
 void pa_mempool_free(pa_mempool *p) {
-    assert(p);
+    pa_assert(p);
+
+    pa_mutex_lock(p->mutex);
 
     while (p->imports)
         pa_memimport_free(p->imports);
@@ -486,30 +698,65 @@ void pa_mempool_free(pa_mempool *p) {
     while (p->exports)
         pa_memexport_free(p->exports);
 
-    if (pa_atomic_load(&p->stat.n_allocated) > 0)
-        pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed!");
+    pa_mutex_unlock(p->mutex);
+
+    pa_flist_free(p->free_slots, NULL);
+
+    if (pa_atomic_load(&p->stat.n_allocated) > 0) {
+/*         raise(SIGTRAP);  */
+        pa_log_warn("Memory pool destroyed but not all memory blocks freed! %u remain.", pa_atomic_load(&p->stat.n_allocated));
+    }
 
     pa_shm_free(&p->memory);
+
+    pa_mutex_free(p->mutex);
+    pa_semaphore_free(p->semaphore);
+
     pa_xfree(p);
 }
 
+/* No lock necessary */
 const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p) {
-    assert(p);
+    pa_assert(p);
 
     return &p->stat;
 }
 
+/* No lock necessary */
+size_t pa_mempool_block_size_max(pa_mempool *p) {
+    pa_assert(p);
+
+    return p->block_size - PA_ALIGN(sizeof(struct mempool_slot)) - PA_ALIGN(sizeof(pa_memblock));
+}
+
+/* No lock necessary */
 void pa_mempool_vacuum(pa_mempool *p) {
     struct mempool_slot *slot;
+    pa_flist *list;
+
+    pa_assert(p);
+
+    list = pa_flist_new(p->n_blocks*2);
 
-    assert(p);
+    while ((slot = pa_flist_pop(p->free_slots)))
+        while (pa_flist_push(list, slot) < 0)
+            ;
 
-    for (slot = p->free_slots; slot; slot = slot->next)
-        pa_shm_punch(&p->memory, (uint8_t*) slot + sizeof(struct mempool_slot) - (uint8_t*) p->memory.ptr, p->block_size - sizeof(struct mempool_slot));
+    while ((slot = pa_flist_pop(list))) {
+        pa_shm_punch(&p->memory,
+                     (uint8_t*) slot - (uint8_t*) p->memory.ptr + PA_ALIGN(sizeof(struct mempool_slot)),
+                     p->block_size - PA_ALIGN(sizeof(struct mempool_slot)));
+
+        while (pa_flist_push(p->free_slots, slot))
+            ;
+    }
+
+    pa_flist_free(list, NULL);
 }
 
+/* No lock necessary */
 int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) {
-    assert(p);
+    pa_assert(p);
 
     if (!p->memory.shared)
         return -1;
@@ -519,8 +766,9 @@ int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) {
     return 0;
 }
 
+/* No lock necessary */
 int pa_mempool_is_shared(pa_mempool *p) {
-    assert(p);
+    pa_assert(p);
 
     return !!p->memory.shared;
 }
@@ -529,22 +777,27 @@ int pa_mempool_is_shared(pa_mempool *p) {
 pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void *userdata) {
     pa_memimport *i;
 
-    assert(p);
-    assert(cb);
+    pa_assert(p);
+    pa_assert(cb);
 
     i = pa_xnew(pa_memimport, 1);
+    i->mutex = pa_mutex_new(TRUE, TRUE);
     i->pool = p;
     i->segments = pa_hashmap_new(NULL, NULL);
     i->blocks = pa_hashmap_new(NULL, NULL);
     i->release_cb = cb;
     i->userdata = userdata;
 
+    pa_mutex_lock(p->mutex);
     PA_LLIST_PREPEND(pa_memimport, p->imports, i);
+    pa_mutex_unlock(p->mutex);
+
     return i;
 }
 
 static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i);
 
+/* Should be called locked */
 static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) {
     pa_memimport_segment* seg;
 
@@ -565,59 +818,79 @@ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) {
     return seg;
 }
 
+/* Should be called locked */
 static void segment_detach(pa_memimport_segment *seg) {
-    assert(seg);
+    pa_assert(seg);
 
     pa_hashmap_remove(seg->import->segments, PA_UINT32_TO_PTR(seg->memory.id));
     pa_shm_free(&seg->memory);
     pa_xfree(seg);
 }
 
+/* Self-locked. Not multiple-caller safe */
 void pa_memimport_free(pa_memimport *i) {
     pa_memexport *e;
     pa_memblock *b;
 
-    assert(i);
+    pa_assert(i);
+
+    pa_mutex_lock(i->mutex);
+
+    while ((b = pa_hashmap_get_first(i->blocks)))
+        memblock_replace_import(b);
+
+    pa_assert(pa_hashmap_size(i->segments) == 0);
+
+    pa_mutex_unlock(i->mutex);
+
+    pa_mutex_lock(i->pool->mutex);
 
     /* If we've exported this block further we need to revoke that export */
     for (e = i->pool->exports; e; e = e->next)
         memexport_revoke_blocks(e, i);
 
-    while ((b = pa_hashmap_get_first(i->blocks)))
-        memblock_replace_import(b);
+    PA_LLIST_REMOVE(pa_memimport, i->pool->imports, i);
 
-    assert(pa_hashmap_size(i->segments) == 0);
+    pa_mutex_unlock(i->pool->mutex);
 
     pa_hashmap_free(i->blocks, NULL, NULL);
     pa_hashmap_free(i->segments, NULL, NULL);
 
-    PA_LLIST_REMOVE(pa_memimport, i->pool->imports, i);
+    pa_mutex_free(i->mutex);
+
     pa_xfree(i);
 }
 
+/* Self-locked */
 pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_id, size_t offset, size_t size) {
-    pa_memblock *b;
+    pa_memblock *b = NULL;
     pa_memimport_segment *seg;
 
-    assert(i);
+    pa_assert(i);
+
+    pa_mutex_lock(i->mutex);
 
     if (pa_hashmap_size(i->blocks) >= PA_MEMIMPORT_SLOTS_MAX)
-        return NULL;
+        goto finish;
 
     if (!(seg = pa_hashmap_get(i->segments, PA_UINT32_TO_PTR(shm_id))))
         if (!(seg = segment_attach(i, shm_id)))
-            return NULL;
+            goto finish;
 
     if (offset+size > seg->memory.size)
-        return NULL;
+        goto finish;
 
-    b = pa_xnew(pa_memblock, 1);
+    if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks))))
+        b = pa_xnew(pa_memblock, 1);
+
+    PA_REFCNT_INIT(b);
+    b->pool = i->pool;
     b->type = PA_MEMBLOCK_IMPORTED;
     b->read_only = 1;
-    PA_REFCNT_INIT(b);
+    pa_atomic_ptr_store(&b->data, (uint8_t*) seg->memory.ptr + offset);
     b->length = size;
-    b->data = (uint8_t*) seg->memory.ptr + offset;
-    b->pool = i->pool;
+    pa_atomic_store(&b->n_acquired, 0);
+    pa_atomic_store(&b->please_signal, 0);
     b->per_type.imported.id = block_id;
     b->per_type.imported.segment = seg;
 
@@ -625,6 +898,10 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i
 
     seg->n_blocks++;
 
+finish:
+    pa_mutex_unlock(i->mutex);
+
+    if (b)
     stat_add(b);
 
     return b;
@@ -632,26 +909,36 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i
 
 int pa_memimport_process_revoke(pa_memimport *i, uint32_t id) {
     pa_memblock *b;
-    assert(i);
+    int ret = 0;
+    pa_assert(i);
 
-    if (!(b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(id))))
-        return -1;
+    pa_mutex_lock(i->mutex);
+
+    if (!(b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(id)))) {
+        ret = -1;
+        goto finish;
+    }
 
     memblock_replace_import(b);
-    return 0;
+
+finish:
+    pa_mutex_unlock(i->mutex);
+
+    return ret;
 }
 
 /* For sending blocks to other nodes */
 pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void *userdata) {
     pa_memexport *e;
 
-    assert(p);
-    assert(cb);
+    pa_assert(p);
+    pa_assert(cb);
 
     if (!p->memory.shared)
         return NULL;
 
     e = pa_xnew(pa_memexport, 1);
+    e->mutex = pa_mutex_new(TRUE, TRUE);
     e->pool = p;
     PA_LLIST_HEAD_INIT(struct memexport_slot, e->free_slots);
     PA_LLIST_HEAD_INIT(struct memexport_slot, e->used_slots);
@@ -659,50 +946,75 @@ pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void
     e->revoke_cb = cb;
     e->userdata = userdata;
 
+    pa_mutex_lock(p->mutex);
     PA_LLIST_PREPEND(pa_memexport, p->exports, e);
+    pa_mutex_unlock(p->mutex);
     return e;
 }
 
 void pa_memexport_free(pa_memexport *e) {
-    assert(e);
+    pa_assert(e);
 
+    pa_mutex_lock(e->mutex);
     while (e->used_slots)
         pa_memexport_process_release(e, e->used_slots - e->slots);
+    pa_mutex_unlock(e->mutex);
 
+    pa_mutex_lock(e->pool->mutex);
     PA_LLIST_REMOVE(pa_memexport, e->pool->exports, e);
+    pa_mutex_unlock(e->pool->mutex);
+
+    pa_mutex_free(e->mutex);
     pa_xfree(e);
 }
 
+/* Self-locked */
 int pa_memexport_process_release(pa_memexport *e, uint32_t id) {
-    assert(e);
+    pa_memblock *b;
+
+    pa_assert(e);
+
+    pa_mutex_lock(e->mutex);
 
     if (id >= e->n_init)
-        return -1;
+        goto fail;
 
     if (!e->slots[id].block)
-        return -1;
+        goto fail;
+
+    b = e->slots[id].block;
+    e->slots[id].block = NULL;
+
+    PA_LLIST_REMOVE(struct memexport_slot, e->used_slots, &e->slots[id]);
+    PA_LLIST_PREPEND(struct memexport_slot, e->free_slots, &e->slots[id]);
+
+    pa_mutex_unlock(e->mutex);
 
 /*     pa_log("Processing release for %u", id); */
 
-    assert(pa_atomic_load(&e->pool->stat.n_exported) > 0);
-    assert(pa_atomic_load(&e->pool->stat.exported_size) >= (int) e->slots[id].block->length);
+    pa_assert(pa_atomic_load(&e->pool->stat.n_exported) > 0);
+    pa_assert(pa_atomic_load(&e->pool->stat.exported_size) >= (int) b->length);
 
     pa_atomic_dec(&e->pool->stat.n_exported);
-    pa_atomic_sub(&e->pool->stat.exported_size, e->slots[id].block->length);
+    pa_atomic_sub(&e->pool->stat.exported_size, b->length);
 
-    pa_memblock_unref(e->slots[id].block);
-    e->slots[id].block = NULL;
-
-    PA_LLIST_REMOVE(struct memexport_slot, e->used_slots, &e->slots[id]);
-    PA_LLIST_PREPEND(struct memexport_slot, e->free_slots, &e->slots[id]);
+    pa_memblock_unref(b);
 
     return 0;
+
+fail:
+    pa_mutex_unlock(e->mutex);
+
+    return -1;
 }
 
+/* Self-locked */
 static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i) {
     struct memexport_slot *slot, *next;
-    assert(e);
-    assert(i);
+    pa_assert(e);
+    pa_assert(i);
+
+    pa_mutex_lock(e->mutex);
 
     for (slot = e->used_slots; slot; slot = next) {
         uint32_t idx;
@@ -716,49 +1028,57 @@ static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i) {
         e->revoke_cb(e, idx, e->userdata);
         pa_memexport_process_release(e, idx);
     }
+
+    pa_mutex_unlock(e->mutex);
 }
 
+/* No lock necessary */
 static pa_memblock *memblock_shared_copy(pa_mempool *p, pa_memblock *b) {
     pa_memblock *n;
 
-    assert(p);
-    assert(b);
+    pa_assert(p);
+    pa_assert(b);
 
     if (b->type == PA_MEMBLOCK_IMPORTED ||
         b->type == PA_MEMBLOCK_POOL ||
         b->type == PA_MEMBLOCK_POOL_EXTERNAL) {
-        assert(b->pool == p);
+        pa_assert(b->pool == p);
         return pa_memblock_ref(b);
     }
 
     if (!(n = pa_memblock_new_pool(p, b->length)))
         return NULL;
 
-    memcpy(n->data, b->data, b->length);
+    memcpy(pa_atomic_ptr_load(&n->data), pa_atomic_ptr_load(&b->data), b->length);
     return n;
 }
 
+/* Self-locked */
 int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32_t *shm_id, size_t *offset, size_t * size) {
     pa_shm *memory;
     struct memexport_slot *slot;
+    void *data;
 
-    assert(e);
-    assert(b);
-    assert(block_id);
-    assert(shm_id);
-    assert(offset);
-    assert(size);
-    assert(b->pool == e->pool);
+    pa_assert(e);
+    pa_assert(b);
+    pa_assert(block_id);
+    pa_assert(shm_id);
+    pa_assert(offset);
+    pa_assert(size);
+    pa_assert(b->pool == e->pool);
 
     if (!(b = memblock_shared_copy(e->pool, b)))
         return -1;
 
+    pa_mutex_lock(e->mutex);
+
     if (e->free_slots) {
         slot = e->free_slots;
         PA_LLIST_REMOVE(struct memexport_slot, e->free_slots, slot);
-    } else if (e->n_init < PA_MEMEXPORT_SLOTS_MAX) {
+    } else if (e->n_init < PA_MEMEXPORT_SLOTS_MAX)
         slot = &e->slots[e->n_init++];
-    } else {
+    else {
+        pa_mutex_unlock(e->mutex);
         pa_memblock_unref(b);
         return -1;
     }
@@ -767,24 +1087,29 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32
     slot->block = b;
     *block_id = slot - e->slots;
 
+    pa_mutex_unlock(e->mutex);
 /*     pa_log("Got block id %u", *block_id); */
 
+    data = pa_memblock_acquire(b);
+
     if (b->type == PA_MEMBLOCK_IMPORTED) {
-        assert(b->per_type.imported.segment);
+        pa_assert(b->per_type.imported.segment);
         memory = &b->per_type.imported.segment->memory;
     } else {
-        assert(b->type == PA_MEMBLOCK_POOL || b->type == PA_MEMBLOCK_POOL_EXTERNAL);
-        assert(b->pool);
+        pa_assert(b->type == PA_MEMBLOCK_POOL || b->type == PA_MEMBLOCK_POOL_EXTERNAL);
+        pa_assert(b->pool);
         memory = &b->pool->memory;
     }
 
-    assert(b->data >= memory->ptr);
-    assert((uint8_t*) b->data + b->length <= (uint8_t*) memory->ptr + memory->size);
+    pa_assert(data >= memory->ptr);
+    pa_assert((uint8_t*) data + b->length <= (uint8_t*) memory->ptr + memory->size);
 
     *shm_id = memory->id;
-    *offset = (uint8_t*) b->data - (uint8_t*) memory->ptr;
+    *offset = (uint8_t*) data - (uint8_t*) memory->ptr;
     *size = b->length;
 
+    pa_memblock_release(b);
+
     pa_atomic_inc(&e->pool->stat.n_exported);
     pa_atomic_add(&e->pool->stat.exported_size, b->length);
 
index fe4773d445dcfa2206f58296f5d00e809ee8efc6..c704014a6c4fc03185cbde23333631bf9c382e51 100644 (file)
@@ -28,6 +28,7 @@
 #include <sys/types.h>
 #include <inttypes.h>
 
+#include <pulse/def.h>
 #include <pulsecore/llist.h>
 #include <pulsecore/refcnt.h>
 #include <pulsecore/atomic.h>
@@ -58,45 +59,25 @@ typedef struct pa_memexport pa_memexport;
 typedef void (*pa_memimport_release_cb_t)(pa_memimport *i, uint32_t block_id, void *userdata);
 typedef void (*pa_memexport_revoke_cb_t)(pa_memexport *e, uint32_t block_id, void *userdata);
 
-struct pa_memblock {
-    pa_memblock_type_t type;
-    int read_only; /* boolean */
-    PA_REFCNT_DECLARE; /* the reference counter */
-    size_t length;
-    void *data;
-    pa_mempool *pool;
-
-    union {
-        struct {
-            void (*free_cb)(void *p);  /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */
-        } user;
-
-        struct  {
-            uint32_t id;
-            pa_memimport_segment *segment;
-        } imported;
-    } per_type;
-};
-
 /* Please note that updates to this structure are not locked,
  * i.e. n_allocated might be updated at a point in time where
  * n_accumulated is not yet. Take these values with a grain of salt,
- * threy are here for purely statistical reasons.*/
+ * they are here for purely statistical reasons.*/
 struct pa_mempool_stat {
-    pa_atomic_int_t n_allocated;
-    pa_atomic_int_t n_accumulated;
-    pa_atomic_int_t n_imported;
-    pa_atomic_int_t n_exported;
-    pa_atomic_int_t allocated_size;
-    pa_atomic_int_t accumulated_size;
-    pa_atomic_int_t imported_size;
-    pa_atomic_int_t exported_size;
-
-    pa_atomic_int_t n_too_large_for_pool;
-    pa_atomic_int_t n_pool_full;
-
-    pa_atomic_int_t n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX];
-    pa_atomic_int_t n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX];
+    pa_atomic_t n_allocated;
+    pa_atomic_t n_accumulated;
+    pa_atomic_t n_imported;
+    pa_atomic_t n_exported;
+    pa_atomic_t allocated_size;
+    pa_atomic_t accumulated_size;
+    pa_atomic_t imported_size;
+    pa_atomic_t exported_size;
+
+    pa_atomic_t n_too_large_for_pool;
+    pa_atomic_t n_pool_full;
+
+    pa_atomic_t n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX];
+    pa_atomic_t n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX];
 };
 
 /* Allocate a new memory block of type PA_MEMBLOCK_MEMPOOL or PA_MEMBLOCK_APPENDED, depending on the size */
@@ -120,9 +101,20 @@ pa_memblock* pa_memblock_ref(pa_memblock*b);
 /* This special unref function has to be called by the owner of the
 memory of a static memory block when he wants to release all
 references to the memory. This causes the memory to be copied and
-converted into a PA_MEMBLOCK_DYNAMIC type memory block */
+converted into a pool or malloc'ed memory block. Please note that this
+function is not multiple caller safe, i.e. needs to be locked
+manually if called from more than one thread at the same time.  */
 void pa_memblock_unref_fixed(pa_memblock*b);
 
+int pa_memblock_is_read_only(pa_memblock *b);
+int pa_memblock_ref_is_one(pa_memblock *b);
+void* pa_memblock_acquire(pa_memblock *b);
+void pa_memblock_release(pa_memblock *b);
+size_t pa_memblock_get_length(pa_memblock *b);
+pa_mempool * pa_memblock_get_pool(pa_memblock *b);
+
+pa_memblock *pa_memblock_will_need(pa_memblock *b);
+
 /* The memory block manager */
 pa_mempool* pa_mempool_new(int shared);
 void pa_mempool_free(pa_mempool *p);
@@ -130,6 +122,7 @@ const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p);
 void pa_mempool_vacuum(pa_mempool *p);
 int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id);
 int pa_mempool_is_shared(pa_mempool *p);
+size_t pa_mempool_block_size_max(pa_mempool *p);
 
 /* For recieving blocks from other nodes */
 pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void *userdata);
index e31fb6dfb4d27a47c2afe630f0a77a20da2b38ab..a46155a9f34c7d503819cf44fe5dee61509faf1a 100644 (file)
@@ -28,7 +28,6 @@
 #include <sys/time.h>
 #include <time.h>
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
 
 #include <pulsecore/log.h>
 #include <pulsecore/mcalign.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/flist.h>
 
 #include "memblockq.h"
 
-struct memblock_list {
-    struct memblock_list *next, *prev;
+struct list_item {
+    struct list_item *next, *prev;
     int64_t index;
     pa_memchunk chunk;
 };
 
+PA_STATIC_FLIST_DECLARE(list_items, 0, pa_xfree);
+
 struct pa_memblockq {
-    struct memblock_list *blocks, *blocks_tail;
+    struct list_item *blocks, *blocks_tail;
     unsigned n_blocks;
     size_t maxlength, tlength, base, prebuf, minreq;
     int64_t read_index, write_index;
-    enum { PREBUF, RUNNING } state;
+    pa_bool_t in_prebuf;
     pa_memblock *silence;
     pa_mcalign *mcalign;
+    int64_t missing;
+    size_t requested;
 };
 
 pa_memblockq* pa_memblockq_new(
@@ -66,8 +71,8 @@ pa_memblockq* pa_memblockq_new(
 
     pa_memblockq* bq;
 
-    assert(base > 0);
-    assert(maxlength >= base);
+    pa_assert(base > 0);
+    pa_assert(maxlength >= base);
 
     bq = pa_xnew(pa_memblockq, 1);
     bq->blocks = bq->blocks_tail = NULL;
@@ -77,13 +82,13 @@ pa_memblockq* pa_memblockq_new(
     bq->read_index = bq->write_index = idx;
 
     pa_log_debug("memblockq requested: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu",
-        (unsigned long)maxlength, (unsigned long)tlength, (unsigned long)base, (unsigned long)prebuf, (unsigned long)minreq);
+        (unsigned long) maxlength, (unsigned long) tlength, (unsigned long) base, (unsigned long) prebuf, (unsigned long) minreq);
 
     bq->maxlength = ((maxlength+base-1)/base)*base;
-    assert(bq->maxlength >= base);
+    pa_assert(bq->maxlength >= base);
 
     bq->tlength = ((tlength+base-1)/base)*base;
-    if (!bq->tlength || bq->tlength >= bq->maxlength)
+    if (bq->tlength <= 0 || bq->tlength > bq->maxlength)
         bq->tlength = bq->maxlength;
 
     bq->prebuf = (prebuf == (size_t) -1) ? bq->tlength/2 : prebuf;
@@ -102,15 +107,18 @@ pa_memblockq* pa_memblockq_new(
     pa_log_debug("memblockq sanitized: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu",
         (unsigned long)bq->maxlength, (unsigned long)bq->tlength, (unsigned long)bq->base, (unsigned long)bq->prebuf, (unsigned long)bq->minreq);
 
-    bq->state = bq->prebuf ? PREBUF : RUNNING;
+    bq->in_prebuf = bq->prebuf > 0;
     bq->silence = silence ? pa_memblock_ref(silence) : NULL;
     bq->mcalign = NULL;
 
+    bq->missing = bq->tlength;
+    bq->requested = 0;
+
     return bq;
 }
 
 void pa_memblockq_free(pa_memblockq* bq) {
-    assert(bq);
+    pa_assert(bq);
 
     pa_memblockq_flush(bq);
 
@@ -123,11 +131,11 @@ void pa_memblockq_free(pa_memblockq* bq) {
     pa_xfree(bq);
 }
 
-static void drop_block(pa_memblockq *bq, struct memblock_list *q) {
-    assert(bq);
-    assert(q);
+static void drop_block(pa_memblockq *bq, struct list_item *q) {
+    pa_assert(bq);
+    pa_assert(q);
 
-    assert(bq->n_blocks >= 1);
+    pa_assert(bq->n_blocks >= 1);
 
     if (q->prev)
         q->prev->next = q->next;
@@ -140,15 +148,17 @@ static void drop_block(pa_memblockq *bq, struct memblock_list *q) {
         bq->blocks_tail = q->prev;
 
     pa_memblock_unref(q->chunk.memblock);
-    pa_xfree(q);
+
+    if (pa_flist_push(PA_STATIC_FLIST_GET(list_items), q) < 0)
+        pa_xfree(q);
 
     bq->n_blocks--;
 }
 
-static int can_push(pa_memblockq *bq, size_t l) {
+static pa_bool_t can_push(pa_memblockq *bq, size_t l) {
     int64_t end;
 
-    assert(bq);
+    pa_assert(bq);
 
     if (bq->read_index > bq->write_index) {
         size_t d =  bq->read_index - bq->write_index;
@@ -156,7 +166,7 @@ static int can_push(pa_memblockq *bq, size_t l) {
         if (l > d)
             l -= d;
         else
-            return 1;
+            return TRUE;
     }
 
     end = bq->blocks_tail ? bq->blocks_tail->index + bq->blocks_tail->chunk.length : 0;
@@ -164,21 +174,21 @@ static int can_push(pa_memblockq *bq, size_t l) {
     /* Make sure that the list doesn't get too long */
     if (bq->write_index + (int64_t)l > end)
         if (bq->write_index + l - bq->read_index > bq->maxlength)
-            return 0;
+            return FALSE;
 
-    return 1;
+    return TRUE;
 }
 
 int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
-
-    struct memblock_list *q, *n;
+    struct list_item *q, *n;
     pa_memchunk chunk;
+    int64_t old, delta;
 
-    assert(bq);
-    assert(uchunk);
-    assert(uchunk->memblock);
-    assert(uchunk->length > 0);
-    assert(uchunk->index + uchunk->length <= uchunk->memblock->length);
+    pa_assert(bq);
+    pa_assert(uchunk);
+    pa_assert(uchunk->memblock);
+    pa_assert(uchunk->length > 0);
+    pa_assert(uchunk->index + uchunk->length <= pa_memblock_get_length(uchunk->memblock));
 
     if (uchunk->length % bq->base)
         return -1;
@@ -186,6 +196,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
     if (!can_push(bq, uchunk->length))
         return -1;
 
+    old = bq->write_index;
     chunk = *uchunk;
 
     if (bq->read_index > bq->write_index) {
@@ -198,11 +209,11 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
         if (chunk.length > d) {
             chunk.index += d;
             chunk.length -= d;
-            bq->write_index = bq->read_index;
+            bq->write_index += d;
         } else {
             /* We drop the incoming data completely */
             bq->write_index += chunk.length;
-            return 0;
+            goto finish;
         }
     }
 
@@ -212,10 +223,10 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
     q = bq->blocks_tail;
     while (q) {
 
-        if (bq->write_index >= q->index + (int64_t)q->chunk.length)
+        if (bq->write_index >= q->index + (int64_t) q->chunk.length)
             /* We found the entry where we need to place the new entry immediately after */
             break;
-        else if (bq->write_index + (int64_t)chunk.length <= q->index) {
+        else if (bq->write_index + (int64_t) chunk.length <= q->index) {
             /* This entry isn't touched at all, let's skip it */
             q = q->prev;
         } else if (bq->write_index <= q->index &&
@@ -223,7 +234,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
 
             /* This entry is fully replaced by the new entry, so let's drop it */
 
-            struct memblock_list *p;
+            struct list_item *p;
             p = q;
             q = q->prev;
             drop_block(bq, p);
@@ -234,17 +245,19 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
             if (bq->write_index + chunk.length < q->index + q->chunk.length) {
 
                 /* We need to save the end of this memchunk */
-                struct memblock_list *p;
+                struct list_item *p;
                 size_t d;
 
                 /* Create a new list entry for the end of thie memchunk */
-                p = pa_xnew(struct memblock_list, 1);
+                if (!(p = pa_flist_pop(PA_STATIC_FLIST_GET(list_items))))
+                    p = pa_xnew(struct list_item, 1);
+
                 p->chunk = q->chunk;
                 pa_memblock_ref(p->chunk.memblock);
 
                 /* Calculate offset */
                 d = bq->write_index + chunk.length - q->index;
-                assert(d > 0);
+                pa_assert(d > 0);
 
                 /* Drop it from the new entry */
                 p->index = q->index + d;
@@ -263,7 +276,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
 
             /* Truncate the chunk */
             if (!(q->chunk.length = bq->write_index - q->index)) {
-                struct memblock_list *p;
+                struct list_item *p;
                 p = q;
                 q = q->prev;
                 drop_block(bq, p);
@@ -274,7 +287,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
         } else {
             size_t d;
 
-            assert(bq->write_index + (int64_t)chunk.length > q->index &&
+            pa_assert(bq->write_index + (int64_t)chunk.length > q->index &&
                    bq->write_index + (int64_t)chunk.length < q->index + (int64_t)q->chunk.length &&
                    bq->write_index < q->index);
 
@@ -287,12 +300,11 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
 
             q = q->prev;
         }
-
     }
 
     if (q) {
-        assert(bq->write_index >=  q->index + (int64_t)q->chunk.length);
-        assert(!q->next || (bq->write_index + (int64_t)chunk.length <= q->next->index));
+        pa_assert(bq->write_index >=  q->index + (int64_t)q->chunk.length);
+        pa_assert(!q->next || (bq->write_index + (int64_t)chunk.length <= q->next->index));
 
         /* Try to merge memory blocks */
 
@@ -302,13 +314,14 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
 
             q->chunk.length += chunk.length;
             bq->write_index += chunk.length;
-            return 0;
+            goto finish;
         }
     } else
-        assert(!bq->blocks || (bq->write_index + (int64_t)chunk.length <= bq->blocks->index));
+        pa_assert(!bq->blocks || (bq->write_index + (int64_t)chunk.length <= bq->blocks->index));
 
+    if (!(n = pa_flist_pop(PA_STATIC_FLIST_GET(list_items))))
+        n = pa_xnew(struct list_item, 1);
 
-    n = pa_xnew(struct memblock_list, 1);
     n->chunk = chunk;
     pa_memblock_ref(n->chunk.memblock);
     n->index = bq->write_index;
@@ -328,27 +341,52 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
         bq->blocks = n;
 
     bq->n_blocks++;
+
+finish:
+
+    delta = bq->write_index - old;
+
+    if (delta >= bq->requested) {
+        delta -= bq->requested;
+        bq->requested = 0;
+    } else {
+        bq->requested -= delta;
+        delta = 0;
+    }
+
+    bq->missing -= delta;
+
     return 0;
 }
 
-int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
-    assert(bq);
-    assert(chunk);
+static pa_bool_t memblockq_check_prebuf(pa_memblockq *bq) {
+    pa_assert(bq);
 
-    if (bq->state == PREBUF) {
+    if (bq->in_prebuf) {
 
-        /* We need to pre-buffer */
         if (pa_memblockq_get_length(bq) < bq->prebuf)
-            return -1;
+            return TRUE;
 
-        bq->state = RUNNING;
+        bq->in_prebuf = FALSE;
+        return FALSE;
+    } else {
 
-    } else if (bq->prebuf > 0 && bq->read_index >= bq->write_index) {
+        if (bq->prebuf > 0 && bq->read_index >= bq->write_index) {
+            bq->in_prebuf = TRUE;
+            return TRUE;
+        }
 
-        /* Buffer underflow protection */
-        bq->state = PREBUF;
-        return -1;
+        return FALSE;
     }
+}
+
+int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
+    pa_assert(bq);
+    pa_assert(chunk);
+
+    /* We need to pre-buffer */
+    if (memblockq_check_prebuf(bq))
+        return -1;
 
     /* Do we need to spit out silence? */
     if (!bq->blocks || bq->blocks->index > bq->read_index) {
@@ -362,8 +400,8 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
         if (bq->silence) {
             chunk->memblock = pa_memblock_ref(bq->silence);
 
-            if (!length || length > chunk->memblock->length)
-                length = chunk->memblock->length;
+            if (!length || length > pa_memblock_get_length(chunk->memblock))
+                length = pa_memblock_get_length(chunk->memblock);
 
             chunk->length = length;
         } else {
@@ -382,7 +420,7 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
     }
 
     /* Ok, let's pass real data to the caller */
-    assert(bq->blocks->index == bq->read_index);
+    pa_assert(bq->blocks->index == bq->read_index);
 
     *chunk = bq->blocks->chunk;
     pa_memblock_ref(chunk->memblock);
@@ -390,48 +428,23 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
     return 0;
 }
 
-void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length) {
-    assert(bq);
-    assert(length % bq->base == 0);
-
-    assert(!chunk || length <= chunk->length);
+void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
+    int64_t old, delta;
+    pa_assert(bq);
+    pa_assert(length % bq->base == 0);
 
-    if (chunk) {
-
-        if (bq->blocks && bq->blocks->index == bq->read_index) {
-            /* The first item in queue is valid */
-
-            /* Does the chunk match with what the user supplied us? */
-            if (memcmp(chunk, &bq->blocks->chunk, sizeof(pa_memchunk)) != 0)
-                return;
-
-        } else {
-            size_t l;
-
-            /* The first item in the queue is not yet relevant */
-
-            assert(!bq->blocks || bq->blocks->index > bq->read_index);
-            l = bq->blocks ? bq->blocks->index - bq->read_index : 0;
-
-            if (bq->silence) {
-
-                if (!l || l > bq->silence->length)
-                    l = bq->silence->length;
-
-            }
-
-            /* Do the entries still match? */
-            if (chunk->index != 0 || chunk->length != l || chunk->memblock != bq->silence)
-                return;
-        }
-    }
+    old = bq->read_index;
 
     while (length > 0) {
 
+        /* Do not drop any data when we are in prebuffering mode */
+        if (memblockq_check_prebuf(bq))
+            break;
+
         if (bq->blocks) {
             size_t d;
 
-            assert(bq->blocks->index >= bq->read_index);
+            pa_assert(bq->blocks->index >= bq->read_index);
 
             d = (size_t) (bq->blocks->index - bq->read_index);
 
@@ -446,7 +459,7 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length
                 bq->read_index += d;
             }
 
-            assert(bq->blocks->index == bq->read_index);
+            pa_assert(bq->blocks->index == bq->read_index);
 
             if (bq->blocks->chunk.length <= length) {
                 /* We need to drop the full block */
@@ -472,35 +485,25 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length
             break;
         }
     }
+
+    delta = bq->read_index - old;
+    bq->missing += delta;
 }
 
 int pa_memblockq_is_readable(pa_memblockq *bq) {
-    assert(bq);
-
-    if (bq->prebuf > 0) {
-        size_t l = pa_memblockq_get_length(bq);
-
-        if (bq->state == PREBUF && l < bq->prebuf)
-            return 0;
-
-        if (l <= 0)
-            return 0;
-    }
-
-    return 1;
-}
+    pa_assert(bq);
 
-int pa_memblockq_is_writable(pa_memblockq *bq, size_t length) {
-    assert(bq);
+    if (memblockq_check_prebuf(bq))
+        return 0;
 
-    if (length % bq->base)
+    if (pa_memblockq_get_length(bq) <= 0)
         return 0;
 
-    return pa_memblockq_get_length(bq) + length <= bq->tlength;
+    return 1;
 }
 
 size_t pa_memblockq_get_length(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
 
     if (bq->write_index <= bq->read_index)
         return 0;
@@ -510,76 +513,106 @@ size_t pa_memblockq_get_length(pa_memblockq *bq) {
 
 size_t pa_memblockq_missing(pa_memblockq *bq) {
     size_t l;
-    assert(bq);
+    pa_assert(bq);
 
     if ((l = pa_memblockq_get_length(bq)) >= bq->tlength)
         return 0;
 
     l = bq->tlength - l;
-    return (l >= bq->minreq) ? l : 0;
+
+    return l >= bq->minreq ? l : 0;
 }
 
 size_t pa_memblockq_get_minreq(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
 
     return bq->minreq;
 }
 
 void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) {
-    assert(bq);
+    int64_t old, delta;
+    pa_assert(bq);
+
+    old = bq->write_index;
 
     switch (seek) {
         case PA_SEEK_RELATIVE:
             bq->write_index += offset;
-            return;
+            break;
         case PA_SEEK_ABSOLUTE:
             bq->write_index = offset;
-            return;
+            break;
         case PA_SEEK_RELATIVE_ON_READ:
             bq->write_index = bq->read_index + offset;
-            return;
+            break;
         case PA_SEEK_RELATIVE_END:
-            bq->write_index = (bq->blocks_tail ? bq->blocks_tail->index + (int64_t)bq->blocks_tail->chunk.length : bq->read_index) + offset;
-            return;
+            bq->write_index = (bq->blocks_tail ? bq->blocks_tail->index + (int64_t) bq->blocks_tail->chunk.length : bq->read_index) + offset;
+            break;
+        default:
+            pa_assert_not_reached();
     }
 
-    assert(0);
+    delta = bq->write_index - old;
+
+    if (delta >= bq->requested) {
+        delta -= bq->requested;
+        bq->requested = 0;
+    } else if (delta >= 0) {
+        bq->requested -= delta;
+        delta = 0;
+    }
+
+    bq->missing -= delta;
 }
 
 void pa_memblockq_flush(pa_memblockq *bq) {
-    assert(bq);
+    int64_t old, delta;
+    pa_assert(bq);
 
     while (bq->blocks)
         drop_block(bq, bq->blocks);
 
-    assert(bq->n_blocks == 0);
+    pa_assert(bq->n_blocks == 0);
 
+    old = bq->write_index;
     bq->write_index = bq->read_index;
 
     pa_memblockq_prebuf_force(bq);
+
+    delta = bq->write_index - old;
+
+    if (delta > bq->requested) {
+        delta -= bq->requested;
+        bq->requested = 0;
+    } else if (delta >= 0) {
+        bq->requested -= delta;
+        delta = 0;
+    }
+
+    bq->missing -= delta;
 }
 
 size_t pa_memblockq_get_tlength(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
 
     return bq->tlength;
 }
 
 int64_t pa_memblockq_get_read_index(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
     return bq->read_index;
 }
 
 int64_t pa_memblockq_get_write_index(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
     return bq->write_index;
 }
 
 int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk) {
     pa_memchunk rchunk;
 
-    assert(bq);
-    assert(chunk && bq->base);
+    pa_assert(bq);
+    pa_assert(chunk);
 
     if (bq->base == 1)
         return pa_memblockq_push(bq, chunk);
@@ -606,36 +639,52 @@ int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk) {
 
 void pa_memblockq_shorten(pa_memblockq *bq, size_t length) {
     size_t l;
-    assert(bq);
+    pa_assert(bq);
 
     l = pa_memblockq_get_length(bq);
 
     if (l > length)
-        pa_memblockq_drop(bq, NULL, l - length);
+        pa_memblockq_drop(bq, l - length);
 }
 
 void pa_memblockq_prebuf_disable(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
 
-    if (bq->state == PREBUF)
-        bq->state = RUNNING;
+    bq->in_prebuf = FALSE;
 }
 
 void pa_memblockq_prebuf_force(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
 
-    if (bq->state == RUNNING && bq->prebuf > 0)
-        bq->state = PREBUF;
+    if (!bq->in_prebuf && bq->prebuf > 0)
+        bq->in_prebuf = TRUE;
 }
 
 size_t pa_memblockq_get_maxlength(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
 
     return bq->maxlength;
 }
 
 size_t pa_memblockq_get_prebuf(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
 
     return bq->prebuf;
 }
+
+size_t pa_memblockq_pop_missing(pa_memblockq *bq) {
+    size_t l;
+
+    pa_assert(bq);
+
+/*     pa_log("pop: %lli", bq->missing); */
+
+    if (bq->missing <= 0)
+        return 0;
+
+    l = (size_t) bq->missing;
+    bq->missing = 0;
+    bq->requested += l;
+
+    return l;
+}
index 437c5a41956fc79a59fe6fce3f8d48eac9d6de01..8c3e70fc3baf7269bb9e1462ccb68c6e05daa305 100644 (file)
@@ -62,7 +62,7 @@ typedef struct pa_memblockq pa_memblockq;
    - minreq:    pa_memblockq_missing() will only return values greater
                 than this value. Pass 0 for the default.
 
-   - silence:   return this memblock whzen reading unitialized data
+   - silence:   return this memblock when reading unitialized data
 */
 pa_memblockq* pa_memblockq_new(
         int64_t idx,
@@ -83,26 +83,30 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *chunk);
  * you know what you do. */
 int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk);
 
-/* Return a copy of the next memory chunk in the queue. It is not removed from the queue */
+/* Return a copy of the next memory chunk in the queue. It is not
+ * removed from the queue. There are two reasons this function might
+ * fail: 1. prebuffering is active, 2. queue is empty and no silence
+ * memblock was passed at initialization. If the queue is not empty,
+ * but we're currently at a hole in the queue and no silence memblock
+ * was passed we return the length of the hole in chunk->length. */
 int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk);
 
-/* Drop the specified bytes from the queue, but only if the first
- * chunk in the queue matches the one passed here. If NULL is passed,
- * this check isn't done. */
-void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length);
+/* Drop the specified bytes from the queue. */
+void pa_memblockq_drop(pa_memblockq *bq, size_t length);
 
 /* Test if the pa_memblockq is currently readable, that is, more data than base */
 int pa_memblockq_is_readable(pa_memblockq *bq);
 
-/* Test if the pa_memblockq is currently writable for the specified amount of bytes */
-int pa_memblockq_is_writable(pa_memblockq *bq, size_t length);
-
 /* Return the length of the queue in bytes */
 size_t pa_memblockq_get_length(pa_memblockq *bq);
 
 /* Return how many bytes are missing in queue to the specified fill amount */
 size_t pa_memblockq_missing(pa_memblockq *bq);
 
+/* Return the number of bytes that are missing since the last call to
+ * this function, reset the internal counter to 0. */
+size_t pa_memblockq_pop_missing(pa_memblockq *bq);
+
 /* Returns the minimal request value */
 size_t pa_memblockq_get_minreq(pa_memblockq *bq);
 
index 7111e1ec18efe75a19f4fc5d090608f2a887c276..4e73b6361147fa3647166b06d719e365be80de38 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <assert.h>
 #include <string.h>
+#include <errno.h>
 
 #include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
 
 #include "memchunk.h"
 
-void pa_memchunk_make_writable(pa_memchunk *c, size_t min) {
+pa_memchunk* pa_memchunk_make_writable(pa_memchunk *c, size_t min) {
     pa_memblock *n;
     size_t l;
+    void *tdata, *sdata;
 
-    assert(c);
-    assert(c->memblock);
-    assert(PA_REFCNT_VALUE(c->memblock) > 0);
+    pa_assert(c);
+    pa_assert(c->memblock);
 
-    if (PA_REFCNT_VALUE(c->memblock) == 1 &&
-        !c->memblock->read_only &&
-        c->memblock->length >= c->index+min)
-        return;
+    if (pa_memblock_ref_is_one(c->memblock) &&
+        !pa_memblock_is_read_only(c->memblock) &&
+        pa_memblock_get_length(c->memblock) >= c->index+min)
+        return c;
 
     l = c->length;
     if (l < min)
         l = min;
 
-    n = pa_memblock_new(c->memblock->pool, l);
-    memcpy(n->data, (uint8_t*) c->memblock->data + c->index, c->length);
+    n = pa_memblock_new(pa_memblock_get_pool(c->memblock), l);
+    tdata = pa_memblock_acquire(n);
+    sdata = pa_memblock_acquire(c->memblock);
+    memcpy(tdata, (uint8_t*) sdata + c->index, c->length);
+    pa_memblock_release(n);
+    pa_memblock_release(c->memblock);
     pa_memblock_unref(c->memblock);
     c->memblock = n;
     c->index = 0;
+
+    return c;
 }
 
-void pa_memchunk_reset(pa_memchunk *c) {
-    assert(c);
+pa_memchunk* pa_memchunk_reset(pa_memchunk *c) {
+    pa_assert(c);
 
     c->memblock = NULL;
     c->length = c->index = 0;
+
+    return c;
+}
+
+pa_memchunk *pa_memchunk_will_need(const pa_memchunk *c) {
+    void *p;
+
+    pa_assert(c);
+    pa_assert(c->memblock);
+
+    /* A version of pa_memblock_will_need() that works on memchunks
+     * instead of memblocks */
+
+    p = (uint8_t*) pa_memblock_acquire(c->memblock) + c->index;
+    pa_will_need(p, c->length);
+    pa_memblock_release(c->memblock);
+
+    return (pa_memchunk*) c;
 }
index 0b982b6d34bdf562b0a31a15bdf4fb4c055f11b3..e6105acebdba812f511f73f7c0617c3e1185a8f5 100644 (file)
@@ -37,11 +37,16 @@ typedef struct pa_memchunk {
 
 /* Make a memchunk writable, i.e. make sure that the caller may have
  * exclusive access to the memblock and it is not read_only. If needed
- * the memblock in the structure is replaced by a copy. */
-void pa_memchunk_make_writable(pa_memchunk *c, size_t min);
+ * the memblock in the structure is replaced by a copy. If min is not
+ * 0 it is made sure that the returned memblock is at least of the
+ * specified size, i.e. is enlarged if necessary. */
+pa_memchunk* pa_memchunk_make_writable(pa_memchunk *c, size_t min);
 
 /* Invalidate a memchunk. This does not free the cotaining memblock,
  * but sets all members to zero. */
-void pa_memchunk_reset(pa_memchunk *c);
+pa_memchunk* pa_memchunk_reset(pa_memchunk *c);
+
+/* Map a memory chunk back into memory if it was swapped out */
+pa_memchunk *pa_memchunk_will_need(const pa_memchunk *c);
 
 #endif
index 3733f65501a60701da0e9ed6b52b55fabb12f992..1311af3c18b1c8839aca4f43fdb355b4d421f19c 100644 (file)
@@ -26,7 +26,6 @@
 #endif
 
 #include <ctype.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -39,6 +38,7 @@
 #include <pulsecore/sink.h>
 #include <pulsecore/source.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
 
 #include "modargs.h"
 
@@ -48,7 +48,10 @@ struct entry {
 
 static int add_key_value(pa_hashmap *map, char *key, char *value, const char* const valid_keys[]) {
     struct entry *e;
-    assert(map && key && value);
+
+    pa_assert(map);
+    pa_assert(key);
+    pa_assert(value);
 
     if (valid_keys) {
         const char*const* v;
@@ -63,10 +66,11 @@ static int add_key_value(pa_hashmap *map, char *key, char *value, const char* co
         }
     }
 
-    e = pa_xmalloc(sizeof(struct entry));
+    e = pa_xnew(struct entry, 1);
     e->key = key;
     e->value = value;
     pa_hashmap_put(map, key, e);
+
     return 0;
 }
 
@@ -74,7 +78,6 @@ pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) {
     pa_hashmap *map = NULL;
 
     map = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-    assert(map);
 
     if (args) {
         enum { WHITESPACE, KEY, VALUE_START, VALUE_SIMPLE, VALUE_DOUBLE_QUOTES, VALUE_TICKS } state;
@@ -166,10 +169,10 @@ fail:
     return NULL;
 }
 
-
 static void free_func(void *p, PA_GCC_UNUSED void*userdata) {
     struct entry *e = p;
-    assert(e);
+    pa_assert(e);
+
     pa_xfree(e->key);
     pa_xfree(e->value);
     pa_xfree(e);
@@ -192,7 +195,10 @@ const char *pa_modargs_get_value(pa_modargs *ma, const char *key, const char *de
 
 int pa_modargs_get_value_u32(pa_modargs *ma, const char *key, uint32_t *value) {
     const char *v;
-    assert(ma && key && value);
+
+    pa_assert(ma);
+    pa_assert(key);
+    pa_assert(value);
 
     if (!(v = pa_modargs_get_value(ma, key, NULL)))
         return 0;
@@ -205,7 +211,10 @@ int pa_modargs_get_value_u32(pa_modargs *ma, const char *key, uint32_t *value) {
 
 int pa_modargs_get_value_s32(pa_modargs *ma, const char *key, int32_t *value) {
     const char *v;
-    assert(ma && key && value);
+
+    pa_assert(ma);
+    pa_assert(key);
+    pa_assert(value);
 
     if (!(v = pa_modargs_get_value(ma, key, NULL)))
         return 0;
@@ -219,7 +228,10 @@ int pa_modargs_get_value_s32(pa_modargs *ma, const char *key, int32_t *value) {
 int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, int *value) {
     const char *v;
     int r;
-    assert(ma && key && value);
+
+    pa_assert(ma);
+    pa_assert(key);
+    pa_assert(value);
 
     if (!(v = pa_modargs_get_value(ma, key, NULL)))
         return 0;
@@ -238,9 +250,9 @@ int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *rss) {
     const char *format;
     uint32_t channels;
     pa_sample_spec ss;
-    assert(ma && rss);
 
-/*    DEBUG_TRAP;*/
+    pa_assert(ma);
+    pa_assert(rss);
 
     ss = *rss;
     if ((pa_modargs_get_value_u32(ma, "rate", &ss.rate)) < 0)
@@ -263,16 +275,16 @@ int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *rss) {
     return 0;
 }
 
-int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *rmap) {
+int pa_modargs_get_channel_map(pa_modargs *ma, const char *name, pa_channel_map *rmap) {
     pa_channel_map map;
     const char *cm;
 
-    assert(ma);
-    assert(rmap);
+    pa_assert(ma);
+    pa_assert(rmap);
 
     map = *rmap;
 
-    if ((cm = pa_modargs_get_value(ma, "channel_map", NULL)))
+    if ((cm = pa_modargs_get_value(ma, name ? name : "channel_map", NULL)))
         if (!pa_channel_map_parse(&map, cm))
             return -1;
 
@@ -287,9 +299,9 @@ int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *r
     pa_sample_spec ss;
     pa_channel_map map;
 
-    assert(ma);
-    assert(rss);
-    assert(rmap);
+    pa_assert(ma);
+    pa_assert(rss);
+    pa_assert(rmap);
 
     ss = *rss;
 
@@ -299,7 +311,7 @@ int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *r
     if (!pa_channel_map_init_auto(&map, ss.channels, def))
         map.channels = 0;
 
-    if (pa_modargs_get_channel_map(ma, &map) < 0)
+    if (pa_modargs_get_channel_map(ma, NULL, &map) < 0)
         return -1;
 
     if (map.channels != ss.channels)
index 77262e1e93887c4c432826698b90d49bf148552f..aa175885d812eb9832e8e227522ee9777ba55a1f 100644 (file)
@@ -49,8 +49,8 @@ int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, int *value);
 /* Return sample spec data from the three arguments "rate", "format" and "channels" */
 int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *ss);
 
-/* Return channel map data from the argument "channel_map" */
-int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *map);
+/* Return channel map data from the argument "channel_map" if name is NULL, otherwise read from the specified argument */
+int pa_modargs_get_channel_map(pa_modargs *ma, const char *name, pa_channel_map *map);
 
 /* Combination of pa_modargs_get_sample_spec() and
 pa_modargs_get_channel_map(). Not always suitable, since this routine
index 58394e594d6e42d8daf11a64f33a65693643c75a..da2df6535b22c5fac5bc4dac2ebf616b5ffad165 100644 (file)
 #endif
 
 #include <ltdl.h>
-#include <assert.h>
 
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/ltdl-helper.h>
 
 #include "modinfo.h"
 
 #define PA_SYMBOL_USAGE "pa__get_usage"
 #define PA_SYMBOL_VERSION "pa__get_version"
 
-/* lt_dlsym() violates ISO C, so confide the breakage into this function to
- * avoid warnings. */
-typedef void (*fnptr)(void);
-static inline fnptr lt_dlsym_fn(lt_dlhandle handle, const char *symbol) {
-    return (fnptr) (long) lt_dlsym(handle, symbol);
-}
-
-pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl) {
+pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl, const char *module_name) {
     pa_modinfo *i;
     const char* (*func)(void);
-    assert(dl);
+
+    pa_assert(dl);
 
     i = pa_xnew0(pa_modinfo, 1);
 
-    if ((func = (const char* (*)(void)) lt_dlsym_fn(dl, PA_SYMBOL_AUTHOR)))
+    if ((func = (const char* (*)(void)) pa_load_sym(dl, module_name, PA_SYMBOL_AUTHOR)))
         i->author = pa_xstrdup(func());
 
-    if ((func = (const char* (*)(void)) lt_dlsym_fn(dl, PA_SYMBOL_DESCRIPTION)))
+    if ((func = (const char* (*)(void)) pa_load_sym(dl, module_name, PA_SYMBOL_DESCRIPTION)))
         i->description = pa_xstrdup(func());
 
-    if ((func = (const char* (*)(void)) lt_dlsym_fn(dl, PA_SYMBOL_USAGE)))
+    if ((func = (const char* (*)(void)) pa_load_sym(dl, module_name, PA_SYMBOL_USAGE)))
         i->usage = pa_xstrdup(func());
 
-    if ((func = (const char* (*)(void)) lt_dlsym_fn(dl, PA_SYMBOL_VERSION)))
+    if ((func = (const char* (*)(void)) pa_load_sym(dl, module_name, PA_SYMBOL_VERSION)))
         i->version = pa_xstrdup(func());
 
     return i;
@@ -72,21 +67,23 @@ pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl) {
 pa_modinfo *pa_modinfo_get_by_name(const char *name) {
     lt_dlhandle dl;
     pa_modinfo *i;
-    assert(name);
+
+    pa_assert(name);
 
     if (!(dl = lt_dlopenext(name))) {
         pa_log("Failed to open module \"%s\": %s", name, lt_dlerror());
         return NULL;
     }
 
-    i = pa_modinfo_get_by_handle(dl);
+    i = pa_modinfo_get_by_handle(dl, name);
     lt_dlclose(dl);
 
     return i;
 }
 
 void pa_modinfo_free(pa_modinfo *i) {
-    assert(i);
+    pa_assert(i);
+
     pa_xfree(i->author);
     pa_xfree(i->description);
     pa_xfree(i->usage);
index 3ee33ede4cda3c2609a4e2cb9995d560789e6f31..02e536c66d6d7d92bb463fab5d0027befcdbcf6a 100644 (file)
@@ -34,7 +34,7 @@ typedef struct pa_modinfo {
 } pa_modinfo;
 
 /* Read meta data from an libtool handle */
-pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl);
+pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl, const char *module_name);
 
 /* Read meta data from a module file */
 pa_modinfo *pa_modinfo_get_by_name(const char *name);
index 09b15b8b01f917f45fc301d63b6cf3d9f858300d..dce91a71027273b54d57247fc05a54cd0e834931 100644 (file)
@@ -29,7 +29,6 @@
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <assert.h>
 #include <string.h>
 #include <errno.h>
 #include <ctype.h>
@@ -40,6 +39,8 @@
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/log.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/ltdl-helper.h>
 
 #include "module.h"
 
 
 #define UNLOAD_POLL_TIME 2
 
-/* lt_dlsym() violates ISO C, so confide the breakage into this function to
- * avoid warnings. */
-typedef void (*fnptr)(void);
-static inline fnptr lt_dlsym_fn(lt_dlhandle handle, const char *symbol) {
-    return (fnptr) (long) lt_dlsym(handle, symbol);
-}
-
 static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) {
-    pa_core *c = userdata;
+    pa_core *c = PA_CORE(userdata);
     struct timeval ntv;
-    assert(c && c->mainloop == m && c->module_auto_unload_event == e);
+
+    pa_core_assert_ref(c);
+    pa_assert(c->mainloop == m);
+    pa_assert(c->module_auto_unload_event == e);
 
     pa_module_unload_unused(c);
 
     pa_gettimeofday(&ntv);
-    ntv.tv_sec += UNLOAD_POLL_TIME;
+    pa_timeval_add(&ntv, UNLOAD_POLL_TIME*1000000);
     m->time_restart(e, &ntv);
 }
 
-static inline fnptr load_sym(lt_dlhandle handle, const char *module, const char *symbol) {
-    char *buffer, *ch;
-    size_t buflen;
-    fnptr res;
-
-    res = lt_dlsym_fn(handle, symbol);
-    if (res)
-        return res;
-
-    /* As the .la files might have been cleansed from the system, we should
-     * try with the ltdl prefix as well. */
-
-    buflen = strlen(symbol) + strlen(module) + strlen("_LTX_") + 1;
-    buffer = pa_xmalloc(buflen);
-    assert(buffer);
-
-    strcpy(buffer, module);
-
-    for (ch = buffer;*ch != '\0';ch++) {
-        if (!isalnum(*ch))
-            *ch = '_';
-    }
-
-    strcat(buffer, "_LTX_");
-    strcat(buffer, symbol);
-
-    res = lt_dlsym_fn(handle, buffer);
-
-    pa_xfree(buffer);
-
-    return res;
-}
-
 pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
     pa_module *m = NULL;
-    int r;
 
-    assert(c && name);
+    pa_assert(c);
+    pa_assert(name);
 
     if (c->disallow_module_loading)
         goto fail;
 
-    m = pa_xmalloc(sizeof(pa_module));
-
+    m = pa_xnew(pa_module, 1);
     m->name = pa_xstrdup(name);
     m->argument = pa_xstrdup(argument);
 
@@ -119,24 +82,19 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
         goto fail;
     }
 
-    if (!(m->init = (int (*)(pa_core *_c, pa_module*_m)) load_sym(m->dl, name, PA_SYMBOL_INIT))) {
+    if (!(m->init = (int (*)(pa_module*_m)) pa_load_sym(m->dl, name, PA_SYMBOL_INIT))) {
         pa_log("Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.", name);
         goto fail;
     }
 
-    if (!(m->done = (void (*)(pa_core *_c, pa_module*_m)) load_sym(m->dl, name, PA_SYMBOL_DONE))) {
-        pa_log("Failed to load module \"%s\": symbol \""PA_SYMBOL_DONE"\" not found.", name);
-        goto fail;
-    }
-
+    m->done = (void (*)(pa_module*_m)) pa_load_sym(m->dl, name, PA_SYMBOL_DONE);
     m->userdata = NULL;
     m->core = c;
     m->n_used = -1;
     m->auto_unload = 0;
     m->unload_requested = 0;
 
-    assert(m->init);
-    if (m->init(c, m) < 0) {
+    if (m->init(m) < 0) {
         pa_log_error("Failed to load  module \"%s\" (argument: \"%s\"): initialization failed.", name, argument ? argument : "");
         goto fail;
     }
@@ -147,14 +105,12 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
     if (!c->module_auto_unload_event) {
         struct timeval ntv;
         pa_gettimeofday(&ntv);
-        ntv.tv_sec += UNLOAD_POLL_TIME;
+        pa_timeval_add(&ntv, UNLOAD_POLL_TIME*1000000);
         c->module_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c);
     }
-    assert(c->module_auto_unload_event);
 
-    assert(c->modules);
-    r = pa_idxset_put(c->modules, m, &m->index);
-    assert(r >= 0 && m->index != PA_IDXSET_INVALID);
+    pa_assert_se(pa_idxset_put(c->modules, m, &m->index) >= 0);
+    pa_assert(m->index != PA_IDXSET_INVALID);
 
     pa_log_info("Loaded \"%s\" (index: #%u; argument: \"%s\").", m->name, m->index, m->argument ? m->argument : "");
 
@@ -178,14 +134,16 @@ fail:
 }
 
 static void pa_module_free(pa_module *m) {
-    assert(m && m->done && m->core);
+    pa_assert(m);
+    pa_assert(m->core);
 
     if (m->core->disallow_module_loading)
         return;
 
     pa_log_info("Unloading \"%s\" (index: #%u).", m->name, m->index);
 
-    m->done(m->core, m);
+    if (m->done)
+        m->done(m);
 
     lt_dlclose(m->dl);
 
@@ -199,9 +157,10 @@ static void pa_module_free(pa_module *m) {
 }
 
 void pa_module_unload(pa_core *c, pa_module *m) {
-    assert(c && m);
+    pa_assert(c);
+    pa_assert(m);
 
-    assert(c->modules);
+    pa_assert(c->modules);
     if (!(m = pa_idxset_remove_by_data(c->modules, m, NULL)))
         return;
 
@@ -210,9 +169,9 @@ void pa_module_unload(pa_core *c, pa_module *m) {
 
 void pa_module_unload_by_index(pa_core *c, uint32_t idx) {
     pa_module *m;
-    assert(c && idx != PA_IDXSET_INVALID);
+    pa_assert(c);
+    pa_assert(idx != PA_IDXSET_INVALID);
 
-    assert(c->modules);
     if (!(m = pa_idxset_remove_by_index(c->modules, idx)))
         return;
 
@@ -221,13 +180,14 @@ void pa_module_unload_by_index(pa_core *c, uint32_t idx) {
 
 static void free_callback(void *p, PA_GCC_UNUSED void *userdata) {
     pa_module *m = p;
-    assert(m);
+    pa_assert(m);
     pa_module_free(m);
 }
 
 void pa_module_unload_all(pa_core *c) {
     pa_module *m;
-    assert(c);
+
+    pa_assert(c);
 
     if (!c->modules)
         return;
@@ -252,7 +212,10 @@ void pa_module_unload_all(pa_core *c) {
 static int unused_callback(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void *userdata) {
     pa_module *m = p;
     time_t *now = userdata;
-    assert(p && del && now);
+
+    pa_assert(m);
+    pa_assert(del);
+    pa_assert(now);
 
     if (m->n_used == 0 && m->auto_unload && m->last_used_time+m->core->module_idle_time <= *now) {
         pa_module_free(m);
@@ -264,7 +227,7 @@ static int unused_callback(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void *
 
 void pa_module_unload_unused(pa_core *c) {
     time_t now;
-    assert(c);
+    pa_assert(c);
 
     if (!c->modules)
         return;
@@ -275,7 +238,7 @@ void pa_module_unload_unused(pa_core *c) {
 
 static int unload_callback(void *p, PA_GCC_UNUSED uint32_t idx, int *del, PA_GCC_UNUSED void *userdata) {
     pa_module *m = p;
-    assert(m);
+    pa_assert(m);
 
     if (m->unload_requested) {
         pa_module_free(m);
@@ -286,18 +249,19 @@ static int unload_callback(void *p, PA_GCC_UNUSED uint32_t idx, int *del, PA_GCC
 }
 
 static void defer_cb(pa_mainloop_api*api, pa_defer_event *e, void *userdata) {
-    pa_core *core = userdata;
+    pa_core *core = PA_CORE(userdata);
+
+    pa_core_assert_ref(core);
     api->defer_enable(e, 0);
 
     if (!core->modules)
         return;
 
     pa_idxset_foreach(core->modules, unload_callback, NULL);
-
 }
 
 void pa_module_unload_request(pa_module *m) {
-    assert(m);
+    pa_assert(m);
 
     m->unload_requested = 1;
 
@@ -308,19 +272,19 @@ void pa_module_unload_request(pa_module *m) {
 }
 
 void pa_module_set_used(pa_module*m, int used) {
-    assert(m);
+    pa_assert(m);
 
     if (m->n_used != used)
         pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_CHANGE, m->index);
 
-    if (m->n_used != used && used == 0)
+    if (used == 0 && m->n_used > 0)
         time(&m->last_used_time);
 
     m->n_used = used;
 }
 
 pa_modinfo *pa_module_get_info(pa_module *m) {
-    assert(m);
+    pa_assert(m);
 
-    return pa_modinfo_get_by_handle(m->dl);
+    return pa_modinfo_get_by_handle(m->dl, m->name);
 }
index 750dfaa8dd1f133c09ec96c5b4b7194c4d232111..7a93a071aac7191f72beabadcccd15007d09a0f9 100644 (file)
@@ -39,8 +39,8 @@ struct pa_module {
 
     lt_dlhandle dl;
 
-    int (*init)(pa_core *c, pa_module*m);
-    void (*done)(pa_core *c, pa_module*m);
+    int (*init)(pa_module*m);
+    void (*done)(pa_module*m);
 
     void *userdata;
 
@@ -62,9 +62,9 @@ void pa_module_unload_request(pa_module *m);
 
 void pa_module_set_used(pa_module*m, int used);
 
-#define PA_MODULE_AUTHOR(s) const char * pa__get_author(void) { return s; }
-#define PA_MODULE_DESCRIPTION(s) const char * pa__get_description(void) { return s; }
-#define PA_MODULE_USAGE(s) const char * pa__get_usage(void) { return s; }
+#define PA_MODULE_AUTHOR(s) const char *pa__get_author(void) { return s; }
+#define PA_MODULE_DESCRIPTION(s) const char *pa__get_description(void) { return s; }
+#define PA_MODULE_USAGE(s) const char *pa__get_usage(void) { return s; }
 #define PA_MODULE_VERSION(s) const char * pa__get_version(void) { return s; }
 
 pa_modinfo *pa_module_get_info(pa_module *m);
diff --git a/src/pulsecore/msgobject.c b/src/pulsecore/msgobject.c
new file mode 100644 (file)
index 0000000..f54e69f
--- /dev/null
@@ -0,0 +1,49 @@
+/* $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 "msgobject.h"
+
+PA_DEFINE_CHECK_TYPE(pa_msgobject, pa_object);
+
+pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name)) {
+    pa_msgobject *o;
+
+    pa_assert(size > sizeof(pa_msgobject));
+    pa_assert(type_name);
+
+    if (!check_type)
+        check_type = pa_msgobject_check_type;
+
+    pa_assert(check_type(type_name));
+    pa_assert(check_type("pa_object"));
+    pa_assert(check_type("pa_msgobject"));
+
+    o = PA_MSGOBJECT(pa_object_new_internal(size, type_name, check_type));
+    o->process_msg = NULL;
+    return o;
+}
diff --git a/src/pulsecore/msgobject.h b/src/pulsecore/msgobject.h
new file mode 100644 (file)
index 0000000..8221cc3
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef foopulsemsgobjecthfoo
+#define foopulsemsgobjecthfoo
+
+/* $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.
+***/
+
+#include <sys/types.h>
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/refcnt.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/object.h>
+#include <pulsecore/memchunk.h>
+
+typedef struct pa_msgobject pa_msgobject;
+
+struct pa_msgobject {
+    pa_object parent;
+    int (*process_msg)(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
+};
+
+pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name));
+
+int pa_msgobject_check_type(const char *type);
+
+#define pa_msgobject_new(type) ((type*) pa_msgobject_new_internal(sizeof(type), #type, type##_check_type))
+#define pa_msgobject_free ((void (*) (pa_msgobject* o)) pa_object_free)
+
+#define PA_MSGOBJECT(o) pa_msgobject_cast(o)
+
+PA_DECLARE_CLASS(pa_msgobject);
+
+#endif
index 52e731b36acda5365f017584805f74c3e1cddb7d..1b13ede1506cdb20f45eceeafaea7f6850d2ee89 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <pthread.h>
-
-#include <atomic_ops.h>
+#include <errno.h>
 
 #include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/log.h>
+#include <pulsecore/core-error.h>
 
 #include "mutex.h"
 
-#define ASSERT_SUCCESS(x) do { \
-    int _r = (x); \
-    assert(_r == 0); \
-} while(0)
-
 struct pa_mutex {
     pthread_mutex_t mutex;
 };
@@ -47,68 +43,88 @@ struct pa_cond {
     pthread_cond_t cond;
 };
 
-pa_mutex* pa_mutex_new(int recursive) {
+pa_mutex* pa_mutex_new(pa_bool_t recursive, pa_bool_t inherit_priority) {
     pa_mutex *m;
     pthread_mutexattr_t attr;
+    int r;
 
-    pthread_mutexattr_init(&attr);
+    pa_assert_se(pthread_mutexattr_init(&attr) == 0);
 
     if (recursive)
-        ASSERT_SUCCESS(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE));
+        pa_assert_se(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) == 0);
+
+#ifdef HAVE_PTHREAD_PRIO_INHERIT
+    if (inherit_priority)
+        pa_assert_se(pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT) == 0);
+#endif
 
     m = pa_xnew(pa_mutex, 1);
 
-    ASSERT_SUCCESS(pthread_mutex_init(&m->mutex, &attr));
+#ifndef HAVE_PTHREAD_PRIO_INHERIT
+    pa_assert_se(pthread_mutex_init(&m->mutex, &attr) == 0);
+
+#else
+    if ((r = pthread_mutex_init(&m->mutex, &attr))) {
+
+        /* If this failed, then this was probably due to non-available
+         * priority inheritance. In which case we fall back to normal
+         * mutexes. */
+        pa_assert(r == ENOTSUP && inherit_priority);
+
+        pa_assert_se(pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_NONE) == 0);
+        pa_assert_se(pthread_mutex_init(&m->mutex, &attr) == 0);
+    }
+#endif
+
     return m;
 }
 
 void pa_mutex_free(pa_mutex *m) {
-    assert(m);
+    pa_assert(m);
 
-    ASSERT_SUCCESS(pthread_mutex_destroy(&m->mutex));
+    pa_assert_se(pthread_mutex_destroy(&m->mutex) == 0);
     pa_xfree(m);
 }
 
 void pa_mutex_lock(pa_mutex *m) {
-    assert(m);
+    pa_assert(m);
 
-    ASSERT_SUCCESS(pthread_mutex_lock(&m->mutex));
+    pa_assert_se(pthread_mutex_lock(&m->mutex) == 0);
 }
 
 void pa_mutex_unlock(pa_mutex *m) {
-    assert(m);
+    pa_assert(m);
 
-    ASSERT_SUCCESS(pthread_mutex_unlock(&m->mutex));
+    pa_assert_se(pthread_mutex_unlock(&m->mutex) == 0);
 }
 
 pa_cond *pa_cond_new(void) {
     pa_cond *c;
 
     c = pa_xnew(pa_cond, 1);
-
-    ASSERT_SUCCESS(pthread_cond_init(&c->cond, NULL));
+    pa_assert_se(pthread_cond_init(&c->cond, NULL) == 0);
     return c;
 }
 
 void pa_cond_free(pa_cond *c) {
-    assert(c);
+    pa_assert(c);
 
-    ASSERT_SUCCESS(pthread_cond_destroy(&c->cond));
+    pa_assert_se(pthread_cond_destroy(&c->cond) == 0);
     pa_xfree(c);
 }
 
 void pa_cond_signal(pa_cond *c, int broadcast) {
-    assert(c);
+    pa_assert(c);
 
     if (broadcast)
-        ASSERT_SUCCESS(pthread_cond_broadcast(&c->cond));
+        pa_assert_se(pthread_cond_broadcast(&c->cond) == 0);
     else
-        ASSERT_SUCCESS(pthread_cond_signal(&c->cond));
+        pa_assert_se(pthread_cond_signal(&c->cond) == 0);
 }
 
 int pa_cond_wait(pa_cond *c, pa_mutex *m) {
-    assert(c);
-    assert(m);
+    pa_assert(c);
+    pa_assert(m);
 
     return pthread_cond_wait(&c->cond, &m->mutex);
 }
index 1f16e24c7f2db3ece634af12fbb40a8d77107c0b..77d63d15904311457fd8fd9bbcc130e3d80982fa 100644 (file)
@@ -40,7 +40,7 @@ struct pa_cond {
     pa_hashmap *wait_events;
 };
 
-pa_mutex* pa_mutex_new(int recursive) {
+pa_mutex* pa_mutex_new(pa_bool_t recursive, pa_bool_t inherit_priority) {
     pa_mutex *m;
 
     m = pa_xnew(pa_mutex, 1);
index b2e34c07a8d8459a82fda64891d28fc124f144c3..72e887819175adc7d1925b314fd88659907b31e5 100644 (file)
   USA.
 ***/
 
+#include <pulsecore/macro.h>
+
 typedef struct pa_mutex pa_mutex;
 
-pa_mutex* pa_mutex_new(int recursive);
+/* Please think twice before enabling priority inheritance. This is no
+ * magic wand! Use it only when the potentially priorized threads are
+ * good candidates for it. Don't use this blindly! Also, note that
+ * only very few operating systems actually implement this, hence this
+ * is merely a hint. */
+pa_mutex* pa_mutex_new(pa_bool_t recursive, pa_bool_t inherit_priority);
+
 void pa_mutex_free(pa_mutex *m);
 void pa_mutex_lock(pa_mutex *m);
 void pa_mutex_unlock(pa_mutex *m);
index 7f66af0595ec8caccb51a00d66d1a39d82685be0..fe2be4671490778e6dd0f7a917b46bef1bd56764 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 
@@ -38,6 +37,7 @@
 #include <pulsecore/sink.h>
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
 
 #include "namereg.h"
 
@@ -90,23 +90,22 @@ static char* cleanup_name(const char *name) {
 }
 
 void pa_namereg_free(pa_core *c) {
-    assert(c);
+    pa_assert(c);
 
     if (!c->namereg)
         return;
 
-    assert(pa_hashmap_size(c->namereg) == 0);
+    pa_assert(pa_hashmap_size(c->namereg) == 0);
     pa_hashmap_free(c->namereg, NULL, NULL);
 }
 
 const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail) {
     struct namereg_entry *e;
     char *n = NULL;
-    int r;
 
-    assert(c);
-    assert(name);
-    assert(data);
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(data);
 
     if (!*name)
         return NULL;
@@ -142,7 +141,7 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t
         k = pa_xnew(char, l+4);
 
         for (i = 2; i <= 99; i++) {
-            snprintf(k, l+4, "%s.%u", name, i);
+            pa_snprintf(k, l+4, "%s.%u", name, i);
 
             if (!(e = pa_hashmap_get(c->namereg, k)))
                 break;
@@ -163,8 +162,7 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t
     e->name = n ? n : pa_xstrdup(name);
     e->data = data;
 
-    r = pa_hashmap_put(c->namereg, e->name, e);
-    assert (r >= 0);
+    pa_assert_se(pa_hashmap_put(c->namereg, e->name, e) >= 0);
 
     return e->name;
 }
@@ -172,11 +170,10 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t
 void pa_namereg_unregister(pa_core *c, const char *name) {
     struct namereg_entry *e;
 
-    assert(c);
-    assert(name);
+    pa_assert(c);
+    pa_assert(name);
 
-    e = pa_hashmap_remove(c->namereg, name);
-    assert(e);
+    pa_assert_se(e = pa_hashmap_remove(c->namereg, name));
 
     pa_xfree(e->name);
     pa_xfree(e);
@@ -185,7 +182,7 @@ void pa_namereg_unregister(pa_core *c, const char *name) {
 void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int autoload) {
     struct namereg_entry *e;
     uint32_t idx;
-    assert(c);
+    pa_assert(c);
 
     if (!name) {
 
@@ -245,8 +242,8 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int a
 int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) {
     char **s;
 
-    assert(c);
-    assert(type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE);
+    pa_assert(c);
+    pa_assert(type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE);
 
     s = type == PA_NAMEREG_SINK ? &c->default_sink_name : &c->default_source_name;
 
@@ -269,7 +266,7 @@ int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type)
 const char *pa_namereg_get_default_sink_name(pa_core *c) {
     pa_sink *s;
 
-    assert(c);
+    pa_assert(c);
 
     if (c->default_sink_name)
         return c->default_sink_name;
@@ -284,7 +281,7 @@ const char *pa_namereg_get_default_source_name(pa_core *c) {
     pa_source *s;
     uint32_t idx;
 
-    assert(c);
+    pa_assert(c);
 
     if (c->default_source_name)
         return c->default_source_name;
index f7a7da1de84bcf5b600d688dafe3a4ef5573251f..9defc4a53e044c88a6d72289f6e34fd44f9ed3d0 100644 (file)
@@ -115,6 +115,11 @@ enum {
     PA_COMMAND_MOVE_SINK_INPUT,
     PA_COMMAND_MOVE_SOURCE_OUTPUT,
 
+    PA_COMMAND_SET_SINK_INPUT_MUTE,
+
+    PA_COMMAND_SUSPEND_SINK,
+    PA_COMMAND_SUSPEND_SOURCE,
+
     PA_COMMAND_MAX
 };
 
diff --git a/src/pulsecore/object.c b/src/pulsecore/object.c
new file mode 100644 (file)
index 0000000..6c36242
--- /dev/null
@@ -0,0 +1,72 @@
+/* $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 "object.h"
+
+pa_object *pa_object_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name)) {
+    pa_object *o;
+
+    pa_assert(size > sizeof(pa_object));
+    pa_assert(type_name);
+
+    if (!check_type)
+        check_type = pa_object_check_type;
+
+    pa_assert(check_type(type_name));
+    pa_assert(check_type("pa_object"));
+
+    o = pa_xmalloc(size);
+    PA_REFCNT_INIT(o);
+    o->type_name = type_name;
+    o->free = pa_object_free;
+    o->check_type = check_type;
+
+    return o;
+}
+
+pa_object *pa_object_ref(pa_object *o) {
+    pa_object_assert_ref(o);
+
+    PA_REFCNT_INC(o);
+    return o;
+}
+
+void pa_object_unref(pa_object *o) {
+    pa_object_assert_ref(o);
+
+    if (PA_REFCNT_DEC(o) <= 0) {
+        pa_assert(o->free);
+        o->free(o);
+    }
+}
+
+int pa_object_check_type(const char *type_name) {
+    pa_assert(type_name);
+
+    return strcmp(type_name, "pa_object") == 0;
+}
diff --git a/src/pulsecore/object.h b/src/pulsecore/object.h
new file mode 100644 (file)
index 0000000..562fd11
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef foopulseobjecthfoo
+#define foopulseobjecthfoo
+
+/* $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.
+***/
+
+#include <string.h>
+#include <sys/types.h>
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/refcnt.h>
+#include <pulsecore/macro.h>
+
+typedef struct pa_object pa_object;
+
+struct pa_object {
+    PA_REFCNT_DECLARE;
+    const char *type_name;
+    void (*free)(pa_object *o);
+    int (*check_type)(const char *type_name);
+};
+
+pa_object *pa_object_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name));
+#define pa_object_new(type) ((type*) pa_object_new_internal(sizeof(type), #type, type##_check_type)
+
+#define pa_object_free ((void (*) (pa_object* o)) pa_xfree)
+
+int pa_object_check_type(const char *type);
+
+static inline int pa_object_isinstance(void *o) {
+    pa_object *obj = (pa_object*) o;
+    return obj ? obj->check_type("pa_object") : 0;
+}
+
+pa_object *pa_object_ref(pa_object *o);
+void pa_object_unref(pa_object *o);
+
+static inline int pa_object_refcnt(pa_object *o) {
+    return o ? PA_REFCNT_VALUE(o) : 0;
+}
+
+static inline pa_object* pa_object_cast(void *o) {
+    pa_object *obj = (pa_object*) o;
+    pa_assert(!obj || obj->check_type("pa_object"));
+    return obj;
+}
+
+#define pa_object_assert_ref(o) pa_assert(pa_object_refcnt(o) > 0)
+
+#define PA_OBJECT(o) pa_object_cast(o)
+
+#define PA_DECLARE_CLASS(c)                                             \
+    static inline int c##_isinstance(void *o) {                         \
+        pa_object *obj = (pa_object*) o;                                \
+        return obj ? obj->check_type(#c) : 1;                           \
+    }                                                                   \
+    static inline c* c##_cast(void *o) {                                \
+        pa_assert(c##_isinstance(o));                                   \
+        return (c*) o;                                                  \
+    }                                                                   \
+    static inline c* c##_ref(c *o) {                                    \
+        return (c*) pa_object_ref(PA_OBJECT(o));                        \
+    }                                                                   \
+    static inline void c##_unref(c* o) {                                \
+        pa_object_unref(PA_OBJECT(o));                                  \
+    }                                                                   \
+    static inline int c##_refcnt(c* o) {                                \
+        return pa_object_refcnt(PA_OBJECT(o));                          \
+    }                                                                   \
+    static inline void c##_assert_ref(c *o) {                           \
+        pa_object_assert_ref(PA_OBJECT(o));                             \
+    }                                                                   \
+    struct __stupid_useless_struct_to_allow_trailing_semicolon
+
+#define PA_DEFINE_CHECK_TYPE(c, parent)                                 \
+    int c##_check_type(const char *type) {                              \
+        pa_assert(type);                                                \
+        if (strcmp(type, #c) == 0)                                      \
+            return 1;                                                   \
+        return parent##_check_type(type);                               \
+    }                                                                   \
+    struct __stupid_useless_struct_to_allow_trailing_semicolon
+
+
+#endif
diff --git a/src/pulsecore/once-posix.c b/src/pulsecore/once-posix.c
deleted file mode 100644 (file)
index 4af7b36..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/* $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 <pthread.h>
-#include <assert.h>
-
-#include <pulsecore/mutex.h>
-
-#include "once.h"
-
-#define ASSERT_SUCCESS(x) do { \
-    int _r = (x); \
-    assert(_r == 0); \
-} while(0)
-
-static pa_mutex *global_mutex;
-static pthread_once_t global_mutex_once = PTHREAD_ONCE_INIT;
-
-static void global_mutex_once_func(void) {
-    global_mutex = pa_mutex_new(0);
-}
-
-void pa_once(pa_once_t *control, pa_once_func_t func) {
-    assert(control);
-    assert(func);
-
-    /* Create the global mutex */
-    ASSERT_SUCCESS(pthread_once(&global_mutex_once, global_mutex_once_func));
-
-    /* Create the local mutex */
-    pa_mutex_lock(global_mutex);
-    if (!control->mutex)
-        control->mutex = pa_mutex_new(1);
-    pa_mutex_unlock(global_mutex);
-
-    /* Execute function */
-    pa_mutex_lock(control->mutex);
-    if (!control->once_value) {
-        control->once_value = 1;
-        func();
-    }
-    pa_mutex_unlock(control->mutex);
-
-    /* Caveat: We have to make sure that the once func has completed
-     * before returning, even if the once func is not actually
-     * executed by us. Hence the awkward locking. */
-}
diff --git a/src/pulsecore/once-win32.c b/src/pulsecore/once-win32.c
deleted file mode 100644 (file)
index b30097c..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/* $Id$ */
-
-/***
-  This file is part of PulseAudio.
-
-  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 <assert.h>
-#include <stdio.h>
-
-#include <windows.h>
-
-#include <pulsecore/mutex.h>
-
-#include "once.h"
-
-void pa_once(pa_once_t *control, pa_once_func_t func) {
-    HANDLE mutex;
-    char name[64];
-
-    assert(control);
-    assert(func);
-
-    /* Create the global mutex */
-    sprintf(name, "pulse%d", (int)GetCurrentProcessId());
-
-    mutex = CreateMutex(NULL, FALSE, name);
-    assert(mutex);
-
-    /* Create the local mutex */
-    WaitForSingleObject(mutex, INFINITE);
-    if (!control->mutex)
-        control->mutex = pa_mutex_new(1);
-    ReleaseMutex(mutex);
-
-    CloseHandle(mutex);
-
-    /* Execute function */
-    pa_mutex_lock(control->mutex);
-    if (!control->once_value) {
-        control->once_value = 1;
-        func();
-    }
-    pa_mutex_unlock(control->mutex);
-
-    /* Caveat: We have to make sure that the once func has completed
-     * before returning, even if the once func is not actually
-     * executed by us. Hence the awkward locking. */
-}
diff --git a/src/pulsecore/once.c b/src/pulsecore/once.c
new file mode 100644 (file)
index 0000000..a358cf6
--- /dev/null
@@ -0,0 +1,96 @@
+/* $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/macro.h>
+#include <pulsecore/mutex.h>
+
+#include "once.h"
+
+int pa_once_begin(pa_once *control) {
+    pa_mutex *m;
+
+    pa_assert(control);
+
+    if (pa_atomic_load(&control->done))
+        return 0;
+
+    pa_atomic_inc(&control->ref);
+
+    /* Caveat: We have to make sure that the once func has completed
+     * before returning, even if the once func is not actually
+     * executed by us. Hence the awkward locking. */
+
+    for (;;) {
+
+        if ((m = pa_atomic_ptr_load(&control->mutex))) {
+
+            /* The mutex is stored in locked state, hence let's just
+             * wait until it is unlocked */
+            pa_mutex_lock(m);
+
+            pa_once_end(control);
+            return 0;
+        }
+
+        pa_assert_se(m = pa_mutex_new(FALSE, FALSE));
+        pa_mutex_lock(m);
+
+        if (pa_atomic_ptr_cmpxchg(&control->mutex, NULL, m))
+            return 1;
+
+        pa_mutex_unlock(m);
+        pa_mutex_free(m);
+    }
+}
+
+void pa_once_end(pa_once *control) {
+    pa_mutex *m;
+
+    pa_assert(control);
+
+    pa_atomic_store(&control->done, 1);
+
+    pa_assert_se(m = pa_atomic_ptr_load(&control->mutex));
+    pa_mutex_unlock(m);
+
+    if (pa_atomic_dec(&control->ref) <= 1) {
+        pa_assert_se(pa_atomic_ptr_cmpxchg(&control->mutex, m, NULL));
+        pa_mutex_free(m);
+    }
+}
+
+/* Not reentrant -- how could it be? */
+void pa_run_once(pa_once *control, pa_once_func_t func) {
+    pa_assert(control);
+    pa_assert(func);
+
+    if (pa_once_begin(control)) {
+        func();
+        pa_once_end(control);
+    }
+}
+
index c20fc0b4c8836d9faf7e4cf2aa9e188997f05f28..c9fe6d0a4942a726384de853bd4c7ce9ac53118d 100644 (file)
 ***/
 
 #include <pulsecore/mutex.h>
+#include <pulsecore/atomic.h>
 
 typedef struct pa_once {
-    unsigned int once_value;
-    pa_mutex *mutex;
-} pa_once_t;
+    pa_atomic_ptr_t mutex;
+    pa_atomic_t ref, done;
+} pa_once;
 
-#define PA_ONCE_INIT { .once_value = 0, .mutex = NULL }
+#define PA_ONCE_INIT                                                    \
+    {                                                                   \
+        .mutex = PA_ATOMIC_PTR_INIT(NULL),                              \
+        .ref = PA_ATOMIC_INIT(0),                                       \
+        .done = PA_ATOMIC_INIT(0)                                       \
+    }
 
-typedef void (*pa_once_func_t) (void);
+/* Not to be called directly, use the macros defined below instead */
+int pa_once_begin(pa_once *o);
+void pa_once_end(pa_once *o);
+
+#define PA_ONCE_BEGIN                                                   \
+    do {                                                                \
+        static pa_once _once = PA_ONCE_INIT;                            \
+        if (pa_once_begin(&_once)) {{
+
+#define PA_ONCE_END                                                     \
+            }                                                           \
+            pa_once_end(&_once);                                        \
+        }                                                               \
+    } while(0)
+
+/*
+
+  Usage of these macros is like this:
+
+  void foo() {
 
-void pa_once(pa_once_t *o, pa_once_func_t f);
+      PA_ONCE_BEGIN {
+
+          ... stuff to be called just once ...
+
+      } PA_ONCE_END;
+  }
+
+*/
+
+/* Same API but calls a function */
+typedef void (*pa_once_func_t) (void);
+void pa_run_once(pa_once *o, pa_once_func_t f);
 
 #endif
index ce57cb3e322a607f4946869a571bbb4bf7fcd01f..2706efeaaefb7bd95d869e65b71c1d94b3e371ad 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdlib.h>
 
 #include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
 
 #include "packet.h"
 
 pa_packet* pa_packet_new(size_t length) {
     pa_packet *p;
 
-    assert(length);
+    pa_assert(length > 0);
 
-    p = pa_xmalloc(sizeof(pa_packet)+length);
-    p->ref = 1;
+    p = pa_xmalloc(PA_ALIGN(sizeof(pa_packet)) + length);
+    PA_REFCNT_INIT(p);
     p->length = length;
-    p->data = (uint8_t*) (p+1);
+    p->data = (uint8_t*) p + PA_ALIGN(sizeof(pa_packet));
     p->type = PA_PACKET_APPENDED;
 
     return p;
@@ -49,11 +49,11 @@ pa_packet* pa_packet_new(size_t length) {
 pa_packet* pa_packet_new_dynamic(void* data, size_t length) {
     pa_packet *p;
 
-    assert(data);
-    assert(length);
+    pa_assert(data);
+    pa_assert(length > 0);
 
     p = pa_xnew(pa_packet, 1);
-    p->ref = 1;
+    PA_REFCNT_INIT(p);
     p->length = length;
     p->data = data;
     p->type = PA_PACKET_DYNAMIC;
@@ -62,18 +62,18 @@ pa_packet* pa_packet_new_dynamic(void* data, size_t length) {
 }
 
 pa_packet* pa_packet_ref(pa_packet *p) {
-    assert(p);
-    assert(p->ref >= 1);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) >= 1);
 
-    p->ref++;
+    PA_REFCNT_INC(p);
     return p;
 }
 
 void pa_packet_unref(pa_packet *p) {
-    assert(p);
-    assert(p->ref >= 1);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) >= 1);
 
-    if (--p->ref == 0) {
+    if (PA_REFCNT_DEC(p) <= 0) {
         if (p->type == PA_PACKET_DYNAMIC)
             pa_xfree(p->data);
         pa_xfree(p);
index 842582c8668936355f50ff65e6c89c6b1b3666ab..bcac4a7f3fcce94f27ecc94ec27c11d26d3816e8 100644 (file)
 #include <sys/types.h>
 #include <inttypes.h>
 
+#include <pulsecore/refcnt.h>
+
 typedef struct pa_packet {
+    PA_REFCNT_DECLARE;
     enum { PA_PACKET_APPENDED, PA_PACKET_DYNAMIC } type;
-    unsigned ref;
     size_t length;
     uint8_t *data;
 } pa_packet;
index a49a09ed7d93df67ecefb1e3fec03ca5dff49c51..65ba64c1c26533653a49875a239bce49a8bacc09 100644 (file)
 #endif
 
 #include <string.h>
-#include <assert.h>
 #include <stdlib.h>
 
 #include <pulse/xmalloc.h>
-
 #include <pulse/util.h>
+
 #include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
 
 #include "parseaddr.h"
 
@@ -45,7 +45,9 @@
  *  Return a newly allocated string of the hostname and fill in *ret_port if specified  */
 
 static char *parse_host(const char *s, uint16_t *ret_port) {
-    assert(s && ret_port);
+    pa_assert(s);
+    pa_assert(ret_port);
+
     if (*s == '[') {
         char *e;
         if (!(e = strchr(s+1, ']')))
@@ -70,7 +72,10 @@ static char *parse_host(const char *s, uint16_t *ret_port) {
 
 int pa_parse_address(const char *name, pa_parsed_address *ret_p) {
     const char *p;
-    assert(name && ret_p);
+
+    pa_assert(name);
+    pa_assert(ret_p);
+
     memset(ret_p, 0, sizeof(pa_parsed_address));
     ret_p->type = PA_PARSED_ADDRESS_TCP_AUTO;
 
@@ -112,6 +117,5 @@ int pa_parse_address(const char *name, pa_parsed_address *ret_p) {
         if (!(ret_p->path_or_host = parse_host(p, &ret_p->port)))
             return -1;
 
-
     return 0;
 }
index 10238acb058bb40a549318b1372fed1f7d31f8be..2c95d7407e83a51d9655c8cd958de81dfa6e1288 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <assert.h>
 
 #include <pulse/timeval.h>
 #include <pulse/xmalloc.h>
@@ -37,6 +36,8 @@
 #include <pulsecore/llist.h>
 #include <pulsecore/log.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/refcnt.h>
 
 #include "pdispatch.h"
 
@@ -108,7 +109,7 @@ struct reply_info {
 };
 
 struct pa_pdispatch {
-    int ref;
+    PA_REFCNT_DECLARE;
     pa_mainloop_api *mainloop;
     const pa_pdispatch_cb_t *callback_table;
     unsigned n_commands;
@@ -119,7 +120,9 @@ struct pa_pdispatch {
 };
 
 static void reply_info_free(struct reply_info *r) {
-    assert(r && r->pdispatch && r->pdispatch->mainloop);
+    pa_assert(r);
+    pa_assert(r->pdispatch);
+    pa_assert(r->pdispatch->mainloop);
 
     if (r->time_event)
         r->pdispatch->mainloop->time_free(r->time_event);
@@ -131,12 +134,12 @@ static void reply_info_free(struct reply_info *r) {
 
 pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_t*table, unsigned entries) {
     pa_pdispatch *pd;
-    assert(mainloop);
+    pa_assert(mainloop);
 
-    assert((entries && table) || (!entries && !table));
+    pa_assert((entries && table) || (!entries && !table));
 
-    pd = pa_xmalloc(sizeof(pa_pdispatch));
-    pd->ref = 1;
+    pd = pa_xnew(pa_pdispatch, 1);
+    PA_REFCNT_INIT(pd);
     pd->mainloop = mainloop;
     pd->callback_table = table;
     pd->n_commands = entries;
@@ -149,7 +152,7 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_
 }
 
 static void pdispatch_free(pa_pdispatch *pd) {
-    assert(pd);
+    pa_assert(pd);
 
     while (pd->replies) {
         if (pd->replies->free_cb)
@@ -165,7 +168,7 @@ static void run_action(pa_pdispatch *pd, struct reply_info *r, uint32_t command,
     pa_pdispatch_cb_t callback;
     void *userdata;
     uint32_t tag;
-    assert(r);
+    pa_assert(r);
 
     pa_pdispatch_ref(pd);
 
@@ -187,7 +190,12 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds,
     uint32_t tag, command;
     pa_tagstruct *ts = NULL;
     int ret = -1;
-    assert(pd && packet && packet->data);
+
+    pa_assert(pd);
+    pa_assert(PA_REFCNT_VALUE(pd) >= 1);
+    pa_assert(packet);
+    pa_assert(PA_REFCNT_VALUE(packet) >= 1);
+    pa_assert(packet->data);
 
     pa_pdispatch_ref(pd);
 
@@ -195,7 +203,6 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds,
         goto finish;
 
     ts = pa_tagstruct_new(packet->data, packet->length);
-    assert(ts);
 
     if (pa_tagstruct_getu32(ts, &command) < 0 ||
         pa_tagstruct_getu32(ts, &tag) < 0)
@@ -206,7 +213,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds,
     char t[256];
     char const *p;
     if (!(p = command_names[command]))
-        snprintf((char*) (p = t), sizeof(t), "%u", command);
+        pa_snprintf((char*) (p = t), sizeof(t), "%u", command);
 
     pa_log("Recieved opcode <%s>", p);
 }
@@ -248,7 +255,12 @@ finish:
 
 static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) {
     struct reply_info*r = userdata;
-    assert(r && r->time_event == e && r->pdispatch && r->pdispatch->mainloop == m && r->callback);
+
+    pa_assert(r);
+    pa_assert(r->time_event == e);
+    pa_assert(r->pdispatch);
+    pa_assert(r->pdispatch->mainloop == m);
+    pa_assert(r->callback);
 
     run_action(r->pdispatch, r, PA_COMMAND_TIMEOUT, NULL);
 }
@@ -256,7 +268,10 @@ static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, PA_GCC_UNUSED c
 void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t cb, void *userdata, pa_free_cb_t free_cb) {
     struct reply_info *r;
     struct timeval tv;
-    assert(pd && pd->ref >= 1 && cb);
+
+    pa_assert(pd);
+    pa_assert(PA_REFCNT_VALUE(pd) >= 1);
+    pa_assert(cb);
 
     r = pa_xnew(struct reply_info, 1);
     r->pdispatch = pd;
@@ -268,21 +283,22 @@ void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa
     pa_gettimeofday(&tv);
     tv.tv_sec += timeout;
 
-    r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r);
-    assert(r->time_event);
+    pa_assert_se(r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r));
 
     PA_LLIST_PREPEND(struct reply_info, pd->replies, r);
 }
 
 int pa_pdispatch_is_pending(pa_pdispatch *pd) {
-    assert(pd);
+    pa_assert(pd);
+    pa_assert(PA_REFCNT_VALUE(pd) >= 1);
 
     return !!pd->replies;
 }
 
 void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, void (*cb)(pa_pdispatch *pd, void *userdata), void *userdata) {
-    assert(pd);
-    assert(!cb || pa_pdispatch_is_pending(pd));
+    pa_assert(pd);
+    pa_assert(PA_REFCNT_VALUE(pd) >= 1);
+    pa_assert(!cb || pa_pdispatch_is_pending(pd));
 
     pd->drain_callback = cb;
     pd->drain_userdata = userdata;
@@ -290,7 +306,9 @@ void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, void (*cb)(pa_pdispatch *
 
 void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata) {
     struct reply_info *r, *n;
-    assert(pd);
+
+    pa_assert(pd);
+    pa_assert(PA_REFCNT_VALUE(pd) >= 1);
 
     for (r = pd->replies; r; r = n) {
         n = r->next;
@@ -301,21 +319,24 @@ void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata) {
 }
 
 void pa_pdispatch_unref(pa_pdispatch *pd) {
-    assert(pd && pd->ref >= 1);
+    pa_assert(pd);
+    pa_assert(PA_REFCNT_VALUE(pd) >= 1);
 
-    if (!(--(pd->ref)))
+    if (PA_REFCNT_DEC(pd) <= 0)
         pdispatch_free(pd);
 }
 
 pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd) {
-    assert(pd && pd->ref >= 1);
-    pd->ref++;
+    pa_assert(pd);
+    pa_assert(PA_REFCNT_VALUE(pd) >= 1);
+
+    PA_REFCNT_INC(pd);
     return pd;
 }
 
 const pa_creds * pa_pdispatch_creds(pa_pdispatch *pd) {
-    assert(pd);
-    assert(pd->ref >= 1);
+    pa_assert(pd);
+    pa_assert(PA_REFCNT_VALUE(pd) >= 1);
 
     return pd->creds;
 }
index 5e670e17afd53a145a34a1a5799525fea9af9201..55ff2088b1a307b24d9152c3d530b2af4dc1a851 100644 (file)
@@ -33,7 +33,6 @@
 #include <sys/stat.h>
 #include <string.h>
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <limits.h>
 #include <signal.h>
@@ -47,6 +46,7 @@
 #include <pulsecore/core-error.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "pid.h"
 
@@ -57,11 +57,11 @@ static pid_t read_pid(const char *fn, int fd) {
     char t[20], *e;
     uint32_t pid;
 
-    assert(fn && fd >= 0);
+    pa_assert(fn);
+    pa_assert(fd >= 0);
 
     if ((r = pa_loop_read(fd, t, sizeof(t)-1, NULL)) < 0) {
-        pa_log_warn("WARNING: failed to read PID file '%s': %s",
-            fn, pa_cstrerror(errno));
+        pa_log_warn("Failed to read PID file '%s': %s", fn, pa_cstrerror(errno));
         return (pid_t) -1;
     }
 
@@ -73,7 +73,7 @@ static pid_t read_pid(const char *fn, int fd) {
         *e = 0;
 
     if (pa_atou(t, &pid) < 0) {
-        pa_log("WARNING: failed to parse PID file '%s'", fn);
+        pa_log_warn("Failed to parse PID file '%s'", fn);
         return (pid_t) -1;
     }
 
@@ -83,13 +83,22 @@ static pid_t read_pid(const char *fn, int fd) {
 static int open_pid_file(const char *fn, int mode) {
     int fd = -1;
 
+    pa_assert(fn);
+
     for (;;) {
         struct stat st;
 
-        if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) {
+        if ((fd = open(fn, mode
+#ifdef O_NOCTTY
+                       |O_NOCTTY
+#endif
+#ifdef O_NOFOLLOW
+                       |O_NOFOLLOW
+#endif
+                       , S_IRUSR|S_IWUSR
+             )) < 0) {
             if (mode != O_RDONLY || errno != ENOENT)
-                pa_log_warn("WARNING: failed to open PID file '%s': %s",
-                    fn, pa_cstrerror(errno));
+                pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
             goto fail;
         }
 
@@ -98,8 +107,7 @@ static int open_pid_file(const char *fn, int mode) {
             goto fail;
 
         if (fstat(fd, &st) < 0) {
-            pa_log_warn("WARNING: failed to fstat() PID file '%s': %s",
-                fn, pa_cstrerror(errno));
+            pa_log_warn("Failed to fstat() PID file '%s': %s", fn, pa_cstrerror(errno));
             goto fail;
         }
 
@@ -110,9 +118,9 @@ static int open_pid_file(const char *fn, int mode) {
         if (pa_lock_fd(fd, 0) < 0)
             goto fail;
 
-        if (close(fd) < 0) {
-            pa_log_warn("WARNING: failed to close file '%s': %s",
-                fn, pa_cstrerror(errno));
+        if (pa_close(fd) < 0) {
+            pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
+            fd = -1;
             goto fail;
         }
 
@@ -125,7 +133,7 @@ fail:
 
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
-        close(fd);
+        pa_close(fd);
     }
 
     return -1;
@@ -150,7 +158,7 @@ int pa_pid_file_create(void) {
         goto fail;
 
     if ((pid = read_pid(fn, fd)) == (pid_t) -1)
-        pa_log("corrupt PID file, overwriting.");
+        pa_log_warn("Corrupt PID file, overwriting.");
     else if (pid > 0) {
 #ifdef OS_IS_WIN32
         if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) {
@@ -158,25 +166,24 @@ int pa_pid_file_create(void) {
 #else
         if (kill(pid, 0) >= 0 || errno != ESRCH) {
 #endif
-            pa_log("daemon already running.");
+            pa_log("Daemon already running.");
             goto fail;
         }
 
-        pa_log("stale PID file, overwriting.");
+        pa_log_warn("Stale PID file, overwriting.");
     }
 
     /* Overwrite the current PID file */
     if (lseek(fd, 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, 0) < 0) {
-        pa_log("failed to truncate PID file '%s': %s",
-            fn, pa_cstrerror(errno));
+        pa_log("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
         goto fail;
     }
 
-    snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid());
+    pa_snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid());
     l = strlen(t);
 
     if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) {
-        pa_log("failed to write PID file.");
+        pa_log("Failed to write PID file.");
         goto fail;
     }
 
@@ -185,7 +192,11 @@ int pa_pid_file_create(void) {
 fail:
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
-        close(fd);
+
+        if (pa_close(fd) < 0) {
+            pa_log("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
+            ret = -1;
+        }
     }
 
     return ret;
@@ -201,8 +212,7 @@ int pa_pid_file_remove(void) {
     pa_runtime_path("pid", fn, sizeof(fn));
 
     if ((fd = open_pid_file(fn, O_RDWR)) < 0) {
-        pa_log_warn("WARNING: failed to open PID file '%s': %s",
-            fn, pa_cstrerror(errno));
+        pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
         goto fail;
     }
 
@@ -210,13 +220,12 @@ int pa_pid_file_remove(void) {
         goto fail;
 
     if (pid != getpid()) {
-        pa_log("WARNING: PID file '%s' not mine!", fn);
+        pa_log("PID file '%s' not mine!", fn);
         goto fail;
     }
 
     if (ftruncate(fd, 0) < 0) {
-        pa_log_warn("WARNING: failed to truncate PID file '%s': %s",
-            fn, pa_cstrerror(errno));
+        pa_log_warn("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno));
         goto fail;
     }
 
@@ -227,8 +236,7 @@ int pa_pid_file_remove(void) {
 #endif
 
     if (unlink(fn) < 0) {
-        pa_log_warn("WARNING: failed to remove PID file '%s': %s",
-            fn, pa_cstrerror(errno));
+        pa_log_warn("Failed to remove PID file '%s': %s", fn, pa_cstrerror(errno));
         goto fail;
     }
 
@@ -238,7 +246,11 @@ fail:
 
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
-        close(fd);
+
+        if (pa_close(fd) < 0) {
+            pa_log_warn("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
+            ret = -1;
+        }
     }
 
     return ret;
@@ -280,7 +292,7 @@ fail:
 
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
-        close(fd);
+        pa_close(fd);
     }
 
     return ret;
index 7f6bb2e9e3dd6201dbfd01bc5319c8ed813d6913..e614c9c6254bf26a7da144a78bd08940e57c9bd1 100644 (file)
@@ -149,14 +149,14 @@ int pipe(int filedes[2]) {
     return 0;
 
 error:
-       if (listener >= 0)
-               pa_close(listener);
-       if (filedes[0] >= 0)
-               pa_close(filedes[0]);
-       if (filedes[1] >= 0)
-               pa_close(filedes[0]);
-
-       return -1;
+        if (listener >= 0)
+                pa_close(listener);
+        if (filedes[0] >= 0)
+                pa_close(filedes[0]);
+        if (filedes[1] >= 0)
+                pa_close(filedes[0]);
+
+        return -1;
 }
 
 #endif /* HAVE_PIPE */
index 76edd27a0bb63242cf23b90fc71ea59efbb24dc2..5d3c2d391d3bfee9e87066c1e17d2abb86bcea0f 100644 (file)
@@ -26,7 +26,6 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 
 
 #include <pulsecore/sink-input.h>
 #include <pulsecore/gccmacro.h>
+#include <pulsecore/thread-mq.h>
 
 #include "play-memblockq.h"
 
-static void sink_input_kill(pa_sink_input *i) {
-    pa_memblockq *q;
-    assert(i);
-    assert(i->userdata);
+typedef struct memblockq_stream {
+    pa_msgobject parent;
+    pa_core *core;
+    pa_sink_input *sink_input;
+    pa_memblockq *memblockq;
+} memblockq_stream;
 
-    q = i->userdata;
+enum {
+    MEMBLOCKQ_STREAM_MESSAGE_UNLINK,
+};
 
-    pa_sink_input_disconnect(i);
-    pa_sink_input_unref(i);
+PA_DECLARE_CLASS(memblockq_stream);
+#define MEMBLOCKQ_STREAM(o) (memblockq_stream_cast(o))
+static PA_DEFINE_CHECK_TYPE(memblockq_stream, pa_msgobject);
+
+static void memblockq_stream_unlink(memblockq_stream *u) {
+    pa_assert(u);
+
+    if (!u->sink_input)
+        return;
+
+    pa_sink_input_unlink(u->sink_input);
 
-    pa_memblockq_free(q);
+    pa_sink_input_unref(u->sink_input);
+    u->sink_input = NULL;
+
+    memblockq_stream_unref(u);
 }
 
-static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
-    pa_memblockq *q;
-    assert(i);
-    assert(chunk);
-    assert(i->userdata);
+static void memblockq_stream_free(pa_object *o) {
+    memblockq_stream *u = MEMBLOCKQ_STREAM(o);
+    pa_assert(u);
+
+    memblockq_stream_unlink(u);
 
-    q = i->userdata;
+    if (u->memblockq)
+        pa_memblockq_free(u->memblockq);
 
-    return pa_memblockq_peek(q, chunk);
+    pa_xfree(u);
 }
 
-static void si_kill(PA_GCC_UNUSED pa_mainloop_api *m, void *i) {
-    sink_input_kill(i);
+static int memblockq_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
+    memblockq_stream *u = MEMBLOCKQ_STREAM(o);
+    memblockq_stream_assert_ref(u);
+
+    switch (code) {
+        case MEMBLOCKQ_STREAM_MESSAGE_UNLINK:
+            memblockq_stream_unlink(u);
+            break;
+    }
+
+    return 0;
+}
+
+static void sink_input_kill_cb(pa_sink_input *i) {
+    pa_sink_input_assert_ref(i);
+
+    memblockq_stream_unlink(MEMBLOCKQ_STREAM(i->userdata));
 }
 
-static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t length) {
-    pa_memblockq *q;
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+    memblockq_stream *u;
 
-    assert(i);
-    assert(length > 0);
-    assert( i->userdata);
+    pa_assert(i);
+    pa_assert(chunk);
+    u = MEMBLOCKQ_STREAM(i->userdata);
+    memblockq_stream_assert_ref(u);
 
-    q = i->userdata;
+    if (!u->memblockq)
+        return -1;
 
-    pa_memblockq_drop(q, chunk, length);
+    if (pa_memblockq_peek(u->memblockq, chunk) < 0) {
+        pa_memblockq_free(u->memblockq);
+        u->memblockq = NULL;
+        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), MEMBLOCKQ_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
+        return -1;
+    }
 
-    if (pa_memblockq_get_length(q) <= 0)
-        pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i);
+    return 0;
 }
 
-int pa_play_memblockq(
+static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
+    memblockq_stream *u;
+
+    pa_assert(i);
+    pa_assert(length > 0);
+    u = MEMBLOCKQ_STREAM(i->userdata);
+    memblockq_stream_assert_ref(u);
+
+    if (!u->memblockq)
+        return;
+
+    pa_memblockq_drop(u->memblockq, length);
+}
+
+pa_sink_input* pa_memblockq_sink_input_new(
         pa_sink *sink,
         const char *name,
         const pa_sample_spec *ss,
@@ -88,41 +140,97 @@ int pa_play_memblockq(
         pa_memblockq *q,
         pa_cvolume *volume) {
 
-    pa_sink_input *si;
+    memblockq_stream *u = NULL;
     pa_sink_input_new_data data;
 
-    assert(sink);
-    assert(ss);
-    assert(q);
+    pa_assert(sink);
+    pa_assert(ss);
 
-    if (pa_memblockq_get_length(q) <= 0) {
+    /* We allow creating this stream with no q set, so that it can be
+     * filled in later */
+
+    if (q && pa_memblockq_get_length(q) <= 0) {
         pa_memblockq_free(q);
-        return 0;
+        return NULL;
     }
 
     if (volume && pa_cvolume_is_muted(volume)) {
         pa_memblockq_free(q);
-        return 0;
+        return NULL;
     }
 
+    u = pa_msgobject_new(memblockq_stream);
+    u->parent.parent.free = memblockq_stream_free;
+    u->parent.process_msg = memblockq_stream_process_msg;
+    u->core = sink->core;
+    u->sink_input = NULL;
+    u->memblockq = q;
+
     pa_sink_input_new_data_init(&data);
     data.sink = sink;
     data.name = name;
     data.driver = __FILE__;
-    pa_sink_input_new_data_set_channel_map(&data, map);
     pa_sink_input_new_data_set_sample_spec(&data, ss);
+    pa_sink_input_new_data_set_channel_map(&data, map);
     pa_sink_input_new_data_set_volume(&data, volume);
 
-    if (!(si = pa_sink_input_new(sink->core, &data, 0)))
-        return -1;
+    if (!(u->sink_input = pa_sink_input_new(sink->core, &data, 0)))
+        goto fail;
+
+    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;
+
+    if (q)
+        pa_memblockq_prebuf_disable(q);
 
-    si->peek = sink_input_peek;
-    si->drop = sink_input_drop;
-    si->kill = sink_input_kill;
+    /* The reference to u is dangling here, because we want
+     * to keep this stream around until it is fully played. */
 
-    si->userdata = q;
+    /* This sink input is not "put" yet, i.e. pa_sink_input_put() has
+     * not been called! */
 
-    pa_sink_notify(si->sink);
+    return pa_sink_input_ref(u->sink_input);
+
+fail:
+    if (u)
+        memblockq_stream_unref(u);
+
+    return NULL;
+}
+
+int pa_play_memblockq(
+        pa_sink *sink,
+        const char *name,
+        const pa_sample_spec *ss,
+        const pa_channel_map *map,
+        pa_memblockq *q,
+        pa_cvolume *volume) {
+
+    pa_sink_input *i;
+
+    pa_assert(sink);
+    pa_assert(ss);
+    pa_assert(q);
+
+    if (!(i = pa_memblockq_sink_input_new(sink, name, ss, map, q, volume)))
+        return -1;
+
+    pa_sink_input_put(i);
+    pa_sink_input_unref(i);
 
     return 0;
 }
+
+void pa_memblockq_sink_input_set_queue(pa_sink_input *i, pa_memblockq *q) {
+    memblockq_stream *u;
+
+    pa_sink_input_assert_ref(i);
+    u = MEMBLOCKQ_STREAM(i->userdata);
+    memblockq_stream_assert_ref(u);
+
+    if (u->memblockq)
+        pa_memblockq_free(u->memblockq);
+    u->memblockq = q;
+}
index 8248e8597a1dbc344aadd72f15ce4622fabfea46..d8790316a45a83f766e0de85fea4e92b624a1074 100644 (file)
 #include <pulsecore/sink.h>
 #include <pulsecore/memblockq.h>
 
+pa_sink_input* pa_memblockq_sink_input_new(
+        pa_sink *sink,
+        const char *name,
+        const pa_sample_spec *ss,
+        const pa_channel_map *map,
+        pa_memblockq *q,
+        pa_cvolume *volume);
+
+void pa_memblockq_sink_input_set_queue(pa_sink_input *i, pa_memblockq *q);
+
 int pa_play_memblockq(
     pa_sink *sink,
     const char *name,
index 9132e294519ec20eb90f829289156d3b7e7bb74d..6aaec56722116299d9f5090e3c610a135c298585 100644 (file)
@@ -26,7 +26,6 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 
 
 #include <pulsecore/sink-input.h>
 #include <pulsecore/gccmacro.h>
+#include <pulsecore/thread-mq.h>
 
 #include "play-memchunk.h"
 
-static void sink_input_kill(pa_sink_input *i) {
-    pa_memchunk *c;
-    assert(i && i->userdata);
-    c = i->userdata;
+typedef struct memchunk_stream {
+    pa_msgobject parent;
+    pa_core *core;
+    pa_sink_input *sink_input;
+    pa_memchunk memchunk;
+} memchunk_stream;
 
-    pa_sink_input_disconnect(i);
-    pa_sink_input_unref(i);
+enum {
+    MEMCHUNK_STREAM_MESSAGE_UNLINK,
+};
 
-    pa_memblock_unref(c->memblock);
-    pa_xfree(c);
+PA_DECLARE_CLASS(memchunk_stream);
+#define MEMCHUNK_STREAM(o) (memchunk_stream_cast(o))
+static PA_DEFINE_CHECK_TYPE(memchunk_stream, pa_msgobject);
+
+static void memchunk_stream_unlink(memchunk_stream *u) {
+    pa_assert(u);
+
+    if (!u->sink_input)
+        return;
+
+    pa_sink_input_unlink(u->sink_input);
+
+    pa_sink_input_unref(u->sink_input);
+    u->sink_input = NULL;
+
+    memchunk_stream_unref(u);
 }
 
-static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
-    pa_memchunk *c;
-    assert(i && chunk && i->userdata);
-    c = i->userdata;
+static void memchunk_stream_free(pa_object *o) {
+    memchunk_stream *u = MEMCHUNK_STREAM(o);
+    pa_assert(u);
 
-    if (c->length <= 0)
-        return -1;
+    memchunk_stream_unlink(u);
+
+    if (u->memchunk.memblock)
+        pa_memblock_unref(u->memchunk.memblock);
+
+    pa_xfree(u);
+}
+
+static int memchunk_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
+    memchunk_stream *u = MEMCHUNK_STREAM(o);
+    memchunk_stream_assert_ref(u);
 
-    assert(c->memblock && c->memblock->length);
-    *chunk = *c;
-    pa_memblock_ref(c->memblock);
+    switch (code) {
+        case MEMCHUNK_STREAM_MESSAGE_UNLINK:
+            memchunk_stream_unlink(u);
+            break;
+    }
 
     return 0;
 }
 
-static void si_kill(PA_GCC_UNUSED pa_mainloop_api *m, void *i) {
-    sink_input_kill(i);
+static void sink_input_kill_cb(pa_sink_input *i) {
+    pa_sink_input_assert_ref(i);
+
+    memchunk_stream_unlink(MEMCHUNK_STREAM(i->userdata));
 }
 
-static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t length) {
-    pa_memchunk *c;
-    assert(i && length && i->userdata);
-    c = i->userdata;
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+    memchunk_stream *u;
+
+    pa_assert(i);
+    pa_assert(chunk);
+    u = MEMCHUNK_STREAM(i->userdata);
+    memchunk_stream_assert_ref(u);
 
-    assert(!memcmp(chunk, c, sizeof(chunk)));
-    assert(length <= c->length);
+    if (!u->memchunk.memblock)
+        return -1;
+
+    if (u->memchunk.length <= 0) {
+        pa_memblock_unref(u->memchunk.memblock);
+        u->memchunk.memblock = NULL;
+        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), MEMCHUNK_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
+        return -1;
+    }
 
-    c->length -= length;
-    c->index += length;
+    pa_assert(u->memchunk.memblock);
+    *chunk = u->memchunk;
+    pa_memblock_ref(chunk->memblock);
 
-    if (c->length <= 0)
-        pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i);
+    return 0;
+}
+
+static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
+    memchunk_stream *u;
+
+    pa_assert(i);
+    pa_assert(length > 0);
+    u = MEMCHUNK_STREAM(i->userdata);
+    memchunk_stream_assert_ref(u);
+
+    if (length < u->memchunk.length) {
+        u->memchunk.length -= length;
+        u->memchunk.index += length;
+    } else
+        u->memchunk.length = 0;
 }
 
 int pa_play_memchunk(
@@ -91,38 +145,52 @@ int pa_play_memchunk(
         const pa_memchunk *chunk,
         pa_cvolume *volume) {
 
-    pa_sink_input *si;
-    pa_memchunk *nchunk;
+    memchunk_stream *u = NULL;
     pa_sink_input_new_data data;
 
-    assert(sink);
-    assert(ss);
-    assert(chunk);
+    pa_assert(sink);
+    pa_assert(ss);
+    pa_assert(chunk);
 
     if (volume && pa_cvolume_is_muted(volume))
         return 0;
 
+    pa_memchunk_will_need(chunk);
+
+    u = pa_msgobject_new(memchunk_stream);
+    u->parent.parent.free = memchunk_stream_free;
+    u->parent.process_msg = memchunk_stream_process_msg;
+    u->core = sink->core;
+    u->memchunk = *chunk;
+    pa_memblock_ref(u->memchunk.memblock);
+
     pa_sink_input_new_data_init(&data);
     data.sink = sink;
-    data.name = name;
     data.driver = __FILE__;
+    data.name = name;
     pa_sink_input_new_data_set_sample_spec(&data, ss);
     pa_sink_input_new_data_set_channel_map(&data, map);
     pa_sink_input_new_data_set_volume(&data, volume);
 
-    if (!(si = pa_sink_input_new(sink->core, &data, 0)))
-        return -1;
-
-    si->peek = sink_input_peek;
-    si->drop = sink_input_drop;
-    si->kill = sink_input_kill;
+    if (!(u->sink_input = pa_sink_input_new(sink->core, &data, 0)))
+        goto fail;
 
-    si->userdata = nchunk = pa_xnew(pa_memchunk, 1);
-    *nchunk = *chunk;
+    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;
 
-    pa_memblock_ref(chunk->memblock);
+    pa_sink_input_put(u->sink_input);
 
-    pa_sink_notify(si->sink);
+    /* The reference to u is dangling here, because we want to keep
+     * this stream around until it is fully played. */
 
     return 0;
+
+fail:
+    if (u)
+        memchunk_stream_unref(u);
+
+    return -1;
 }
+
index 2f8eae89bd343fc9548a70d18d7c04be9846502e..288f7dfb2baf1fc85f4bed5fd26fd7eb282e9a20 100644 (file)
@@ -45,7 +45,7 @@
 
 #include "winsock.h"
 
-#ifndef HAVE_SYS_POLL_H
+#ifndef HAVE_POLL_H
 
 #include <pulsecore/core-util.h>
 
index 4a39f0fb989f91f8f10e0917be006a43c23a52f4..cbf748dfb93d8c347cb7e301c8bd5ab2889158d1 100644 (file)
   USA.
 ***/
 
-#include <assert.h>
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
 
 #include <pulse/xmalloc.h>
-
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "props.h"
 
@@ -37,9 +39,11 @@ typedef struct pa_property {
 /* Allocate a new property object */
 static pa_property* property_new(const char *name, void *data) {
     pa_property* p;
-    assert(name && data);
 
-    p = pa_xmalloc(sizeof(pa_property));
+    pa_assert(name);
+    pa_assert(data);
+
+    p = pa_xnew(pa_property, 1);
     p->name = pa_xstrdup(name);
     p->data = data;
 
@@ -48,7 +52,7 @@ static pa_property* property_new(const char *name, void *data) {
 
 /* Free a property object */
 static void property_free(pa_property *p) {
-    assert(p);
+    pa_assert(p);
 
     pa_xfree(p->name);
     pa_xfree(p);
@@ -56,7 +60,10 @@ static void property_free(pa_property *p) {
 
 void* pa_property_get(pa_core *c, const char *name) {
     pa_property *p;
-    assert(c && name && c->properties);
+
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(c->properties);
 
     if (!(p = pa_hashmap_get(c->properties, name)))
         return NULL;
@@ -66,7 +73,11 @@ void* pa_property_get(pa_core *c, const char *name) {
 
 int pa_property_set(pa_core *c, const char *name, void *data) {
     pa_property *p;
-    assert(c && name && data && c->properties);
+
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(data);
+    pa_assert(c->properties);
 
     if (pa_hashmap_get(c->properties, name))
         return -1;
@@ -78,7 +89,10 @@ int pa_property_set(pa_core *c, const char *name, void *data) {
 
 int pa_property_remove(pa_core *c, const char *name) {
     pa_property *p;
-    assert(c && name && c->properties);
+
+    pa_assert(c);
+    pa_assert(name);
+    pa_assert(c->properties);
 
     if (!(p = pa_hashmap_remove(c->properties, name)))
         return -1;
@@ -88,18 +102,18 @@ int pa_property_remove(pa_core *c, const char *name) {
 }
 
 void pa_property_init(pa_core *c) {
-    assert(c);
+    pa_assert(c);
 
     c->properties = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
 }
 
 void pa_property_cleanup(pa_core *c) {
-    assert(c);
+    pa_assert(c);
 
     if (!c->properties)
         return;
 
-    assert(!pa_hashmap_size(c->properties));
+    pa_assert(!pa_hashmap_size(c->properties));
 
     pa_hashmap_free(c->properties, NULL, NULL);
     c->properties = NULL;
@@ -109,14 +123,17 @@ void pa_property_cleanup(pa_core *c) {
 void pa_property_dump(pa_core *c, pa_strbuf *s) {
     void *state = NULL;
     pa_property *p;
-    assert(c && s);
+
+    pa_assert(c);
+    pa_assert(s);
 
     while ((p = pa_hashmap_iterate(c->properties, &state, NULL)))
         pa_strbuf_printf(s, "[%s] -> [%p]\n", p->name, p->data);
 }
 
 int pa_property_replace(pa_core *c, const char *name, void *data) {
-    assert(c && name);
+    pa_assert(c);
+    pa_assert(name);
 
     pa_property_remove(c, name);
     return pa_property_set(c, name, data);
index 1d543ae55031c213ea5ccd9e24c2d24dcea5c726..ceb6ae4d86fbad867ae5bfe106c762ceedd9ca4a 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdlib.h>
 
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/cli.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "protocol-cli.h"
 
@@ -47,7 +47,8 @@ struct pa_protocol_cli {
 
 static void cli_eof_cb(pa_cli*c, void*userdata) {
     pa_protocol_cli *p = userdata;
-    assert(p);
+    pa_assert(p);
+
     pa_idxset_remove_by_data(p->connections, c, NULL);
     pa_cli_free(c);
 }
@@ -55,7 +56,10 @@ static void cli_eof_cb(pa_cli*c, void*userdata) {
 static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) {
     pa_protocol_cli *p = userdata;
     pa_cli *c;
-    assert(s && io && p);
+
+    pa_assert(s);
+    pa_assert(io);
+    pa_assert(p);
 
     if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
         pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
@@ -64,7 +68,6 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
     }
 
     c = pa_cli_new(p->core, io, p->module);
-    assert(c);
     pa_cli_set_eof_callback(c, cli_eof_cb, p);
 
     pa_idxset_put(p->connections, c, NULL);
@@ -72,9 +75,11 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
 
 pa_protocol_cli* pa_protocol_cli_new(pa_core *core, pa_socket_server *server, pa_module *m, PA_GCC_UNUSED pa_modargs *ma) {
     pa_protocol_cli* p;
-    assert(core && server);
 
-    p = pa_xmalloc(sizeof(pa_protocol_cli));
+    pa_core_assert_ref(core);
+    pa_assert(server);
+
+    p = pa_xnew(pa_protocol_cli, 1);
     p->module = m;
     p->core = core;
     p->server = server;
@@ -86,12 +91,13 @@ pa_protocol_cli* pa_protocol_cli_new(pa_core *core, pa_socket_server *server, pa
 }
 
 static void free_connection(void *p, PA_GCC_UNUSED void *userdata) {
-    assert(p);
+    pa_assert(p);
+
     pa_cli_free(p);
 }
 
 void pa_protocol_cli_free(pa_protocol_cli *p) {
-    assert(p);
+    pa_assert(p);
 
     pa_idxset_free(p->connections, free_connection, NULL);
     pa_socket_server_unref(p->server);
index 49a78d410234d922a58f10e0d04ab90c406c50c6..76ba9dd08b0871c39dd33f158d508543e2f8325d 100644 (file)
@@ -29,7 +29,6 @@
 #include <errno.h>
 #include <string.h>
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <limits.h>
 
@@ -53,6 +52,8 @@
 #include <pulsecore/core-util.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/ipacl.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/thread-mq.h>
 
 #include "endianmacros.h"
 
 
 /* This is heavily based on esound's code */
 
-struct connection {
+typedef struct connection {
+    pa_msgobject parent;
+
     uint32_t index;
-    int dead;
+    pa_bool_t dead;
     pa_protocol_esound *protocol;
     pa_iochannel *io;
     pa_client *client;
-    int authorized, swap_byte_order;
+    pa_bool_t authorized, swap_byte_order;
     void *write_data;
     size_t write_data_alloc, write_data_index, write_data_length;
     void *read_data;
@@ -100,6 +103,7 @@ struct connection {
     struct {
         pa_memblock *current_memblock;
         size_t memblock_index, fragment_size;
+        pa_atomic_t missing;
     } playback;
 
     struct {
@@ -109,46 +113,62 @@ struct connection {
     } scache;
 
     pa_time_event *auth_timeout_event;
-};
+} connection;
+
+PA_DECLARE_CLASS(connection);
+#define CONNECTION(o) (connection_cast(o))
+static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject);
 
 struct pa_protocol_esound {
-    int public;
     pa_module *module;
     pa_core *core;
+    int public;
     pa_socket_server *server;
     pa_idxset *connections;
+
     char *sink_name, *source_name;
     unsigned n_player;
     uint8_t esd_key[ESD_KEY_LEN];
     pa_ip_acl *auth_ip_acl;
 };
 
+enum {
+    SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */
+    SINK_INPUT_MESSAGE_DISABLE_PREBUF
+};
+
+enum {
+    CONNECTION_MESSAGE_REQUEST_DATA,
+    CONNECTION_MESSAGE_POST_DATA,
+    CONNECTION_MESSAGE_UNLINK_CONNECTION
+};
+
 typedef struct proto_handler {
     size_t data_length;
-    int (*proc)(struct connection *c, esd_proto_t request, const void *data, size_t length);
+    int (*proc)(connection *c, esd_proto_t request, const void *data, size_t length);
     const char *description;
 } esd_proto_handler_info_t;
 
-static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length);
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk);
+static void sink_input_drop_cb(pa_sink_input *i, size_t length);
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
 static void sink_input_kill_cb(pa_sink_input *i);
-static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i);
+static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
 static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
 
 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
 static void source_output_kill_cb(pa_source_output *o);
 
-static int esd_proto_connect(struct connection *c, esd_proto_t request, const void *data, size_t length);
-static int esd_proto_stream_play(struct connection *c, esd_proto_t request, const void *data, size_t length);
-static int esd_proto_stream_record(struct connection *c, esd_proto_t request, const void *data, size_t length);
-static int esd_proto_get_latency(struct connection *c, esd_proto_t request, const void *data, size_t length);
-static int esd_proto_server_info(struct connection *c, esd_proto_t request, const void *data, size_t length);
-static int esd_proto_all_info(struct connection *c, esd_proto_t request, const void *data, size_t length);
-static int esd_proto_stream_pan(struct connection *c, esd_proto_t request, const void *data, size_t length);
-static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, const void *data, size_t length);
-static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t request, const void *data, size_t length);
-static int esd_proto_sample_get_id(struct connection *c, esd_proto_t request, const void *data, size_t length);
-static int esd_proto_standby_or_resume(struct connection *c, esd_proto_t request, const void *data, size_t length);
+static int esd_proto_connect(connection *c, esd_proto_t request, const void *data, size_t length);
+static int esd_proto_stream_play(connection *c, esd_proto_t request, const void *data, size_t length);
+static int esd_proto_stream_record(connection *c, esd_proto_t request, const void *data, size_t length);
+static int esd_proto_get_latency(connection *c, esd_proto_t request, const void *data, size_t length);
+static int esd_proto_server_info(connection *c, esd_proto_t request, const void *data, size_t length);
+static int esd_proto_all_info(connection *c, esd_proto_t request, const void *data, size_t length);
+static int esd_proto_stream_pan(connection *c, esd_proto_t request, const void *data, size_t length);
+static int esd_proto_sample_cache(connection *c, esd_proto_t request, const void *data, size_t length);
+static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, const void *data, size_t length);
+static int esd_proto_sample_get_id(connection *c, esd_proto_t request, const void *data, size_t length);
+static int esd_proto_standby_or_resume(connection *c, esd_proto_t request, const void *data, size_t length);
 
 /* the big map of protocol handler info */
 static struct proto_handler proto_map[ESD_PROTO_MAX] = {
@@ -185,25 +205,56 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = {
     { 0,                              esd_proto_get_latency, "get latency" }
 };
 
-static void connection_free(struct connection *c) {
-    assert(c);
-    pa_idxset_remove_by_data(c->protocol->connections, c, NULL);
+static void connection_unlink(connection *c) {
+    pa_assert(c);
 
-    if (c->state == ESD_STREAMING_DATA)
-        c->protocol->n_player--;
-
-    pa_client_free(c->client);
+    if (!c->protocol)
+        return;
 
     if (c->sink_input) {
-        pa_sink_input_disconnect(c->sink_input);
+        pa_sink_input_unlink(c->sink_input);
         pa_sink_input_unref(c->sink_input);
+        c->sink_input = NULL;
     }
 
     if (c->source_output) {
-        pa_source_output_disconnect(c->source_output);
+        pa_source_output_unlink(c->source_output);
         pa_source_output_unref(c->source_output);
+        c->source_output = NULL;
     }
 
+    if (c->client) {
+        pa_client_free(c->client);
+        c->client = NULL;
+    }
+
+    if (c->state == ESD_STREAMING_DATA)
+        c->protocol->n_player--;
+
+    if (c->io) {
+        pa_iochannel_free(c->io);
+        c->io = NULL;
+    }
+
+    if (c->defer_event) {
+        c->protocol->core->mainloop->defer_free(c->defer_event);
+        c->defer_event = NULL;
+    }
+
+    if (c->auth_timeout_event) {
+        c->protocol->core->mainloop->time_free(c->auth_timeout_event);
+        c->auth_timeout_event = NULL;
+    }
+
+    pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
+    c->protocol = NULL;
+    connection_unref(c);
+}
+
+static void connection_free(pa_object *obj) {
+    connection *c = CONNECTION(obj);
+    pa_assert(c);
+
     if (c->input_memblockq)
         pa_memblockq_free(c->input_memblockq);
     if (c->output_memblockq)
@@ -215,54 +266,44 @@ static void connection_free(struct connection *c) {
     pa_xfree(c->read_data);
     pa_xfree(c->write_data);
 
-    if (c->io)
-        pa_iochannel_free(c->io);
-
-    if (c->defer_event)
-        c->protocol->core->mainloop->defer_free(c->defer_event);
-
     if (c->scache.memchunk.memblock)
         pa_memblock_unref(c->scache.memchunk.memblock);
     pa_xfree(c->scache.name);
 
-    if (c->auth_timeout_event)
-        c->protocol->core->mainloop->time_free(c->auth_timeout_event);
-
     pa_xfree(c->original_name);
     pa_xfree(c);
 }
 
-static void connection_write_prepare(struct connection *c, size_t length) {
+static void connection_write_prepare(connection *c, size_t length) {
     size_t t;
-    assert(c);
+    pa_assert(c);
 
     t = c->write_data_length+length;
 
     if (c->write_data_alloc < t)
         c->write_data = pa_xrealloc(c->write_data, c->write_data_alloc = t);
 
-    assert(c->write_data);
+    pa_assert(c->write_data);
 }
 
-static void connection_write(struct connection *c, const void *data, size_t length) {
+static void connection_write(connection *c, const void *data, size_t length) {
     size_t i;
-    assert(c);
+    pa_assert(c);
 
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
     c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
 
     connection_write_prepare(c, length);
 
-    assert(c->write_data);
+    pa_assert(c->write_data);
 
     i = c->write_data_length;
     c->write_data_length += length;
 
-    memcpy((char*)c->write_data + i, data, length);
+    memcpy((uint8_t*) c->write_data + i, data, length);
 }
 
-static void format_esd2native(int format, int swap_bytes, pa_sample_spec *ss) {
-    assert(ss);
+static void format_esd2native(int format, pa_bool_t swap_bytes, pa_sample_spec *ss) {
+    pa_assert(ss);
 
     ss->channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1;
     if ((format & ESD_MASK_BITS) == ESD_BITS16)
@@ -289,11 +330,13 @@ static int format_native2esd(pa_sample_spec *ss) {
 
 /*** esound commands ***/
 
-static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
+static int esd_proto_connect(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
     uint32_t ekey;
     int ok;
 
-    assert(length == (ESD_KEY_LEN + sizeof(uint32_t)));
+    connection_assert_ref(c);
+    pa_assert(data);
+    pa_assert(length == (ESD_KEY_LEN + sizeof(uint32_t)));
 
     if (!c->authorized) {
         if (memcmp(data, c->protocol->esd_key, ESD_KEY_LEN) != 0) {
@@ -301,7 +344,7 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req
             return -1;
         }
 
-        c->authorized = 1;
+        c->authorized = TRUE;
         if (c->auth_timeout_event) {
             c->protocol->core->mainloop->time_free(c->auth_timeout_event);
             c->auth_timeout_event = NULL;
@@ -312,11 +355,11 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req
 
     memcpy(&ekey, data, sizeof(uint32_t));
     if (ekey == ESD_ENDIAN_KEY)
-        c->swap_byte_order = 0;
+        c->swap_byte_order = FALSE;
     else if (ekey == ESD_SWAP_ENDIAN_KEY)
-        c->swap_byte_order = 1;
+        c->swap_byte_order = TRUE;
     else {
-        pa_log("client sent invalid endian key");
+        pa_log_warn("Client sent invalid endian key");
         return -1;
     }
 
@@ -325,7 +368,7 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req
     return 0;
 }
 
-static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
+static int esd_proto_stream_play(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
     char name[ESD_NAME_MAX], *utf8_name;
     int32_t format, rate;
     pa_sample_spec ss;
@@ -333,15 +376,17 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t
     pa_sink *sink = NULL;
     pa_sink_input_new_data sdata;
 
-    assert(c && length == (sizeof(int32_t)*2+ESD_NAME_MAX));
+    connection_assert_ref(c);
+    pa_assert(data);
+    pa_assert(length == (sizeof(int32_t)*2+ESD_NAME_MAX));
 
     memcpy(&format, data, sizeof(int32_t));
-    format = MAYBE_INT32_SWAP(c->swap_byte_order, format);
-    data = (const char*)data + sizeof(int32_t);
+    format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
+    data = (const char*) data + sizeof(int32_t);
 
     memcpy(&rate, data, sizeof(int32_t));
-    rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate);
-    data = (const char*)data + sizeof(int32_t);
+    rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
+    data = (const char*) data + sizeof(int32_t);
 
     ss.rate = rate;
     format_esd2native(format, c->swap_byte_order, &ss);
@@ -362,7 +407,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t
 
     c->original_name = pa_xstrdup(name);
 
-    assert(!c->sink_input && !c->input_memblockq);
+    pa_assert(!c->sink_input && !c->input_memblockq);
 
     pa_sink_input_new_data_init(&sdata);
     sdata.sink = sink;
@@ -385,22 +430,26 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t
             l/PLAYBACK_BUFFER_FRAGMENTS,
             NULL);
     pa_iochannel_socket_set_rcvbuf(c->io, l/PLAYBACK_BUFFER_FRAGMENTS*2);
-    c->playback.fragment_size = l/10;
+    c->playback.fragment_size = l/PLAYBACK_BUFFER_FRAGMENTS;
 
+    c->sink_input->parent.process_msg = sink_input_process_msg;
     c->sink_input->peek = sink_input_peek_cb;
     c->sink_input->drop = sink_input_drop_cb;
     c->sink_input->kill = sink_input_kill_cb;
-    c->sink_input->get_latency = sink_input_get_latency_cb;
     c->sink_input->userdata = c;
 
     c->state = ESD_STREAMING_DATA;
 
     c->protocol->n_player++;
 
+    pa_atomic_store(&c->playback.missing, pa_memblockq_missing(c->input_memblockq));
+
+    pa_sink_input_put(c->sink_input);
+
     return 0;
 }
 
-static int esd_proto_stream_record(struct connection *c, esd_proto_t request, const void *data, size_t length) {
+static int esd_proto_stream_record(connection *c, esd_proto_t request, const void *data, size_t length) {
     char name[ESD_NAME_MAX], *utf8_name;
     int32_t format, rate;
     pa_source *source = NULL;
@@ -408,15 +457,17 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co
     size_t l;
     pa_source_output_new_data sdata;
 
-    assert(c && length == (sizeof(int32_t)*2+ESD_NAME_MAX));
+    connection_assert_ref(c);
+    pa_assert(data);
+    pa_assert(length == (sizeof(int32_t)*2+ESD_NAME_MAX));
 
     memcpy(&format, data, sizeof(int32_t));
-    format = MAYBE_INT32_SWAP(c->swap_byte_order, format);
-    data = (const char*)data + sizeof(int32_t);
+    format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
+    data = (const char*) data + sizeof(int32_t);
 
     memcpy(&rate, data, sizeof(int32_t));
-    rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate);
-    data = (const char*)data + sizeof(int32_t);
+    rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
+    data = (const char*) data + sizeof(int32_t);
 
     ss.rate = rate;
     format_esd2native(format, c->swap_byte_order, &ss);
@@ -436,7 +487,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co
             return -1;
         }
     } else {
-        assert(request == ESD_PROTO_STREAM_REC);
+        pa_assert(request == ESD_PROTO_STREAM_REC);
 
         if (c->protocol->source_name) {
             if (!(source = pa_namereg_get(c->protocol->core, c->protocol->source_name, PA_NAMEREG_SOURCE, 1))) {
@@ -455,7 +506,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co
 
     c->original_name = pa_xstrdup(name);
 
-    assert(!c->output_memblockq && !c->source_output);
+    pa_assert(!c->output_memblockq && !c->source_output);
 
     pa_source_output_new_data_init(&sdata);
     sdata.source = source;
@@ -488,14 +539,18 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co
 
     c->protocol->n_player++;
 
+    pa_source_output_put(c->source_output);
+
     return 0;
 }
 
-static int esd_proto_get_latency(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
+static int esd_proto_get_latency(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
     pa_sink *sink;
     int32_t latency;
 
-    assert(c && !data && length == 0);
+    connection_ref(c);
+    pa_assert(!data);
+    pa_assert(length == 0);
 
     if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1)))
         latency = 0;
@@ -504,17 +559,19 @@ static int esd_proto_get_latency(struct connection *c, PA_GCC_UNUSED esd_proto_t
         latency = (int) ((usec*44100)/1000000);
     }
 
-    latency = MAYBE_INT32_SWAP(c->swap_byte_order, latency);
+    latency = PA_MAYBE_INT32_SWAP(c->swap_byte_order, latency);
     connection_write(c, &latency, sizeof(int32_t));
     return 0;
 }
 
-static int esd_proto_server_info(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
+static int esd_proto_server_info(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
     int32_t rate = 44100, format = ESD_STEREO|ESD_BITS16;
     int32_t response;
     pa_sink *sink;
 
-    assert(c && data && length == sizeof(int32_t));
+    connection_ref(c);
+    pa_assert(data);
+    pa_assert(length == sizeof(int32_t));
 
     if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) {
         rate = sink->sample_spec.rate;
@@ -525,22 +582,24 @@ static int esd_proto_server_info(struct connection *c, PA_GCC_UNUSED esd_proto_t
 
     response = 0;
     connection_write(c, &response, sizeof(int32_t));
-    rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate);
+    rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
     connection_write(c, &rate, sizeof(int32_t));
-    format = MAYBE_INT32_SWAP(c->swap_byte_order, format);
+    format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
     connection_write(c, &format, sizeof(int32_t));
 
     return 0;
 }
 
-static int esd_proto_all_info(struct connection *c, esd_proto_t request, const void *data, size_t length) {
+static int esd_proto_all_info(connection *c, esd_proto_t request, const void *data, size_t length) {
     size_t t, k, s;
-    struct connection *conn;
+    connection *conn;
     uint32_t idx = PA_IDXSET_INVALID;
     unsigned nsamples;
     char terminator[sizeof(int32_t)*6+ESD_NAME_MAX];
 
-    assert(c && data && length == sizeof(int32_t));
+    connection_ref(c);
+    pa_assert(data);
+    pa_assert(length == sizeof(int32_t));
 
     if (esd_proto_server_info(c, request, data, length) < 0)
         return -1;
@@ -561,7 +620,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
         if (conn->state != ESD_STREAMING_DATA)
             continue;
 
-        assert(t >= k*2+s);
+        pa_assert(t >= k*2+s);
 
         if (conn->sink_input) {
             pa_cvolume volume = *pa_sink_input_get_volume(conn->sink_input);
@@ -572,7 +631,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
         }
 
         /* id */
-        id = MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) (conn->index+1));
+        id = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) (conn->index+1));
         connection_write(c, &id, sizeof(int32_t));
 
         /* name */
@@ -584,25 +643,25 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
         connection_write(c, name, ESD_NAME_MAX);
 
         /* rate */
-        rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate);
+        rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
         connection_write(c, &rate, sizeof(int32_t));
 
         /* left */
-        lvolume = MAYBE_INT32_SWAP(c->swap_byte_order, lvolume);
+        lvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, lvolume);
         connection_write(c, &lvolume, sizeof(int32_t));
 
         /*right*/
-        rvolume = MAYBE_INT32_SWAP(c->swap_byte_order, rvolume);
+        rvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rvolume);
         connection_write(c, &rvolume, sizeof(int32_t));
 
         /*format*/
-        format = MAYBE_INT32_SWAP(c->swap_byte_order, format);
+        format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
         connection_write(c, &format, sizeof(int32_t));
 
         t -= k;
     }
 
-    assert(t == s*(nsamples+1)+k);
+    pa_assert(t == s*(nsamples+1)+k);
     t -= k;
 
     connection_write(c, terminator, k);
@@ -615,10 +674,10 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
             int32_t id, rate, lvolume, rvolume, format, len;
             char name[ESD_NAME_MAX];
 
-            assert(t >= s*2);
+            pa_assert(t >= s*2);
 
             /* id */
-            id = MAYBE_INT32_SWAP(c->swap_byte_order, (int) (ce->index+1));
+            id = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int) (ce->index+1));
             connection_write(c, &id, sizeof(int32_t));
 
             /* name */
@@ -626,57 +685,59 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
             if (strncmp(ce->name, SCACHE_PREFIX, sizeof(SCACHE_PREFIX)-1) == 0)
                 strncpy(name, ce->name+sizeof(SCACHE_PREFIX)-1, ESD_NAME_MAX);
             else
-                snprintf(name, ESD_NAME_MAX, "native.%s", ce->name);
+                pa_snprintf(name, ESD_NAME_MAX, "native.%s", ce->name);
             connection_write(c, name, ESD_NAME_MAX);
 
             /* rate */
-            rate = MAYBE_UINT32_SWAP(c->swap_byte_order, ce->sample_spec.rate);
+            rate = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, ce->sample_spec.rate);
             connection_write(c, &rate, sizeof(int32_t));
 
             /* left */
-            lvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
+            lvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
             connection_write(c, &lvolume, sizeof(int32_t));
 
             /*right*/
-            rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
+            rvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
             connection_write(c, &rvolume, sizeof(int32_t));
 
             /*format*/
-            format = MAYBE_INT32_SWAP(c->swap_byte_order, format_native2esd(&ce->sample_spec));
+            format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format_native2esd(&ce->sample_spec));
             connection_write(c, &format, sizeof(int32_t));
 
             /*length*/
-            len = MAYBE_INT32_SWAP(c->swap_byte_order, (int) ce->memchunk.length);
+            len = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int) ce->memchunk.length);
             connection_write(c, &len, sizeof(int32_t));
 
             t -= s;
         }
     }
 
-    assert(t == s);
+    pa_assert(t == s);
 
     connection_write(c, terminator, s);
 
     return 0;
 }
 
-static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
+static int esd_proto_stream_pan(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
     int32_t ok;
     uint32_t idx, lvolume, rvolume;
-    struct connection *conn;
+    connection *conn;
 
-    assert(c && data && length == sizeof(int32_t)*3);
+    connection_assert_ref(c);
+    pa_assert(data);
+    pa_assert(length == sizeof(int32_t)*3);
 
     memcpy(&idx, data, sizeof(uint32_t));
-    idx = MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1;
+    idx = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1;
     data = (const char*)data + sizeof(uint32_t);
 
     memcpy(&lvolume, data, sizeof(uint32_t));
-    lvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, lvolume);
+    lvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, lvolume);
     data = (const char*)data + sizeof(uint32_t);
 
     memcpy(&rvolume, data, sizeof(uint32_t));
-    rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume);
+    rvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume);
     data = (const char*)data + sizeof(uint32_t);
 
     if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx)) && conn->sink_input) {
@@ -694,20 +755,22 @@ static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t
     return 0;
 }
 
-static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
+static int esd_proto_sample_cache(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
     pa_sample_spec ss;
     int32_t format, rate, sc_length;
     uint32_t idx;
     char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1];
 
-    assert(c && data && length == (ESD_NAME_MAX+3*sizeof(int32_t)));
+    connection_assert_ref(c);
+    pa_assert(data);
+    pa_assert(length == (ESD_NAME_MAX+3*sizeof(int32_t)));
 
     memcpy(&format, data, sizeof(int32_t));
-    format = MAYBE_INT32_SWAP(c->swap_byte_order, format);
+    format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
     data = (const char*)data + sizeof(int32_t);
 
     memcpy(&rate, data, sizeof(int32_t));
-    rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate);
+    rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
     data = (const char*)data + sizeof(int32_t);
 
     ss.rate = rate;
@@ -716,7 +779,7 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_
     CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification.");
 
     memcpy(&sc_length, data, sizeof(int32_t));
-    sc_length = MAYBE_INT32_SWAP(c->swap_byte_order, sc_length);
+    sc_length = PA_MAYBE_INT32_SWAP(c->swap_byte_order, sc_length);
     data = (const char*)data + sizeof(int32_t);
 
     CHECK_VALIDITY(sc_length <= MAX_CACHE_SAMPLE_SIZE, "Sample too large (%d bytes).", (int)sc_length);
@@ -727,12 +790,12 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_
 
     CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name.");
 
-    assert(!c->scache.memchunk.memblock);
+    pa_assert(!c->scache.memchunk.memblock);
     c->scache.memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, sc_length);
     c->scache.memchunk.index = 0;
     c->scache.memchunk.length = sc_length;
     c->scache.sample_spec = ss;
-    assert(!c->scache.name);
+    pa_assert(!c->scache.name);
     c->scache.name = pa_xstrdup(name);
 
     c->state = ESD_CACHING_SAMPLE;
@@ -745,12 +808,14 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_
     return 0;
 }
 
-static int esd_proto_sample_get_id(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
+static int esd_proto_sample_get_id(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
     int32_t ok;
     uint32_t idx;
     char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1];
 
-    assert(c && data && length == ESD_NAME_MAX);
+    connection_assert_ref(c);
+    pa_assert(data);
+    pa_assert(length == ESD_NAME_MAX);
 
     strcpy(name, SCACHE_PREFIX);
     strncpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX);
@@ -767,15 +832,17 @@ static int esd_proto_sample_get_id(struct connection *c, PA_GCC_UNUSED esd_proto
     return 0;
 }
 
-static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t request, const void *data, size_t length) {
+static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, const void *data, size_t length) {
     int32_t ok;
     const char *name;
     uint32_t idx;
 
-    assert(c && data && length == sizeof(int32_t));
+    connection_assert_ref(c);
+    pa_assert(data);
+    pa_assert(length == sizeof(int32_t));
 
     memcpy(&idx, data, sizeof(uint32_t));
-    idx = MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1;
+    idx = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1;
 
     ok = 0;
 
@@ -787,7 +854,7 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque
                 if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM) >= 0)
                     ok = idx + 1;
         } else {
-            assert(request == ESD_PROTO_SAMPLE_FREE);
+            pa_assert(request == ESD_PROTO_SAMPLE_FREE);
 
             if (pa_scache_remove_item(c->protocol->core, name) >= 0)
                 ok = idx + 1;
@@ -799,9 +866,11 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque
     return 0;
 }
 
-static int esd_proto_standby_or_resume(struct connection *c, PA_GCC_UNUSED esd_proto_t request, PA_GCC_UNUSED const void *data, PA_GCC_UNUSED size_t length) {
+static int esd_proto_standby_or_resume(connection *c, PA_GCC_UNUSED esd_proto_t request, PA_GCC_UNUSED const void *data, PA_GCC_UNUSED size_t length) {
     int32_t ok;
 
+    connection_assert_ref(c);
+
     connection_write_prepare(c, sizeof(int32_t) * 2);
 
     ok = 1;
@@ -814,20 +883,21 @@ static int esd_proto_standby_or_resume(struct connection *c, PA_GCC_UNUSED esd_p
 /*** client callbacks ***/
 
 static void client_kill_cb(pa_client *c) {
-    assert(c && c->userdata);
-    connection_free(c->userdata);
+    pa_assert(c);
+
+    connection_unlink(CONNECTION(c->userdata));
 }
 
 /*** pa_iochannel callbacks ***/
 
-static int do_read(struct connection *c) {
-    assert(c && c->io);
+static int do_read(connection *c) {
+    connection_assert_ref(c);
 
-/*      pa_log("READ");  */
+/*     pa_log("READ"); */
 
     if (c->state == ESD_NEXT_REQUEST) {
         ssize_t r;
-        assert(c->read_data_length < sizeof(c->request));
+        pa_assert(c->read_data_length < sizeof(c->request));
 
         if ((r = pa_iochannel_read(c->io, ((uint8_t*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) {
             pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
@@ -837,7 +907,7 @@ static int do_read(struct connection *c) {
         if ((c->read_data_length+= r) >= sizeof(c->request)) {
             struct proto_handler *handler;
 
-            c->request = MAYBE_INT32_SWAP(c->swap_byte_order, c->request);
+            c->request = PA_MAYBE_INT32_SWAP(c->swap_byte_order, c->request);
 
             if (c->request < ESD_PROTO_CONNECT || c->request > ESD_PROTO_MAX) {
                 pa_log("recieved invalid request.");
@@ -862,7 +932,7 @@ static int do_read(struct connection *c) {
             } else {
                 if (c->read_data_alloc < handler->data_length)
                     c->read_data = pa_xrealloc(c->read_data, c->read_data_alloc = handler->data_length);
-                assert(c->read_data);
+                pa_assert(c->read_data);
 
                 c->state = ESD_NEEDS_REQDATA;
                 c->read_data_length = 0;
@@ -873,18 +943,21 @@ static int do_read(struct connection *c) {
         ssize_t r;
         struct proto_handler *handler = proto_map+c->request;
 
-        assert(handler->proc);
+        pa_assert(handler->proc);
 
-        assert(c->read_data && c->read_data_length < handler->data_length);
+        pa_assert(c->read_data && c->read_data_length < handler->data_length);
 
         if ((r = pa_iochannel_read(c->io, (uint8_t*) c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) {
+            if (r < 0 && (errno == EINTR || errno == EAGAIN))
+                return 0;
+
             pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
             return -1;
         }
 
         if ((c->read_data_length += r) >= handler->data_length) {
             size_t l = c->read_data_length;
-            assert(handler->proc);
+            pa_assert(handler->proc);
 
             c->state = ESD_NEXT_REQUEST;
             c->read_data_length = 0;
@@ -894,16 +967,26 @@ static int do_read(struct connection *c) {
         }
     } else if (c->state == ESD_CACHING_SAMPLE) {
         ssize_t r;
+        void *p;
 
-        assert(c->scache.memchunk.memblock && c->scache.name && c->scache.memchunk.index < c->scache.memchunk.length);
+        pa_assert(c->scache.memchunk.memblock);
+        pa_assert(c->scache.name);
+        pa_assert(c->scache.memchunk.index < c->scache.memchunk.length);
+
+        p = pa_memblock_acquire(c->scache.memchunk.memblock);
+        r = pa_iochannel_read(c->io, (uint8_t*) p+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index);
+        pa_memblock_release(c->scache.memchunk.memblock);
+
+        if (r <= 0) {
+            if (r < 0 && (errno == EINTR || errno == EAGAIN))
+                return 0;
 
-        if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache.memchunk.memblock->data+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) {
             pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
             return -1;
         }
 
         c->scache.memchunk.index += r;
-        assert(c->scache.memchunk.index <= c->scache.memchunk.length);
+        pa_assert(c->scache.memchunk.index <= c->scache.memchunk.length);
 
         if (c->scache.memchunk.index == c->scache.memchunk.length) {
             uint32_t idx;
@@ -928,31 +1011,39 @@ static int do_read(struct connection *c) {
         pa_memchunk chunk;
         ssize_t r;
         size_t l;
+        void *p;
 
-        assert(c->input_memblockq);
+        pa_assert(c->input_memblockq);
 
 /*         pa_log("STREAMING_DATA"); */
 
-        if (!(l = pa_memblockq_missing(c->input_memblockq)))
+        if (!(l = pa_atomic_load(&c->playback.missing)))
             return 0;
 
         if (l > c->playback.fragment_size)
             l = c->playback.fragment_size;
 
         if (c->playback.current_memblock)
-            if (c->playback.current_memblock->length - c->playback.memblock_index < l) {
+            if (pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index < l) {
                 pa_memblock_unref(c->playback.current_memblock);
                 c->playback.current_memblock = NULL;
                 c->playback.memblock_index = 0;
             }
 
         if (!c->playback.current_memblock) {
-            c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2);
-            assert(c->playback.current_memblock && c->playback.current_memblock->length >= l);
+            pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2));
             c->playback.memblock_index = 0;
         }
 
-        if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) {
+        p = pa_memblock_acquire(c->playback.current_memblock);
+        r = pa_iochannel_read(c->io, (uint8_t*) p+c->playback.memblock_index, l);
+        pa_memblock_release(c->playback.current_memblock);
+
+        if (r <= 0) {
+
+            if (r < 0 && (errno == EINTR || errno == EAGAIN))
+                return 0;
+
             pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
             return -1;
         }
@@ -960,29 +1051,30 @@ static int do_read(struct connection *c) {
         chunk.memblock = c->playback.current_memblock;
         chunk.index = c->playback.memblock_index;
         chunk.length = r;
-        assert(chunk.memblock);
 
         c->playback.memblock_index += r;
 
-        assert(c->input_memblockq);
-        pa_memblockq_push_align(c->input_memblockq, &chunk);
-        assert(c->sink_input);
-        pa_sink_notify(c->sink_input->sink);
+        pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, &chunk, NULL);
+        pa_atomic_sub(&c->playback.missing, r);
     }
 
     return 0;
 }
 
-static int do_write(struct connection *c) {
-    assert(c && c->io);
+static int do_write(connection *c) {
+    connection_assert_ref(c);
 
 /*     pa_log("WRITE"); */
 
     if (c->write_data_length) {
         ssize_t r;
 
-        assert(c->write_data_index < c->write_data_length);
+        pa_assert(c->write_data_index < c->write_data_length);
         if ((r = pa_iochannel_write(c->io, (uint8_t*) c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) {
+
+            if (r < 0 && (errno == EINTR || errno == EAGAIN))
+                return 0;
+
             pa_log("write(): %s", pa_cstrerror(errno));
             return -1;
         }
@@ -993,32 +1085,38 @@ static int do_write(struct connection *c) {
     } else if (c->state == ESD_STREAMING_DATA && c->source_output) {
         pa_memchunk chunk;
         ssize_t r;
+        void *p;
 
-        assert(c->output_memblockq);
         if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0)
             return 0;
 
-        assert(chunk.memblock && chunk.length);
+        pa_assert(chunk.memblock);
+        pa_assert(chunk.length);
+
+        p = pa_memblock_acquire(chunk.memblock);
+        r = pa_iochannel_write(c->io, (uint8_t*) p+chunk.index, chunk.length);
+        pa_memblock_release(chunk.memblock);
+
+        pa_memblock_unref(chunk.memblock);
+
+        if (r < 0) {
+
+            if (r < 0 && (errno == EINTR || errno == EAGAIN))
+                return 0;
 
-        if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) {
-            pa_memblock_unref(chunk.memblock);
             pa_log("write(): %s", pa_cstrerror(errno));
             return -1;
         }
 
-        pa_memblockq_drop(c->output_memblockq, &chunk, r);
-        pa_memblock_unref(chunk.memblock);
-
-        pa_source_notify(c->source_output->source);
+        pa_memblockq_drop(c->output_memblockq, r);
     }
 
     return 0;
 }
 
-static void do_work(struct connection *c) {
-    assert(c);
+static void do_work(connection *c) {
+    connection_assert_ref(c);
 
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
     c->protocol->core->mainloop->defer_enable(c->defer_event, 0);
 
     if (c->dead)
@@ -1044,122 +1142,196 @@ static void do_work(struct connection *c) {
 fail:
 
     if (c->state == ESD_STREAMING_DATA && c->sink_input) {
-        c->dead = 1;
+        c->dead = TRUE;
 
         pa_iochannel_free(c->io);
         c->io = NULL;
 
-        pa_memblockq_prebuf_disable(c->input_memblockq);
-        pa_sink_notify(c->sink_input->sink);
+        pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_DISABLE_PREBUF, NULL, 0, NULL, NULL);
     } else
-        connection_free(c);
+        connection_unlink(c);
 }
 
 static void io_callback(pa_iochannel*io, void *userdata) {
-    struct connection *c = userdata;
-    assert(io && c && c->io == io);
+    connection *c = CONNECTION(userdata);
+
+    connection_assert_ref(c);
+    pa_assert(io);
 
     do_work(c);
 }
 
-/*** defer callback ***/
-
 static void defer_callback(pa_mainloop_api*a, pa_defer_event *e, void *userdata) {
-    struct connection *c = userdata;
-    assert(a && c && c->defer_event == e);
+    connection *c = CONNECTION(userdata);
 
-/*     pa_log("DEFER"); */
+    connection_assert_ref(c);
+    pa_assert(e);
 
     do_work(c);
 }
 
-/*** sink_input callbacks ***/
+static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
+    connection *c = CONNECTION(o);
+    connection_assert_ref(c);
 
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
-    struct connection*c;
-    assert(i && i->userdata && chunk);
-    c = i->userdata;
+    switch (code) {
+        case CONNECTION_MESSAGE_REQUEST_DATA:
+            do_work(c);
+            break;
 
-    if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) {
+        case CONNECTION_MESSAGE_POST_DATA:
+/*             pa_log("got data %u", chunk->length); */
+            pa_memblockq_push_align(c->output_memblockq, chunk);
+            do_work(c);
+            break;
 
-        if (c->dead)
-            connection_free(c);
-
-        return -1;
+        case CONNECTION_MESSAGE_UNLINK_CONNECTION:
+            connection_unlink(c);
+            break;
     }
 
     return 0;
 }
 
-static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
-    struct connection*c = i->userdata;
-    assert(i && c && length);
+/*** sink_input callbacks ***/
+
+/* Called from thread context */
+static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
+    pa_sink_input *i = PA_SINK_INPUT(o);
+    connection*c;
+
+    pa_sink_input_assert_ref(i);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
+
+    switch (code) {
+
+        case SINK_INPUT_MESSAGE_POST_DATA: {
+            pa_assert(chunk);
+
+            /* New data from the main loop */
+            pa_memblockq_push_align(c->input_memblockq, chunk);
+
+/*             pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */
+
+            return 0;
+        }
 
-/*     pa_log("DROP"); */
+        case SINK_INPUT_MESSAGE_DISABLE_PREBUF: {
+            pa_memblockq_prebuf_disable(c->input_memblockq);
+            return 0;
+        }
 
-    pa_memblockq_drop(c->input_memblockq, chunk, length);
+        case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
+            pa_usec_t *r = userdata;
 
-    /* do something */
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
+            *r = pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec);
 
-    if (!c->dead)
-        c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
+            /* Fall through, the default handler will add in the extra
+             * latency added by the resampler */
+        }
 
-/*     assert(pa_memblockq_get_length(c->input_memblockq) > 2048); */
+        default:
+            return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
+    }
 }
 
-static void sink_input_kill_cb(pa_sink_input *i) {
-    assert(i && i->userdata);
-    connection_free((struct connection *) i->userdata);
+/* Called from thread context */
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+    connection*c;
+    int r;
+
+    pa_assert(i);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
+    pa_assert(chunk);
+
+    if ((r = pa_memblockq_peek(c->input_memblockq, chunk)) < 0 && c->dead)
+        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
+
+    return r;
+}
+
+/* Called from thread context */
+static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
+    connection*c;
+    size_t old, new;
+
+    pa_assert(i);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
+    pa_assert(length);
+
+    /*     pa_log("DROP"); */
+
+    old = pa_memblockq_missing(c->input_memblockq);
+    pa_memblockq_drop(c->input_memblockq, length);
+    new = pa_memblockq_missing(c->input_memblockq);
+
+    if (new > old) {
+        if (pa_atomic_add(&c->playback.missing, new - old) <= 0)
+            pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
+    }
 }
 
-static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) {
-    struct connection*c = i->userdata;
-    assert(i && c);
-    return pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec);
+static void sink_input_kill_cb(pa_sink_input *i) {
+    pa_sink_input_assert_ref(i);
+
+    connection_unlink(CONNECTION(i->userdata));
 }
 
 /*** source_output callbacks ***/
 
+/* Called from thread context */
 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
-    struct connection *c = o->userdata;
-    assert(o && c && chunk);
-
-    pa_memblockq_push(c->output_memblockq, chunk);
+    connection *c;
 
-    /* do something */
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
+    pa_assert(o);
+    c = CONNECTION(o->userdata);
+    pa_assert(c);
+    pa_assert(chunk);
 
-    if (!c->dead)
-        c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
+    pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
 }
 
 static void source_output_kill_cb(pa_source_output *o) {
-    assert(o && o->userdata);
-    connection_free((struct connection *) o->userdata);
+    pa_source_output_assert_ref(o);
+
+    connection_unlink(CONNECTION(o->userdata));
 }
 
 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
-    struct connection*c = o->userdata;
-    assert(o && c);
+    connection*c;
+
+    pa_assert(o);
+    c = CONNECTION(o->userdata);
+    pa_assert(c);
+
     return pa_bytes_to_usec(pa_memblockq_get_length(c->output_memblockq), &c->source_output->sample_spec);
 }
 
 /*** socket server callback ***/
 
 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) {
-    struct connection *c = userdata;
-    assert(m && tv && c && c->auth_timeout_event == e);
+    connection *c = CONNECTION(userdata);
+
+    pa_assert(m);
+    pa_assert(tv);
+    connection_assert_ref(c);
+    pa_assert(c->auth_timeout_event == e);
 
     if (!c->authorized)
-        connection_free(c);
+        connection_unlink(c);
 }
 
 static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) {
-    struct connection *c;
+    connection *c;
     pa_protocol_esound *p = userdata;
     char cname[256], pname[128];
-    assert(s && io && p);
+
+    pa_assert(s);
+    pa_assert(io);
+    pa_assert(p);
 
     if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
         pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
@@ -1167,23 +1339,23 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
         return;
     }
 
-    c = pa_xnew(struct connection, 1);
+    c = pa_msgobject_new(connection);
+    c->parent.parent.free = connection_free;
+    c->parent.process_msg = connection_process_msg;
     c->protocol = p;
     c->io = io;
     pa_iochannel_set_callback(c->io, io_callback, c);
 
     pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
-    snprintf(cname, sizeof(cname), "EsounD client (%s)", pname);
-    assert(p->core);
+    pa_snprintf(cname, sizeof(cname), "EsounD client (%s)", pname);
     c->client = pa_client_new(p->core, __FILE__, cname);
-    assert(c->client);
     c->client->owner = p->module;
     c->client->kill = client_kill_cb;
     c->client->userdata = c;
 
     c->authorized = !!p->public;
-    c->swap_byte_order = 0;
-    c->dead = 0;
+    c->swap_byte_order = FALSE;
+    c->dead = FALSE;
 
     c->read_data_length = 0;
     c->read_data = pa_xmalloc(c->read_data_alloc = proto_map[ESD_PROTO_CONNECT].data_length);
@@ -1203,6 +1375,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
     c->playback.current_memblock = NULL;
     c->playback.memblock_index = 0;
     c->playback.fragment_size = 0;
+    pa_atomic_store(&c->playback.missing, 0);
 
     c->scache.memchunk.length = c->scache.memchunk.index = 0;
     c->scache.memchunk.memblock = NULL;
@@ -1212,7 +1385,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
 
     if (!c->authorized && p->auth_ip_acl && pa_ip_acl_check(p->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
         pa_log_info("Client authenticated by IP ACL.");
-        c->authorized = 1;
+        c->authorized = TRUE;
     }
 
     if (!c->authorized) {
@@ -1224,7 +1397,6 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
         c->auth_timeout_event = NULL;
 
     c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c);
-    assert(c->defer_event);
     p->core->mainloop->defer_enable(c->defer_event, 0);
 
     pa_idxset_put(p->connections, c, &c->index);
@@ -1233,22 +1405,22 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
 /*** entry points ***/
 
 pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *server, pa_module *m, pa_modargs *ma) {
-    pa_protocol_esound *p;
+    pa_protocol_esound *p = NULL;
     int public = 0;
     const char *acl;
 
-    assert(core);
-    assert(server);
-    assert(m);
-    assert(ma);
-
-    p = pa_xnew(pa_protocol_esound, 1);
+    pa_assert(core);
+    pa_assert(server);
+    pa_assert(m);
+    pa_assert(ma);
 
     if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) {
         pa_log("auth-anonymous= expects a boolean argument.");
         goto fail;
     }
 
+    p = pa_xnew(pa_protocol_esound, 1);
+
     if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", DEFAULT_COOKIE_FILE), p->esd_key, sizeof(p->esd_key)) < 0)
         goto fail;
 
@@ -1261,13 +1433,12 @@ pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *serve
     } else
         p->auth_ip_acl = NULL;
 
+    p->core = core;
     p->module = m;
     p->public = public;
     p->server = server;
     pa_socket_server_set_callback(p->server, on_connection, p);
-    p->core = core;
     p->connections = pa_idxset_new(NULL, NULL);
-    assert(p->connections);
 
     p->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
     p->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL));
@@ -1281,17 +1452,20 @@ fail:
 }
 
 void pa_protocol_esound_free(pa_protocol_esound *p) {
-    struct connection *c;
-    assert(p);
+    connection *c;
+    pa_assert(p);
 
     while ((c = pa_idxset_first(p->connections, NULL)))
-        connection_free(c);
-
+        connection_unlink(c);
     pa_idxset_free(p->connections, NULL, NULL);
+
     pa_socket_server_unref(p->server);
 
     if (p->auth_ip_acl)
         pa_ip_acl_free(p->auth_ip_acl);
 
+    pa_xfree(p->sink_name);
+    pa_xfree(p->source_name);
+
     pa_xfree(p);
 }
index 3541721aa4264d28a4ebc04cae05f07539514394..d91ae142e2bbb1ceef37f731c9bc4dc5ae88e9e0 100644 (file)
@@ -25,7 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -34,6 +33,7 @@
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/ioline.h>
+#include <pulsecore/macro.h>
 #include <pulsecore/log.h>
 #include <pulsecore/namereg.h>
 #include <pulsecore/cli-text.h>
@@ -65,11 +65,12 @@ struct pa_protocol_http {
 
 static void http_response(struct connection *c, int code, const char *msg, const char *mime) {
     char s[256];
-    assert(c);
-    assert(msg);
-    assert(mime);
 
-    snprintf(s, sizeof(s),
+    pa_assert(c);
+    pa_assert(msg);
+    pa_assert(mime);
+
+    pa_snprintf(s, sizeof(s),
              "HTTP/1.0 %i %s\n"
              "Connection: close\n"
              "Content-Type: %s\n"
@@ -83,14 +84,14 @@ static void http_response(struct connection *c, int code, const char *msg, const
 
 static void http_message(struct connection *c, int code, const char *msg, const char *text) {
     char s[256];
-    assert(c);
+    pa_assert(c);
 
     http_response(c, code, msg, "text/html");
 
     if (!text)
         text = msg;
 
-    snprintf(s, sizeof(s),
+    pa_snprintf(s, sizeof(s),
              "<?xml version=\"1.0\"?>\n"
              "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
              "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title>%s</title></head>\n"
@@ -103,21 +104,22 @@ static void http_message(struct connection *c, int code, const char *msg, const
 
 
 static void connection_free(struct connection *c, int del) {
-    assert(c);
+    pa_assert(c);
 
     if (c->url)
         pa_xfree(c->url);
 
     if (del)
         pa_idxset_remove_by_data(c->protocol->connections, c, NULL);
+
     pa_ioline_unref(c->line);
     pa_xfree(c);
 }
 
 static void line_callback(pa_ioline *line, const char *s, void *userdata) {
     struct connection *c = userdata;
-    assert(line);
-    assert(c);
+    pa_assert(line);
+    pa_assert(c);
 
     if (!s) {
         /* EOF */
@@ -223,7 +225,10 @@ fail:
 static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) {
     pa_protocol_http *p = userdata;
     struct connection *c;
-    assert(s && io && p);
+
+    pa_assert(s);
+    pa_assert(io);
+    pa_assert(p);
 
     if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
         pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
@@ -231,7 +236,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
         return;
     }
 
-    c = pa_xmalloc(sizeof(struct connection));
+    c = pa_xnew(struct connection, 1);
     c->protocol = p;
     c->line = pa_ioline_new(io);
     c->state = REQUEST_LINE;
@@ -243,9 +248,11 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
 
 pa_protocol_http* pa_protocol_http_new(pa_core *core, pa_socket_server *server, pa_module *m, PA_GCC_UNUSED pa_modargs *ma) {
     pa_protocol_http* p;
-    assert(core && server);
 
-    p = pa_xmalloc(sizeof(pa_protocol_http));
+    pa_core_assert_ref(core);
+    pa_assert(server);
+
+    p = pa_xnew(pa_protocol_http, 1);
     p->module = m;
     p->core = core;
     p->server = server;
@@ -257,12 +264,12 @@ pa_protocol_http* pa_protocol_http_new(pa_core *core, pa_socket_server *server,
 }
 
 static void free_connection(void *p, PA_GCC_UNUSED void *userdata) {
-    assert(p);
+    pa_assert(p);
     connection_free(p, 0);
 }
 
 void pa_protocol_http_free(pa_protocol_http *p) {
-    assert(p);
+    pa_assert(p);
 
     pa_idxset_free(p->connections, free_connection, NULL);
     pa_socket_server_unref(p->server);
index dd41b3d569b93dc862a45c1af58995dea9dfbd0a..9ae0f08379db8884ce306cbc78fcd2ad499fe9bd 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <string.h>
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <unistd.h>
 
@@ -61,6 +60,7 @@
 #include <pulsecore/creds.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/ipacl.h>
+#include <pulsecore/thread-mq.h>
 
 #include "protocol-native.h"
 
 
 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
 
-struct connection;
+typedef struct connection connection;
 struct pa_protocol_native;
 
-struct record_stream {
-    struct connection *connection;
+typedef struct record_stream {
+    pa_msgobject parent;
+
+    connection *connection;
     uint32_t index;
+
     pa_source_output *source_output;
     pa_memblockq *memblockq;
     size_t fragment_size;
-};
+} record_stream;
+
+typedef struct output_stream {
+    pa_msgobject parent;
+} output_stream;
 
-struct playback_stream {
-    int type;
-    struct connection *connection;
+typedef struct playback_stream {
+    output_stream parent;
+
+    connection *connection;
     uint32_t index;
+
     pa_sink_input *sink_input;
     pa_memblockq *memblockq;
-    size_t requested_bytes;
     int drain_request;
     uint32_t drain_tag;
     uint32_t syncid;
     int underrun;
 
-    /* Sync group members */
-    PA_LLIST_FIELDS(struct playback_stream);
-};
+    pa_atomic_t missing;
+    size_t minreq;
+
+    /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
+    int64_t read_index, write_index;
+    size_t resampled_chunk_length;
+} playback_stream;
 
-struct upload_stream {
-    int type;
-    struct connection *connection;
+typedef struct upload_stream {
+    output_stream parent;
+
+    connection *connection;
     uint32_t index;
+
     pa_memchunk memchunk;
     size_t length;
     char *name;
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
-};
-
-struct output_stream {
-    int type;
-};
-
-enum {
-    UPLOAD_STREAM,
-    PLAYBACK_STREAM
-};
+} upload_stream;
 
 struct connection {
+    pa_msgobject parent;
+
     int authorized;
     uint32_t version;
     pa_protocol_native *protocol;
@@ -132,10 +139,30 @@ struct connection {
     pa_time_event *auth_timeout_event;
 };
 
+PA_DECLARE_CLASS(record_stream);
+#define RECORD_STREAM(o) (record_stream_cast(o))
+static PA_DEFINE_CHECK_TYPE(record_stream, pa_msgobject);
+
+PA_DECLARE_CLASS(output_stream);
+#define OUTPUT_STREAM(o) (output_stream_cast(o))
+static PA_DEFINE_CHECK_TYPE(output_stream, pa_msgobject);
+
+PA_DECLARE_CLASS(playback_stream);
+#define PLAYBACK_STREAM(o) (playback_stream_cast(o))
+static PA_DEFINE_CHECK_TYPE(playback_stream, output_stream);
+
+PA_DECLARE_CLASS(upload_stream);
+#define UPLOAD_STREAM(o) (upload_stream_cast(o))
+static PA_DEFINE_CHECK_TYPE(upload_stream, output_stream);
+
+PA_DECLARE_CLASS(connection);
+#define CONNECTION(o) (connection_cast(o))
+static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject);
+
 struct pa_protocol_native {
     pa_module *module;
-    int public;
     pa_core *core;
+    int public;
     pa_socket_server *server;
     pa_idxset *connections;
     uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
@@ -146,17 +173,45 @@ struct pa_protocol_native {
     pa_ip_acl *auth_ip_acl;
 };
 
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk);
-static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length);
+enum {
+    SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */
+    SINK_INPUT_MESSAGE_DRAIN, /* disabled prebuf, get playback started. */
+    SINK_INPUT_MESSAGE_FLUSH,
+    SINK_INPUT_MESSAGE_TRIGGER,
+    SINK_INPUT_MESSAGE_SEEK,
+    SINK_INPUT_MESSAGE_PREBUF_FORCE,
+    SINK_INPUT_MESSAGE_UPDATE_LATENCY
+};
+
+enum {
+    PLAYBACK_STREAM_MESSAGE_REQUEST_DATA,      /* data requested from sink input from the main loop */
+    PLAYBACK_STREAM_MESSAGE_UNDERFLOW,
+    PLAYBACK_STREAM_MESSAGE_OVERFLOW,
+    PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
+};
+
+enum {
+    RECORD_STREAM_MESSAGE_POST_DATA         /* data from source output to main loop */
+};
+
+enum {
+    CONNECTION_MESSAGE_RELEASE,
+    CONNECTION_MESSAGE_REVOKE
+};
+
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
+static void sink_input_drop_cb(pa_sink_input *i, size_t length);
 static void sink_input_kill_cb(pa_sink_input *i);
-static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i);
 
+static void send_memblock(connection *c);
 static void request_bytes(struct playback_stream*s);
 
 static void source_output_kill_cb(pa_source_output *o);
 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
 static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
 
+static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
+
 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
@@ -179,8 +234,7 @@ static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag,
 static void command_set_volume(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_set_mute(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
-static void command_flush_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
-static void command_trigger_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
+static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
@@ -193,6 +247,7 @@ static void command_get_autoload_info_list(pa_pdispatch *pd, uint32_t command, u
 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
+static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 
 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_ERROR] = NULL,
@@ -239,12 +294,16 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume,
 
     [PA_COMMAND_SET_SINK_MUTE] = command_set_mute,
+    [PA_COMMAND_SET_SINK_INPUT_MUTE] = command_set_mute,
     [PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute,
 
+    [PA_COMMAND_SUSPEND_SINK] = command_suspend,
+    [PA_COMMAND_SUSPEND_SOURCE] = command_suspend,
+
     [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream,
-    [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_flush_playback_stream,
-    [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream,
-    [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream,
+    [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
+    [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
+    [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
 
     [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream,
     [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream,
@@ -269,74 +328,146 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
 
 /* structure management */
 
-static struct upload_stream* upload_stream_new(
-    struct connection *c,
-    const pa_sample_spec *ss,
-    const pa_channel_map *map,
-    const char *name, size_t length) {
+static void upload_stream_unlink(upload_stream *s) {
+    pa_assert(s);
+
+    if (!s->connection)
+        return;
+
+    pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
+    s->connection = NULL;
+    upload_stream_unref(s);
+}
+
+static void upload_stream_free(pa_object *o) {
+    upload_stream *s = UPLOAD_STREAM(o);
+    pa_assert(s);
+
+    upload_stream_unlink(s);
+
+    pa_xfree(s->name);
 
-    struct upload_stream *s;
-    assert(c && ss && name && length);
+    if (s->memchunk.memblock)
+        pa_memblock_unref(s->memchunk.memblock);
 
-    s = pa_xnew(struct upload_stream, 1);
-    s->type = UPLOAD_STREAM;
+    pa_xfree(s);
+}
+
+static upload_stream* upload_stream_new(
+        connection *c,
+        const pa_sample_spec *ss,
+        const pa_channel_map *map,
+        const char *name, size_t length) {
+
+    upload_stream *s;
+
+    pa_assert(c);
+    pa_assert(ss);
+    pa_assert(name);
+    pa_assert(length > 0);
+
+    s = pa_msgobject_new(upload_stream);
+    s->parent.parent.parent.free = upload_stream_free;
     s->connection = c;
     s->sample_spec = *ss;
     s->channel_map = *map;
     s->name = pa_xstrdup(name);
-
-    s->memchunk.memblock = NULL;
-    s->memchunk.index = 0;
-    s->memchunk.length = 0;
-
+    pa_memchunk_reset(&s->memchunk);
     s->length = length;
 
     pa_idxset_put(c->output_streams, s, &s->index);
+
     return s;
 }
 
-static void upload_stream_free(struct upload_stream *o) {
-    assert(o && o->connection);
+static void record_stream_unlink(record_stream *s) {
+    pa_assert(s);
+
+    if (!s->connection)
+        return;
+
+    if (s->source_output) {
+        pa_source_output_unlink(s->source_output);
+        pa_source_output_unref(s->source_output);
+        s->source_output = NULL;
+    }
+
+    pa_assert_se(pa_idxset_remove_by_data(s->connection->record_streams, s, NULL) == s);
+    s->connection = NULL;
+    record_stream_unref(s);
+}
+
+static void record_stream_free(pa_object *o) {
+    record_stream *s = RECORD_STREAM(o);
+    pa_assert(s);
+
+    record_stream_unlink(s);
+
+    pa_memblockq_free(s->memblockq);
+    pa_xfree(s);
+}
+
+static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
+    record_stream *s = RECORD_STREAM(o);
+    record_stream_assert_ref(s);
 
-    pa_idxset_remove_by_data(o->connection->output_streams, o, NULL);
+    if (!s->connection)
+        return -1;
 
-    pa_xfree(o->name);
+    switch (code) {
 
-    if (o->memchunk.memblock)
-        pa_memblock_unref(o->memchunk.memblock);
+        case RECORD_STREAM_MESSAGE_POST_DATA:
 
-    pa_xfree(o);
+            if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
+/*                 pa_log_warn("Failed to push data into output queue."); */
+                return -1;
+            }
+
+            if (!pa_pstream_is_pending(s->connection->pstream))
+                send_memblock(s->connection);
+
+            break;
+    }
+
+    return 0;
 }
 
-static struct record_stream* record_stream_new(
-    struct connection *c,
-    pa_source *source,
-    const pa_sample_spec *ss,
-    const pa_channel_map *map,
-    const char *name,
-    size_t maxlength,
-    size_t fragment_size) {
+static record_stream* record_stream_new(
+        connection *c,
+        pa_source *source,
+        const pa_sample_spec *ss,
+        const pa_channel_map *map,
+        const char *name,
+        uint32_t *maxlength,
+        uint32_t fragment_size,
+        int corked) {
 
-    struct record_stream *s;
+    record_stream *s;
     pa_source_output *source_output;
     size_t base;
     pa_source_output_new_data data;
 
-    assert(c && ss && name && maxlength);
+    pa_assert(c);
+    pa_assert(ss);
+    pa_assert(name);
+    pa_assert(maxlength);
+    pa_assert(*maxlength > 0);
 
     pa_source_output_new_data_init(&data);
+    data.module = c->protocol->module;
+    data.client = c->client;
     data.source = source;
     data.driver = __FILE__;
     data.name = name;
     pa_source_output_new_data_set_sample_spec(&data, ss);
     pa_source_output_new_data_set_channel_map(&data, map);
-    data.module = c->protocol->module;
-    data.client = c->client;
 
-    if (!(source_output = pa_source_output_new(c->protocol->core, &data, 0)))
+    if (!(source_output = pa_source_output_new(c->protocol->core, &data, corked ? PA_SOURCE_OUTPUT_START_CORKED : 0)))
         return NULL;
 
-    s = pa_xnew(struct record_stream, 1);
+    s = pa_msgobject_new(record_stream);
+    s->parent.parent.free = record_stream_free;
+    s->parent.process_msg = record_stream_process_msg;
     s->connection = c;
     s->source_output = source_output;
     s->source_output->push = source_output_push_cb;
@@ -346,58 +477,159 @@ static struct record_stream* record_stream_new(
 
     s->memblockq = pa_memblockq_new(
             0,
-            maxlength,
+            *maxlength,
             0,
             base = pa_frame_size(ss),
             1,
             0,
             NULL);
-    assert(s->memblockq);
 
     s->fragment_size = (fragment_size/base)*base;
-    if (!s->fragment_size)
+    if (s->fragment_size <= 0)
         s->fragment_size = base;
+    *maxlength = pa_memblockq_get_maxlength(s->memblockq);
 
     pa_idxset_put(c->record_streams, s, &s->index);
+
+    pa_source_output_put(s->source_output);
     return s;
 }
 
-static void record_stream_free(struct record_stream* r) {
-    assert(r && r->connection);
+static void playback_stream_unlink(playback_stream *s) {
+    pa_assert(s);
+
+    if (!s->connection)
+        return;
+
+    if (s->sink_input) {
+        pa_sink_input_unlink(s->sink_input);
+        pa_sink_input_unref(s->sink_input);
+        s->sink_input = NULL;
+    }
+
+    if (s->drain_request)
+        pa_pstream_send_error(s->connection->pstream, s->drain_tag, PA_ERR_NOENTITY);
+
+    pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
+    s->connection = NULL;
+    playback_stream_unref(s);
+}
+
+static void playback_stream_free(pa_object* o) {
+    playback_stream *s = PLAYBACK_STREAM(o);
+    pa_assert(s);
+
+    playback_stream_unlink(s);
+
+    pa_memblockq_free(s->memblockq);
+    pa_xfree(s);
+}
+
+static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
+    playback_stream *s = PLAYBACK_STREAM(o);
+    playback_stream_assert_ref(s);
+
+    if (!s->connection)
+        return -1;
+
+    switch (code) {
+        case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: {
+            pa_tagstruct *t;
+            uint32_t l = 0;
+
+            for (;;) {
+                int32_t k;
+
+                if ((k = pa_atomic_load(&s->missing)) <= 0)
+                    break;
+
+                l += k;
+
+                if (l < s->minreq)
+                    break;
+
+                if (pa_atomic_sub(&s->missing, k) <= k)
+                    break;
+            }
+
+            if (l < s->minreq)
+                break;
+
+            t = pa_tagstruct_new(NULL, 0);
+            pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
+            pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
+            pa_tagstruct_putu32(t, s->index);
+            pa_tagstruct_putu32(t, l);
+            pa_pstream_send_tagstruct(s->connection->pstream, t);
+
+/*             pa_log("Requesting %u bytes", l);     */
+            break;
+        }
+
+        case PLAYBACK_STREAM_MESSAGE_UNDERFLOW: {
+            pa_tagstruct *t;
+
+            /* Report that we're empty */
+            t = pa_tagstruct_new(NULL, 0);
+            pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW);
+            pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
+            pa_tagstruct_putu32(t, s->index);
+            pa_pstream_send_tagstruct(s->connection->pstream, t);
+            break;
+        }
+
+        case PLAYBACK_STREAM_MESSAGE_OVERFLOW: {
+            pa_tagstruct *t;
+
+            /* Notify the user we're overflowed*/
+            t = pa_tagstruct_new(NULL, 0);
+            pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW);
+            pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
+            pa_tagstruct_putu32(t, s->index);
+            pa_pstream_send_tagstruct(s->connection->pstream, t);
+            break;
+        }
 
-    pa_idxset_remove_by_data(r->connection->record_streams, r, NULL);
-    pa_source_output_disconnect(r->source_output);
-    pa_source_output_unref(r->source_output);
-    pa_memblockq_free(r->memblockq);
-    pa_xfree(r);
+        case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK:
+            pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
+            break;
+
+    }
+
+    return 0;
 }
 
-static struct playback_stream* playback_stream_new(
-        struct connection *c,
+static playback_stream* playback_stream_new(
+        connection *c,
         pa_sink *sink,
         const pa_sample_spec *ss,
         const pa_channel_map *map,
         const char *name,
-        size_t maxlength,
-        size_t tlength,
-        size_t prebuf,
-        size_t minreq,
+        uint32_t *maxlength,
+        uint32_t *tlength,
+        uint32_t *prebuf,
+        uint32_t *minreq,
         pa_cvolume *volume,
-        uint32_t syncid) {
+        uint32_t syncid,
+        int corked,
+        uint32_t *missing) {
 
-    struct playback_stream *s, *ssync;
+    playback_stream *s, *ssync;
     pa_sink_input *sink_input;
     pa_memblock *silence;
     uint32_t idx;
     int64_t start_index;
     pa_sink_input_new_data data;
 
-    assert(c && ss && name && maxlength);
+    pa_assert(c);
+    pa_assert(ss);
+    pa_assert(name);
+    pa_assert(maxlength);
 
     /* Find syncid group */
     for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) {
 
-        if (ssync->type != PLAYBACK_STREAM)
+        if (!playback_stream_isinstance(ssync))
             continue;
 
         if (ssync->syncid == syncid)
@@ -405,8 +637,13 @@ static struct playback_stream* playback_stream_new(
     }
 
     /* Synced streams must connect to the same sink */
-    if (ssync)
-        sink = ssync->sink_input->sink;
+    if (ssync) {
+
+        if (!sink)
+            sink = ssync->sink_input->sink;
+        else if (sink != ssync->sink_input->sink)
+            return NULL;
+    }
 
     pa_sink_input_new_data_init(&data);
     data.sink = sink;
@@ -417,146 +654,158 @@ static struct playback_stream* playback_stream_new(
     pa_sink_input_new_data_set_volume(&data, volume);
     data.module = c->protocol->module;
     data.client = c->client;
+    data.sync_base = ssync ? ssync->sink_input : NULL;
 
-    if (!(sink_input = pa_sink_input_new(c->protocol->core, &data, 0)))
+    if (!(sink_input = pa_sink_input_new(c->protocol->core, &data, corked ? PA_SINK_INPUT_START_CORKED : 0)))
         return NULL;
 
-    s = pa_xnew(struct playback_stream, 1);
-    s->type = PLAYBACK_STREAM;
+    s = pa_msgobject_new(playback_stream);
+    s->parent.parent.parent.free = playback_stream_free;
+    s->parent.parent.process_msg = playback_stream_process_msg;
     s->connection = c;
     s->syncid = syncid;
     s->sink_input = sink_input;
     s->underrun = 1;
 
+    s->sink_input->parent.process_msg = sink_input_process_msg;
     s->sink_input->peek = sink_input_peek_cb;
     s->sink_input->drop = sink_input_drop_cb;
     s->sink_input->kill = sink_input_kill_cb;
-    s->sink_input->get_latency = sink_input_get_latency_cb;
     s->sink_input->userdata = s;
 
-    if (ssync) {
-        /* Sync id found, now find head of list */
-        PA_LLIST_FIND_HEAD(struct playback_stream, ssync, &ssync);
-
-        /* Prepend ourselves */
-        PA_LLIST_PREPEND(struct playback_stream, ssync, s);
-
-        /* Set our start index to the current read index of the other grozp member(s) */
-        assert(ssync->next);
-        start_index = pa_memblockq_get_read_index(ssync->next->memblockq);
-    } else {
-        /* This ia a new sync group */
-        PA_LLIST_INIT(struct playback_stream, s);
-        start_index = 0;
-    }
+    start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
 
     silence = pa_silence_memblock_new(c->protocol->core->mempool, ss, 0);
 
     s->memblockq = pa_memblockq_new(
             start_index,
-            maxlength,
-            tlength,
+            *maxlength,
+            *tlength,
             pa_frame_size(ss),
-            prebuf,
-            minreq,
+            *prebuf,
+            *minreq,
             silence);
 
     pa_memblock_unref(silence);
 
-    s->requested_bytes = 0;
+    *maxlength = (uint32_t) pa_memblockq_get_maxlength(s->memblockq);
+    *tlength = (uint32_t) pa_memblockq_get_tlength(s->memblockq);
+    *prebuf = (uint32_t) pa_memblockq_get_prebuf(s->memblockq);
+    *minreq = (uint32_t) pa_memblockq_get_minreq(s->memblockq);
+    *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
+
+    s->minreq = pa_memblockq_get_minreq(s->memblockq);
+    pa_atomic_store(&s->missing, 0);
     s->drain_request = 0;
 
     pa_idxset_put(c->output_streams, s, &s->index);
 
+    pa_sink_input_put(s->sink_input);
+
     return s;
 }
 
-static void playback_stream_free(struct playback_stream* p) {
-    struct playback_stream *head;
-    assert(p && p->connection);
+static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
+    connection *c = CONNECTION(o);
+    connection_assert_ref(c);
 
-    if (p->drain_request)
-        pa_pstream_send_error(p->connection->pstream, p->drain_tag, PA_ERR_NOENTITY);
+    if (!c->protocol)
+        return -1;
 
-    PA_LLIST_FIND_HEAD(struct playback_stream, p, &head);
-    PA_LLIST_REMOVE(struct playback_stream, head, p);
+    switch (code) {
 
-    pa_idxset_remove_by_data(p->connection->output_streams, p, NULL);
-    pa_sink_input_disconnect(p->sink_input);
-    pa_sink_input_unref(p->sink_input);
-    pa_memblockq_free(p->memblockq);
-    pa_xfree(p);
+        case CONNECTION_MESSAGE_REVOKE:
+            pa_pstream_send_revoke(c->pstream, PA_PTR_TO_UINT(userdata));
+            break;
+
+        case CONNECTION_MESSAGE_RELEASE:
+            pa_pstream_send_release(c->pstream, PA_PTR_TO_UINT(userdata));
+            break;
+    }
+
+    return 0;
 }
 
-static void connection_free(struct connection *c) {
-    struct record_stream *r;
-    struct output_stream *o;
-    assert(c && c->protocol);
+static void connection_unlink(connection *c) {
+    record_stream *r;
+    output_stream *o;
+
+    pa_assert(c);
+
+    if (!c->protocol)
+        return;
 
-    pa_idxset_remove_by_data(c->protocol->connections, c, NULL);
     while ((r = pa_idxset_first(c->record_streams, NULL)))
-        record_stream_free(r);
-    pa_idxset_free(c->record_streams, NULL, NULL);
+        record_stream_unlink(r);
 
     while ((o = pa_idxset_first(c->output_streams, NULL)))
-        if (o->type == PLAYBACK_STREAM)
-            playback_stream_free((struct playback_stream*) o);
+        if (playback_stream_isinstance(o))
+            playback_stream_unlink(PLAYBACK_STREAM(o));
         else
-            upload_stream_free((struct upload_stream*) o);
-    pa_idxset_free(c->output_streams, NULL, NULL);
-
-    pa_pdispatch_unref(c->pdispatch);
-    pa_pstream_close(c->pstream);
-    pa_pstream_unref(c->pstream);
-    pa_client_free(c->client);
+            upload_stream_unlink(UPLOAD_STREAM(o));
 
     if (c->subscription)
         pa_subscription_free(c->subscription);
 
-    if (c->auth_timeout_event)
+    if (c->pstream)
+        pa_pstream_unlink(c->pstream);
+
+    if (c->auth_timeout_event) {
         c->protocol->core->mainloop->time_free(c->auth_timeout_event);
+        c->auth_timeout_event = NULL;
+    }
 
-    pa_xfree(c);
+    pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
+    c->protocol = NULL;
+    connection_unref(c);
 }
 
-static void request_bytes(struct playback_stream *s) {
-    pa_tagstruct *t;
-    size_t l;
-    assert(s);
+static void connection_free(pa_object *o) {
+    connection *c = CONNECTION(o);
 
-    if (!(l = pa_memblockq_missing(s->memblockq)))
-        return;
+    pa_assert(c);
 
-    if (l <= s->requested_bytes)
-        return;
+    connection_unlink(c);
 
-    l -= s->requested_bytes;
+    pa_idxset_free(c->record_streams, NULL, NULL);
+    pa_idxset_free(c->output_streams, NULL, NULL);
 
-    if (l < pa_memblockq_get_minreq(s->memblockq))
-        return;
+    pa_pdispatch_unref(c->pdispatch);
+    pa_pstream_unref(c->pstream);
+    pa_client_free(c->client);
 
-    s->requested_bytes += l;
+    pa_xfree(c);
+}
 
-    t = pa_tagstruct_new(NULL, 0);
-    assert(t);
-    pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
-    pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
-    pa_tagstruct_putu32(t, s->index);
-    pa_tagstruct_putu32(t, l);
-    pa_pstream_send_tagstruct(s->connection->pstream, t);
+/* Called from thread context */
+static void request_bytes(playback_stream *s) {
+    size_t m, previous_missing;
 
-/*     pa_log("Requesting %u bytes", l);  */
+    playback_stream_assert_ref(s);
+
+    m = pa_memblockq_pop_missing(s->memblockq);
+
+    if (m <= 0)
+        return;
+
+/*     pa_log("request_bytes(%u)", m); */
+
+    previous_missing = pa_atomic_add(&s->missing, m);
+    if (previous_missing < s->minreq && previous_missing+m >= s->minreq) {
+        pa_assert(pa_thread_mq_get());
+        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
+    }
 }
 
-static void send_memblock(struct connection *c) {
+static void send_memblock(connection *c) {
     uint32_t start;
-    struct record_stream *r;
+    record_stream *r;
 
     start = PA_IDXSET_INVALID;
     for (;;) {
         pa_memchunk chunk;
 
-        if (!(r = pa_idxset_rrobin(c->record_streams, &c->rrobin_index)))
+        if (!(r = RECORD_STREAM(pa_idxset_rrobin(c->record_streams, &c->rrobin_index))))
             return;
 
         if (start == PA_IDXSET_INVALID)
@@ -571,7 +820,8 @@ static void send_memblock(struct connection *c) {
                 schunk.length = r->fragment_size;
 
             pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk);
-            pa_memblockq_drop(r->memblockq, &chunk, schunk.length);
+
+            pa_memblockq_drop(r->memblockq, schunk.length);
             pa_memblock_unref(schunk.memblock);
 
             return;
@@ -579,9 +829,9 @@ static void send_memblock(struct connection *c) {
     }
 }
 
-static void send_playback_stream_killed(struct playback_stream *p) {
+static void send_playback_stream_killed(playback_stream *p) {
     pa_tagstruct *t;
-    assert(p);
+    playback_stream_assert_ref(p);
 
     t = pa_tagstruct_new(NULL, 0);
     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
@@ -590,9 +840,9 @@ static void send_playback_stream_killed(struct playback_stream *p) {
     pa_pstream_send_tagstruct(p->connection->pstream, t);
 }
 
-static void send_record_stream_killed(struct record_stream *r) {
+static void send_record_stream_killed(record_stream *r) {
     pa_tagstruct *t;
-    assert(r);
+    record_stream_assert_ref(r);
 
     t = pa_tagstruct_new(NULL, 0);
     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
@@ -601,96 +851,219 @@ static void send_record_stream_killed(struct record_stream *r) {
     pa_pstream_send_tagstruct(r->connection->pstream, t);
 }
 
-/*** sinkinput callbacks ***/
+/*** sink input callbacks ***/
 
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
-    struct playback_stream *s;
-    assert(i && i->userdata && chunk);
-    s = i->userdata;
+/* Called from thread context */
+static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
+    pa_sink_input *i = PA_SINK_INPUT(o);
+    playback_stream *s;
 
-    if (pa_memblockq_get_length(s->memblockq) <= 0 && !s->underrun) {
-        pa_tagstruct *t;
+    pa_sink_input_assert_ref(i);
+    s = PLAYBACK_STREAM(i->userdata);
+    playback_stream_assert_ref(s);
+
+    switch (code) {
+
+        case SINK_INPUT_MESSAGE_SEEK:
+            pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata));
+            request_bytes(s);
+            return 0;
+
+        case SINK_INPUT_MESSAGE_POST_DATA: {
+            pa_assert(chunk);
+
+/*             pa_log("sink input post: %u", chunk->length); */
+
+            if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
+
+                pa_log_warn("Failed to push data into queue");
+                pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL);
+                pa_memblockq_seek(s->memblockq, chunk->length, PA_SEEK_RELATIVE);
+            }
 
-        /* Report that we're empty */
+            request_bytes(s);
 
-        t = pa_tagstruct_new(NULL, 0);
-        pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW);
-        pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
-        pa_tagstruct_putu32(t, s->index);
-        pa_pstream_send_tagstruct(s->connection->pstream, t);
+            s->underrun = 0;
+            return 0;
+        }
+
+        case SINK_INPUT_MESSAGE_DRAIN: {
+
+            pa_memblockq_prebuf_disable(s->memblockq);
 
+            if (!pa_memblockq_is_readable(s->memblockq))
+                pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, userdata, 0, NULL, NULL);
+            else {
+                s->drain_tag = PA_PTR_TO_UINT(userdata);
+                s->drain_request = 1;
+            }
+            request_bytes(s);
+
+            return 0;
+        }
+
+        case SINK_INPUT_MESSAGE_FLUSH:
+        case SINK_INPUT_MESSAGE_PREBUF_FORCE:
+        case SINK_INPUT_MESSAGE_TRIGGER: {
+
+            pa_sink_input *isync;
+            void (*func)(pa_memblockq *bq);
+
+            switch  (code) {
+                case SINK_INPUT_MESSAGE_FLUSH:
+                    func = pa_memblockq_flush;
+                    break;
+
+                case SINK_INPUT_MESSAGE_PREBUF_FORCE:
+                    func = pa_memblockq_prebuf_force;
+                    break;
+
+                case SINK_INPUT_MESSAGE_TRIGGER:
+                    func = pa_memblockq_prebuf_disable;
+                    break;
+
+                default:
+                    pa_assert_not_reached();
+            }
+
+            func(s->memblockq);
+            s->underrun = 0;
+            request_bytes(s);
+
+            /* Do the same for all other members in the sync group */
+            for (isync = i->sync_prev; isync; isync = isync->sync_prev) {
+                playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
+                func(ssync->memblockq);
+                ssync->underrun = 0;
+                request_bytes(ssync);
+            }
+
+            for (isync = i->sync_next; isync; isync = isync->sync_next) {
+                playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
+                func(ssync->memblockq);
+                ssync->underrun = 0;
+                request_bytes(ssync);
+            }
+
+            return 0;
+        }
+
+        case SINK_INPUT_MESSAGE_UPDATE_LATENCY:
+
+            s->read_index = pa_memblockq_get_read_index(s->memblockq);
+            s->write_index = pa_memblockq_get_write_index(s->memblockq);
+            s->resampled_chunk_length = s->sink_input->thread_info.resampled_chunk.memblock ? s->sink_input->thread_info.resampled_chunk.length : 0;
+            return 0;
+
+        case PA_SINK_INPUT_MESSAGE_SET_STATE:
+
+            pa_memblockq_prebuf_force(s->memblockq);
+            request_bytes(s);
+            break;
+
+        case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
+            pa_usec_t *r = userdata;
+
+            *r = pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->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, userdata, offset, chunk);
+}
+
+/* Called from thread context */
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+    playback_stream *s;
+
+    pa_sink_input_assert_ref(i);
+    s = PLAYBACK_STREAM(i->userdata);
+    playback_stream_assert_ref(s);
+    pa_assert(chunk);
+
+    if (pa_memblockq_get_length(s->memblockq) <= 0 && !s->underrun) {
+        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
         s->underrun = 1;
     }
 
     if (pa_memblockq_peek(s->memblockq, chunk) < 0) {
-/*         pa_log("peek: failure");    */
+/*         pa_log("peek: failure");     */
         return -1;
     }
 
-/*     pa_log("peek: %u", chunk->length);    */
+/*     pa_log("peek: %u", chunk->length); */
+
+    request_bytes(s);
 
     return 0;
 }
 
-static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
-    struct playback_stream *s;
-    assert(i && i->userdata && length);
-    s = i->userdata;
+/* Called from thread context */
+static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
+    playback_stream *s;
 
-    pa_memblockq_drop(s->memblockq, chunk, length);
+    pa_sink_input_assert_ref(i);
+    s = PLAYBACK_STREAM(i->userdata);
+    playback_stream_assert_ref(s);
+    pa_assert(length > 0);
 
-    request_bytes(s);
+    pa_memblockq_drop(s->memblockq, length);
 
     if (s->drain_request && !pa_memblockq_is_readable(s->memblockq)) {
-        pa_pstream_send_simple_ack(s->connection->pstream, s->drain_tag);
         s->drain_request = 0;
+        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, PA_UINT_TO_PTR(s->drain_tag), 0, NULL, NULL);
     }
 
-/*     pa_log("after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq));   */
-}
+    request_bytes(s);
 
-static void sink_input_kill_cb(pa_sink_input *i) {
-    assert(i && i->userdata);
-    send_playback_stream_killed((struct playback_stream *) i->userdata);
-    playback_stream_free((struct playback_stream *) i->userdata);
+/*     pa_log("after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */
 }
 
-static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) {
-    struct playback_stream *s;
-    assert(i && i->userdata);
-    s = i->userdata;
+static void sink_input_kill_cb(pa_sink_input *i) {
+    playback_stream *s;
 
-    /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
+    pa_sink_input_assert_ref(i);
+    s = PLAYBACK_STREAM(i->userdata);
+    playback_stream_assert_ref(s);
 
-    return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec);
+    send_playback_stream_killed(s);
+    playback_stream_unlink(s);
 }
 
 /*** source_output callbacks ***/
 
+/* Called from thread context */
 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
-    struct record_stream *s;
-    assert(o && o->userdata && chunk);
-    s = o->userdata;
+    record_stream *s;
 
-    if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
-        pa_log_warn("Failed to push data into output queue.");
-        return;
-    }
+    pa_source_output_assert_ref(o);
+    s = RECORD_STREAM(o->userdata);
+    record_stream_assert_ref(s);
+    pa_assert(chunk);
 
-    if (!pa_pstream_is_pending(s->connection->pstream))
-        send_memblock(s->connection);
+    pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), RECORD_STREAM_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
 }
 
 static void source_output_kill_cb(pa_source_output *o) {
-    assert(o && o->userdata);
-    send_record_stream_killed((struct record_stream *) o->userdata);
-    record_stream_free((struct record_stream *) o->userdata);
+    record_stream *s;
+
+    pa_source_output_assert_ref(o);
+    s = RECORD_STREAM(o->userdata);
+    record_stream_assert_ref(s);
+
+    send_record_stream_killed(s);
+    record_stream_unlink(s);
 }
 
 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
-    struct record_stream *s;
-    assert(o && o->userdata);
-    s = o->userdata;
+    record_stream *s;
+
+    pa_source_output_assert_ref(o);
+    s = RECORD_STREAM(o->userdata);
+    record_stream_assert_ref(s);
 
     /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
 
@@ -699,9 +1072,9 @@ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
 
 /*** pdispatch callbacks ***/
 
-static void protocol_error(struct connection *c) {
+static void protocol_error(connection *c) {
     pa_log("protocol error, kicking client");
-    connection_free(c);
+    connection_unlink(c);
 }
 
 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
@@ -721,9 +1094,9 @@ static pa_tagstruct *reply_new(uint32_t tag) {
 }
 
 static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
-    struct playback_stream *s;
-    uint32_t maxlength, tlength, prebuf, minreq, sink_index, syncid;
+    connection *c = CONNECTION(userdata);
+    playback_stream *s;
+    uint32_t maxlength, tlength, prebuf, minreq, sink_index, syncid, missing;
     const char *name, *sink_name;
     pa_sample_spec ss;
     pa_channel_map map;
@@ -732,7 +1105,8 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
     pa_cvolume volume;
     int corked;
 
-    assert(c && t && c->protocol && c->protocol->core);
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_get(
             t,
@@ -773,34 +1147,35 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
         CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
     }
 
-    s = playback_stream_new(c, sink, &ss, &map, name, maxlength, tlength, prebuf, minreq, &volume, syncid);
+    s = playback_stream_new(c, sink, &ss, &map, name, &maxlength, &tlength, &prebuf, &minreq, &volume, syncid, corked, &missing);
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
 
-    pa_sink_input_cork(s->sink_input, corked);
-
     reply = reply_new(tag);
     pa_tagstruct_putu32(reply, s->index);
-    assert(s->sink_input);
+    pa_assert(s->sink_input);
     pa_tagstruct_putu32(reply, s->sink_input->index);
-    pa_tagstruct_putu32(reply, s->requested_bytes = pa_memblockq_missing(s->memblockq));
+    pa_tagstruct_putu32(reply, missing);
+
+/*     pa_log("initial request is %u", missing); */
 
     if (c->version >= 9) {
         /* Since 0.9 we support sending the buffer metrics back to the client */
 
-        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq));
-        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_tlength(s->memblockq));
-        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_prebuf(s->memblockq));
-        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_minreq(s->memblockq));
+        pa_tagstruct_putu32(reply, (uint32_t) maxlength);
+        pa_tagstruct_putu32(reply, (uint32_t) tlength);
+        pa_tagstruct_putu32(reply, (uint32_t) prebuf);
+        pa_tagstruct_putu32(reply, (uint32_t) minreq);
     }
 
     pa_pstream_send_tagstruct(c->pstream, reply);
-    request_bytes(s);
 }
 
 static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t channel;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &channel) < 0 ||
         !pa_tagstruct_eof(t)) {
@@ -810,39 +1185,52 @@ static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma
 
     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
 
-    if (command == PA_COMMAND_DELETE_PLAYBACK_STREAM) {
-        struct playback_stream *s;
-        if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != PLAYBACK_STREAM)) {
-            pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
-            return;
+    switch (command) {
+
+        case PA_COMMAND_DELETE_PLAYBACK_STREAM: {
+            playback_stream *s;
+            if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !playback_stream_isinstance(s)) {
+                pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
+                return;
+            }
+
+            playback_stream_unlink(s);
+            break;
         }
 
-        playback_stream_free(s);
-    } else if (command == PA_COMMAND_DELETE_RECORD_STREAM) {
-        struct record_stream *s;
-        if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
-            pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
-            return;
+        case PA_COMMAND_DELETE_RECORD_STREAM: {
+            record_stream *s;
+            if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
+                pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
+                return;
+            }
+
+            record_stream_unlink(s);
+            break;
         }
 
-        record_stream_free(s);
-    } else {
-        struct upload_stream *s;
-        assert(command == PA_COMMAND_DELETE_UPLOAD_STREAM);
-        if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) {
-            pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
-            return;
+        case PA_COMMAND_DELETE_UPLOAD_STREAM: {
+            upload_stream *s;
+
+            if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !upload_stream_isinstance(s)) {
+                pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
+                return;
+            }
+
+            upload_stream_unlink(s);
+            break;
         }
 
-        upload_stream_free(s);
+        default:
+            pa_assert_not_reached();
     }
 
     pa_pstream_send_simple_ack(c->pstream, tag);
 }
 
 static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
-    struct record_stream *s;
+    connection *c = CONNECTION(userdata);
+    record_stream *s;
     uint32_t maxlength, fragment_size;
     uint32_t source_index;
     const char *name, *source_name;
@@ -851,7 +1239,9 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     pa_tagstruct *reply;
     pa_source *source = NULL;
     int corked;
-    assert(c && t && c->protocol && c->protocol->core);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_gets(t, &name) < 0 ||
         pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
@@ -882,20 +1272,18 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
         CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
     }
 
-    s = record_stream_new(c, source, &ss, &map, name, maxlength, fragment_size);
+    s = record_stream_new(c, source, &ss, &map, name, &maxlength, fragment_size, corked);
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
 
-    pa_source_output_cork(s->source_output, corked);
-
     reply = reply_new(tag);
     pa_tagstruct_putu32(reply, s->index);
-    assert(s->source_output);
+    pa_assert(s->source_output);
     pa_tagstruct_putu32(reply, s->source_output->index);
 
     if (c->version >= 9) {
         /* Since 0.9 we support sending the buffer metrics back to the client */
 
-        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq));
+        pa_tagstruct_putu32(reply, (uint32_t) maxlength);
         pa_tagstruct_putu32(reply, (uint32_t) s->fragment_size);
     }
 
@@ -903,8 +1291,10 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 }
 
 static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
-    assert(c && t);
+    connection *c = CONNECTION(userdata);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (!pa_tagstruct_eof(t)) {
         protocol_error(c);
@@ -913,16 +1303,17 @@ static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
 
     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
 
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop);
     c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0);
     pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
 }
 
 static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     const void*cookie;
     pa_tagstruct *reply;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &c->version) < 0 ||
         pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
@@ -1015,9 +1406,11 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
 }
 
 static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     const char *name;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_gets(t, &name) < 0 ||
         !pa_tagstruct_eof(t)) {
@@ -1032,10 +1425,12 @@ static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE
 }
 
 static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     const char *name;
     uint32_t idx = PA_IDXSET_INVALID;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_gets(t, &name) < 0 ||
         !pa_tagstruct_eof(t)) {
@@ -1052,7 +1447,7 @@ static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uin
             idx = sink->index;
     } else {
         pa_source *source;
-        assert(command == PA_COMMAND_LOOKUP_SOURCE);
+        pa_assert(command == PA_COMMAND_LOOKUP_SOURCE);
         if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1)))
             idx = source->index;
     }
@@ -1068,10 +1463,12 @@ static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uin
 }
 
 static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t idx;
-    struct playback_stream *s;
-    assert(c && t);
+    playback_stream *s;
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         !pa_tagstruct_eof(t)) {
@@ -1082,29 +1479,18 @@ static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC
     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
     s = pa_idxset_get_by_index(c->output_streams, idx);
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
-    CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
+    CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
 
-    s->drain_request = 0;
-
-    pa_memblockq_prebuf_disable(s->memblockq);
-
-    if (!pa_memblockq_is_readable(s->memblockq)) {
-/*         pa_log("immediate drain: %u", pa_memblockq_get_length(s->memblockq));  */
-        pa_pstream_send_simple_ack(c->pstream, tag);
-    } else {
-/*         pa_log("slow drain triggered");  */
-        s->drain_request = 1;
-        s->drain_tag = tag;
-
-        pa_sink_notify(s->sink_input->sink);
-    }
+    pa_asyncmsgq_post(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_DRAIN, PA_UINT_TO_PTR(tag), 0, NULL, NULL);
 }
 
 static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     pa_tagstruct *reply;
     const pa_mempool_stat *stat;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (!pa_tagstruct_eof(t)) {
         protocol_error(c);
@@ -1125,13 +1511,15 @@ static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
 }
 
 static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     pa_tagstruct *reply;
-    struct playback_stream *s;
+    playback_stream *s;
     struct timeval tv, now;
     uint32_t idx;
     pa_usec_t latency;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         pa_tagstruct_get_timeval(t, &tv) < 0 ||
@@ -1143,31 +1531,34 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
     s = pa_idxset_get_by_index(c->output_streams, idx);
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
-    CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
+    CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
+    CHECK_VALIDITY(c->pstream, pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_UPDATE_LATENCY, s, 0, NULL) == 0, tag, PA_ERR_NOENTITY)
 
     reply = reply_new(tag);
 
     latency = pa_sink_get_latency(s->sink_input->sink);
-    if (s->sink_input->resampled_chunk.memblock)
-        latency += pa_bytes_to_usec(s->sink_input->resampled_chunk.length, &s->sink_input->sample_spec);
+    latency += pa_bytes_to_usec(s->resampled_chunk_length, &s->sink_input->sample_spec);
+
     pa_tagstruct_put_usec(reply, latency);
 
     pa_tagstruct_put_usec(reply, 0);
-    pa_tagstruct_put_boolean(reply, s->sink_input->state == PA_SINK_INPUT_RUNNING);
+    pa_tagstruct_put_boolean(reply, pa_sink_input_get_state(s->sink_input) == PA_SINK_INPUT_RUNNING);
     pa_tagstruct_put_timeval(reply, &tv);
     pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
-    pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
-    pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq));
+    pa_tagstruct_puts64(reply, s->write_index);
+    pa_tagstruct_puts64(reply, s->read_index);
     pa_pstream_send_tagstruct(c->pstream, reply);
 }
 
 static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     pa_tagstruct *reply;
-    struct record_stream *s;
+    record_stream *s;
     struct timeval tv, now;
     uint32_t idx;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         pa_tagstruct_get_timeval(t, &tv) < 0 ||
@@ -1192,14 +1583,16 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN
 }
 
 static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
-    struct upload_stream *s;
+    connection *c = CONNECTION(userdata);
+    upload_stream *s;
     uint32_t length;
     const char *name;
     pa_sample_spec ss;
     pa_channel_map map;
     pa_tagstruct *reply;
-    assert(c && t && c->protocol && c->protocol->core);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_gets(t, &name) < 0 ||
         pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
@@ -1228,11 +1621,13 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 }
 
 static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t channel;
-    struct upload_stream *s;
+    upload_stream *s;
     uint32_t idx;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &channel) < 0 ||
         !pa_tagstruct_eof(t)) {
@@ -1244,23 +1639,25 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 
     s = pa_idxset_get_by_index(c->output_streams, channel);
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
-    CHECK_VALIDITY(c->pstream, s->type == UPLOAD_STREAM, tag, PA_ERR_NOENTITY);
+    CHECK_VALIDITY(c->pstream, upload_stream_isinstance(s), tag, PA_ERR_NOENTITY);
 
     if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, &idx) < 0)
         pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL);
     else
         pa_pstream_send_simple_ack(c->pstream, tag);
 
-    upload_stream_free(s);
+    upload_stream_unlink(s);
 }
 
 static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t sink_index;
     pa_volume_t volume;
     pa_sink *sink;
     const char *name, *sink_name;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
         pa_tagstruct_gets(t, &sink_name) < 0 ||
@@ -1291,9 +1688,11 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui
 }
 
 static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     const char *name;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_gets(t, &name) < 0 ||
         !pa_tagstruct_eof(t)) {
@@ -1313,7 +1712,9 @@ static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED
 }
 
 static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) {
-    assert(t && sink);
+    pa_assert(t);
+    pa_sink_assert_ref(sink);
+
     pa_tagstruct_put(
         t,
         PA_TAG_U32, sink->index,
@@ -1321,22 +1722,21 @@ static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) {
         PA_TAG_STRING, sink->description,
         PA_TAG_SAMPLE_SPEC, &sink->sample_spec,
         PA_TAG_CHANNEL_MAP, &sink->channel_map,
-        PA_TAG_U32, sink->owner ? sink->owner->index : PA_INVALID_INDEX,
-        PA_TAG_CVOLUME, pa_sink_get_volume(sink, PA_MIXER_HARDWARE),
-        PA_TAG_BOOLEAN, pa_sink_get_mute(sink, PA_MIXER_HARDWARE),
+        PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX,
+        PA_TAG_CVOLUME, pa_sink_get_volume(sink),
+        PA_TAG_BOOLEAN, pa_sink_get_mute(sink),
         PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
         PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL,
         PA_TAG_USEC, pa_sink_get_latency(sink),
         PA_TAG_STRING, sink->driver,
-        PA_TAG_U32,
-        (sink->get_hw_volume ? PA_SINK_HW_VOLUME_CTRL : 0) |
-        (sink->get_latency ? PA_SINK_LATENCY : 0) |
-        (sink->is_hardware ? PA_SINK_HARDWARE : 0),
+        PA_TAG_U32, sink->flags,
         PA_TAG_INVALID);
 }
 
 static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) {
-    assert(t && source);
+    pa_assert(t);
+    pa_source_assert_ref(source);
+
     pa_tagstruct_put(
         t,
         PA_TAG_U32, source->index,
@@ -1344,22 +1744,21 @@ static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) {
         PA_TAG_STRING, source->description,
         PA_TAG_SAMPLE_SPEC, &source->sample_spec,
         PA_TAG_CHANNEL_MAP, &source->channel_map,
-        PA_TAG_U32, source->owner ? source->owner->index : PA_INVALID_INDEX,
-        PA_TAG_CVOLUME, pa_source_get_volume(source, PA_MIXER_HARDWARE),
-        PA_TAG_BOOLEAN, pa_source_get_mute(source, PA_MIXER_HARDWARE),
+        PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX,
+        PA_TAG_CVOLUME, pa_source_get_volume(source),
+        PA_TAG_BOOLEAN, pa_source_get_mute(source),
         PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX,
         PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL,
         PA_TAG_USEC, pa_source_get_latency(source),
         PA_TAG_STRING, source->driver,
-        PA_TAG_U32,
-        (source->get_hw_volume ? PA_SOURCE_HW_VOLUME_CTRL : 0) |
-        (source->get_latency ? PA_SOURCE_LATENCY : 0) |
-        (source->is_hardware ? PA_SOURCE_HARDWARE : 0),
+        PA_TAG_U32, source->flags,
         PA_TAG_INVALID);
 }
 
 static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) {
-    assert(t && client);
+    pa_assert(t);
+    pa_assert(client);
+
     pa_tagstruct_putu32(t, client->index);
     pa_tagstruct_puts(t, client->name);
     pa_tagstruct_putu32(t, client->owner ? client->owner->index : PA_INVALID_INDEX);
@@ -1367,7 +1766,9 @@ static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) {
 }
 
 static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) {
-    assert(t && module);
+    pa_assert(t);
+    pa_assert(module);
+
     pa_tagstruct_putu32(t, module->index);
     pa_tagstruct_puts(t, module->name);
     pa_tagstruct_puts(t, module->argument);
@@ -1375,8 +1776,10 @@ static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) {
     pa_tagstruct_put_boolean(t, module->auto_unload);
 }
 
-static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *s) {
-    assert(t && s);
+static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_input *s) {
+    pa_assert(t);
+    pa_sink_input_assert_ref(s);
+
     pa_tagstruct_putu32(t, s->index);
     pa_tagstruct_puts(t, s->name);
     pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
@@ -1389,10 +1792,14 @@ static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *s) {
     pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink));
     pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
     pa_tagstruct_puts(t, s->driver);
+    if (c->version >= 11)
+        pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s));
 }
 
 static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) {
-    assert(t && s);
+    pa_assert(t);
+    pa_source_output_assert_ref(s);
+
     pa_tagstruct_putu32(t, s->index);
     pa_tagstruct_puts(t, s->name);
     pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
@@ -1407,7 +1814,9 @@ static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) {
 }
 
 static void scache_fill_tagstruct(pa_tagstruct *t, pa_scache_entry *e) {
-    assert(t && e);
+    pa_assert(t);
+    pa_assert(e);
+
     pa_tagstruct_putu32(t, e->index);
     pa_tagstruct_puts(t, e->name);
     pa_tagstruct_put_cvolume(t, &e->volume);
@@ -1420,7 +1829,7 @@ static void scache_fill_tagstruct(pa_tagstruct *t, pa_scache_entry *e) {
 }
 
 static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t idx;
     pa_sink *sink = NULL;
     pa_source *source = NULL;
@@ -1431,7 +1840,9 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u
     pa_scache_entry *sce = NULL;
     const char *name;
     pa_tagstruct *reply;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         (command != PA_COMMAND_GET_CLIENT_INFO &&
@@ -1466,7 +1877,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u
     else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
         so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
     else {
-        assert(command == PA_COMMAND_GET_SAMPLE_INFO);
+        pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO);
         if (idx != PA_INVALID_INDEX)
             sce = pa_idxset_get_by_index(c->protocol->core->scache, idx);
         else
@@ -1488,7 +1899,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u
     else if (module)
         module_fill_tagstruct(reply, module);
     else if (si)
-        sink_input_fill_tagstruct(reply, si);
+        sink_input_fill_tagstruct(c, reply, si);
     else if (so)
         source_output_fill_tagstruct(reply, so);
     else
@@ -1497,12 +1908,14 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u
 }
 
 static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     pa_idxset *i;
     uint32_t idx;
     void *p;
     pa_tagstruct *reply;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (!pa_tagstruct_eof(t)) {
         protocol_error(c);
@@ -1526,7 +1939,7 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma
     else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
         i = c->protocol->core->source_outputs;
     else {
-        assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
+        pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
         i = c->protocol->core->scache;
     }
 
@@ -1541,11 +1954,11 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma
             else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
                 module_fill_tagstruct(reply, p);
             else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
-                sink_input_fill_tagstruct(reply, p);
+                sink_input_fill_tagstruct(c, reply, p);
             else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
                 source_output_fill_tagstruct(reply, p);
             else {
-                assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
+                pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
                 scache_fill_tagstruct(reply, p);
             }
         }
@@ -1555,11 +1968,13 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma
 }
 
 static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     pa_tagstruct *reply;
     char txt[256];
     const char *n;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (!pa_tagstruct_eof(t)) {
         protocol_error(c);
@@ -1587,8 +2002,9 @@ static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE
 
 static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
     pa_tagstruct *t;
-    struct connection *c = userdata;
-    assert(c && core);
+    connection *c = CONNECTION(userdata);
+
+    connection_assert_ref(c);
 
     t = pa_tagstruct_new(NULL, 0);
     pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
@@ -1599,9 +2015,11 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint3
 }
 
 static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     pa_subscription_mask_t m;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &m) < 0 ||
         !pa_tagstruct_eof(t)) {
@@ -1617,7 +2035,7 @@ static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint
 
     if (m != 0) {
         c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
-        assert(c->subscription);
+        pa_assert(c->subscription);
     } else
         c->subscription = NULL;
 
@@ -1631,14 +2049,16 @@ static void command_set_volume(
         pa_tagstruct *t,
         void *userdata) {
 
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t idx;
     pa_cvolume volume;
     pa_sink *sink = NULL;
     pa_source *source = NULL;
     pa_sink_input *si = NULL;
     const char *name = NULL;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
@@ -1653,27 +2073,36 @@ static void command_set_volume(
     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
     CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
 
-    if (command == PA_COMMAND_SET_SINK_VOLUME) {
-        if (idx != PA_INVALID_INDEX)
-            sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
-        else
-            sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
-    } else if (command == PA_COMMAND_SET_SOURCE_VOLUME) {
-        if (idx != (uint32_t) -1)
-            source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
-        else
-            source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
-    }  else {
-        assert(command == PA_COMMAND_SET_SINK_INPUT_VOLUME);
-        si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
+    switch (command) {
+
+        case PA_COMMAND_SET_SINK_VOLUME:
+            if (idx != PA_INVALID_INDEX)
+                sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
+            else
+                sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
+            break;
+
+        case PA_COMMAND_SET_SOURCE_VOLUME:
+            if (idx != PA_INVALID_INDEX)
+                source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
+            else
+                source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
+            break;
+
+        case PA_COMMAND_SET_SINK_INPUT_VOLUME:
+            si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
+            break;
+
+        default:
+            pa_assert_not_reached();
     }
 
     CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
 
     if (sink)
-        pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &volume);
+        pa_sink_set_volume(sink, &volume);
     else if (source)
-        pa_source_set_volume(source, PA_MIXER_HARDWARE, &volume);
+        pa_source_set_volume(source, &volume);
     else if (si)
         pa_sink_input_set_volume(si, &volume);
 
@@ -1687,16 +2116,20 @@ static void command_set_mute(
         pa_tagstruct *t,
         void *userdata) {
 
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t idx;
     int mute;
     pa_sink *sink = NULL;
     pa_source *source = NULL;
+    pa_sink_input *si = NULL;
     const char *name = NULL;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
-        pa_tagstruct_gets(t, &name) < 0 ||
+        (command == PA_COMMAND_SET_SINK_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
+        (command == PA_COMMAND_SET_SOURCE_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
         pa_tagstruct_get_boolean(t, &mute) ||
         !pa_tagstruct_eof(t)) {
         protocol_error(c);
@@ -1706,35 +2139,53 @@ static void command_set_mute(
     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
 
-    if (command == PA_COMMAND_SET_SINK_MUTE) {
-        if (idx != PA_INVALID_INDEX)
-            sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
-        else
-            sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
-    } else {
-        assert(command == PA_COMMAND_SET_SOURCE_MUTE);
-        if (idx != (uint32_t) -1)
-            source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
-        else
-            source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
+    switch (command) {
+
+        case PA_COMMAND_SET_SINK_MUTE:
+
+            if (idx != PA_INVALID_INDEX)
+                sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
+            else
+                sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
+
+            break;
+
+        case PA_COMMAND_SET_SOURCE_MUTE:
+            if (idx != PA_INVALID_INDEX)
+                source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
+            else
+                source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
+
+            break;
+
+        case PA_COMMAND_SET_SINK_INPUT_MUTE:
+            si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
+            break;
+
+        default:
+            pa_assert_not_reached();
     }
 
-    CHECK_VALIDITY(c->pstream, sink || source, tag, PA_ERR_NOENTITY);
+    CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
 
     if (sink)
-        pa_sink_set_mute(sink, PA_MIXER_HARDWARE, mute);
+        pa_sink_set_mute(sink, mute);
     else if (source)
-        pa_source_set_mute(source, PA_MIXER_HARDWARE, mute);
+        pa_source_set_mute(source, mute);
+    else if (si)
+        pa_sink_input_set_mute(si, mute);
 
     pa_pstream_send_simple_ack(c->pstream, tag);
 }
 
 static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t idx;
     int b;
-    struct playback_stream *s, *ssync;
-    assert(c && t);
+    playback_stream *s;
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         pa_tagstruct_get_boolean(t, &b) < 0 ||
@@ -1747,73 +2198,19 @@ static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
     s = pa_idxset_get_by_index(c->output_streams, idx);
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
-    CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
+    CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
 
     pa_sink_input_cork(s->sink_input, b);
-    pa_memblockq_prebuf_force(s->memblockq);
-
-    /* Do the same for all other members in the sync group */
-    for (ssync = s->prev; ssync; ssync = ssync->prev) {
-        pa_sink_input_cork(ssync->sink_input, b);
-        pa_memblockq_prebuf_force(ssync->memblockq);
-    }
-
-    for (ssync = s->next; ssync; ssync = ssync->next) {
-        pa_sink_input_cork(ssync->sink_input, b);
-        pa_memblockq_prebuf_force(ssync->memblockq);
-    }
-
     pa_pstream_send_simple_ack(c->pstream, tag);
 }
 
-static void command_flush_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+static void command_trigger_or_flush_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+    connection *c = CONNECTION(userdata);
     uint32_t idx;
-    struct playback_stream *s, *ssync;
-    assert(c && t);
-
-    if (pa_tagstruct_getu32(t, &idx) < 0 ||
-        !pa_tagstruct_eof(t)) {
-        protocol_error(c);
-        return;
-    }
-
-    CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
-    CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
-    s = pa_idxset_get_by_index(c->output_streams, idx);
-    CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
-    CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
-
-    pa_memblockq_flush(s->memblockq);
-    s->underrun = 0;
+    playback_stream *s;
 
-    /* Do the same for all other members in the sync group */
-    for (ssync = s->prev; ssync; ssync = ssync->prev) {
-        pa_memblockq_flush(ssync->memblockq);
-        ssync->underrun = 0;
-    }
-
-    for (ssync = s->next; ssync; ssync = ssync->next) {
-        pa_memblockq_flush(ssync->memblockq);
-        ssync->underrun = 0;
-    }
-
-    pa_pstream_send_simple_ack(c->pstream, tag);
-    pa_sink_notify(s->sink_input->sink);
-    request_bytes(s);
-
-    for (ssync = s->prev; ssync; ssync = ssync->prev)
-        request_bytes(ssync);
-
-    for (ssync = s->next; ssync; ssync = ssync->next)
-        request_bytes(ssync);
-}
-
-static void command_trigger_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
-    uint32_t idx;
-    struct playback_stream *s;
-    assert(c && t);
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         !pa_tagstruct_eof(t)) {
@@ -1825,32 +2222,36 @@ static void command_trigger_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch
     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
     s = pa_idxset_get_by_index(c->output_streams, idx);
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
-    CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
+    CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
 
     switch (command) {
+        case PA_COMMAND_FLUSH_PLAYBACK_STREAM:
+            pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_FLUSH, NULL, 0, NULL);
+            break;
+
         case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
-            pa_memblockq_prebuf_force(s->memblockq);
+            pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL);
             break;
 
         case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
-            pa_memblockq_prebuf_disable(s->memblockq);
+            pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL);
             break;
 
         default:
-            abort();
+            pa_assert_not_reached();
     }
 
-    pa_sink_notify(s->sink_input->sink);
     pa_pstream_send_simple_ack(c->pstream, tag);
-    request_bytes(s);
 }
 
 static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t idx;
-    struct record_stream *s;
+    record_stream *s;
     int b;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         pa_tagstruct_get_boolean(t, &b) < 0 ||
@@ -1869,10 +2270,12 @@ static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN
 }
 
 static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t idx;
-    struct record_stream *s;
-    assert(c && t);
+    record_stream *s;
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         !pa_tagstruct_eof(t)) {
@@ -1889,9 +2292,11 @@ static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_U
 }
 
 static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     const char *s;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_gets(t, &s) < 0 ||
         !pa_tagstruct_eof(t)) {
@@ -1907,10 +2312,12 @@ static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, u
 }
 
 static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t idx;
     const char *name;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         pa_tagstruct_gets(t, &name) < 0 ||
@@ -1923,16 +2330,16 @@ static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t com
     CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
 
     if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
-        struct playback_stream *s;
+        playback_stream *s;
 
         s = pa_idxset_get_by_index(c->output_streams, idx);
         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
-        CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
+        CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
 
         pa_sink_input_set_name(s->sink_input, name);
 
     } else {
-        struct record_stream *s;
+        record_stream *s;
 
         s = pa_idxset_get_by_index(c->record_streams, idx);
         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
@@ -1944,9 +2351,11 @@ static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t com
 }
 
 static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t idx;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         !pa_tagstruct_eof(t)) {
@@ -1961,6 +2370,8 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3
 
         client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
         CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
+
+        connection_ref(c);
         pa_client_kill(client);
 
     } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
@@ -1969,27 +2380,32 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3
         s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
 
+        connection_ref(c);
         pa_sink_input_kill(s);
     } else {
         pa_source_output *s;
 
-        assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
+        pa_assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
 
         s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
 
+        connection_ref(c);
         pa_source_output_kill(s);
     }
 
     pa_pstream_send_simple_ack(c->pstream, tag);
+    connection_unref(c);
 }
 
 static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     pa_module *m;
     const char *name, *argument;
     pa_tagstruct *reply;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_gets(t, &name) < 0 ||
         pa_tagstruct_gets(t, &argument) < 0 ||
@@ -2013,10 +2429,12 @@ static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui
 }
 
 static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t idx;
     pa_module *m;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         !pa_tagstruct_eof(t)) {
@@ -2033,12 +2451,14 @@ static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED
 }
 
 static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     const char *name, *module, *argument;
     uint32_t type;
     uint32_t idx;
     pa_tagstruct *reply;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_gets(t, &name) < 0 ||
         pa_tagstruct_getu32(t, &type) < 0 ||
@@ -2066,11 +2486,13 @@ static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED u
 }
 
 static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     const char *name = NULL;
     uint32_t type, idx = PA_IDXSET_INVALID;
     int r;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if ((pa_tagstruct_getu32(t, &idx) < 0 &&
         (pa_tagstruct_gets(t, &name) < 0 ||
@@ -2095,7 +2517,7 @@ static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE
 }
 
 static void autoload_fill_tagstruct(pa_tagstruct *t, const pa_autoload_entry *e) {
-    assert(t && e);
+    pa_assert(t && e);
 
     pa_tagstruct_putu32(t, e->index);
     pa_tagstruct_puts(t, e->name);
@@ -2105,12 +2527,14 @@ static void autoload_fill_tagstruct(pa_tagstruct *t, const pa_autoload_entry *e)
 }
 
 static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     const pa_autoload_entry *a = NULL;
     uint32_t type, idx;
     const char *name;
     pa_tagstruct *reply;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if ((pa_tagstruct_getu32(t, &idx) < 0 &&
         (pa_tagstruct_gets(t, &name) < 0 ||
@@ -2137,9 +2561,11 @@ static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNU
 }
 
 static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     pa_tagstruct *reply;
-    assert(c && t);
+
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (!pa_tagstruct_eof(t)) {
         protocol_error(c);
@@ -2162,12 +2588,12 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
 }
 
 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = CONNECTION(userdata);
     uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
     const char *name = NULL;
 
-    assert(c);
-    assert(t);
+    connection_assert_ref(c);
+    pa_assert(t);
 
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         pa_tagstruct_getu32(t, &idx_device) < 0 ||
@@ -2202,6 +2628,8 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag
         pa_source_output *so = NULL;
         pa_source *source;
 
+        pa_assert(command == PA_COMMAND_MOVE_SOURCE_OUTPUT);
+
         so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
 
         if (idx_device != PA_INVALID_INDEX)
@@ -2218,67 +2646,122 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag
     }
 
     pa_pstream_send_simple_ack(c->pstream, tag);
+}
+
+static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+    connection *c = CONNECTION(userdata);
+    uint32_t idx = PA_INVALID_INDEX;
+    const char *name = NULL;
+    int b;
+
+    connection_assert_ref(c);
+    pa_assert(t);
+
+    if (pa_tagstruct_getu32(t, &idx) < 0 ||
+        pa_tagstruct_gets(t, &name) < 0 ||
+        pa_tagstruct_get_boolean(t, &b) < 0 ||
+        !pa_tagstruct_eof(t)) {
+        protocol_error(c);
+        return;
+    }
+
+    CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
+    CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || !*name || pa_utf8_valid(name), tag, PA_ERR_INVALID);
 
+    if (command == PA_COMMAND_SUSPEND_SINK) {
+
+        if (idx == PA_INVALID_INDEX && name && !*name) {
+
+            if (pa_sink_suspend_all(c->protocol->core, b) < 0) {
+                pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
+                return;
+            }
+        } else {
+            pa_sink *sink = NULL;
+
+            if (idx != PA_INVALID_INDEX)
+                sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
+            else
+                sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
+
+            CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
+
+            if (pa_sink_suspend(sink, b) < 0) {
+                pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
+                return;
+            }
+        }
+    } else {
+
+        pa_assert(command == PA_COMMAND_SUSPEND_SOURCE);
+
+        if (idx == PA_INVALID_INDEX && name && !*name) {
+
+            if (pa_source_suspend_all(c->protocol->core, b) < 0) {
+                pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
+                return;
+            }
+
+        } else {
+            pa_source *source;
+
+            if (idx != PA_INVALID_INDEX)
+                source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
+            else
+                source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
+
+            CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
+
+            if (pa_source_suspend(source, b) < 0) {
+                pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
+                return;
+            }
+        }
+    }
+
+    pa_pstream_send_simple_ack(c->pstream, tag);
 }
 
 /*** pstream callbacks ***/
 
 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
-    struct connection *c = userdata;
-    assert(p && packet && packet->data && c);
+    connection *c = CONNECTION(userdata);
+
+    pa_assert(p);
+    pa_assert(packet);
+    connection_assert_ref(c);
 
     if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) {
         pa_log("invalid packet.");
-        connection_free(c);
+        connection_unlink(c);
     }
 }
 
 static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) {
-    struct connection *c = userdata;
-    struct output_stream *stream;
-    assert(p && chunk && userdata);
+    connection *c = CONNECTION(userdata);
+    output_stream *stream;
+
+    pa_assert(p);
+    pa_assert(chunk);
+    connection_assert_ref(c);
 
-    if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) {
+    if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) {
         pa_log("client sent block for invalid stream.");
         /* Ignoring */
         return;
     }
 
-    if (stream->type == PLAYBACK_STREAM) {
-        struct playback_stream *ps = (struct playback_stream*) stream;
-        if (chunk->length >= ps->requested_bytes)
-            ps->requested_bytes = 0;
-        else
-            ps->requested_bytes -= chunk->length;
-
-        pa_memblockq_seek(ps->memblockq, offset, seek);
-
-        if (pa_memblockq_push_align(ps->memblockq, chunk) < 0) {
-            pa_tagstruct *t;
-
-            pa_log_warn("failed to push data into queue");
-
-            /* Pushing this block into the queue failed, so we simulate
-             * it by skipping ahead */
-
-            pa_memblockq_seek(ps->memblockq, chunk->length, PA_SEEK_RELATIVE);
+    if (playback_stream_isinstance(stream)) {
+        playback_stream *ps = PLAYBACK_STREAM(stream);
 
-            /* Notify the user */
-            t = pa_tagstruct_new(NULL, 0);
-            pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW);
-            pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
-            pa_tagstruct_putu32(t, ps->index);
-            pa_pstream_send_tagstruct(p, t);
-        }
+        if (seek != PA_SEEK_RELATIVE || offset != 0)
+            pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset, NULL, NULL);
 
-        ps->underrun = 0;
-
-        pa_sink_notify(ps->sink_input->sink);
+        pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
 
     } else {
-        struct upload_stream *u = (struct upload_stream*) stream;
+        upload_stream *u = UPLOAD_STREAM(stream);
         size_t l;
-        assert(u->type == UPLOAD_STREAM);
 
         if (!u->memchunk.memblock) {
             if (u->length == chunk->length) {
@@ -2291,15 +2774,24 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
             }
         }
 
-        assert(u->memchunk.memblock);
+        pa_assert(u->memchunk.memblock);
 
         l = u->length;
         if (l > chunk->length)
             l = chunk->length;
 
+
         if (l > 0) {
-            memcpy((uint8_t*) u->memchunk.memblock->data + u->memchunk.index + u->memchunk.length,
-                   (uint8_t*) chunk->memblock->data+chunk->index, l);
+            void *src, *dst;
+            dst = pa_memblock_acquire(u->memchunk.memblock);
+            src = pa_memblock_acquire(chunk->memblock);
+
+            memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length,
+                   (uint8_t*) src+chunk->index, l);
+
+            pa_memblock_release(u->memchunk.memblock);
+            pa_memblock_release(chunk->memblock);
+
             u->memchunk.length += l;
             u->length -= l;
         }
@@ -2307,43 +2799,72 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
 }
 
 static void pstream_die_callback(pa_pstream *p, void *userdata) {
-    struct connection *c = userdata;
-    assert(p && c);
-    connection_free(c);
+    connection *c = CONNECTION(userdata);
 
-/*    pa_log("connection died.");*/
-}
+    pa_assert(p);
+    connection_assert_ref(c);
 
+    connection_unlink(c);
+    pa_log_info("connection died.");
+}
 
 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
-    struct connection *c = userdata;
-    assert(p && c);
+    connection *c = CONNECTION(userdata);
+
+    pa_assert(p);
+    connection_assert_ref(c);
 
     send_memblock(c);
 }
 
+static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
+    pa_thread_mq *q;
+
+    if (!(q = pa_thread_mq_get()))
+        pa_pstream_send_revoke(p, block_id);
+    else
+        pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_REVOKE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
+}
+
+static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
+    pa_thread_mq *q;
+
+    if (!(q = pa_thread_mq_get()))
+        pa_pstream_send_release(p, block_id);
+    else
+        pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_RELEASE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
+}
+
 /*** client callbacks ***/
 
 static void client_kill_cb(pa_client *c) {
-    assert(c && c->userdata);
-    connection_free(c->userdata);
+    pa_assert(c);
+
+    connection_unlink(CONNECTION(c->userdata));
 }
 
 /*** socket server callbacks ***/
 
 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) {
-    struct connection *c = userdata;
-    assert(m && tv && c && c->auth_timeout_event == e);
+    connection *c = CONNECTION(userdata);
+
+    pa_assert(m);
+    pa_assert(tv);
+    connection_assert_ref(c);
+    pa_assert(c->auth_timeout_event == e);
 
     if (!c->authorized)
-        connection_free(c);
+        connection_unlink(c);
 }
 
 static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, void *userdata) {
     pa_protocol_native *p = userdata;
-    struct connection *c;
+    connection *c;
     char cname[256], pname[128];
-    assert(io && p);
+
+    pa_assert(s);
+    pa_assert(io);
+    pa_assert(p);
 
     if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
         pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
@@ -2351,7 +2872,9 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
         return;
     }
 
-    c = pa_xmalloc(sizeof(struct connection));
+    c = pa_msgobject_new(connection);
+    c->parent.parent.free = connection_free;
+    c->parent.process_msg = connection_process_msg;
 
     c->authorized = !!p->public;
 
@@ -2371,35 +2894,31 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
     c->version = 8;
     c->protocol = p;
     pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
-    snprintf(cname, sizeof(cname), "Native client (%s)", pname);
-    assert(p->core);
+    pa_snprintf(cname, sizeof(cname), "Native client (%s)", pname);
     c->client = pa_client_new(p->core, __FILE__, cname);
-    assert(c->client);
     c->client->kill = client_kill_cb;
     c->client->userdata = c;
     c->client->owner = p->module;
 
     c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
-    assert(c->pstream);
 
     pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
     pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
     pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
     pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
+    pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c);
+    pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c);
 
     c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX);
-    assert(c->pdispatch);
 
     c->record_streams = pa_idxset_new(NULL, NULL);
     c->output_streams = pa_idxset_new(NULL, NULL);
-    assert(c->record_streams && c->output_streams);
 
     c->rrobin_index = PA_IDXSET_INVALID;
     c->subscription = NULL;
 
     pa_idxset_put(p->connections, c, NULL);
 
-
 #ifdef HAVE_CREDS
     if (pa_iochannel_creds_supported(io))
         pa_iochannel_creds_enable(io);
@@ -2410,7 +2929,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
 /*** module entry points ***/
 
 static int load_key(pa_protocol_native*p, const char*fn) {
-    assert(p);
+    pa_assert(p);
 
     p->auth_cookie_in_property = 0;
 
@@ -2440,8 +2959,8 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo
     int public = 0;
     const char *acl;
 
-    assert(c);
-    assert(ma);
+    pa_assert(c);
+    pa_assert(ma);
 
     if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) {
         pa_log("auth-anonymous= expects a boolean argument.");
@@ -2482,7 +3001,6 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo
         goto fail;
 
     p->connections = pa_idxset_new(NULL, NULL);
-    assert(p->connections);
 
     return p;
 
@@ -2517,11 +3035,11 @@ pa_protocol_native* pa_protocol_native_new(pa_core *core, pa_socket_server *serv
 }
 
 void pa_protocol_native_free(pa_protocol_native *p) {
-    struct connection *c;
-    assert(p);
+    connection *c;
+    pa_assert(p);
 
     while ((c = pa_idxset_first(p->connections, NULL)))
-        connection_free(c);
+        connection_unlink(c);
     pa_idxset_free(p->connections, NULL, NULL);
 
     if (p->server) {
@@ -2553,7 +3071,12 @@ void pa_protocol_native_free(pa_protocol_native *p) {
     pa_xfree(p);
 }
 
-pa_protocol_native* pa_protocol_native_new_iochannel(pa_core*core, pa_iochannel *io, pa_module *m, pa_modargs *ma) {
+pa_protocol_native* pa_protocol_native_new_iochannel(
+        pa_core*core,
+        pa_iochannel *io,
+        pa_module *m,
+        pa_modargs *ma) {
+
     pa_protocol_native *p;
 
     if (!(p = protocol_new_internal(core, m, ma)))
index 31ad6dddf03b7f40291780d0593abd4d6cb876c2..64e2a81c817fbdffdb6f686dfb8a4216cfacf23c 100644 (file)
@@ -25,7 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdlib.h>
 #include <limits.h>
 #include <stdio.h>
 #include <pulsecore/namereg.h>
 #include <pulsecore/log.h>
 #include <pulsecore/core-error.h>
+#include <pulsecore/atomic.h>
+#include <pulsecore/thread-mq.h>
 
 #include "protocol-simple.h"
 
 /* Don't allow more than this many concurrent connections */
 #define MAX_CONNECTIONS 10
 
-struct connection {
+typedef struct connection {
+    pa_msgobject parent;
     pa_protocol_simple *protocol;
     pa_iochannel *io;
     pa_sink_input *sink_input;
     pa_source_output *source_output;
     pa_client *client;
     pa_memblockq *input_memblockq, *output_memblockq;
-    pa_defer_event *defer_event;
 
     int dead;
 
     struct {
         pa_memblock *current_memblock;
         size_t memblock_index, fragment_size;
+        pa_atomic_t missing;
     } playback;
-};
+} connection;
+
+PA_DECLARE_CLASS(connection);
+#define CONNECTION(o) (connection_cast(o))
+static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject);
 
 struct pa_protocol_simple {
     pa_module *module;
     pa_core *core;
     pa_socket_server*server;
     pa_idxset *connections;
+
     enum {
         RECORD = 1,
         PLAYBACK = 2,
         DUPLEX = 3
     } mode;
+
     pa_sample_spec sample_spec;
     char *source_name, *sink_name;
 };
 
+enum {
+    SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */
+    SINK_INPUT_MESSAGE_DISABLE_PREBUF /* disabled prebuf, get playback started. */
+};
+
+enum {
+    CONNECTION_MESSAGE_REQUEST_DATA,      /* data requested from sink input from the main loop */
+    CONNECTION_MESSAGE_POST_DATA,         /* data from source output to main loop */
+    CONNECTION_MESSAGE_UNLINK_CONNECTION    /* Please drop a aconnection now */
+};
+
+
 #define PLAYBACK_BUFFER_SECONDS (.5)
 #define PLAYBACK_BUFFER_FRAGMENTS (10)
 #define RECORD_BUFFER_SECONDS (5)
 #define RECORD_BUFFER_FRAGMENTS (100)
 
-static void connection_free(struct connection *c) {
-    assert(c);
+static void connection_unlink(connection *c) {
+    pa_assert(c);
 
-    pa_idxset_remove_by_data(c->protocol->connections, c, NULL);
+    if (!c->protocol)
+        return;
 
-    if (c->playback.current_memblock)
-        pa_memblock_unref(c->playback.current_memblock);
     if (c->sink_input) {
-        pa_sink_input_disconnect(c->sink_input);
+        pa_sink_input_unlink(c->sink_input);
         pa_sink_input_unref(c->sink_input);
+        c->sink_input = NULL;
     }
+
     if (c->source_output) {
-        pa_source_output_disconnect(c->source_output);
+        pa_source_output_unlink(c->source_output);
         pa_source_output_unref(c->source_output);
+        c->source_output = NULL;
     }
-    if (c->client)
+
+    if (c->client) {
         pa_client_free(c->client);
-    if (c->io)
+        c->client = NULL;
+    }
+
+    if (c->io) {
         pa_iochannel_free(c->io);
+        c->io = NULL;
+    }
+
+    pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
+    c->protocol = NULL;
+    connection_unref(c);
+}
+
+static void connection_free(pa_object *o) {
+    connection *c = CONNECTION(o);
+    pa_assert(c);
+
+    connection_unref(c);
+
+    if (c->playback.current_memblock)
+        pa_memblock_unref(c->playback.current_memblock);
+
     if (c->input_memblockq)
         pa_memblockq_free(c->input_memblockq);
     if (c->output_memblockq)
         pa_memblockq_free(c->output_memblockq);
-    if (c->defer_event)
-        c->protocol->core->mainloop->defer_free(c->defer_event);
+
     pa_xfree(c);
 }
 
-static int do_read(struct connection *c) {
+static int do_read(connection *c) {
     pa_memchunk chunk;
     ssize_t r;
     size_t l;
+    void *p;
+
+    connection_assert_ref(c);
 
-    if (!c->sink_input || !(l = pa_memblockq_missing(c->input_memblockq)))
+    if (!c->sink_input || (l = pa_atomic_load(&c->playback.missing)) <= 0)
         return 0;
 
     if (l > c->playback.fragment_size)
         l = c->playback.fragment_size;
 
     if (c->playback.current_memblock)
-        if (c->playback.current_memblock->length - c->playback.memblock_index < l) {
+        if (pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index < l) {
             pa_memblock_unref(c->playback.current_memblock);
             c->playback.current_memblock = NULL;
             c->playback.memblock_index = 0;
         }
 
     if (!c->playback.current_memblock) {
-        c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2);
-        assert(c->playback.current_memblock && c->playback.current_memblock->length >= l);
+        pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, l));
         c->playback.memblock_index = 0;
     }
 
-    if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) {
+    p = pa_memblock_acquire(c->playback.current_memblock);
+    r = pa_iochannel_read(c->io, (uint8_t*) p + c->playback.memblock_index, l);
+    pa_memblock_release(c->playback.current_memblock);
+
+    if (r <= 0) {
+
+        if (r < 0 && (errno == EINTR || errno == EAGAIN))
+            return 0;
+
         pa_log_debug("read(): %s", r == 0 ? "EOF" : pa_cstrerror(errno));
         return -1;
     }
@@ -143,50 +195,55 @@ static int do_read(struct connection *c) {
     chunk.memblock = c->playback.current_memblock;
     chunk.index = c->playback.memblock_index;
     chunk.length = r;
-    assert(chunk.memblock);
 
     c->playback.memblock_index += r;
 
-    assert(c->input_memblockq);
-    pa_memblockq_push_align(c->input_memblockq, &chunk);
-    assert(c->sink_input);
-    pa_sink_notify(c->sink_input->sink);
+    pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, &chunk, NULL);
+    pa_atomic_sub(&c->playback.missing, r);
 
     return 0;
 }
 
-static int do_write(struct connection *c) {
+static int do_write(connection *c) {
     pa_memchunk chunk;
     ssize_t r;
+    void *p;
+
+    connection_assert_ref(c);
 
     if (!c->source_output)
         return 0;
 
-    assert(c->output_memblockq);
-    if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0)
+    if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0) {
+/*         pa_log("peek failed"); */
         return 0;
+    }
+
+    pa_assert(chunk.memblock);
+    pa_assert(chunk.length);
 
-    assert(chunk.memblock && chunk.length);
+    p = pa_memblock_acquire(chunk.memblock);
+    r = pa_iochannel_write(c->io, (uint8_t*) p+chunk.index, chunk.length);
+    pa_memblock_release(chunk.memblock);
+
+    pa_memblock_unref(chunk.memblock);
+
+    if (r < 0) {
+
+        if (errno == EINTR || errno == EAGAIN)
+            return 0;
 
-    if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) {
-        pa_memblock_unref(chunk.memblock);
         pa_log("write(): %s", pa_cstrerror(errno));
         return -1;
     }
 
-    pa_memblockq_drop(c->output_memblockq, &chunk, r);
-    pa_memblock_unref(chunk.memblock);
-
-    pa_source_notify(c->source_output->source);
+    pa_memblockq_drop(c->output_memblockq, r);
 
     return 0;
 }
 
-static void do_work(struct connection *c) {
-    assert(c);
-
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
-    c->protocol->core->mainloop->defer_enable(c->defer_event, 0);
+static void do_work(connection *c) {
+    connection_assert_ref(c);
 
     if (c->dead)
         return;
@@ -207,103 +264,182 @@ static void do_work(struct connection *c) {
 fail:
 
     if (c->sink_input) {
+
+        /* If there is a sink input, we first drain what we already have read before shutting down the connection */
         c->dead = 1;
 
         pa_iochannel_free(c->io);
         c->io = NULL;
 
-        pa_memblockq_prebuf_disable(c->input_memblockq);
-        pa_sink_notify(c->sink_input->sink);
+        pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_DISABLE_PREBUF, NULL, 0, NULL, NULL);
     } else
-        connection_free(c);
+        connection_unlink(c);
 }
 
-/*** sink_input callbacks ***/
+static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
+    connection *c = CONNECTION(o);
+    connection_assert_ref(c);
 
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
-    struct connection*c;
-    assert(i && i->userdata && chunk);
-    c = i->userdata;
+    switch (code) {
+        case CONNECTION_MESSAGE_REQUEST_DATA:
+            do_work(c);
+            break;
 
-    if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) {
+        case CONNECTION_MESSAGE_POST_DATA:
+/*             pa_log("got data %u", chunk->length); */
+            pa_memblockq_push_align(c->output_memblockq, chunk);
+            do_work(c);
+            break;
 
-        if (c->dead)
-            connection_free(c);
-
-        return -1;
+        case CONNECTION_MESSAGE_UNLINK_CONNECTION:
+            connection_unlink(c);
+            break;
     }
 
     return 0;
 }
 
-static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
-    struct connection*c = i->userdata;
-    assert(i && c && length);
+/*** sink_input callbacks ***/
+
+/* Called from thread context */
+static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
+    pa_sink_input *i = PA_SINK_INPUT(o);
+    connection*c;
+
+    pa_sink_input_assert_ref(i);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
+
+    switch (code) {
+
+        case SINK_INPUT_MESSAGE_POST_DATA: {
+            pa_assert(chunk);
+
+            /* New data from the main loop */
+            pa_memblockq_push_align(c->input_memblockq, chunk);
+
+/*             pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */
+
+            return 0;
+        }
+
+        case SINK_INPUT_MESSAGE_DISABLE_PREBUF: {
+            pa_memblockq_prebuf_disable(c->input_memblockq);
+            return 0;
+        }
+
+        case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
+            pa_usec_t *r = userdata;
 
-    pa_memblockq_drop(c->input_memblockq, chunk, length);
+            *r = pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec);
 
-    /* do something */
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
-    c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
+            /* Fall through, the default handler will add in the extra
+             * latency added by the resampler */
+        }
+
+        default:
+            return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
+    }
 }
 
-static void sink_input_kill_cb(pa_sink_input *i) {
-    assert(i && i->userdata);
-    connection_free((struct connection *) i->userdata);
+/* Called from thread context */
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+    connection *c;
+    int r;
+
+    pa_assert(i);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
+    pa_assert(chunk);
+
+    r = pa_memblockq_peek(c->input_memblockq, chunk);
+
+/*     pa_log("peeked %u %i", r >= 0 ? chunk->length: 0, r); */
+
+    if (c->dead && r < 0)
+        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
+
+    return r;
 }
 
+/* Called from thread context */
+static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
+    connection *c;
+    size_t old, new;
+
+    pa_assert(i);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
+    pa_assert(length);
+
+    old = pa_memblockq_missing(c->input_memblockq);
+    pa_memblockq_drop(c->input_memblockq, length);
+    new = pa_memblockq_missing(c->input_memblockq);
 
-static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) {
-    struct connection*c = i->userdata;
-    assert(i && c);
-    return pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec);
+    if (new > old) {
+        if (pa_atomic_add(&c->playback.missing, new - old) <= 0)
+            pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
+    }
+}
+
+/* Called from main context */
+static void sink_input_kill_cb(pa_sink_input *i) {
+    pa_sink_input_assert_ref(i);
+
+    connection_unlink(CONNECTION(i->userdata));
 }
 
 /*** source_output callbacks ***/
 
+/* Called from thread context */
 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
-    struct connection *c = o->userdata;
-    assert(o && c && chunk);
+    connection *c;
 
-    pa_memblockq_push(c->output_memblockq, chunk);
+    pa_assert(o);
+    c = CONNECTION(o->userdata);
+    pa_assert(c);
+    pa_assert(chunk);
 
-    /* do something */
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
-    c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
+    pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
 }
 
+/* Called from main context */
 static void source_output_kill_cb(pa_source_output *o) {
-    assert(o && o->userdata);
-    connection_free((struct connection *) o->userdata);
+    pa_source_output_assert_ref(o);
+
+    connection_unlink(CONNECTION(o->userdata));
 }
 
+/* Called from main context */
 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
-    struct connection*c = o->userdata;
-    assert(o && c);
+    connection*c;
+
+    pa_assert(o);
+    c = CONNECTION(o->userdata);
+    pa_assert(c);
+
     return pa_bytes_to_usec(pa_memblockq_get_length(c->output_memblockq), &c->source_output->sample_spec);
 }
 
 /*** client callbacks ***/
 
-static void client_kill_cb(pa_client *c) {
-    assert(c && c->userdata);
-    connection_free((struct connection *) c->userdata);
+static void client_kill_cb(pa_client *client) {
+    connection*c;
+
+    pa_assert(client);
+    c = CONNECTION(client->userdata);
+    pa_assert(c);
+
+    connection_unlink(c);
 }
 
 /*** pa_iochannel callbacks ***/
 
 static void io_callback(pa_iochannel*io, void *userdata) {
-    struct connection *c = userdata;
-    assert(io && c && c->io == io);
-
-    do_work(c);
-}
-
-/*** fixed callback ***/
+    connection *c = CONNECTION(userdata);
 
-static void defer_callback(pa_mainloop_api*a, pa_defer_event *e, void *userdata) {
-    struct connection *c = userdata;
-    assert(a && c && c->defer_event == e);
+    connection_assert_ref(c);
+    pa_assert(io);
 
     do_work(c);
 }
@@ -312,9 +448,12 @@ static void defer_callback(pa_mainloop_api*a, pa_defer_event *e, void *userdata)
 
 static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) {
     pa_protocol_simple *p = userdata;
-    struct connection *c = NULL;
+    connection *c = NULL;
     char cname[256];
-    assert(s && io && p);
+
+    pa_assert(s);
+    pa_assert(io);
+    pa_assert(p);
 
     if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
         pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
@@ -322,21 +461,22 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
         return;
     }
 
-    c = pa_xmalloc(sizeof(struct connection));
+    c = pa_msgobject_new(connection);
+    c->parent.parent.free = connection_free;
+    c->parent.process_msg = connection_process_msg;
     c->io = io;
     c->sink_input = NULL;
     c->source_output = NULL;
-    c->defer_event = NULL;
     c->input_memblockq = c->output_memblockq = NULL;
     c->protocol = p;
     c->playback.current_memblock = NULL;
     c->playback.memblock_index = 0;
     c->playback.fragment_size = 0;
     c->dead = 0;
+    pa_atomic_store(&c->playback.missing, 0);
 
     pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
-    c->client = pa_client_new(p->core, __FILE__, cname);
-    assert(c->client);
+    pa_assert_se(c->client = pa_client_new(p->core, __FILE__, cname));
     c->client->owner = p->module;
     c->client->kill = client_kill_cb;
     c->client->userdata = c;
@@ -357,10 +497,10 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
             goto fail;
         }
 
+        c->sink_input->parent.process_msg = sink_input_process_msg;
         c->sink_input->peek = sink_input_peek_cb;
         c->sink_input->drop = sink_input_drop_cb;
         c->sink_input->kill = sink_input_kill_cb;
-        c->sink_input->get_latency = sink_input_get_latency_cb;
         c->sink_input->userdata = c;
 
         l = (size_t) (pa_bytes_per_second(&p->sample_spec)*PLAYBACK_BUFFER_SECONDS);
@@ -372,11 +512,12 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
                 (size_t) -1,
                 l/PLAYBACK_BUFFER_FRAGMENTS,
                 NULL);
-        assert(c->input_memblockq);
         pa_iochannel_socket_set_rcvbuf(io, l/PLAYBACK_BUFFER_FRAGMENTS*5);
-        c->playback.fragment_size = l/10;
+        c->playback.fragment_size = l/PLAYBACK_BUFFER_FRAGMENTS;
+
+        pa_atomic_store(&c->playback.missing, pa_memblockq_missing(c->input_memblockq));
 
-        pa_sink_notify(c->sink_input->sink);
+        pa_sink_input_put(c->sink_input);
     }
 
     if (p->mode & RECORD) {
@@ -409,29 +550,29 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
                 0,
                 NULL);
         pa_iochannel_socket_set_sndbuf(io, l/RECORD_BUFFER_FRAGMENTS*2);
-        pa_source_notify(c->source_output->source);
+
+        pa_source_output_put(c->source_output);
     }
 
     pa_iochannel_set_callback(c->io, io_callback, c);
     pa_idxset_put(p->connections, c, NULL);
 
-    c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c);
-    assert(c->defer_event);
-    p->core->mainloop->defer_enable(c->defer_event, 0);
-
     return;
 
 fail:
     if (c)
-        connection_free(c);
+        connection_unlink(c);
 }
 
 pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma) {
     pa_protocol_simple* p = NULL;
     int enable;
-    assert(core && server && ma);
 
-    p = pa_xmalloc0(sizeof(pa_protocol_simple));
+    pa_assert(core);
+    pa_assert(server);
+    pa_assert(ma);
+
+    p = pa_xnew0(pa_protocol_simple, 1);
     p->module = m;
     p->core = core;
     p->server = server;
@@ -472,23 +613,24 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv
 fail:
     if (p)
         pa_protocol_simple_free(p);
+
     return NULL;
 }
 
 
 void pa_protocol_simple_free(pa_protocol_simple *p) {
-    struct connection *c;
-    assert(p);
+    connection *c;
+    pa_assert(p);
 
     if (p->connections) {
         while((c = pa_idxset_first(p->connections, NULL)))
-            connection_free(c);
+            connection_unlink(c);
 
         pa_idxset_free(p->connections, NULL, NULL);
     }
 
     if (p->server)
         pa_socket_server_unref(p->server);
+
     pa_xfree(p);
 }
-
index fae1e49be576a8b0298f76ad1963b6301dc58961..a69321583d49eb453c628a46b493c5a15ed4a3d4 100644 (file)
@@ -25,9 +25,8 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
-
 #include <pulsecore/native-common.h>
+#include <pulsecore/macro.h>
 
 #include "pstream-util.h"
 
@@ -35,20 +34,20 @@ void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const
     size_t length;
     uint8_t *data;
     pa_packet *packet;
-    assert(p);
-    assert(t);
 
-    data = pa_tagstruct_free_data(t, &length);
-    assert(data && length);
-    packet = pa_packet_new_dynamic(data, length);
-    assert(packet);
+    pa_assert(p);
+    pa_assert(t);
+
+    pa_assert_se(data = pa_tagstruct_free_data(t, &length));
+    pa_assert_se(packet = pa_packet_new_dynamic(data, length));
     pa_pstream_send_packet(p, packet, creds);
     pa_packet_unref(packet);
 }
 
 void pa_pstream_send_error(pa_pstream *p, uint32_t tag, uint32_t error) {
-    pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
-    assert(t);
+    pa_tagstruct *t;
+
+    pa_assert_se(t = pa_tagstruct_new(NULL, 0));
     pa_tagstruct_putu32(t, PA_COMMAND_ERROR);
     pa_tagstruct_putu32(t, tag);
     pa_tagstruct_putu32(t, error);
@@ -56,8 +55,9 @@ void pa_pstream_send_error(pa_pstream *p, uint32_t tag, uint32_t error) {
 }
 
 void pa_pstream_send_simple_ack(pa_pstream *p, uint32_t tag) {
-    pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
-    assert(t);
+    pa_tagstruct *t;
+
+    pa_assert_se(t = pa_tagstruct_new(NULL, 0));
     pa_tagstruct_putu32(t, PA_COMMAND_REPLY);
     pa_tagstruct_putu32(t, tag);
     pa_pstream_send_tagstruct(p, t);
index fdb1a66a341e234d658d3e1b09811cb91a165fc8..9d32a363788a78771bdb4132a90fa3bc02aedf37 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <assert.h>
 #include <unistd.h>
 
 #ifdef HAVE_SYS_SOCKET_H
 #include <netinet/in.h>
 #endif
 
-#include "winsock.h"
 
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/winsock.h>
 #include <pulsecore/queue.h>
 #include <pulsecore/log.h>
 #include <pulsecore/core-scache.h>
 #include <pulsecore/creds.h>
-#include <pulsecore/mutex.h>
 #include <pulsecore/refcnt.h>
+#include <pulsecore/flist.h>
+#include <pulsecore/macro.h>
 
 #include "pstream.h"
 
@@ -84,7 +84,8 @@ typedef uint32_t pa_pstream_descriptor[PA_PSTREAM_DESCRIPTOR_MAX];
 
 #define PA_PSTREAM_DESCRIPTOR_SIZE (PA_PSTREAM_DESCRIPTOR_MAX*sizeof(uint32_t))
 #define FRAME_SIZE_MAX_ALLOW PA_SCACHE_ENTRY_SIZE_MAX /* allow uploading a single sample in one frame at max */
-#define FRAME_SIZE_MAX_USE (1024*64)
+
+PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
 
 struct item_info {
     enum {
@@ -94,7 +95,6 @@ struct item_info {
         PA_PSTREAM_ITEM_SHMREVOKE
     } type;
 
-
     /* packet info */
     pa_packet *packet;
 #ifdef HAVE_CREDS
@@ -118,8 +118,8 @@ struct pa_pstream {
     pa_mainloop_api *mainloop;
     pa_defer_event *defer_event;
     pa_iochannel *io;
+
     pa_queue *send_queue;
-    pa_mutex *mutex;
 
     int dead;
 
@@ -129,6 +129,7 @@ struct pa_pstream {
         uint32_t shm_info[PA_PSTREAM_SHM_MAX];
         void *data;
         size_t index;
+        pa_memchunk memchunk;
     } write;
 
     struct {
@@ -156,6 +157,12 @@ struct pa_pstream {
     pa_pstream_notify_cb_t die_callback;
     void *die_callback_userdata;
 
+    pa_pstream_block_id_cb_t revoke_callback;
+    void *revoke_callback_userdata;
+
+    pa_pstream_block_id_cb_t release_callback;
+    void *release_callback_userdata;
+
     pa_mempool *mempool;
 
 #ifdef HAVE_CREDS
@@ -168,13 +175,11 @@ static int do_write(pa_pstream *p);
 static int do_read(pa_pstream *p);
 
 static void do_something(pa_pstream *p) {
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     pa_pstream_ref(p);
 
-    pa_mutex_lock(p->mutex);
-
     p->mainloop->defer_enable(p->defer_event, 0);
 
     if (!p->dead && pa_iochannel_is_readable(p->io)) {
@@ -188,28 +193,24 @@ static void do_something(pa_pstream *p) {
             goto fail;
     }
 
-    pa_mutex_unlock(p->mutex);
-
     pa_pstream_unref(p);
     return;
 
 fail:
 
-    p->dead = 1;
-
     if (p->die_callback)
         p->die_callback(p, p->die_callback_userdata);
 
-    pa_mutex_unlock(p->mutex);
-
+    pa_pstream_unlink(p);
     pa_pstream_unref(p);
 }
 
 static void io_callback(pa_iochannel*io, void *userdata) {
     pa_pstream *p = userdata;
 
-    assert(p);
-    assert(p->io == io);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p->io == io);
 
     do_something(p);
 }
@@ -217,9 +218,10 @@ static void io_callback(pa_iochannel*io, void *userdata) {
 static void defer_callback(pa_mainloop_api *m, pa_defer_event *e, void*userdata) {
     pa_pstream *p = userdata;
 
-    assert(p);
-    assert(p->defer_event == e);
-    assert(p->mainloop == m);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p->defer_event == e);
+    pa_assert(p->mainloop == m);
 
     do_something(p);
 }
@@ -229,9 +231,9 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd
 pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *pool) {
     pa_pstream *p;
 
-    assert(m);
-    assert(io);
-    assert(pool);
+    pa_assert(m);
+    pa_assert(io);
+    pa_assert(pool);
 
     p = pa_xnew(pa_pstream, 1);
     PA_REFCNT_INIT(p);
@@ -239,17 +241,15 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo
     pa_iochannel_set_callback(io, io_callback, p);
     p->dead = 0;
 
-    p->mutex = pa_mutex_new(1);
-
     p->mainloop = m;
     p->defer_event = m->defer_new(m, defer_callback, p);
     m->defer_enable(p->defer_event, 0);
 
     p->send_queue = pa_queue_new();
-    assert(p->send_queue);
 
     p->write.current = NULL;
     p->write.index = 0;
+    pa_memchunk_reset(&p->write.memchunk);
     p->read.memblock = NULL;
     p->read.packet = NULL;
     p->read.index = 0;
@@ -262,6 +262,10 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo
     p->drain_callback_userdata = NULL;
     p->die_callback = NULL;
     p->die_callback_userdata = NULL;
+    p->revoke_callback = NULL;
+    p->revoke_callback_userdata = NULL;
+    p->release_callback = NULL;
+    p->release_callback_userdata = NULL;
 
     p->mempool = pool;
 
@@ -281,56 +285,57 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo
     return p;
 }
 
-static void item_free(void *item, PA_GCC_UNUSED void *p) {
+static void item_free(void *item, PA_GCC_UNUSED void *q) {
     struct item_info *i = item;
-    assert(i);
+    pa_assert(i);
 
     if (i->type == PA_PSTREAM_ITEM_MEMBLOCK) {
-        assert(i->chunk.memblock);
+        pa_assert(i->chunk.memblock);
         pa_memblock_unref(i->chunk.memblock);
     } else if (i->type == PA_PSTREAM_ITEM_PACKET) {
-        assert(i->packet);
+        pa_assert(i->packet);
         pa_packet_unref(i->packet);
     }
 
-    pa_xfree(i);
+    if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0)
+        pa_xfree(i);
 }
 
 static void pstream_free(pa_pstream *p) {
-    assert(p);
+    pa_assert(p);
 
-    pa_pstream_close(p);
+    pa_pstream_unlink(p);
 
     pa_queue_free(p->send_queue, item_free, NULL);
 
     if (p->write.current)
         item_free(p->write.current, NULL);
 
+    if (p->write.memchunk.memblock)
+        pa_memblock_unref(p->write.memchunk.memblock);
+
     if (p->read.memblock)
         pa_memblock_unref(p->read.memblock);
 
     if (p->read.packet)
         pa_packet_unref(p->read.packet);
 
-    if (p->mutex)
-        pa_mutex_free(p->mutex);
-
     pa_xfree(p);
 }
 
 void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *creds) {
     struct item_info *i;
 
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
-    assert(packet);
-
-    pa_mutex_lock(p->mutex);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(packet);
 
     if (p->dead)
-        goto finish;
+        return;
+
+    if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
+        i = pa_xnew(struct item_info, 1);
 
-    i = pa_xnew(struct item_info, 1);
     i->type = PA_PSTREAM_ITEM_PACKET;
     i->packet = pa_packet_ref(packet);
 
@@ -340,37 +345,36 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre
 #endif
 
     pa_queue_push(p->send_queue, i);
-    p->mainloop->defer_enable(p->defer_event, 1);
 
-finish:
-
-    pa_mutex_unlock(p->mutex);
+    p->mainloop->defer_enable(p->defer_event, 1);
 }
 
 void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek_mode, const pa_memchunk *chunk) {
     size_t length, idx;
+    size_t bsm;
 
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
-    assert(channel != (uint32_t) -1);
-    assert(chunk);
-
-    pa_mutex_lock(p->mutex);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(channel != (uint32_t) -1);
+    pa_assert(chunk);
 
     if (p->dead)
-        goto finish;
+        return;
 
-    length = chunk->length;
     idx = 0;
+    length = chunk->length;
+
+    bsm = pa_mempool_block_size_max(p->mempool);
 
     while (length > 0) {
         struct item_info *i;
         size_t n;
 
-        i = pa_xnew(struct item_info, 1);
+        if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
+            i = pa_xnew(struct item_info, 1);
         i->type = PA_PSTREAM_ITEM_MEMBLOCK;
 
-        n = length < FRAME_SIZE_MAX_USE ? length : FRAME_SIZE_MAX_USE;
+        n = MIN(length, bsm);
         i->chunk.index = chunk->index + idx;
         i->chunk.length = n;
         i->chunk.memblock = pa_memblock_ref(chunk->memblock);
@@ -389,27 +393,20 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa
     }
 
     p->mainloop->defer_enable(p->defer_event, 1);
-
-finish:
-
-    pa_mutex_unlock(p->mutex);
 }
 
-static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userdata) {
+void pa_pstream_send_release(pa_pstream *p, uint32_t block_id) {
     struct item_info *item;
-    pa_pstream *p = userdata;
-
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
-
-    pa_mutex_lock(p->mutex);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     if (p->dead)
-        goto finish;
+        return;
 
 /*     pa_log("Releasing block %u", block_id); */
 
-    item = pa_xnew(struct item_info, 1);
+    if (!(item = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
+        item = pa_xnew(struct item_info, 1);
     item->type = PA_PSTREAM_ITEM_SHMRELEASE;
     item->block_id = block_id;
 #ifdef HAVE_CREDS
@@ -418,27 +415,35 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd
 
     pa_queue_push(p->send_queue, item);
     p->mainloop->defer_enable(p->defer_event, 1);
-
-finish:
-
-    pa_mutex_unlock(p->mutex);
 }
 
-static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userdata) {
-    struct item_info *item;
+/* might be called from thread context */
+static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userdata) {
     pa_pstream *p = userdata;
 
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
-
-    pa_mutex_lock(p->mutex);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     if (p->dead)
-        goto finish;
+        return;
 
+    if (p->release_callback)
+        p->release_callback(p, block_id, p->release_callback_userdata);
+    else
+        pa_pstream_send_release(p, block_id);
+}
+
+void pa_pstream_send_revoke(pa_pstream *p, uint32_t block_id) {
+    struct item_info *item;
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
+
+    if (p->dead)
+        return;
 /*     pa_log("Revoking block %u", block_id); */
 
-    item = pa_xnew(struct item_info, 1);
+    if (!(item = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
+        item = pa_xnew(struct item_info, 1);
     item->type = PA_PSTREAM_ITEM_SHMREVOKE;
     item->block_id = block_id;
 #ifdef HAVE_CREDS
@@ -447,21 +452,33 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda
 
     pa_queue_push(p->send_queue, item);
     p->mainloop->defer_enable(p->defer_event, 1);
+}
+
+/* might be called from thread context */
+static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userdata) {
+    pa_pstream *p = userdata;
 
-finish:
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
-    pa_mutex_unlock(p->mutex);
+    if (p->revoke_callback)
+        p->revoke_callback(p, block_id, p->revoke_callback_userdata);
+    else
+        pa_pstream_send_revoke(p, block_id);
 }
 
 static void prepare_next_write_item(pa_pstream *p) {
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
-    if (!(p->write.current = pa_queue_pop(p->send_queue)))
+    p->write.current = pa_queue_pop(p->send_queue);
+
+    if (!p->write.current)
         return;
 
     p->write.index = 0;
     p->write.data = NULL;
+    pa_memchunk_reset(&p->write.memchunk);
 
     p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = 0;
     p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl((uint32_t) -1);
@@ -471,7 +488,7 @@ static void prepare_next_write_item(pa_pstream *p) {
 
     if (p->write.current->type == PA_PSTREAM_ITEM_PACKET) {
 
-        assert(p->write.current->packet);
+        pa_assert(p->write.current->packet);
         p->write.data = p->write.current->packet->data;
         p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->packet->length);
 
@@ -489,8 +506,8 @@ static void prepare_next_write_item(pa_pstream *p) {
         uint32_t flags;
         int send_payload = 1;
 
-        assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK);
-        assert(p->write.current->chunk.memblock);
+        pa_assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK);
+        pa_assert(p->write.current->chunk.memblock);
 
         p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl(p->write.current->channel);
         p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = htonl((uint32_t) (((uint64_t) p->write.current->offset) >> 32));
@@ -502,7 +519,7 @@ static void prepare_next_write_item(pa_pstream *p) {
             uint32_t block_id, shm_id;
             size_t offset, length;
 
-            assert(p->export);
+            pa_assert(p->export);
 
             if (pa_memexport_put(p->export,
                                  p->write.current->chunk.memblock,
@@ -528,7 +545,9 @@ static void prepare_next_write_item(pa_pstream *p) {
 
         if (send_payload) {
             p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length);
-            p->write.data = (uint8_t*) p->write.current->chunk.memblock->data + p->write.current->chunk.index;
+            p->write.memchunk = p->write.current->chunk;
+            pa_memblock_ref(p->write.memchunk.memblock);
+            p->write.data = NULL;
         }
 
         p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = htonl(flags);
@@ -544,9 +563,10 @@ static int do_write(pa_pstream *p) {
     void *d;
     size_t l;
     ssize_t r;
+    pa_memblock *release_memblock = NULL;
 
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     if (!p->write.current)
         prepare_next_write_item(p);
@@ -558,72 +578,105 @@ static int do_write(pa_pstream *p) {
         d = (uint8_t*) p->write.descriptor + p->write.index;
         l = PA_PSTREAM_DESCRIPTOR_SIZE - p->write.index;
     } else {
-        assert(p->write.data);
+        pa_assert(p->write.data || p->write.memchunk.memblock);
+
+        if (p->write.data)
+            d = p->write.data;
+        else {
+            d = (uint8_t*) pa_memblock_acquire(p->write.memchunk.memblock) + p->write.memchunk.index;
+            release_memblock = p->write.memchunk.memblock;
+        }
 
-        d = (uint8_t*) p->write.data + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE;
+        d = (uint8_t*) d + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE;
         l = ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE);
     }
 
-    assert(l > 0);
+    pa_assert(l > 0);
 
 #ifdef HAVE_CREDS
     if (p->send_creds_now) {
 
         if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_creds)) < 0)
-            return -1;
+            goto fail;
 
         p->send_creds_now = 0;
     } else
 #endif
 
     if ((r = pa_iochannel_write(p->io, d, l)) < 0)
-        return -1;
+        goto fail;
+
+    if (release_memblock)
+        pa_memblock_release(release_memblock);
 
     p->write.index += r;
 
     if (p->write.index >= PA_PSTREAM_DESCRIPTOR_SIZE + ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH])) {
-        assert(p->write.current);
-        item_free(p->write.current, (void *) 1);
+        pa_assert(p->write.current);
+        item_free(p->write.current, NULL);
         p->write.current = NULL;
 
+        if (p->write.memchunk.memblock)
+            pa_memblock_unref(p->write.memchunk.memblock);
+
+        pa_memchunk_reset(&p->write.memchunk);
+
         if (p->drain_callback && !pa_pstream_is_pending(p))
             p->drain_callback(p, p->drain_callback_userdata);
     }
 
     return 0;
+
+fail:
+
+    if (release_memblock)
+        pa_memblock_release(release_memblock);
+
+    return -1;
 }
 
 static int do_read(pa_pstream *p) {
     void *d;
     size_t l;
     ssize_t r;
-
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_memblock *release_memblock = NULL;
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     if (p->read.index < PA_PSTREAM_DESCRIPTOR_SIZE) {
         d = (uint8_t*) p->read.descriptor + p->read.index;
         l = PA_PSTREAM_DESCRIPTOR_SIZE - p->read.index;
     } else {
-        assert(p->read.data);
-        d = (uint8_t*) p->read.data + p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE;
+        pa_assert(p->read.data || p->read.memblock);
+
+        if (p->read.data)
+            d = p->read.data;
+        else {
+            d = pa_memblock_acquire(p->read.memblock);
+            release_memblock = p->read.memblock;
+        }
+
+        d = (uint8_t*) d + p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE;
         l = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE);
     }
 
 #ifdef HAVE_CREDS
     {
-        int b = 0;
+        pa_bool_t b = 0;
 
         if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->read_creds, &b)) <= 0)
-            return -1;
+            goto fail;
 
         p->read_creds_valid = p->read_creds_valid || b;
     }
 #else
     if ((r = pa_iochannel_read(p->io, d, l)) <= 0)
-        return -1;
+        goto fail;
 #endif
 
+    if (release_memblock)
+        pa_memblock_release(release_memblock);
+
     p->read.index += r;
 
     if (p->read.index == PA_PSTREAM_DESCRIPTOR_SIZE) {
@@ -643,7 +696,7 @@ static int do_read(pa_pstream *p) {
 
 /*             pa_log("Got release frame for %u", ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); */
 
-            assert(p->export);
+            pa_assert(p->export);
             pa_memexport_process_release(p->export, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI]));
 
             goto frame_done;
@@ -654,7 +707,7 @@ static int do_read(pa_pstream *p) {
 
 /*             pa_log("Got revoke frame for %u", ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); */
 
-            assert(p->import);
+            pa_assert(p->import);
             pa_memimport_process_revoke(p->import, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI]));
 
             goto frame_done;
@@ -667,7 +720,7 @@ static int do_read(pa_pstream *p) {
             return -1;
         }
 
-        assert(!p->read.packet && !p->read.memblock);
+        pa_assert(!p->read.packet && !p->read.memblock);
 
         channel = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]);
 
@@ -704,7 +757,7 @@ static int do_read(pa_pstream *p) {
                 /* Frame is a memblock frame */
 
                 p->read.memblock = pa_memblock_new(p->mempool, length);
-                p->read.data = p->read.memblock->data;
+                p->read.data = NULL;
             } else {
 
                 pa_log_warn("Recieved memblock frame with invalid flags value.");
@@ -771,9 +824,9 @@ static int do_read(pa_pstream *p) {
             } else {
                 pa_memblock *b;
 
-                assert((ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]) & PA_FLAG_SHMMASK) == PA_FLAG_SHMDATA);
+                pa_assert((ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]) & PA_FLAG_SHMMASK) == PA_FLAG_SHMDATA);
 
-                assert(p->import);
+                pa_assert(p->import);
 
                 if (!(b = pa_memimport_get(p->import,
                                           ntohl(p->read.shm_info[PA_PSTREAM_SHM_BLOCKID]),
@@ -791,7 +844,7 @@ static int do_read(pa_pstream *p) {
 
                     chunk.memblock = b;
                     chunk.index = 0;
-                    chunk.length = b->length;
+                    chunk.length = pa_memblock_get_length(b);
 
                     offset = (int64_t) (
                             (((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])) << 32) |
@@ -819,92 +872,104 @@ frame_done:
     p->read.memblock = NULL;
     p->read.packet = NULL;
     p->read.index = 0;
+    p->read.data = NULL;
 
 #ifdef HAVE_CREDS
     p->read_creds_valid = 0;
 #endif
 
     return 0;
+
+fail:
+    if (release_memblock)
+        pa_memblock_release(release_memblock);
+
+    return -1;
 }
 
 void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) {
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
-    pa_mutex_lock(p->mutex);
     p->die_callback = cb;
     p->die_callback_userdata = userdata;
-    pa_mutex_unlock(p->mutex);
 }
 
 void pa_pstream_set_drain_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) {
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
-    pa_mutex_lock(p->mutex);
     p->drain_callback = cb;
     p->drain_callback_userdata = userdata;
-    pa_mutex_unlock(p->mutex);
 }
 
 void pa_pstream_set_recieve_packet_callback(pa_pstream *p, pa_pstream_packet_cb_t cb, void *userdata) {
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
-    pa_mutex_lock(p->mutex);
     p->recieve_packet_callback = cb;
     p->recieve_packet_callback_userdata = userdata;
-    pa_mutex_unlock(p->mutex);
 }
 
 void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, pa_pstream_memblock_cb_t cb, void *userdata) {
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
-    pa_mutex_lock(p->mutex);
     p->recieve_memblock_callback = cb;
     p->recieve_memblock_callback_userdata = userdata;
-    pa_mutex_unlock(p->mutex);
+}
+
+void pa_pstream_set_release_callback(pa_pstream *p, pa_pstream_block_id_cb_t cb, void *userdata) {
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
+
+    p->release_callback = cb;
+    p->release_callback_userdata = userdata;
+}
+
+void pa_pstream_set_revoke_callback(pa_pstream *p, pa_pstream_block_id_cb_t cb, void *userdata) {
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
+
+    p->release_callback = cb;
+    p->release_callback_userdata = userdata;
 }
 
 int pa_pstream_is_pending(pa_pstream *p) {
     int b;
 
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
-
-    pa_mutex_lock(p->mutex);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     if (p->dead)
         b = 0;
     else
         b = p->write.current || !pa_queue_is_empty(p->send_queue);
 
-    pa_mutex_unlock(p->mutex);
-
     return b;
 }
 
 void pa_pstream_unref(pa_pstream*p) {
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     if (PA_REFCNT_DEC(p) <= 0)
         pstream_free(p);
 }
 
 pa_pstream* pa_pstream_ref(pa_pstream*p) {
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     PA_REFCNT_INC(p);
     return p;
 }
 
-void pa_pstream_close(pa_pstream *p) {
-    assert(p);
+void pa_pstream_unlink(pa_pstream *p) {
+    pa_assert(p);
 
-    pa_mutex_lock(p->mutex);
+    if (p->dead)
+        return;
 
     p->dead = 1;
 
@@ -932,15 +997,11 @@ void pa_pstream_close(pa_pstream *p) {
     p->drain_callback = NULL;
     p->recieve_packet_callback = NULL;
     p->recieve_memblock_callback = NULL;
-
-    pa_mutex_unlock(p->mutex);
 }
 
 void pa_pstream_use_shm(pa_pstream *p, int enable) {
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
-
-    pa_mutex_lock(p->mutex);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     p->use_shm = enable;
 
@@ -956,6 +1017,4 @@ void pa_pstream_use_shm(pa_pstream *p, int enable) {
             p->export = NULL;
         }
     }
-
-    pa_mutex_unlock(p->mutex);
 }
index 5900eceabb5eba887d3fc195688c091545ea0f96..72babea9b6156f01200512faf16190a04ff369e4 100644 (file)
@@ -41,6 +41,7 @@ typedef struct pa_pstream pa_pstream;
 typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata);
 typedef void (*pa_pstream_memblock_cb_t)(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata);
 typedef void (*pa_pstream_notify_cb_t)(pa_pstream *p, void *userdata);
+typedef void (*pa_pstream_block_id_cb_t)(pa_pstream *p, uint32_t block_id, void *userdata);
 
 pa_pstream* pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *p);
 void pa_pstream_unref(pa_pstream*p);
@@ -48,17 +49,20 @@ pa_pstream* pa_pstream_ref(pa_pstream*p);
 
 void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *creds);
 void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk);
+void pa_pstream_send_release(pa_pstream *p, uint32_t block_id);
+void pa_pstream_send_revoke(pa_pstream *p, uint32_t block_id);
 
 void pa_pstream_set_recieve_packet_callback(pa_pstream *p, pa_pstream_packet_cb_t cb, void *userdata);
 void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, pa_pstream_memblock_cb_t cb, void *userdata);
 void pa_pstream_set_drain_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata);
-
 void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata);
+void pa_pstream_set_release_callback(pa_pstream *p, pa_pstream_block_id_cb_t cb, void *userdata);
+void pa_pstream_set_revoke_callback(pa_pstream *p, pa_pstream_block_id_cb_t cb, void *userdata);
 
 int pa_pstream_is_pending(pa_pstream *p);
 
 void pa_pstream_use_shm(pa_pstream *p, int enable);
 
-void pa_pstream_close(pa_pstream *p);
+void pa_pstream_unlink(pa_pstream *p);
 
 #endif
index 1dd0f6061bebb6e03ab7ed98869b4c71362c1f16..9b6a37f02c82e906471dc2dcc930025388cd9f8e 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdlib.h>
 
 #include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/flist.h>
 
 #include "queue.h"
 
+PA_STATIC_FLIST_DECLARE(entries, 0, pa_xfree);
+
 struct queue_entry {
     struct queue_entry *next;
     void *data;
@@ -44,25 +47,24 @@ struct pa_queue {
 
 pa_queue* pa_queue_new(void) {
     pa_queue *q = pa_xnew(pa_queue, 1);
+
     q->front = q->back = NULL;
     q->length = 0;
+
     return q;
 }
 
 void pa_queue_free(pa_queue* q, void (*destroy)(void *p, void *userdata), void *userdata) {
-    struct queue_entry *e;
-    assert(q);
-
-    e = q->front;
-    while (e) {
-        struct queue_entry *n = e->next;
+    void *data;
+    pa_assert(q);
 
+    while ((data = pa_queue_pop(q)))
         if (destroy)
-            destroy(e->data, userdata);
+            destroy(data, userdata);
 
-        pa_xfree(e);
-        e = n;
-    }
+    pa_assert(!q->front);
+    pa_assert(!q->back);
+    pa_assert(q->length == 0);
 
     pa_xfree(q);
 }
@@ -70,14 +72,20 @@ void pa_queue_free(pa_queue* q, void (*destroy)(void *p, void *userdata), void *
 void pa_queue_push(pa_queue *q, void *p) {
     struct queue_entry *e;
 
-    e = pa_xnew(struct queue_entry, 1);
+    pa_assert(q);
+    pa_assert(p);
+
+    if (!(e = pa_flist_pop(PA_STATIC_FLIST_GET(entries))))
+        e = pa_xnew(struct queue_entry, 1);
+
     e->data = p;
     e->next = NULL;
 
-    if (q->back)
+    if (q->back) {
+        pa_assert(q->front);
         q->back->next = e;
-    else {
-        assert(!q->front);
+    else {
+        pa_assert(!q->front);
         q->front = e;
     }
 
@@ -88,17 +96,22 @@ void pa_queue_push(pa_queue *q, void *p) {
 void* pa_queue_pop(pa_queue *q) {
     void *p;
     struct queue_entry *e;
-    assert(q);
+    pa_assert(q);
 
     if (!(e = q->front))
         return NULL;
 
     q->front = e->next;
-    if (q->back == e)
+
+    if (q->back == e) {
+        pa_assert(!e->next);
         q->back = NULL;
+    }
 
     p = e->data;
-    pa_xfree(e);
+
+    if (pa_flist_push(PA_STATIC_FLIST_GET(entries), e) < 0)
+        pa_xfree(e);
 
     q->length--;
 
@@ -106,6 +119,7 @@ void* pa_queue_pop(pa_queue *q) {
 }
 
 int pa_queue_is_empty(pa_queue *q) {
-    assert(q);
+    pa_assert(q);
+
     return q->length == 0;
 }
index 3f5919173676a898128eb97af8b301cb60a92a17..87afebfa6bf91bb6784309ac4e121be0bc5639ec 100644 (file)
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
-#include <assert.h>
 #include <time.h>
 
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "random.h"
 
 static int has_whined = 0;
 
-static const char *devices[] = { "/dev/urandom", "/dev/random", NULL };
+static const char * const devices[] = { "/dev/urandom", "/dev/random", NULL };
 
 static int random_proper(void *ret_data, size_t length) {
 #ifdef OS_IS_WIN32
-    assert(ret_data && length);
+    pa_assert(ret_data);
+    pa_assert(length > 0);
 
     return -1;
 
@@ -53,9 +54,10 @@ static int random_proper(void *ret_data, size_t length) {
 
     int fd, ret = -1;
     ssize_t r = 0;
-    const char **device;
+    const char *const * device;
 
-    assert(ret_data && length);
+    pa_assert(ret_data);
+    pa_assert(length > 0);
 
     device = devices;
 
@@ -67,7 +69,7 @@ static int random_proper(void *ret_data, size_t length) {
             if ((r = pa_loop_read(fd, ret_data, length, NULL)) < 0 || (size_t) r != length)
                 ret = -1;
 
-            close(fd);
+            pa_close(fd);
         } else
             ret = -1;
 
@@ -84,7 +86,7 @@ void pa_random_seed(void) {
 
     if (random_proper(&seed, sizeof(unsigned int)) < 0) {
         if (!has_whined)
-            pa_log_warn("failed to get proper entropy. Falling back to seeding with current time.");
+            pa_log_warn("Failed to get proper entropy. Falling back to seeding with current time.");
         has_whined = 1;
 
         seed = (unsigned int) time(NULL);
@@ -97,13 +99,14 @@ void pa_random(void *ret_data, size_t length) {
     uint8_t *p;
     size_t l;
 
-    assert(ret_data && length);
+    pa_assert(ret_data);
+    pa_assert(length > 0);
 
     if (random_proper(ret_data, length) >= 0)
         return;
 
     if (!has_whined)
-        pa_log_warn("failed to get proper entropy. Falling back to unsecure pseudo RNG.");
+        pa_log_warn("Failed to get proper entropy. Falling back to unsecure pseudo RNG.");
     has_whined = 1;
 
     for (p = ret_data, l = length; l > 0; p++, l--)
index 43433ff84100f239e654e49c04df926a8fe70777..64271ab27a77ffc5672102337484397a7e72a5e0 100644 (file)
 #include <pulsecore/atomic.h>
 
 #define PA_REFCNT_DECLARE \
-  pa_atomic_int_t _ref
+    pa_atomic_t _ref
 
 #define PA_REFCNT_INIT(p) \
-  pa_atomic_store(&p->_ref, 1)
+    pa_atomic_store(&(p)->_ref, 1)
 
 #define PA_REFCNT_INC(p) \
-  pa_atomic_inc(&p->_ref)
+    pa_atomic_inc(&(p)->_ref)
 
 #define PA_REFCNT_DEC(p) \
-  (pa_atomic_dec(&p->_ref)-1)
+    (pa_atomic_dec(&(p)->_ref)-1)
 
 #define PA_REFCNT_VALUE(p) \
-  pa_atomic_load(&p->_ref)
+    pa_atomic_load(&(p)->_ref)
 
 #endif
index 3827ff94a30e0049a6561eee4f8b5699453788c4..5bbc6bf4412f0962bf77ca8691111aad1f8ecacf 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <string.h>
 
+#if HAVE_LIBSAMPLERATE
 #include <samplerate.h>
+#endif
+
 #include <liboil/liboilfuncs.h>
 #include <liboil/liboil.h>
 
 #include <pulse/xmalloc.h>
-
 #include <pulsecore/sconv.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+
+#include "speexwrap.h"
+
+#include "ffmpeg/avcodec.h"
 
 #include "resampler.h"
 
+/* Number of samples of extra space we allow the resamplers to return */
+#define EXTRA_SAMPLES 128
+
 struct pa_resampler {
     pa_resample_method_t resample_method;
     pa_sample_spec i_ss, o_ss;
     pa_channel_map i_cm, o_cm;
-    size_t i_fz, o_fz;
+    size_t i_fz, o_fz, w_sz;
     pa_mempool *mempool;
 
-    void (*impl_free)(pa_resampler *r);
-    void (*impl_update_input_rate)(pa_resampler *r, uint32_t rate);
-    void (*impl_run)(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out);
-    void *impl_data;
-};
-
-struct impl_libsamplerate {
-    pa_memblock *buf1_block, *buf2_block, *buf3_block, *buf4_block;
-    float* buf1, *buf2, *buf3, *buf4;
+    pa_memchunk buf1, buf2, buf3, buf4;
     unsigned buf1_samples, buf2_samples, buf3_samples, buf4_samples;
 
-    pa_convert_to_float32ne_func_t to_float32ne_func;
-    pa_convert_from_float32ne_func_t from_float32ne_func;
-    SRC_STATE *src_state;
+    pa_sample_format_t work_format;
+
+    pa_convert_func_t to_work_format_func;
+    pa_convert_func_t from_work_format_func;
 
     int map_table[PA_CHANNELS_MAX][PA_CHANNELS_MAX];
     int map_required;
-};
 
-struct impl_trivial {
-    unsigned o_counter;
-    unsigned i_counter;
+    void (*impl_free)(pa_resampler *r);
+    void (*impl_update_rates)(pa_resampler *r);
+    void (*impl_resample)(pa_resampler *r, const pa_memchunk *in, unsigned in_samples, pa_memchunk *out, unsigned *out_samples);
+
+    struct { /* data specific to the trivial resampler */
+        unsigned o_counter;
+        unsigned i_counter;
+    } trivial;
+
+#ifdef HAVE_LIBSAMPLERATE
+    struct { /* data specific to libsamplerate */
+        SRC_STATE *state;
+    } src;
+#endif
+
+    struct { /* data specific to speex */
+        SpeexResamplerState* state;
+    } speex;
+
+    struct { /* data specific to ffmpeg */
+        struct AVResampleContext *state;
+        pa_memchunk buf[PA_CHANNELS_MAX];
+    } ffmpeg;
 };
 
-static int libsamplerate_init(pa_resampler*r);
+static int copy_init(pa_resampler *r);
 static int trivial_init(pa_resampler*r);
+static int speex_init(pa_resampler*r);
+static int ffmpeg_init(pa_resampler*r);
+#ifdef HAVE_LIBSAMPLERATE
+static int libsamplerate_init(pa_resampler*r);
+#endif
+
+static void calc_map_table(pa_resampler *r);
+
+static int (* const init_table[])(pa_resampler*r) = {
+#ifdef HAVE_LIBSAMPLERATE
+    [PA_RESAMPLER_SRC_SINC_BEST_QUALITY]   = libsamplerate_init,
+    [PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY] = libsamplerate_init,
+    [PA_RESAMPLER_SRC_SINC_FASTEST]        = libsamplerate_init,
+    [PA_RESAMPLER_SRC_ZERO_ORDER_HOLD]     = libsamplerate_init,
+    [PA_RESAMPLER_SRC_LINEAR]              = libsamplerate_init,
+#else
+    [PA_RESAMPLER_SRC_SINC_BEST_QUALITY]   = NULL,
+    [PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY] = NULL,
+    [PA_RESAMPLER_SRC_SINC_FASTEST]        = NULL,
+    [PA_RESAMPLER_SRC_ZERO_ORDER_HOLD]     = NULL,
+    [PA_RESAMPLER_SRC_LINEAR]              = NULL,
+#endif
+    [PA_RESAMPLER_TRIVIAL]                 = trivial_init,
+    [PA_RESAMPLER_SPEEX_FLOAT_BASE+0]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FLOAT_BASE+1]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FLOAT_BASE+2]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FLOAT_BASE+3]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FLOAT_BASE+4]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FLOAT_BASE+5]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FLOAT_BASE+6]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FLOAT_BASE+7]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FLOAT_BASE+8]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FLOAT_BASE+9]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FLOAT_BASE+10]     = speex_init,
+    [PA_RESAMPLER_SPEEX_FIXED_BASE+0]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FIXED_BASE+1]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FIXED_BASE+2]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FIXED_BASE+3]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FIXED_BASE+4]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FIXED_BASE+5]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FIXED_BASE+6]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FIXED_BASE+7]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FIXED_BASE+8]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FIXED_BASE+9]      = speex_init,
+    [PA_RESAMPLER_SPEEX_FIXED_BASE+10]     = speex_init,
+    [PA_RESAMPLER_FFMPEG]                  = ffmpeg_init,
+    [PA_RESAMPLER_AUTO]                    = NULL,
+    [PA_RESAMPLER_COPY]                    = copy_init
+};
+
+static inline size_t sample_size(pa_sample_format_t f) {
+    pa_sample_spec ss = {
+        .format = f,
+        .rate = 0,
+        .channels = 1
+    };
+
+    return pa_sample_size(&ss);
+}
 
 pa_resampler* pa_resampler_new(
         pa_mempool *pool,
@@ -79,25 +159,51 @@ pa_resampler* pa_resampler_new(
         const pa_channel_map *am,
         const pa_sample_spec *b,
         const pa_channel_map *bm,
-        pa_resample_method_t resample_method) {
+        pa_resample_method_t resample_method,
+        int variable_rate) {
 
     pa_resampler *r = NULL;
 
-    assert(pool);
-    assert(a);
-    assert(b);
-    assert(pa_sample_spec_valid(a));
-    assert(pa_sample_spec_valid(b));
-    assert(resample_method != PA_RESAMPLER_INVALID);
+    pa_assert(pool);
+    pa_assert(a);
+    pa_assert(b);
+    pa_assert(pa_sample_spec_valid(a));
+    pa_assert(pa_sample_spec_valid(b));
+    pa_assert(resample_method >= 0);
+    pa_assert(resample_method < PA_RESAMPLER_MAX);
+
+    /* Fix method */
+
+    if (!variable_rate && a->rate == b->rate) {
+        pa_log_info("Forcing resampler 'copy', because of fixed, identical sample rates.");
+        resample_method = PA_RESAMPLER_COPY;
+    }
+
+    if (!pa_resample_method_supported(resample_method)) {
+        pa_log_warn("Support for resampler '%s' not compiled in, reverting to 'auto'.", pa_resample_method_to_string(resample_method));
+        resample_method = PA_RESAMPLER_AUTO;
+    }
+
+    if (resample_method == PA_RESAMPLER_FFMPEG && variable_rate) {
+        pa_log_info("Resampler 'ffmpeg' cannot do variable rate, reverting to resampler 'auto'.");
+        resample_method = PA_RESAMPLER_AUTO;
+    }
+
+    if (resample_method == PA_RESAMPLER_COPY && (variable_rate || a->rate != b->rate)) {
+        pa_log_info("Resampler 'copy' cannot change sampling rate, reverting to resampler 'auto'.");
+        resample_method = PA_RESAMPLER_AUTO;
+    }
+
+    if (resample_method == PA_RESAMPLER_AUTO)
+        resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 0;
 
     r = pa_xnew(pa_resampler, 1);
-    r->impl_data = NULL;
     r->mempool = pool;
     r->resample_method = resample_method;
 
     r->impl_free = NULL;
-    r->impl_update_input_rate = NULL;
-    r->impl_run = NULL;
+    r->impl_update_rates = NULL;
+    r->impl_resample = NULL;
 
     /* Fill sample specs */
     r->i_ss = *a;
@@ -116,25 +222,66 @@ pa_resampler* pa_resampler_new(
     r->i_fz = pa_frame_size(a);
     r->o_fz = pa_frame_size(b);
 
-    /* Choose implementation */
-    if (a->channels != b->channels ||
-        a->format != b->format ||
-        !pa_channel_map_equal(&r->i_cm, &r->o_cm) ||
-        resample_method != PA_RESAMPLER_TRIVIAL) {
+    pa_memchunk_reset(&r->buf1);
+    pa_memchunk_reset(&r->buf2);
+    pa_memchunk_reset(&r->buf3);
+    pa_memchunk_reset(&r->buf4);
+
+    r->buf1_samples = r->buf2_samples = r->buf3_samples = r->buf4_samples = 0;
+
+    calc_map_table(r);
+
+    pa_log_info("Using resampler '%s'", pa_resample_method_to_string(resample_method));
+
+    if ((resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) ||
+        (resample_method == PA_RESAMPLER_FFMPEG))
+        r->work_format = PA_SAMPLE_S16NE;
+    else if (resample_method == PA_RESAMPLER_TRIVIAL || resample_method == PA_RESAMPLER_COPY) {
 
-        /* Use the libsamplerate based resampler for the complicated cases */
-        if (resample_method == PA_RESAMPLER_TRIVIAL)
-            r->resample_method = PA_RESAMPLER_SRC_ZERO_ORDER_HOLD;
+        if (r->map_required || a->format != b->format) {
 
-        if (libsamplerate_init(r) < 0)
+            if (a->format == PA_SAMPLE_FLOAT32NE || a->format == PA_SAMPLE_FLOAT32RE ||
+                b->format == PA_SAMPLE_FLOAT32NE || b->format == PA_SAMPLE_FLOAT32RE)
+                r->work_format = PA_SAMPLE_FLOAT32NE;
+            else
+                r->work_format = PA_SAMPLE_S16NE;
+
+        } else
+            r->work_format = a->format;
+
+    } else
+        r->work_format = PA_SAMPLE_FLOAT32NE;
+
+    pa_log_info("Using %s as working format.", pa_sample_format_to_string(r->work_format));
+
+    r->w_sz = sample_size(r->work_format);
+
+    if (r->i_ss.format == r->work_format)
+        r->to_work_format_func = NULL;
+    else if (r->work_format == PA_SAMPLE_FLOAT32NE) {
+        if (!(r->to_work_format_func = pa_get_convert_to_float32ne_function(r->i_ss.format)))
+            goto fail;
+    } else {
+        pa_assert(r->work_format == PA_SAMPLE_S16NE);
+        if (!(r->to_work_format_func = pa_get_convert_to_s16ne_function(r->i_ss.format)))
             goto fail;
+    }
 
+    if (r->o_ss.format == r->work_format)
+        r->from_work_format_func = NULL;
+    else if (r->work_format == PA_SAMPLE_FLOAT32NE) {
+        if (!(r->from_work_format_func = pa_get_convert_from_float32ne_function(r->o_ss.format)))
+            goto fail;
     } else {
-        /* Use our own simple non-fp resampler for the trivial cases and when the user selects it */
-        if (trivial_init(r) < 0)
+        pa_assert(r->work_format == PA_SAMPLE_S16NE);
+        if (!(r->from_work_format_func = pa_get_convert_from_s16ne_function(r->o_ss.format)))
             goto fail;
     }
 
+    /* initialize implementation */
+    if (init_table[resample_method](r) < 0)
+        goto fail;
+
     return r;
 
 fail:
@@ -145,41 +292,85 @@ fail:
 }
 
 void pa_resampler_free(pa_resampler *r) {
-    assert(r);
+    pa_assert(r);
 
     if (r->impl_free)
         r->impl_free(r);
 
+    if (r->buf1.memblock)
+        pa_memblock_unref(r->buf1.memblock);
+    if (r->buf2.memblock)
+        pa_memblock_unref(r->buf2.memblock);
+    if (r->buf3.memblock)
+        pa_memblock_unref(r->buf3.memblock);
+    if (r->buf4.memblock)
+        pa_memblock_unref(r->buf4.memblock);
+
     pa_xfree(r);
 }
 
 void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) {
-    assert(r);
-    assert(rate > 0);
+    pa_assert(r);
+    pa_assert(rate > 0);
 
     if (r->i_ss.rate == rate)
         return;
 
     r->i_ss.rate = rate;
 
-    if (r->impl_update_input_rate)
-        r->impl_update_input_rate(r, rate);
+    r->impl_update_rates(r);
 }
 
-void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
-    assert(r && in && out && r->impl_run);
+void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) {
+    pa_assert(r);
+    pa_assert(rate > 0);
 
-    r->impl_run(r, in, out);
+    if (r->o_ss.rate == rate)
+        return;
+
+    r->o_ss.rate = rate;
+
+    r->impl_update_rates(r);
 }
 
 size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
-    assert(r);
+    pa_assert(r);
 
     return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz;
 }
 
+size_t pa_resampler_max_block_size(pa_resampler *r) {
+    size_t block_size_max;
+    pa_sample_spec ss;
+    size_t fs;
+
+    pa_assert(r);
+
+    block_size_max = pa_mempool_block_size_max(r->mempool);
+
+    /* We deduce the "largest" sample spec we're using during the
+     * conversion */
+    ss = r->i_ss;
+    if (r->o_ss.channels > ss.channels)
+        ss.channels = r->o_ss.channels;
+
+    /* We silently assume that the format enum is ordered by size */
+    if (r->o_ss.format > ss.format)
+        ss.format = r->o_ss.format;
+    if (r->work_format > ss.format)
+        ss.format = r->work_format;
+
+    if (r->o_ss.rate > ss.rate)
+        ss.rate = r->o_ss.rate;
+
+    fs = pa_frame_size(&ss);
+
+    return (((block_size_max/fs + EXTRA_SAMPLES)*r->i_ss.rate)/ss.rate)*r->i_fz;
+}
+
 pa_resample_method_t pa_resampler_get_method(pa_resampler *r) {
-    assert(r);
+    pa_assert(r);
+
     return r->resample_method;
 }
 
@@ -189,7 +380,32 @@ static const char * const resample_methods[] = {
     "src-sinc-fastest",
     "src-zero-order-hold",
     "src-linear",
-    "trivial"
+    "trivial",
+    "speex-float-0",
+    "speex-float-1",
+    "speex-float-2",
+    "speex-float-3",
+    "speex-float-4",
+    "speex-float-5",
+    "speex-float-6",
+    "speex-float-7",
+    "speex-float-8",
+    "speex-float-9",
+    "speex-float-10",
+    "speex-fixed-0",
+    "speex-fixed-1",
+    "speex-fixed-2",
+    "speex-fixed-3",
+    "speex-fixed-4",
+    "speex-fixed-5",
+    "speex-fixed-6",
+    "speex-fixed-7",
+    "speex-fixed-8",
+    "speex-fixed-9",
+    "speex-fixed-10",
+    "ffmpeg",
+    "auto",
+    "copy"
 };
 
 const char *pa_resample_method_to_string(pa_resample_method_t m) {
@@ -200,52 +416,43 @@ const char *pa_resample_method_to_string(pa_resample_method_t m) {
     return resample_methods[m];
 }
 
-pa_resample_method_t pa_parse_resample_method(const char *string) {
-    pa_resample_method_t m;
+int pa_resample_method_supported(pa_resample_method_t m) {
 
-    assert(string);
+    if (m < 0 || m >= PA_RESAMPLER_MAX)
+        return 0;
 
-    for (m = 0; m < PA_RESAMPLER_MAX; m++)
-        if (!strcmp(string, resample_methods[m]))
-            return m;
+#ifndef HAVE_LIBSAMPLERATE
+    if (m <= PA_RESAMPLER_SRC_LINEAR)
+        return 0;
+#endif
 
-    return PA_RESAMPLER_INVALID;
+    return 1;
 }
 
+pa_resample_method_t pa_parse_resample_method(const char *string) {
+    pa_resample_method_t m;
 
-/*** libsamplerate based implementation ***/
-
-static void libsamplerate_free(pa_resampler *r) {
-    struct impl_libsamplerate *u;
+    pa_assert(string);
 
-    assert(r);
-    assert(r->impl_data);
+    for (m = 0; m < PA_RESAMPLER_MAX; m++)
+        if (!strcmp(string, resample_methods[m]))
+            return m;
 
-    u = r->impl_data;
+    if (!strcmp(string, "speex-fixed"))
+        return PA_RESAMPLER_SPEEX_FIXED_BASE + 0;
 
-    if (u->src_state)
-        src_delete(u->src_state);
+    if (!strcmp(string, "speex-float"))
+        return PA_RESAMPLER_SPEEX_FLOAT_BASE + 0;
 
-    if (u->buf1_block)
-        pa_memblock_unref(u->buf1_block);
-    if (u->buf2_block)
-        pa_memblock_unref(u->buf2_block);
-    if (u->buf3_block)
-        pa_memblock_unref(u->buf3_block);
-    if (u->buf4_block)
-        pa_memblock_unref(u->buf4_block);
-    pa_xfree(u);
+    return PA_RESAMPLER_INVALID;
 }
 
 static void calc_map_table(pa_resampler *r) {
-    struct impl_libsamplerate *u;
     unsigned oc;
-    assert(r);
-    assert(r->impl_data);
 
-    u = r->impl_data;
+    pa_assert(r);
 
-    if (!(u->map_required = (!pa_channel_map_equal(&r->i_cm, &r->o_cm) || r->i_ss.channels != r->o_ss.channels)))
+    if (!(r->map_required = (r->i_ss.channels != r->o_ss.channels || !pa_channel_map_equal(&r->i_cm, &r->o_cm))))
         return;
 
     for (oc = 0; oc < r->o_ss.channels; oc++) {
@@ -263,392 +470,590 @@ static void calc_map_table(pa_resampler *r) {
                 (a == PA_CHANNEL_POSITION_LEFT && b == PA_CHANNEL_POSITION_MONO) ||
                 (a == PA_CHANNEL_POSITION_RIGHT && b == PA_CHANNEL_POSITION_MONO))
 
-                u->map_table[oc][i++] = ic;
+                r->map_table[oc][i++] = ic;
         }
 
         /* Add an end marker */
         if (i < PA_CHANNELS_MAX)
-            u->map_table[oc][i] = -1;
+            r->map_table[oc][i] = -1;
     }
 }
 
-static float * convert_to_float(pa_resampler *r, void *input, unsigned n_frames) {
-    struct impl_libsamplerate *u;
+static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input) {
     unsigned n_samples;
+    void *src, *dst;
 
-    assert(r);
-    assert(input);
-    assert(r->impl_data);
-    u = r->impl_data;
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(input->memblock);
 
-    /* Convert the incoming sample into floats and place them in buf1 */
+    /* Convert the incoming sample into the work sample format and place them in buf1 */
 
-    if (!u->to_float32ne_func)
+    if (!r->to_work_format_func || !input->length)
         return input;
 
-    n_samples = n_frames * r->i_ss.channels;
+    n_samples = (input->length / r->i_fz) * r->i_ss.channels;
 
-    if (u->buf1_samples < n_samples) {
-        if (u->buf1_block)
-            pa_memblock_unref(u->buf1_block);
+    r->buf1.index = 0;
+    r->buf1.length = r->w_sz * n_samples;
 
-        u->buf1_samples = n_samples;
-        u->buf1_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples);
-        u->buf1 = u->buf1_block->data;
+    if (!r->buf1.memblock || r->buf1_samples < n_samples) {
+        if (r->buf1.memblock)
+            pa_memblock_unref(r->buf1.memblock);
+
+        r->buf1_samples = n_samples;
+        r->buf1.memblock = pa_memblock_new(r->mempool, r->buf1.length);
     }
 
-    u->to_float32ne_func(n_samples, input, u->buf1);
+    src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
+    dst = (uint8_t*) pa_memblock_acquire(r->buf1.memblock);
+
+    r->to_work_format_func(n_samples, src, dst);
+
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(r->buf1.memblock);
 
-    return u->buf1;
+    return &r->buf1;
 }
 
-static float *remap_channels(pa_resampler *r, float *input, unsigned n_frames) {
-    struct impl_libsamplerate *u;
-    unsigned n_samples;
+static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
+    unsigned in_n_samples, out_n_samples, n_frames;
     int i_skip, o_skip;
     unsigned oc;
+    void *src, *dst;
 
-    assert(r);
-    assert(input);
-    assert(r->impl_data);
-    u = r->impl_data;
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(input->memblock);
 
     /* Remap channels and place the result int buf2 */
 
-    if (!u->map_required)
+    if (!r->map_required || !input->length)
         return input;
 
-    n_samples = n_frames * r->o_ss.channels;
+    in_n_samples = input->length / r->w_sz;
+    n_frames = in_n_samples / r->i_ss.channels;
+    out_n_samples = n_frames * r->o_ss.channels;
+
+    r->buf2.index = 0;
+    r->buf2.length = r->w_sz * out_n_samples;
 
-    if (u->buf2_samples < n_samples) {
-        if (u->buf2_block)
-            pa_memblock_unref(u->buf2_block);
+    if (!r->buf2.memblock || r->buf2_samples < out_n_samples) {
+        if (r->buf2.memblock)
+            pa_memblock_unref(r->buf2.memblock);
 
-        u->buf2_samples = n_samples;
-        u->buf2_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples);
-        u->buf2 = u->buf2_block->data;
+        r->buf2_samples = out_n_samples;
+        r->buf2.memblock = pa_memblock_new(r->mempool, r->buf2.length);
     }
 
-    memset(u->buf2, 0, n_samples * sizeof(float));
+    src = ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
+    dst = pa_memblock_acquire(r->buf2.memblock);
 
-    o_skip = sizeof(float) * r->o_ss.channels;
-    i_skip = sizeof(float) * r->i_ss.channels;
+    memset(dst, 0, r->buf2.length);
 
-    for (oc = 0; oc < r->o_ss.channels; oc++) {
-        unsigned i;
-        static const float one = 1.0;
-
-        for (i = 0; i < PA_CHANNELS_MAX && u->map_table[oc][i] >= 0; i++)
-            oil_vectoradd_f32(
-                u->buf2 + oc, o_skip,
-                u->buf2 + oc, o_skip,
-                input + u->map_table[oc][i], i_skip,
-                n_frames,
-                &one, &one);
+    o_skip = r->w_sz * r->o_ss.channels;
+    i_skip = r->w_sz * r->i_ss.channels;
+
+    switch (r->work_format) {
+        case PA_SAMPLE_FLOAT32NE:
+
+            for (oc = 0; oc < r->o_ss.channels; oc++) {
+                unsigned i;
+                static const float one = 1.0;
+
+                for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++)
+                    oil_vectoradd_f32(
+                            (float*) dst + oc, o_skip,
+                            (float*) dst + oc, o_skip,
+                            (float*) src + r->map_table[oc][i], i_skip,
+                            n_frames,
+                            &one, &one);
+            }
+
+            break;
+
+        case PA_SAMPLE_S16NE:
+
+            for (oc = 0; oc < r->o_ss.channels; oc++) {
+                unsigned i;
+                static const int16_t one = 1;
+
+                for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++)
+                    oil_vectoradd_s16(
+                            (int16_t*) dst + oc, o_skip,
+                            (int16_t*) dst + oc, o_skip,
+                            (int16_t*) src + r->map_table[oc][i], i_skip,
+                            n_frames,
+                            &one, &one);
+            }
+
+            break;
+
+        default:
+            pa_assert_not_reached();
     }
 
-    return u->buf2;
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(r->buf2.memblock);
+
+    r->buf2.length = out_n_samples * r->w_sz;
+
+    return &r->buf2;
 }
 
-static float *resample(pa_resampler *r, float *input, unsigned *n_frames) {
-    struct impl_libsamplerate *u;
-    SRC_DATA data;
+static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
+    unsigned in_n_frames, in_n_samples;
     unsigned out_n_frames, out_n_samples;
-    int ret;
 
-    assert(r);
-    assert(input);
-    assert(n_frames);
-    assert(r->impl_data);
-    u = r->impl_data;
+    pa_assert(r);
+    pa_assert(input);
 
     /* Resample the data and place the result in buf3 */
 
-    if (!u->src_state)
+    if (!r->impl_resample || !input->length)
         return input;
 
-    out_n_frames = (*n_frames*r->o_ss.rate/r->i_ss.rate)+1024;
+    in_n_samples = input->length / r->w_sz;
+    in_n_frames = in_n_samples / r->o_ss.channels;
+
+    out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+EXTRA_SAMPLES;
     out_n_samples = out_n_frames * r->o_ss.channels;
 
-    if (u->buf3_samples < out_n_samples) {
-        if (u->buf3_block)
-            pa_memblock_unref(u->buf3_block);
+    r->buf3.index = 0;
+    r->buf3.length = r->w_sz * out_n_samples;
+
+    if (!r->buf3.memblock || r->buf3_samples < out_n_samples) {
+        if (r->buf3.memblock)
+            pa_memblock_unref(r->buf3.memblock);
 
-        u->buf3_samples = out_n_samples;
-        u->buf3_block = pa_memblock_new(r->mempool, sizeof(float) * out_n_samples);
-        u->buf3 = u->buf3_block->data;
+        r->buf3_samples = out_n_samples;
+        r->buf3.memblock = pa_memblock_new(r->mempool, r->buf3.length);
     }
 
-    data.data_in = input;
-    data.input_frames = *n_frames;
+    r->impl_resample(r, input, in_n_frames, &r->buf3, &out_n_frames);
+    r->buf3.length = out_n_frames * r->w_sz * r->o_ss.channels;
 
-    data.data_out = u->buf3;
-    data.output_frames = out_n_frames;
+    return &r->buf3;
+}
 
-    data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
-    data.end_of_input = 0;
+static pa_memchunk *convert_from_work_format(pa_resampler *r, pa_memchunk *input) {
+    unsigned n_samples, n_frames;
+    void *src, *dst;
+
+    pa_assert(r);
+    pa_assert(input);
+
+    /* Convert the data into the correct sample type and place the result in buf4 */
+
+    if (!r->from_work_format_func || !input->length)
+        return input;
+
+    n_samples = input->length / r->w_sz;
+    n_frames =  n_samples / r->o_ss.channels;
+
+    r->buf4.index = 0;
+    r->buf4.length = r->o_fz * n_frames;
+
+    if (!r->buf4.memblock || r->buf4_samples < n_samples) {
+        if (r->buf4.memblock)
+            pa_memblock_unref(r->buf4.memblock);
+
+        r->buf4_samples = n_samples;
+        r->buf4.memblock = pa_memblock_new(r->mempool, r->buf4.length);
+    }
 
-    ret = src_process(u->src_state, &data);
-    assert(ret == 0);
-    assert((unsigned) data.input_frames_used == *n_frames);
+    src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
+    dst = pa_memblock_acquire(r->buf4.memblock);
+    r->from_work_format_func(n_samples, src, dst);
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(r->buf4.memblock);
 
-    *n_frames = data.output_frames_gen;
+    r->buf4.length = r->o_fz * n_frames;
 
-    return u->buf3;
+    return &r->buf4;
 }
 
-static void *convert_from_float(pa_resampler *r, float *input, unsigned n_frames) {
-    struct impl_libsamplerate *u;
-    unsigned n_samples;
+void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
+    pa_memchunk *buf;
+
+    pa_assert(r);
+    pa_assert(in);
+    pa_assert(out);
+    pa_assert(in->length);
+    pa_assert(in->memblock);
+    pa_assert(in->length % r->i_fz == 0);
+
+    buf = (pa_memchunk*) in;
+    buf = convert_to_work_format(r, buf);
+    buf = remap_channels(r, buf);
+    buf = resample(r, buf);
+
+    if (buf->length) {
+        buf = convert_from_work_format(r, buf);
+        *out = *buf;
+
+        if (buf == in)
+            pa_memblock_ref(buf->memblock);
+        else
+            pa_memchunk_reset(buf);
+    } else
+        pa_memchunk_reset(out);
+}
 
-    assert(r);
-    assert(input);
-    assert(r->impl_data);
-    u = r->impl_data;
+/*** libsamplerate based implementation ***/
 
-    /* Convert the data into the correct sample type and place the result in buf4 */
+#ifdef HAVE_LIBSAMPLERATE
+static void libsamplerate_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
+    SRC_DATA data;
 
-    if (!u->from_float32ne_func)
-        return input;
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(output);
+    pa_assert(out_n_frames);
 
-    n_samples = n_frames * r->o_ss.channels;
+    memset(&data, 0, sizeof(data));
 
-    if (u->buf4_samples < n_samples) {
-        if (u->buf4_block)
-            pa_memblock_unref(u->buf4_block);
+    data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
+    data.input_frames = in_n_frames;
 
-        u->buf4_samples = n_samples;
-        u->buf4_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples);
-        u->buf4 = u->buf4_block->data;
-    }
+    data.data_out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
+    data.output_frames = *out_n_frames;
 
-    u->from_float32ne_func(n_samples, input, u->buf4);
-
-    return u->buf4;
-}
-
-static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
-    struct impl_libsamplerate *u;
-    float *buf;
-    void *input, *output;
-    unsigned n_frames;
-
-    assert(r);
-    assert(in);
-    assert(out);
-    assert(in->length);
-    assert(in->memblock);
-    assert(in->length % r->i_fz == 0);
-    assert(r->impl_data);
-
-    u = r->impl_data;
-
-    input = ((uint8_t*) in->memblock->data + in->index);
-    n_frames = in->length / r->i_fz;
-    assert(n_frames > 0);
-
-    buf = convert_to_float(r, input, n_frames);
-    buf = remap_channels(r, buf, n_frames);
-    buf = resample(r, buf, &n_frames);
-
-    if (n_frames) {
-        output = convert_from_float(r, buf, n_frames);
-
-        if (output == input) {
-            /* Mm, no adjustment has been necessary, so let's return the original block */
-            out->memblock = pa_memblock_ref(in->memblock);
-            out->index = in->index;
-            out->length = in->length;
-        } else {
-            out->length = n_frames * r->o_fz;
-            out->index = 0;
-            out->memblock = NULL;
-
-            if (output == u->buf1) {
-                u->buf1 = NULL;
-                u->buf1_samples = 0;
-                out->memblock = u->buf1_block;
-                u->buf1_block = NULL;
-            } else if (output == u->buf2) {
-                u->buf2 = NULL;
-                u->buf2_samples = 0;
-                out->memblock = u->buf2_block;
-                u->buf2_block = NULL;
-            } else if (output == u->buf3) {
-                u->buf3 = NULL;
-                u->buf3_samples = 0;
-                out->memblock = u->buf3_block;
-                u->buf3_block = NULL;
-            } else if (output == u->buf4) {
-                u->buf4 = NULL;
-                u->buf4_samples = 0;
-                out->memblock = u->buf4_block;
-                u->buf4_block = NULL;
-            }
+    data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
+    data.end_of_input = 0;
 
-            assert(out->memblock);
-        }
-    } else {
-        out->memblock = NULL;
-        out->index = out->length = 0;
-    }
+    pa_assert_se(src_process(r->src.state, &data) == 0);
+    pa_assert((unsigned) data.input_frames_used == in_n_frames);
+
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(output->memblock);
+
+    *out_n_frames = data.output_frames_gen;
 }
 
-static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) {
-    struct impl_libsamplerate *u;
+static void libsamplerate_update_rates(pa_resampler *r) {
+    pa_assert(r);
 
-    assert(r);
-    assert(rate > 0);
-    assert(r->impl_data);
-    u = r->impl_data;
+    pa_assert_se(src_set_ratio(r->src.state, (double) r->o_ss.rate / r->i_ss.rate) == 0);
+}
 
-    if (!u->src_state) {
-        int err;
-        u->src_state = src_new(r->resample_method, r->o_ss.channels, &err);
-        assert(u->src_state);
-    } else {
-        int ret = src_set_ratio(u->src_state, (double) r->o_ss.rate / rate);
-        assert(ret == 0);
-    }
+static void libsamplerate_free(pa_resampler *r) {
+    pa_assert(r);
+
+    if (r->src.state)
+        src_delete(r->src.state);
 }
 
 static int libsamplerate_init(pa_resampler *r) {
-    struct impl_libsamplerate *u = NULL;
     int err;
 
-    r->impl_data = u = pa_xnew(struct impl_libsamplerate, 1);
+    pa_assert(r);
 
-    u->buf1 = u->buf2 = u->buf3 = u->buf4 = NULL;
-    u->buf1_block = u->buf2_block = u->buf3_block = u->buf4_block = NULL;
-    u->buf1_samples = u->buf2_samples = u->buf3_samples = u->buf4_samples = 0;
+    if (!(r->src.state = src_new(r->resample_method, r->o_ss.channels, &err)))
+        return -1;
 
-    if (r->i_ss.format == PA_SAMPLE_FLOAT32NE)
-        u->to_float32ne_func = NULL;
-    else if (!(u->to_float32ne_func = pa_get_convert_to_float32ne_function(r->i_ss.format)))
-        goto fail;
+    r->impl_free = libsamplerate_free;
+    r->impl_update_rates = libsamplerate_update_rates;
+    r->impl_resample = libsamplerate_resample;
 
-    if (r->o_ss.format == PA_SAMPLE_FLOAT32NE)
-        u->from_float32ne_func = NULL;
-    else if (!(u->from_float32ne_func = pa_get_convert_from_float32ne_function(r->o_ss.format)))
-        goto fail;
+    return 0;
+}
+#endif
 
-    if (r->o_ss.rate == r->i_ss.rate)
-        u->src_state = NULL;
-    else if (!(u->src_state = src_new(r->resample_method, r->o_ss.channels, &err)))
-        goto fail;
+/*** speex based implementation ***/
 
-    r->impl_free = libsamplerate_free;
-    r->impl_update_input_rate = libsamplerate_update_input_rate;
-    r->impl_run = libsamplerate_run;
+static void speex_resample_float(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
+    float *in, *out;
+    uint32_t inf = in_n_frames, outf = *out_n_frames;
 
-    calc_map_table(r);
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(output);
+    pa_assert(out_n_frames);
 
-    return 0;
+    in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
+    out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
 
-fail:
-    pa_xfree(u);
-    return -1;
+    pa_assert_se(paspfl_resampler_process_interleaved_float(r->speex.state, in, &inf, out, &outf) == 0);
+
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(output->memblock);
+
+    pa_assert(inf == in_n_frames);
+    *out_n_frames = outf;
 }
 
-/* Trivial implementation */
+static void speex_resample_int(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
+    int16_t *in, *out;
+    uint32_t inf = in_n_frames, outf = *out_n_frames;
 
-static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
-    size_t fz;
-    unsigned  n_frames;
-    struct impl_trivial *u;
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(output);
+    pa_assert(out_n_frames);
+
+    in = (int16_t*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
+    out = (int16_t*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
+
+    pa_assert_se(paspfx_resampler_process_interleaved_int(r->speex.state, in, &inf, out, &outf) == 0);
+
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(output->memblock);
 
-    assert(r);
-    assert(in);
-    assert(out);
-    assert(r->impl_data);
+    pa_assert(inf == in_n_frames);
+    *out_n_frames = outf;
+}
 
-    u = r->impl_data;
+static void speex_update_rates(pa_resampler *r) {
+    pa_assert(r);
 
-    fz = r->i_fz;
-    assert(fz == r->o_fz);
+    if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX)
+        pa_assert_se(paspfx_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0);
+    else {
+        pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
+        pa_assert_se(paspfl_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0);
+    }
+}
 
-    n_frames = in->length/fz;
+static void speex_free(pa_resampler *r) {
+    pa_assert(r);
 
-    if (r->i_ss.rate == r->o_ss.rate) {
+    if (!r->speex.state)
+        return;
+
+    if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX)
+        paspfx_resampler_destroy(r->speex.state);
+    else {
+        pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
+        paspfl_resampler_destroy(r->speex.state);
+    }
+}
 
-        /* In case there's no diefference in sample types, do nothing */
-        *out = *in;
-        pa_memblock_ref(out->memblock);
+static int speex_init(pa_resampler *r) {
+    int q, err;
 
-        u->o_counter += n_frames;
+    pa_assert(r);
+
+    r->impl_free = speex_free;
+    r->impl_update_rates = speex_update_rates;
+
+    if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) {
+        q = r->resample_method - PA_RESAMPLER_SPEEX_FIXED_BASE;
+
+        pa_log_info("Choosing speex quality setting %i.", q);
+
+        if (!(r->speex.state = paspfx_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
+            return -1;
+
+        r->impl_resample = speex_resample_int;
     } else {
-        /* Do real resampling */
-        size_t l;
-        unsigned o_index;
+        pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
+        q = r->resample_method - PA_RESAMPLER_SPEEX_FLOAT_BASE;
+
+        pa_log_info("Choosing speex quality setting %i.", q);
 
-        /* The length of the new memory block rounded up */
-        l = ((((n_frames+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz;
+        if (!(r->speex.state = paspfl_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
+            return -1;
 
-        out->index = 0;
-        out->memblock = pa_memblock_new(r->mempool, l);
+        r->impl_resample = speex_resample_float;
+    }
 
-        for (o_index = 0;; o_index++, u->o_counter++) {
-            unsigned j;
+    return 0;
+}
 
-            j = (u->o_counter * r->i_ss.rate / r->o_ss.rate);
-            j = j > u->i_counter ? j - u->i_counter : 0;
+/* Trivial implementation */
 
-            if (j >= n_frames)
-                break;
+static void trivial_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
+    size_t fz;
+    unsigned o_index;
+    void *src, *dst;
 
-            assert(o_index*fz < out->memblock->length);
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(output);
+    pa_assert(out_n_frames);
 
-            memcpy((uint8_t*) out->memblock->data + fz*o_index,
-                   (uint8_t*) in->memblock->data + in->index + fz*j, fz);
+    fz = r->w_sz * r->o_ss.channels;
 
-        }
+    src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
+    dst = (uint8_t*) pa_memblock_acquire(output->memblock) + output->index;
+
+    for (o_index = 0;; o_index++, r->trivial.o_counter++) {
+        unsigned j;
 
-        out->length = o_index*fz;
+        j = ((r->trivial.o_counter * r->i_ss.rate) / r->o_ss.rate);
+        j = j > r->trivial.i_counter ? j - r->trivial.i_counter : 0;
+
+        if (j >= in_n_frames)
+            break;
+
+        pa_assert(o_index * fz < pa_memblock_get_length(output->memblock));
+
+        oil_memcpy((uint8_t*) dst + fz * o_index,
+                   (uint8_t*) src + fz * j, fz);
     }
 
-    u->i_counter += n_frames;
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(output->memblock);
+
+    *out_n_frames = o_index;
+
+    r->trivial.i_counter += in_n_frames;
 
     /* Normalize counters */
-    while (u->i_counter >= r->i_ss.rate) {
-        u->i_counter -= r->i_ss.rate;
-        assert(u->o_counter >= r->o_ss.rate);
-        u->o_counter -= r->o_ss.rate;
+    while (r->trivial.i_counter >= r->i_ss.rate) {
+        pa_assert(r->trivial.o_counter >= r->o_ss.rate);
+
+        r->trivial.i_counter -= r->i_ss.rate;
+        r->trivial.o_counter -= r->o_ss.rate;
     }
 }
 
-static void trivial_free(pa_resampler *r) {
-    assert(r);
+static void trivial_update_rates(pa_resampler *r) {
+    pa_assert(r);
 
-    pa_xfree(r->impl_data);
+    r->trivial.i_counter = 0;
+    r->trivial.o_counter = 0;
 }
 
-static void trivial_update_input_rate(pa_resampler *r, uint32_t rate) {
-    struct impl_trivial *u;
+static int trivial_init(pa_resampler*r) {
+    pa_assert(r);
+
+    r->trivial.o_counter = r->trivial.i_counter = 0;
 
-    assert(r);
-    assert(rate > 0);
-    assert(r->impl_data);
+    r->impl_resample = trivial_resample;
+    r->impl_update_rates = trivial_update_rates;
+    r->impl_free = NULL;
 
-    u = r->impl_data;
-    u->i_counter = 0;
-    u->o_counter = 0;
+    return 0;
 }
 
-static int trivial_init(pa_resampler*r) {
-    struct impl_trivial *u;
+/*** ffmpeg based implementation ***/
+
+static void ffmpeg_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
+    unsigned used_frames = 0, c;
+
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(output);
+    pa_assert(out_n_frames);
+
+    for (c = 0; c < r->o_ss.channels; c++) {
+        unsigned u;
+        pa_memblock *b, *w;
+        int16_t *p, *t, *k, *q, *s;
+        int consumed_frames;
+        unsigned in, l;
+
+        /* Allocate a new block */
+        b = pa_memblock_new(r->mempool, r->ffmpeg.buf[c].length + in_n_frames * sizeof(int16_t));
+        p = pa_memblock_acquire(b);
+
+        /* Copy the remaining data into it */
+        l = r->ffmpeg.buf[c].length;
+        if (r->ffmpeg.buf[c].memblock) {
+            t = (int16_t*) ((uint8_t*) pa_memblock_acquire(r->ffmpeg.buf[c].memblock) + r->ffmpeg.buf[c].index);
+            memcpy(p, t, l);
+            pa_memblock_release(r->ffmpeg.buf[c].memblock);
+            pa_memblock_unref(r->ffmpeg.buf[c].memblock);
+            pa_memchunk_reset(&r->ffmpeg.buf[c]);
+        }
+
+        /* Now append the new data, splitting up channels */
+        t = ((int16_t*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index)) + c;
+        k = (int16_t*) ((uint8_t*) p + l);
+        for (u = 0; u < in_n_frames; u++) {
+            *k = *t;
+            t += r->o_ss.channels;
+            k ++;
+        }
+        pa_memblock_release(input->memblock);
+
+        /* Calculate the resulting number of frames */
+        in = in_n_frames + l / sizeof(int16_t);
+
+        /* Allocate buffer for the result */
+        w = pa_memblock_new(r->mempool, *out_n_frames * sizeof(int16_t));
+        q = pa_memblock_acquire(w);
+
+        /* Now, resample */
+        used_frames = av_resample(r->ffmpeg.state,
+                                  q, p,
+                                  &consumed_frames,
+                                  in, *out_n_frames,
+                                  c >= (unsigned) r->o_ss.channels-1);
+
+        pa_memblock_release(b);
+
+        /* Now store the remaining samples away */
+        pa_assert(consumed_frames <= (int) in);
+        if (consumed_frames < (int) in) {
+            r->ffmpeg.buf[c].memblock = b;
+            r->ffmpeg.buf[c].index = consumed_frames * sizeof(int16_t);
+            r->ffmpeg.buf[c].length = (in - consumed_frames) * sizeof(int16_t);
+        } else
+            pa_memblock_unref(b);
+
+        /* And place the results in the output buffer */
+        s = (short*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index) + c;
+        for (u = 0; u < used_frames; u++) {
+            *s = *q;
+            q++;
+            s += r->o_ss.channels;
+        }
+        pa_memblock_release(output->memblock);
+        pa_memblock_release(w);
+        pa_memblock_unref(w);
+    }
+
+    *out_n_frames = used_frames;
+}
+
+static void ffmpeg_free(pa_resampler *r) {
+    unsigned c;
 
-    assert(r);
-    assert(r->i_ss.format == r->o_ss.format);
-    assert(r->i_ss.channels == r->o_ss.channels);
+    pa_assert(r);
 
-    r->impl_data = u = pa_xnew(struct impl_trivial, 1);
-    u->o_counter = u->i_counter = 0;
+    if (r->ffmpeg.state)
+        av_resample_close(r->ffmpeg.state);
 
-    r->impl_run = trivial_run;
-    r->impl_free = trivial_free;
-    r->impl_update_input_rate = trivial_update_input_rate;
+    for (c = 0; c < PA_ELEMENTSOF(r->ffmpeg.buf); c++)
+        if (r->ffmpeg.buf[c].memblock)
+            pa_memblock_unref(r->ffmpeg.buf[c].memblock);
+}
+
+static int ffmpeg_init(pa_resampler *r) {
+    unsigned c;
+
+    pa_assert(r);
+
+    /* We could probably implement different quality levels by
+     * adjusting the filter parameters here. However, ffmpeg
+     * internally only uses these hardcoded values, so let's use them
+     * here for now as well until ffmpeg makes this configurable. */
+
+    if (!(r->ffmpeg.state = av_resample_init(r->o_ss.rate, r->i_ss.rate, 16, 10, 0, 0.8)))
+        return -1;
+
+    r->impl_free = ffmpeg_free;
+    r->impl_resample = ffmpeg_resample;
+
+    for (c = 0; c < PA_ELEMENTSOF(r->ffmpeg.buf); c++)
+        pa_memchunk_reset(&r->ffmpeg.buf[c]);
 
     return 0;
 }
 
+/*** copy (noop) implementation ***/
 
+static int copy_init(pa_resampler *r) {
+    pa_assert(r);
+
+    pa_assert(r->o_ss.rate == r->i_ss.rate);
+
+    r->impl_free = NULL;
+    r->impl_resample = NULL;
+    r->impl_update_rates = NULL;
+
+    return 0;
+}
index c283593d679f0bfe934a9d703489d09a5c666904..23e1acb7659a877ab9b40002601ad8507eb5d3e7 100644 (file)
@@ -24,8 +24,6 @@
   USA.
 ***/
 
-#include <samplerate.h>
-
 #include <pulse/sample.h>
 #include <pulse/channelmap.h>
 #include <pulsecore/memblock.h>
@@ -35,12 +33,19 @@ typedef struct pa_resampler pa_resampler;
 
 typedef enum pa_resample_method {
     PA_RESAMPLER_INVALID                 = -1,
-    PA_RESAMPLER_SRC_SINC_BEST_QUALITY   = SRC_SINC_BEST_QUALITY,
-    PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY = SRC_SINC_MEDIUM_QUALITY,
-    PA_RESAMPLER_SRC_SINC_FASTEST        = SRC_SINC_FASTEST,
-    PA_RESAMPLER_SRC_ZERO_ORDER_HOLD     = SRC_ZERO_ORDER_HOLD,
-    PA_RESAMPLER_SRC_LINEAR              = SRC_LINEAR,
+    PA_RESAMPLER_SRC_SINC_BEST_QUALITY   = 0, /* = SRC_SINC_BEST_QUALITY */
+    PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY = 1, /* = SRC_SINC_MEDIUM_QUALITY */
+    PA_RESAMPLER_SRC_SINC_FASTEST        = 2, /* = SRC_SINC_FASTEST */
+    PA_RESAMPLER_SRC_ZERO_ORDER_HOLD     = 3, /* = SRC_ZERO_ORDER_HOLD */
+    PA_RESAMPLER_SRC_LINEAR              = 4, /* = SRC_LINEAR */
     PA_RESAMPLER_TRIVIAL,
+    PA_RESAMPLER_SPEEX_FLOAT_BASE,
+    PA_RESAMPLER_SPEEX_FLOAT_MAX = PA_RESAMPLER_SPEEX_FLOAT_BASE + 10,
+    PA_RESAMPLER_SPEEX_FIXED_BASE,
+    PA_RESAMPLER_SPEEX_FIXED_MAX = PA_RESAMPLER_SPEEX_FIXED_BASE + 10,
+    PA_RESAMPLER_FFMPEG,
+    PA_RESAMPLER_AUTO, /* automatic select based on sample format */
+    PA_RESAMPLER_COPY,
     PA_RESAMPLER_MAX
 } pa_resample_method_t;
 
@@ -50,19 +55,26 @@ pa_resampler* pa_resampler_new(
         const pa_channel_map *am,
         const pa_sample_spec *b,
         const pa_channel_map *bm,
-        pa_resample_method_t resample_method);
+        pa_resample_method_t resample_method,
+        int variable_rate);
 
 void pa_resampler_free(pa_resampler *r);
 
 /* Returns the size of an input memory block which is required to return the specified amount of output data */
 size_t pa_resampler_request(pa_resampler *r, size_t out_length);
 
+/* Returns the maximum size of input blocks we can process without needing bounce buffers larger than the mempool tile size. */
+size_t pa_resampler_max_block_size(pa_resampler *r);
+
 /* Pass the specified memory chunk to the resampler and return the newly resampled data */
 void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out);
 
 /* Change the input rate of the resampler object */
 void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate);
 
+/* Change the output rate of the resampler object */
+void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate);
+
 /* Return the resampling method of the resampler object */
 pa_resample_method_t pa_resampler_get_method(pa_resampler *r);
 
@@ -72,4 +84,7 @@ pa_resample_method_t pa_parse_resample_method(const char *string);
 /* return a human readable string for the specified resampling method. Inverse of pa_parse_resample_method() */
 const char *pa_resample_method_to_string(pa_resample_method_t m);
 
+/* Return 1 when the specified resampling method is supported */
+int pa_resample_method_supported(pa_resample_method_t m);
+
 #endif
diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c
new file mode 100644 (file)
index 0000000..07d776e
--- /dev/null
@@ -0,0 +1,98 @@
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, 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 <stddef.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include <pulse/timeval.h>
+#include <pulsecore/macro.h>
+
+#include "rtclock.h"
+
+pa_usec_t pa_rtclock_age(const struct timeval *tv) {
+    struct timeval now;
+    pa_assert(tv);
+
+    return pa_timeval_diff(pa_rtclock_get(&now), tv);
+}
+
+struct timeval *pa_rtclock_get(struct timeval *tv) {
+#ifdef HAVE_CLOCK_GETTIME
+    struct timespec ts;
+
+#ifdef CLOCK_MONOTONIC
+    /* No locking or atomic ops for no_monotonic here */
+    static pa_bool_t no_monotonic = FALSE;
+
+    if (!no_monotonic)
+        if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
+            no_monotonic = TRUE;
+
+    if (no_monotonic)
+#endif
+        pa_assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
+
+    pa_assert(tv);
+
+    tv->tv_sec = ts.tv_sec;
+    tv->tv_usec = ts.tv_nsec / 1000;
+
+    return tv;
+
+#else /* HAVE_CLOCK_GETTIME */
+
+    return pa_gettimeofday(tv);
+
+#endif
+}
+
+pa_bool_t pa_rtclock_hrtimer(void) {
+#ifdef HAVE_CLOCK_GETTIME
+    struct timespec ts;
+
+#ifdef CLOCK_MONOTONIC
+    if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0)
+        return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000;
+#endif
+
+    pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0);
+    return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000;
+
+#else /* HAVE_CLOCK_GETTIME */
+
+    return FALSE;
+
+#endif
+}
+
+pa_usec_t pa_rtclock_usec(void) {
+    struct timeval tv;
+
+    return pa_timeval_load(pa_rtclock_get(&tv));
+}
diff --git a/src/pulsecore/rtclock.h b/src/pulsecore/rtclock.h
new file mode 100644 (file)
index 0000000..f0360af
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef foopulsertclockhfoo
+#define foopulsertclockhfoo
+
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#include <pulsecore/macro.h>
+
+struct timeval;
+
+/* Something like pulse/timeval.h but based on CLOCK_MONOTONIC */
+
+struct timeval *pa_rtclock_get(struct timeval *ts);
+
+pa_usec_t pa_rtclock_usec(void);
+
+pa_usec_t pa_rtclock_age(const struct timeval *tv);
+pa_bool_t pa_rtclock_hrtimer(void);
+
+/* timer with a resolution better than this are considered high-resolution */
+#define PA_HRTIMER_THRESHOLD_USEC 10
+
+#endif
diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
new file mode 100644 (file)
index 0000000..354c4c0
--- /dev/null
@@ -0,0 +1,751 @@
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, 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/types.h>
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef __linux__
+#include <sys/utsname.h>
+#endif
+
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#else
+#include <pulsecore/poll.h>
+#endif
+
+#include <pulse/xmalloc.h>
+#include <pulse/timeval.h>
+
+#include <pulsecore/core-error.h>
+#include <pulsecore/rtclock.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/llist.h>
+#include <pulsecore/rtsig.h>
+#include <pulsecore/flist.h>
+#include <pulsecore/core-util.h>
+
+#include <pulsecore/winsock.h>
+
+#include "rtpoll.h"
+
+struct pa_rtpoll {
+    struct pollfd *pollfd, *pollfd2;
+    unsigned n_pollfd_alloc, n_pollfd_used;
+
+    pa_bool_t timer_enabled;
+    struct timeval next_elapse;
+    pa_usec_t period;
+
+    pa_bool_t scan_for_dead;
+    pa_bool_t running, installed, rebuild_needed, quit;
+
+#ifdef HAVE_PPOLL
+    int rtsig;
+    sigset_t sigset_unblocked;
+    timer_t timer;
+#ifdef __linux__
+    pa_bool_t dont_use_ppoll;
+#endif
+#endif
+
+    PA_LLIST_HEAD(pa_rtpoll_item, items);
+};
+
+struct pa_rtpoll_item {
+    pa_rtpoll *rtpoll;
+    pa_bool_t dead;
+
+    pa_rtpoll_priority_t priority;
+
+    struct pollfd *pollfd;
+    unsigned n_pollfd;
+
+    int (*work_cb)(pa_rtpoll_item *i);
+    int (*before_cb)(pa_rtpoll_item *i);
+    void (*after_cb)(pa_rtpoll_item *i);
+    void *userdata;
+
+    PA_LLIST_FIELDS(pa_rtpoll_item);
+};
+
+PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
+
+static void signal_handler_noop(int s) { }
+
+pa_rtpoll *pa_rtpoll_new(void) {
+    pa_rtpoll *p;
+
+    p = pa_xnew(pa_rtpoll, 1);
+
+#ifdef HAVE_PPOLL
+
+#ifdef __linux__
+    /* ppoll is broken on Linux < 2.6.16 */
+    p->dont_use_ppoll = FALSE;
+
+    {
+        struct utsname u;
+        unsigned major, minor, micro;
+
+        pa_assert_se(uname(&u) == 0);
+
+        if (sscanf(u.release, "%u.%u.%u", &major, &minor, &micro) != 3 ||
+            (major < 2) ||
+            (major == 2 && minor < 6) ||
+            (major == 2 && minor == 6 && micro < 16))
+
+            p->dont_use_ppoll = TRUE;
+    }
+
+#endif
+
+    p->rtsig = -1;
+    sigemptyset(&p->sigset_unblocked);
+    p->timer = (timer_t) -1;
+
+#endif
+
+    p->n_pollfd_alloc = 32;
+    p->pollfd = pa_xnew(struct pollfd, p->n_pollfd_alloc);
+    p->pollfd2 = pa_xnew(struct pollfd, p->n_pollfd_alloc);
+    p->n_pollfd_used = 0;
+
+    p->period = 0;
+    memset(&p->next_elapse, 0, sizeof(p->next_elapse));
+    p->timer_enabled = FALSE;
+
+    p->running = FALSE;
+    p->installed = FALSE;
+    p->scan_for_dead = FALSE;
+    p->rebuild_needed = FALSE;
+    p->quit = FALSE;
+
+    PA_LLIST_HEAD_INIT(pa_rtpoll_item, p->items);
+
+    return p;
+}
+
+void pa_rtpoll_install(pa_rtpoll *p) {
+    pa_assert(p);
+    pa_assert(!p->installed);
+
+    p->installed = 1;
+
+#ifdef HAVE_PPOLL
+    if (p->dont_use_ppoll)
+        return;
+
+    if ((p->rtsig = pa_rtsig_get_for_thread()) < 0) {
+        pa_log_warn("Failed to reserve POSIX realtime signal.");
+        return;
+    }
+
+    pa_log_debug("Acquired POSIX realtime signal %s", pa_sig2str(p->rtsig));
+
+    {
+        sigset_t ss;
+        struct sigaction sa;
+
+        pa_assert_se(sigemptyset(&ss) == 0);
+        pa_assert_se(sigaddset(&ss, p->rtsig) == 0);
+        pa_assert_se(pthread_sigmask(SIG_BLOCK, &ss, &p->sigset_unblocked) == 0);
+        pa_assert_se(sigdelset(&p->sigset_unblocked, p->rtsig) == 0);
+
+        memset(&sa, 0, sizeof(sa));
+        sa.sa_handler = signal_handler_noop;
+        pa_assert_se(sigemptyset(&sa.sa_mask) == 0);
+
+        pa_assert_se(sigaction(p->rtsig, &sa, NULL) == 0);
+
+        /* We never reset the signal handler. Why should we? */
+    }
+
+#endif
+}
+
+static void rtpoll_rebuild(pa_rtpoll *p) {
+
+    struct pollfd *e, *t;
+    pa_rtpoll_item *i;
+    int ra = 0;
+
+    pa_assert(p);
+
+    p->rebuild_needed = FALSE;
+
+    if (p->n_pollfd_used > p->n_pollfd_alloc) {
+        /* Hmm, we have to allocate some more space */
+        p->n_pollfd_alloc = p->n_pollfd_used * 2;
+        p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
+        ra = 1;
+    }
+
+    e = p->pollfd2;
+
+    for (i = p->items; i; i = i->next) {
+
+        if (i->n_pollfd > 0)  {
+            size_t l = i->n_pollfd * sizeof(struct pollfd);
+
+            if (i->pollfd)
+                memcpy(e, i->pollfd, l);
+            else
+                memset(e, 0, l);
+
+            i->pollfd = e;
+        } else
+            i->pollfd = NULL;
+
+        e += i->n_pollfd;
+    }
+
+    pa_assert((unsigned) (e - p->pollfd2) == p->n_pollfd_used);
+    t = p->pollfd;
+    p->pollfd = p->pollfd2;
+    p->pollfd2 = t;
+
+    if (ra)
+        p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
+
+}
+
+static void rtpoll_item_destroy(pa_rtpoll_item *i) {
+    pa_rtpoll *p;
+
+    pa_assert(i);
+
+    p = i->rtpoll;
+
+    PA_LLIST_REMOVE(pa_rtpoll_item, p->items, i);
+
+    p->n_pollfd_used -= i->n_pollfd;
+
+    if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0)
+        pa_xfree(i);
+
+    p->rebuild_needed = TRUE;
+}
+
+void pa_rtpoll_free(pa_rtpoll *p) {
+    pa_assert(p);
+
+    while (p->items)
+        rtpoll_item_destroy(p->items);
+
+    pa_xfree(p->pollfd);
+    pa_xfree(p->pollfd2);
+
+#ifdef HAVE_PPOLL
+    if (p->timer != (timer_t) -1)
+        timer_delete(p->timer);
+#endif
+
+    pa_xfree(p);
+}
+
+static void reset_revents(pa_rtpoll_item *i) {
+    struct pollfd *f;
+    unsigned n;
+
+    pa_assert(i);
+
+    if (!(f = pa_rtpoll_item_get_pollfd(i, &n)))
+        return;
+
+    for (; n > 0; n--)
+        f[n-1].revents = 0;
+}
+
+static void reset_all_revents(pa_rtpoll *p) {
+    pa_rtpoll_item *i;
+
+    pa_assert(p);
+
+    for (i = p->items; i; i = i->next) {
+
+        if (i->dead)
+            continue;
+
+        reset_revents(i);
+    }
+}
+
+int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
+    pa_rtpoll_item *i;
+    int r = 0;
+    struct timeval timeout;
+
+    pa_assert(p);
+    pa_assert(!p->running);
+    pa_assert(p->installed);
+
+    p->running = TRUE;
+
+    /* First, let's do some work */
+    for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
+        int k;
+
+        if (i->dead)
+            continue;
+
+        if (!i->work_cb)
+            continue;
+
+        if (p->quit)
+            goto finish;
+
+        if ((k = i->work_cb(i)) != 0) {
+            if (k < 0)
+                r = k;
+
+            goto finish;
+        }
+    }
+
+    /* Now let's prepare for entering the sleep */
+    for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
+        int k = 0;
+
+        if (i->dead)
+            continue;
+
+        if (!i->before_cb)
+            continue;
+
+        if (p->quit || (k = i->before_cb(i)) != 0) {
+
+            /* Hmm, this one doesn't let us enter the poll, so rewind everything */
+
+            for (i = i->prev; i; i = i->prev) {
+
+                if (i->dead)
+                    continue;
+
+                if (!i->after_cb)
+                    continue;
+
+                i->after_cb(i);
+            }
+
+            if (k < 0)
+                r = k;
+
+            goto finish;
+        }
+    }
+
+    if (p->rebuild_needed)
+        rtpoll_rebuild(p);
+
+    /* Calculate timeout */
+    if (!wait || p->quit) {
+        timeout.tv_sec = 0;
+        timeout.tv_usec = 0;
+    } else if (p->timer_enabled) {
+        struct timeval now;
+        pa_rtclock_get(&now);
+
+        memset(&timeout, 0, sizeof(timeout));
+        if (pa_timeval_cmp(&p->next_elapse, &now) > 0)
+            pa_timeval_add(&timeout, pa_timeval_diff(&p->next_elapse, &now));
+    }
+
+    /* OK, now let's sleep */
+#ifdef HAVE_PPOLL
+
+#ifdef __linux__
+    if (!p->dont_use_ppoll)
+#endif
+    {
+        struct timespec ts;
+        ts.tv_sec = timeout.tv_sec;
+        ts.tv_nsec = timeout.tv_usec * 1000;
+        r = ppoll(p->pollfd, p->n_pollfd_used, p->timer_enabled ? &ts : NULL, p->rtsig < 0 ? NULL : &p->sigset_unblocked);
+    }
+#ifdef __linux__
+    else
+#endif
+
+#endif
+        r = poll(p->pollfd, p->n_pollfd_used, p->timer_enabled ? (timeout.tv_sec*1000) + (timeout.tv_usec / 1000) : -1);
+
+    if (r < 0) {
+        if (errno == EAGAIN || errno == EINTR)
+            r = 0;
+        else
+            pa_log_error("poll(): %s", pa_cstrerror(errno));
+
+        reset_all_revents(p);
+    }
+
+    if (p->timer_enabled) {
+        if (p->period > 0) {
+            struct timeval now;
+            pa_rtclock_get(&now);
+
+            pa_timeval_add(&p->next_elapse, p->period);
+
+            /* Guarantee that the next timeout will happen in the future */
+            if (pa_timeval_cmp(&p->next_elapse, &now) < 0)
+                pa_timeval_add(&p->next_elapse, (pa_timeval_diff(&now, &p->next_elapse) / p->period + 1) * p->period);
+
+        } else
+            p->timer_enabled = FALSE;
+    }
+
+    /* Let's tell everyone that we left the sleep */
+    for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
+
+        if (i->dead)
+            continue;
+
+        if (!i->after_cb)
+            continue;
+
+        i->after_cb(i);
+    }
+
+finish:
+
+    p->running = FALSE;
+
+    if (p->scan_for_dead) {
+        pa_rtpoll_item *n;
+
+        p->scan_for_dead = FALSE;
+
+        for (i = p->items; i; i = n) {
+            n = i->next;
+
+            if (i->dead)
+                rtpoll_item_destroy(i);
+        }
+    }
+
+    return r < 0 ? r : !p->quit;
+}
+
+static void update_timer(pa_rtpoll *p) {
+    pa_assert(p);
+
+#ifdef HAVE_PPOLL
+
+#ifdef __linux__
+    if (!p->dont_use_ppoll) {
+#endif
+
+        if (p->timer == (timer_t) -1) {
+            struct sigevent se;
+
+            memset(&se, 0, sizeof(se));
+            se.sigev_notify = SIGEV_SIGNAL;
+            se.sigev_signo = p->rtsig;
+
+            if (timer_create(CLOCK_MONOTONIC, &se, &p->timer) < 0)
+                if (timer_create(CLOCK_REALTIME, &se, &p->timer) < 0) {
+                    pa_log_warn("Failed to allocate POSIX timer: %s", pa_cstrerror(errno));
+                    p->timer = (timer_t) -1;
+                }
+        }
+
+        if (p->timer != (timer_t) -1) {
+            struct itimerspec its;
+            memset(&its, 0, sizeof(its));
+
+            if (p->timer_enabled) {
+                its.it_value.tv_sec = p->next_elapse.tv_sec;
+                its.it_value.tv_nsec = p->next_elapse.tv_usec*1000;
+
+                /* Make sure that 0,0 is not understood as
+                 * "disarming" */
+                if (its.it_value.tv_sec == 0)
+                    its.it_value.tv_nsec = 1;
+
+                if (p->period > 0) {
+                    struct timeval tv;
+                    pa_timeval_store(&tv, p->period);
+                    its.it_interval.tv_sec = tv.tv_sec;
+                    its.it_interval.tv_nsec = tv.tv_usec*1000;
+                }
+            }
+
+            pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
+        }
+
+#ifdef __linux__
+    }
+#endif
+
+#endif
+}
+
+void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timeval *ts) {
+    pa_assert(p);
+    pa_assert(ts);
+
+    p->next_elapse = *ts;
+    p->period = 0;
+    p->timer_enabled = TRUE;
+
+    update_timer(p);
+}
+
+void pa_rtpoll_set_timer_periodic(pa_rtpoll *p, pa_usec_t usec) {
+    pa_assert(p);
+
+    p->period = usec;
+    pa_rtclock_get(&p->next_elapse);
+    pa_timeval_add(&p->next_elapse, usec);
+    p->timer_enabled = TRUE;
+
+    update_timer(p);
+}
+
+void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
+    pa_assert(p);
+
+    p->period = 0;
+    pa_rtclock_get(&p->next_elapse);
+    pa_timeval_add(&p->next_elapse, usec);
+    p->timer_enabled = TRUE;
+
+    update_timer(p);
+}
+
+void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) {
+    pa_assert(p);
+
+    p->period = 0;
+    memset(&p->next_elapse, 0, sizeof(p->next_elapse));
+    p->timer_enabled = FALSE;
+
+    update_timer(p);
+}
+
+pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds) {
+    pa_rtpoll_item *i, *j, *l = NULL;
+
+    pa_assert(p);
+
+    if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
+        i = pa_xnew(pa_rtpoll_item, 1);
+
+    i->rtpoll = p;
+    i->dead = FALSE;
+    i->n_pollfd = n_fds;
+    i->pollfd = NULL;
+    i->priority = prio;
+
+    i->userdata = NULL;
+    i->before_cb = NULL;
+    i->after_cb = NULL;
+    i->work_cb = NULL;
+
+    for (j = p->items; j; j = j->next) {
+        if (prio <= j->priority)
+            break;
+
+        l = j;
+    }
+
+    PA_LLIST_INSERT_AFTER(pa_rtpoll_item, p->items, j ? j->prev : l, i);
+
+    if (n_fds > 0) {
+        p->rebuild_needed = 1;
+        p->n_pollfd_used += n_fds;
+    }
+
+    return i;
+}
+
+void pa_rtpoll_item_free(pa_rtpoll_item *i) {
+    pa_assert(i);
+
+    if (i->rtpoll->running) {
+        i->dead = TRUE;
+        i->rtpoll->scan_for_dead = TRUE;
+        return;
+    }
+
+    rtpoll_item_destroy(i);
+}
+
+struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds) {
+    pa_assert(i);
+
+    if (i->n_pollfd > 0)
+        if (i->rtpoll->rebuild_needed)
+            rtpoll_rebuild(i->rtpoll);
+
+    if (n_fds)
+        *n_fds = i->n_pollfd;
+
+    return i->pollfd;
+}
+
+void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i)) {
+    pa_assert(i);
+    pa_assert(i->priority < PA_RTPOLL_NEVER);
+
+    i->before_cb = before_cb;
+}
+
+void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i)) {
+    pa_assert(i);
+    pa_assert(i->priority < PA_RTPOLL_NEVER);
+
+    i->after_cb = after_cb;
+}
+
+void pa_rtpoll_item_set_work_callback(pa_rtpoll_item *i, int (*work_cb)(pa_rtpoll_item *i)) {
+    pa_assert(i);
+    pa_assert(i->priority < PA_RTPOLL_NEVER);
+
+    i->work_cb = work_cb;
+}
+
+void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata) {
+    pa_assert(i);
+
+    i->userdata = userdata;
+}
+
+void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i) {
+    pa_assert(i);
+
+    return i->userdata;
+}
+
+static int fdsem_before(pa_rtpoll_item *i) {
+
+    if (pa_fdsem_before_poll(i->userdata) < 0)
+        return 1; /* 1 means immediate restart of the loop */
+
+    return 0;
+}
+
+static void fdsem_after(pa_rtpoll_item *i) {
+    pa_assert(i);
+
+    pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
+    pa_fdsem_after_poll(i->userdata);
+}
+
+pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_fdsem *f) {
+    pa_rtpoll_item *i;
+    struct pollfd *pollfd;
+
+    pa_assert(p);
+    pa_assert(f);
+
+    i = pa_rtpoll_item_new(p, prio, 1);
+
+    pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
+
+    pollfd->fd = pa_fdsem_get(f);
+    pollfd->events = POLLIN;
+
+    i->before_cb = fdsem_before;
+    i->after_cb = fdsem_after;
+    i->userdata = f;
+
+    return i;
+}
+
+static int asyncmsgq_before(pa_rtpoll_item *i) {
+    pa_assert(i);
+
+    if (pa_asyncmsgq_before_poll(i->userdata) < 0)
+        return 1; /* 1 means immediate restart of the loop */
+
+    return 0;
+}
+
+static void asyncmsgq_after(pa_rtpoll_item *i) {
+    pa_assert(i);
+
+    pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
+    pa_asyncmsgq_after_poll(i->userdata);
+}
+
+static int asyncmsgq_work(pa_rtpoll_item *i) {
+    pa_msgobject *object;
+    int code;
+    void *data;
+    pa_memchunk chunk;
+    int64_t offset;
+
+    pa_assert(i);
+
+    if (pa_asyncmsgq_get(i->userdata, &object, &code, &data, &offset, &chunk, 0) == 0) {
+        int ret;
+
+        if (!object && code == PA_MESSAGE_SHUTDOWN) {
+            pa_asyncmsgq_done(i->userdata, 0);
+            pa_rtpoll_quit(i->rtpoll);
+            return 1;
+        }
+
+        ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
+        pa_asyncmsgq_done(i->userdata, ret);
+        return 1;
+    }
+
+    return 0;
+}
+
+pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q) {
+    pa_rtpoll_item *i;
+    struct pollfd *pollfd;
+
+    pa_assert(p);
+    pa_assert(q);
+
+    i = pa_rtpoll_item_new(p, prio, 1);
+
+    pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
+    pollfd->fd = pa_asyncmsgq_get_fd(q);
+    pollfd->events = POLLIN;
+
+    i->before_cb = asyncmsgq_before;
+    i->after_cb = asyncmsgq_after;
+    i->work_cb = asyncmsgq_work;
+    i->userdata = q;
+
+    return i;
+}
+
+void pa_rtpoll_quit(pa_rtpoll *p) {
+    pa_assert(p);
+
+    p->quit = TRUE;
+}
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
new file mode 100644 (file)
index 0000000..02f5c7c
--- /dev/null
@@ -0,0 +1,116 @@
+#ifndef foopulsertpollhfoo
+#define foopulsertpollhfoo
+
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#include <sys/types.h>
+#include <limits.h>
+
+#include <pulse/sample.h>
+#include <pulsecore/asyncmsgq.h>
+#include <pulsecore/fdsem.h>
+#include <pulsecore/macro.h>
+
+/* An implementation of a "real-time" poll loop. Basically, this is
+ * yet another wrapper around poll(). However it has certain
+ * advantages over pa_mainloop and suchlike:
+ *
+ * 1) It uses timer_create() and POSIX real time signals to guarantee
+ * optimal high-resolution timing. Starting with Linux 2.6.21 hrtimers
+ * are available, and since right now only nanosleep() and the POSIX
+ * clock and timer interfaces have been ported to hrtimers (and not
+ * ppoll/pselect!) we have to combine ppoll() with timer_create(). The
+ * fact that POSIX timers and POSIX rt signals are used internally is
+ * completely hidden.
+ *
+ * 2) It allows raw access to the pollfd data to users
+ *
+ * 3) It allows arbitrary functions to be run before entering the
+ * actual poll() and after it.
+ *
+ * Only a single interval timer is supported..*/
+
+typedef struct pa_rtpoll pa_rtpoll;
+typedef struct pa_rtpoll_item pa_rtpoll_item;
+
+typedef enum pa_rtpoll_priority {
+    PA_RTPOLL_EARLY  = -100,          /* For veeery important stuff, like handling control messages */
+    PA_RTPOLL_NORMAL = 0,             /* For normal stuff */
+    PA_RTPOLL_LATE   = +100,          /* For housekeeping */
+    PA_RTPOLL_NEVER  = INT_MAX,       /* For stuff that doesn't register any callbacks, but only fds to listen on */
+} pa_rtpoll_priority_t;
+
+pa_rtpoll *pa_rtpoll_new(void);
+void pa_rtpoll_free(pa_rtpoll *p);
+
+/* Install the rtpoll in the current thread */
+void pa_rtpoll_install(pa_rtpoll *p);
+
+/* Sleep on the rtpoll until the time event, or any of the fd events
+ * is triggered. If "wait" is 0 we don't sleep but only update the
+ * struct pollfd. Returns negative on error, positive if the loop
+ * should continue to run, 0 when the loop should be terminated
+ * cleanly. */
+int pa_rtpoll_run(pa_rtpoll *f, pa_bool_t wait);
+
+void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timeval *ts);
+void pa_rtpoll_set_timer_periodic(pa_rtpoll *p, pa_usec_t usec);
+void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec);
+void pa_rtpoll_set_timer_disabled(pa_rtpoll *p);
+
+/* A new fd wakeup item for pa_rtpoll */
+pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds);
+void pa_rtpoll_item_free(pa_rtpoll_item *i);
+
+/* Please note that this pointer might change on every call and when
+ * pa_rtpoll_run() is called. Hence: call this immediately before
+ * using the pointer and don't save the result anywhere */
+struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds);
+
+/* Set the callback that shall be called when there's time to do some work: If the
+ * callback returns a value > 0, the poll is skipped and the next
+ * iteraton of the loop will start immediately. */
+void pa_rtpoll_item_set_work_callback(pa_rtpoll_item *i, int (*work_cb)(pa_rtpoll_item *i));
+
+/* Set the callback that shall be called immediately before entering
+ * the sleeping poll: If the callback returns a value > 0, the poll is
+ * skipped and the next iteraton of the loop will start
+ * immediately.. */
+void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i));
+
+/* Set the callback that shall be called immediately after having
+ * entered the sleeping poll */
+void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i));
+
+void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata);
+void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i);
+
+pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_fdsem *s);
+pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q);
+
+/* Requests the loop to exit. Will cause the next iteration of
+ * pa_rtpoll_run() to return 0 */
+void pa_rtpoll_quit(pa_rtpoll *p);
+
+#endif
diff --git a/src/pulsecore/rtsig.c b/src/pulsecore/rtsig.c
new file mode 100644 (file)
index 0000000..bfc49c8
--- /dev/null
@@ -0,0 +1,133 @@
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, 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 <signal.h>
+
+#include <pulsecore/macro.h>
+#include <pulsecore/flist.h>
+#include <pulsecore/once.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/core-util.h>
+
+#include "rtsig.h"
+
+#ifdef SIGRTMIN
+
+static void _free_rtsig(void *p) {
+    pa_rtsig_put(PA_PTR_TO_INT(p));
+}
+
+PA_STATIC_FLIST_DECLARE(rtsig_flist, pa_make_power_of_two(SIGRTMAX-SIGRTMIN+1), NULL);
+PA_STATIC_TLS_DECLARE(rtsig_tls, _free_rtsig);
+
+static pa_atomic_t rtsig_current = PA_ATOMIC_INIT(-1);
+
+static int rtsig_start = -1, rtsig_end = -1;
+
+int pa_rtsig_get(void) {
+    void *p;
+    int sig;
+
+    if ((p = pa_flist_pop(PA_STATIC_FLIST_GET(rtsig_flist))))
+        return PA_PTR_TO_INT(p);
+
+    sig = pa_atomic_dec(&rtsig_current);
+
+    pa_assert(sig <= SIGRTMAX);
+    pa_assert(sig <= rtsig_end);
+
+    if (sig < rtsig_start) {
+        pa_atomic_inc(&rtsig_current);
+        return -1;
+    }
+
+    return sig;
+}
+
+int pa_rtsig_get_for_thread(void) {
+    int sig;
+    void *p;
+
+    if ((p = PA_STATIC_TLS_GET(rtsig_tls)))
+        return PA_PTR_TO_INT(p);
+
+    if ((sig = pa_rtsig_get()) < 0)
+        return -1;
+
+    PA_STATIC_TLS_SET(rtsig_tls, PA_INT_TO_PTR(sig));
+    return sig;
+}
+
+void pa_rtsig_put(int sig) {
+    pa_assert(sig >= rtsig_start);
+    pa_assert(sig <= rtsig_end);
+
+    pa_assert_se(pa_flist_push(PA_STATIC_FLIST_GET(rtsig_flist), PA_INT_TO_PTR(sig)) >= 0);
+}
+
+void pa_rtsig_configure(int start, int end) {
+    int s;
+    sigset_t ss;
+
+    pa_assert(pa_atomic_load(&rtsig_current) == -1);
+
+    pa_assert(SIGRTMIN <= start);
+    pa_assert(start <= end);
+    pa_assert(end <= SIGRTMAX);
+
+    rtsig_start = start;
+    rtsig_end = end;
+
+    sigemptyset(&ss);
+
+    for (s = rtsig_start; s <= rtsig_end; s++)
+        pa_assert_se(sigaddset(&ss, s) == 0);
+
+    pa_assert(pthread_sigmask(SIG_BLOCK, &ss, NULL) == 0);
+
+    /* We allocate starting from the end */
+    pa_atomic_store(&rtsig_current, rtsig_end);
+}
+
+#else /* SIGRTMIN */
+
+int pa_rtsig_get(void) {
+    return -1;
+}
+
+int pa_rtsig_get_for_thread(void) {
+    return -1;
+}
+
+void pa_rtsig_put(int sig) {
+}
+
+void pa_rtsig_configure(int start, int end) {
+}
+
+#endif /* SIGRTMIN */
diff --git a/src/pulsecore/rtsig.h b/src/pulsecore/rtsig.h
new file mode 100644 (file)
index 0000000..7830d27
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef foopulsertsighfoo
+#define foopulsertsighfoo
+
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+/* Return the next unused POSIX Realtime signals */
+int pa_rtsig_get(void);
+
+/* If not called before in the current thread, return the next unused
+ * rtsig, and install it in a TLS region and give it up automatically
+ * when the thread shuts down */
+int pa_rtsig_get_for_thread(void);
+
+/* Give an rtsig back. */
+void pa_rtsig_put(int sig);
+
+/* Block all RT signals */
+void pa_rtsig_configure(int start, int end);
+
+#endif
index a99714080b97d4114e7c4a699206cfbdd4d7e5b1..21771302a2a17e9f6800a15d0f0833c3b5cb87c8 100644 (file)
 
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 #include <stdlib.h>
 
 #include <liboil/liboilfuncs.h>
+#include <liboil/liboil.h>
 
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "sample-util.h"
 #include "endianmacros.h"
 
-#define PA_SILENCE_MAX (1024*1024*1)
+#define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
 
 pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spec, size_t length) {
     size_t fs;
-    assert(pool);
-    assert(spec);
+    pa_assert(pool);
+    pa_assert(spec);
 
-    if (length == 0)
+    if (length <= 0)
         length = pa_bytes_per_second(spec)/20; /* 50 ms */
 
     if (length > PA_SILENCE_MAX)
         length = PA_SILENCE_MAX;
 
     fs = pa_frame_size(spec);
-    length = ((PA_SILENCE_MAX+fs-1) / fs) * fs;
+
+    length = (length+fs-1)/fs;
 
     if (length <= 0)
-        length = fs;
+        length = 1;
+
+    length *= fs;
 
     return pa_silence_memblock(pa_memblock_new(pool, length), spec);
 }
 
 pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
-    assert(b && b->data && spec);
-    pa_silence_memory(b->data, b->length, spec);
+    void *data;
+
+    pa_assert(b);
+    pa_assert(spec);
+
+    data = pa_memblock_acquire(b);
+    pa_silence_memory(data, pa_memblock_get_length(b), spec);
+    pa_memblock_release(b);
     return b;
 }
 
 void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
-    assert(c && c->memblock && c->memblock->data && spec && c->length);
+    void *data;
 
-    pa_silence_memory((uint8_t*) c->memblock->data+c->index, c->length, spec);
+    pa_assert(c);
+    pa_assert(c->memblock);
+    pa_assert(spec);
+
+    data = pa_memblock_acquire(c->memblock);
+    pa_silence_memory((uint8_t*) data+c->index, c->length, spec);
+    pa_memblock_release(c->memblock);
 }
 
 void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
     uint8_t c = 0;
-    assert(p && length && spec);
+    pa_assert(p);
+    pa_assert(length > 0);
+    pa_assert(spec);
 
     switch (spec->format) {
         case PA_SAMPLE_U8:
@@ -87,37 +105,51 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
             c = 0;
             break;
         case PA_SAMPLE_ALAW:
+            c = 0xd5;
+            break;
         case PA_SAMPLE_ULAW:
-            c = 80;
+            c = 0xff;
             break;
         default:
-            assert(0);
+            pa_assert_not_reached();
     }
 
     memset(p, c, length);
 }
 
 size_t pa_mix(
-    const pa_mix_info streams[],
-    unsigned nstreams,
-    void *data,
-    size_t length,
-    const pa_sample_spec *spec,
-    const pa_cvolume *volume,
-    int mute) {
+        pa_mix_info streams[],
+        unsigned nstreams,
+        void *data,
+        size_t length,
+        const pa_sample_spec *spec,
+        const pa_cvolume *volume,
+        int mute) {
+
+    pa_cvolume full_volume;
+    size_t d = 0;
+    unsigned k;
+
+    pa_assert(streams);
+    pa_assert(data);
+    pa_assert(length);
+    pa_assert(spec);
 
-    assert(streams && data && length && spec);
+    if (!volume)
+        volume = pa_cvolume_reset(&full_volume, spec->channels);
+
+    for (k = 0; k < nstreams; k++)
+        streams[k].internal = pa_memblock_acquire(streams[k].chunk.memblock);
 
     switch (spec->format) {
         case PA_SAMPLE_S16NE:{
-            size_t d;
             unsigned channel = 0;
 
             for (d = 0;; d += sizeof(int16_t)) {
                 int32_t sum = 0;
 
                 if (d >= length)
-                    return d;
+                    goto finish;
 
                 if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
                     unsigned i;
@@ -127,12 +159,12 @@ size_t pa_mix(
                         pa_volume_t cvolume = streams[i].volume.values[channel];
 
                         if (d >= streams[i].chunk.length)
-                            return d;
+                            goto finish;
 
                         if (cvolume == PA_VOLUME_MUTED)
                             v = 0;
                         else {
-                            v = *((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d));
+                            v = *((int16_t*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d));
 
                             if (cvolume != PA_VOLUME_NORM)
                                 v = (int32_t) (v * pa_sw_volume_to_linear(cvolume));
@@ -144,28 +176,27 @@ size_t pa_mix(
                     if (volume->values[channel] != PA_VOLUME_NORM)
                         sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel]));
 
-                    if (sum < -0x8000) sum = -0x8000;
-                    if (sum > 0x7FFF) sum = 0x7FFF;
-
+                    sum = CLAMP(sum, -0x8000, 0x7FFF);
                 }
 
-                *((int16_t*) data) = sum;
+                *((int16_t*) data) = (int16_t) sum;
                 data = (uint8_t*) data + sizeof(int16_t);
 
                 if (++channel >= spec->channels)
                     channel = 0;
             }
+
+            break;
         }
 
         case PA_SAMPLE_S16RE:{
-            size_t d;
             unsigned channel = 0;
 
             for (d = 0;; d += sizeof(int16_t)) {
                 int32_t sum = 0;
 
                 if (d >= length)
-                    return d;
+                    goto finish;
 
                 if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
                     unsigned i;
@@ -175,12 +206,12 @@ size_t pa_mix(
                         pa_volume_t cvolume = streams[i].volume.values[channel];
 
                         if (d >= streams[i].chunk.length)
-                            return d;
+                            goto finish;
 
                         if (cvolume == PA_VOLUME_MUTED)
                             v = 0;
                         else {
-                            v = INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)));
+                            v = PA_INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d)));
 
                             if (cvolume != PA_VOLUME_NORM)
                                 v = (int32_t) (v * pa_sw_volume_to_linear(cvolume));
@@ -192,28 +223,27 @@ size_t pa_mix(
                     if (volume->values[channel] != PA_VOLUME_NORM)
                         sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel]));
 
-                    if (sum < -0x8000) sum = -0x8000;
-                    if (sum > 0x7FFF) sum = 0x7FFF;
-
+                    sum = CLAMP(sum, -0x8000, 0x7FFF);
                 }
 
-                *((int16_t*) data) = INT16_SWAP(sum);
+                *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum);
                 data = (uint8_t*) data + sizeof(int16_t);
 
                 if (++channel >= spec->channels)
                     channel = 0;
             }
+
+            break;
         }
 
         case PA_SAMPLE_U8: {
-            size_t d;
             unsigned channel = 0;
 
             for (d = 0;; d ++) {
                 int32_t sum = 0;
 
                 if (d >= length)
-                    return d;
+                    goto finish;
 
                 if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
                     unsigned i;
@@ -223,12 +253,12 @@ size_t pa_mix(
                         pa_volume_t cvolume = streams[i].volume.values[channel];
 
                         if (d >= streams[i].chunk.length)
-                            return d;
+                            goto finish;
 
                         if (cvolume == PA_VOLUME_MUTED)
                             v = 0;
                         else {
-                            v = (int32_t) *((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d) - 0x80;
+                            v = (int32_t) *((uint8_t*) streams[i].internal + streams[i].chunk.index + d) - 0x80;
 
                             if (cvolume != PA_VOLUME_NORM)
                                 v = (int32_t) (v * pa_sw_volume_to_linear(cvolume));
@@ -240,9 +270,7 @@ size_t pa_mix(
                     if (volume->values[channel] != PA_VOLUME_NORM)
                         sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel]));
 
-                    if (sum < -0x80) sum = -0x80;
-                    if (sum > 0x7F) sum = 0x7F;
-
+                    sum = CLAMP(sum, -0x80, 0x7F);
                 }
 
                 *((uint8_t*) data) = (uint8_t) (sum + 0x80);
@@ -251,17 +279,18 @@ size_t pa_mix(
                 if (++channel >= spec->channels)
                     channel = 0;
             }
+
+            break;
         }
 
         case PA_SAMPLE_FLOAT32NE: {
-            size_t d;
             unsigned channel = 0;
 
             for (d = 0;; d += sizeof(float)) {
                 float sum = 0;
 
                 if (d >= length)
-                    return d;
+                    goto finish;
 
                 if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
                     unsigned i;
@@ -271,12 +300,12 @@ size_t pa_mix(
                         pa_volume_t cvolume = streams[i].volume.values[channel];
 
                         if (d >= streams[i].chunk.length)
-                            return d;
+                            goto finish;
 
                         if (cvolume == PA_VOLUME_MUTED)
                             v = 0;
                         else {
-                            v = *((float*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d));
+                            v = *((float*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d));
 
                             if (cvolume != PA_VOLUME_NORM)
                                 v *= pa_sw_volume_to_linear(cvolume);
@@ -295,18 +324,35 @@ size_t pa_mix(
                 if (++channel >= spec->channels)
                     channel = 0;
             }
+
+            break;
         }
 
         default:
             pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format));
             abort();
     }
+
+finish:
+
+    for (k = 0; k < nstreams; k++)
+        pa_memblock_release(streams[k].chunk.memblock);
+
+    return d;
 }
 
 
-void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvolume *volume) {
-    assert(c && spec && (c->length % pa_frame_size(spec) == 0));
-    assert(volume);
+void pa_volume_memchunk(
+        pa_memchunk*c,
+        const pa_sample_spec *spec,
+        const pa_cvolume *volume) {
+
+    void *ptr;
+
+    pa_assert(c);
+    pa_assert(spec);
+    pa_assert(c->length % pa_frame_size(spec) == 0);
+    pa_assert(volume);
 
     if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM))
         return;
@@ -316,24 +362,25 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol
         return;
     }
 
+    ptr = pa_memblock_acquire(c->memblock);
+
     switch (spec->format) {
+
         case PA_SAMPLE_S16NE: {
             int16_t *d;
             size_t n;
             unsigned channel;
-            double linear[PA_CHANNELS_MAX];
+            int32_t linear[PA_CHANNELS_MAX];
 
             for (channel = 0; channel < spec->channels; channel++)
-                linear[channel] = pa_sw_volume_to_linear(volume->values[channel]);
-
-            for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
-                int32_t t = (int32_t)(*d);
+                linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);
 
-                t = (int32_t) (t * linear[channel]);
-
-                if (t < -0x8000) t = -0x8000;
-                if (t > 0x7FFF) t = 0x7FFF;
+            for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
+                int32_t t;
 
+                t = (int32_t)(*d);
+                t = (t * linear[channel]) / 0x10000;
+                t = CLAMP(t, -0x8000, 0x7FFF);
                 *d = (int16_t) t;
 
                 if (++channel >= spec->channels)
@@ -346,20 +393,18 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol
             int16_t *d;
             size_t n;
             unsigned channel;
-            double linear[PA_CHANNELS_MAX];
+            int32_t linear[PA_CHANNELS_MAX];
 
             for (channel = 0; channel < spec->channels; channel++)
-                linear[channel] = pa_sw_volume_to_linear(volume->values[channel]);
-
-            for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
-                int32_t t = (int32_t)(INT16_SWAP(*d));
+                linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);
 
-                t = (int32_t) (t * linear[channel]);
+            for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
+                int32_t t;
 
-                if (t < -0x8000) t = -0x8000;
-                if (t > 0x7FFF) t = 0x7FFF;
-
-                *d = INT16_SWAP((int16_t) t);
+                t = (int32_t)(PA_INT16_SWAP(*d));
+                t = (t * linear[channel]) / 0x10000;
+                t = CLAMP(t, -0x8000, 0x7FFF);
+                *d = PA_INT16_SWAP((int16_t) t);
 
                 if (++channel >= spec->channels)
                     channel = 0;
@@ -371,16 +416,18 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol
         case PA_SAMPLE_U8: {
             uint8_t *d;
             size_t n;
-            unsigned channel = 0;
-
-            for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) {
-                int32_t t = (int32_t) *d - 0x80;
+            unsigned channel;
+            int32_t linear[PA_CHANNELS_MAX];
 
-                t = (int32_t) (t * pa_sw_volume_to_linear(volume->values[channel]));
+            for (channel = 0; channel < spec->channels; channel++)
+                linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);
 
-                if (t < -0x80) t = -0x80;
-                if (t > 0x7F) t = 0x7F;
+            for (channel = 0, d = (uint8_t*) ptr + c->index, n = c->length; n > 0; d++, n--) {
+                int32_t t;
 
+                t = (int32_t) *d - 0x80;
+                t = (t * linear[channel]) / 0x10000;
+                t = CLAMP(t, -0x80, 0x7F);
                 *d = (uint8_t) (t + 0x80);
 
                 if (++channel >= spec->channels)
@@ -395,7 +442,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol
             unsigned n;
             unsigned channel;
 
-            d = (float*) ((uint8_t*) c->memblock->data + c->index);
+            d = (float*) ((uint8_t*) ptr + c->index);
             skip = spec->channels * sizeof(float);
             n = c->length/sizeof(float)/spec->channels;
 
@@ -406,7 +453,6 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol
                     continue;
 
                 v = (float) pa_sw_volume_to_linear(volume->values[channel]);
-
                 t = d + channel;
                 oil_scalarmult_f32(t, skip, t, skip, &v, n);
             }
@@ -414,9 +460,85 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol
         }
 
         default:
-            pa_log_error("ERROR: Unable to change volume of format %s.",
-                pa_sample_format_to_string(spec->format));
-            abort();
+            pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec->format));
+            /* If we cannot change the volume, we just don't do it */
     }
+
+    pa_memblock_release(c->memblock);
+}
+
+size_t pa_frame_align(size_t l, const pa_sample_spec *ss) {
+    size_t fs;
+
+    pa_assert(ss);
+
+    fs = pa_frame_size(ss);
+
+    return (l/fs) * fs;
 }
 
+int pa_frame_aligned(size_t l, const pa_sample_spec *ss) {
+    size_t fs;
+
+    pa_assert(ss);
+
+    fs = pa_frame_size(ss);
+
+    return l % fs == 0;
+}
+
+void pa_interleave(const void *src[], unsigned channels, void *dst, size_t ss, unsigned n) {
+    unsigned c;
+    size_t fs;
+
+    pa_assert(src);
+    pa_assert(channels > 0);
+    pa_assert(dst);
+    pa_assert(ss > 0);
+    pa_assert(n > 0);
+
+    fs = ss * channels;
+
+    for (c = 0; c < channels; c++) {
+        unsigned j;
+        void *d;
+        const void *s;
+
+        s = src[c];
+        d = (uint8_t*) dst + c * ss;
+
+        for (j = 0; j < n; j ++) {
+            oil_memcpy(d, s, ss);
+            s = (uint8_t*) s + ss;
+            d = (uint8_t*) d + fs;
+        }
+    }
+}
+
+void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss, unsigned n) {
+    size_t fs;
+    unsigned c;
+
+    pa_assert(src);
+    pa_assert(dst);
+    pa_assert(channels > 0);
+    pa_assert(ss > 0);
+    pa_assert(n > 0);
+
+    fs = ss * channels;
+
+    for (c = 0; c < channels; c++) {
+        unsigned j;
+        const void *s;
+        void *d;
+
+        s = (uint8_t*) src + c * ss;
+        d = dst[c];
+
+        for (j = 0; j < n; j ++) {
+            oil_memcpy(d, s, ss);
+            s = (uint8_t*) s + fs;
+            d = (uint8_t*) d + ss;
+        }
+    }
+}
index 3ff065ab2100afe7509782ae539d74134b8cfcc0..0a39d5ca1ad2569e8c4c9dbd550bd483676fbcbc 100644 (file)
@@ -39,10 +39,11 @@ typedef struct pa_mix_info {
     pa_memchunk chunk;
     pa_cvolume volume;
     void *userdata;
+    void *internal; /* Used internally by pa_mix(), should not be initialised when calling pa_mix() */
 } pa_mix_info;
 
 size_t pa_mix(
-    const pa_mix_info channels[],
+    pa_mix_info channels[],
     unsigned nchannels,
     void *data,
     size_t length,
@@ -55,4 +56,11 @@ void pa_volume_memchunk(
     const pa_sample_spec *spec,
     const pa_cvolume *volume);
 
+size_t pa_frame_align(size_t l, const pa_sample_spec *ss) PA_GCC_PURE;
+
+int pa_frame_aligned(size_t l, const pa_sample_spec *ss) PA_GCC_PURE;
+
+void pa_interleave(const void *src[], unsigned channels, void *dst, size_t ss, unsigned n);
+void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss, unsigned n);
+
 #endif
index c530e79b8f86def080c1ffd3787b5ae1a2d3bd89..f74d028297a20f412283f57527ed1a353147f868 100644 (file)
 
 #include "endianmacros.h"
 
-#define INT16_FROM INT16_FROM_BE
-#define INT16_TO INT16_TO_BE
+#define INT16_FROM PA_INT16_FROM_BE
+#define INT16_TO PA_INT16_TO_BE
 
 #define pa_sconv_s16le_to_float32ne pa_sconv_s16be_to_float32ne
 #define pa_sconv_s16le_from_float32ne pa_sconv_s16be_from_float32ne
 
+#define pa_sconv_s16le_to_float32re pa_sconv_s16be_to_float32re
+#define pa_sconv_s16le_from_float32re pa_sconv_s16be_from_float32re
+
 #ifdef WORDS_BIGENDIAN
 #define SWAP_WORDS 0
 #else
index 6b736f69b9d827f5d7caa078382df3aaee20be2e..ad034489ec66560276aa3961d40ebd1ebd901ac6 100644 (file)
   USA.
 ***/
 
-void pa_sconv_s16be_to_float32ne(unsigned n, const void *a, float *b);
-void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, void *b);
+#include <inttypes.h>
+
+void pa_sconv_s16be_to_float32ne(unsigned n, const int16_t *a, float *b);
+void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, int16_t *b);
+void pa_sconv_s16be_to_float32re(unsigned n, const int16_t *a, float *b);
+void pa_sconv_s16be_from_float32re(unsigned n, const float *a, int16_t *b);
+
+#ifdef WORDS_BIGENDIAN
+#define pa_sconv_float32be_to_s16ne pa_sconv_s16be_from_float32ne
+#define pa_sconv_float32be_from_s16ne pa_sconv_s16be_to_float32ne
+#define pa_sconv_float32le_to_s16ne pa_sconv_s16be_from_float32re
+#define pa_sconv_float32le_from_s16ne pa_sconv_s16be_to_float32re
+#endif
 
 #endif
index 5f45ef66d46cc9286eb0f807f80036561709ec8b..6925052cffa43218af03fe561ff87509c589be5f 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <inttypes.h>
 
 #include <liboil/liboilfuncs.h>
 
 #include <pulsecore/sconv.h>
+#include <pulsecore/macro.h>
 #include <pulsecore/log.h>
 
 #include "endianmacros.h"
 #include "sconv-s16le.h"
 
 #ifndef INT16_FROM
-#define INT16_FROM INT16_FROM_LE
+#define INT16_FROM PA_INT16_FROM_LE
 #endif
 
 #ifndef INT16_TO
-#define INT16_TO INT16_TO_LE
+#define INT16_TO PA_INT16_TO_LE
 #endif
 
 #ifndef SWAP_WORDS
 #endif
 #endif
 
-void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b) {
-    const int16_t *ca = a;
-
-    assert(a);
-    assert(b);
+void pa_sconv_s16le_to_float32ne(unsigned n, const int16_t *a, float *b) {
+    pa_assert(a);
+    pa_assert(b);
 
 #if SWAP_WORDS == 1
 
     for (; n > 0; n--) {
-        int16_t s = *(ca++);
+        int16_t s = *(a++);
         *(b++) = ((float) INT16_FROM(s))/0x7FFF;
     }
 
 #else
 {
     static const double add = 0, factor = 1.0/0x7FFF;
-    oil_scaleconv_f32_s16(b, ca, n, &add, &factor);
+    oil_scaleconv_f32_s16(b, a, n, &add, &factor);
 }
 #endif
 }
 
-void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b) {
-    int16_t *cb = b;
-
-    assert(a);
-    assert(b);
+void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b) {
+    pa_assert(a);
+    pa_assert(b);
 
 #if SWAP_WORDS == 1
 
@@ -86,20 +82,43 @@ void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b) {
         int16_t s;
         float v = *(a++);
 
-        if (v > 1)
-            v = 1;
-
-        if (v < -1)
-            v = -1;
-
+        v = CLAMP(v, -1, 1);
         s = (int16_t) (v * 0x7FFF);
-        *(cb++) = INT16_TO(s);
+        *(b++) = INT16_TO(s);
     }
 
 #else
 {
     static const double add = 0, factor = 0x7FFF;
-    oil_scaleconv_s16_f32(cb, a, n, &add, &factor);
+    oil_scaleconv_s16_f32(b, a, n, &add, &factor);
 }
 #endif
 }
+
+void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b) {
+    pa_assert(a);
+    pa_assert(b);
+
+    for (; n > 0; n--) {
+        int16_t s = *(a++);
+        float k = ((float) INT16_FROM(s))/0x7FFF;
+        uint32_t *j = (uint32_t*) &k;
+        *j = PA_UINT32_SWAP(*j);
+        *(b++) = k;
+    }
+}
+
+void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) {
+    pa_assert(a);
+    pa_assert(b);
+
+    for (; n > 0; n--) {
+        int16_t s;
+        float v = *(a++);
+        uint32_t *j = (uint32_t*) &v;
+        *j = PA_UINT32_SWAP(*j);
+        v = CLAMP(v, -1, 1);
+        s = (int16_t) (v * 0x7FFF);
+        *(b++) = INT16_TO(s);
+    }
+}
index c4e4911ad8821ada2ebe61b2e8afcf70e7a3d72d..4203315a186ff6676639cc4d05f656f6ab7f9e11 100644 (file)
   USA.
 ***/
 
-void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b);
-void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b);
+#include <inttypes.h>
+
+void pa_sconv_s16le_to_float32ne(unsigned n, const int16_t *a, float *b);
+void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b);
+void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b);
+void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b);
+
+#ifndef WORDS_BIGENDIAN
+#define pa_sconv_float32be_to_s16ne pa_sconv_s16le_from_float32re
+#define pa_sconv_float32be_from_s16ne pa_sconv_s16le_to_float32re
+#define pa_sconv_float32le_to_s16ne pa_sconv_s16le_from_float32ne
+#define pa_sconv_float32le_from_s16ne pa_sconv_s16le_to_float32ne
+#endif
 
 #endif
index d15cec84765cf342b319c491df6612b2900bf2db..7f5da63f0eb7b6775d4db0b2f211986b7a321840 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <assert.h>
 
 #include <liboil/liboilfuncs.h>
 #include <liboil/liboil.h>
 
 #include <pulsecore/g711.h>
+#include <pulsecore/macro.h>
 
 #include "endianmacros.h"
 #include "sconv-s16le.h"
 
 #include "sconv.h"
 
-static void u8_to_float32ne(unsigned n, const void *a, float *b) {
-    const uint8_t *ca = a;
-    static const double add = -128.0/127.0, factor = 1.0/127.0;
+/* u8 */
+static void u8_to_float32ne(unsigned n, const uint8_t *a, float *b) {
+    static const double add = -1, factor = 1.0/128.0;
 
-    assert(a);
-    assert(b);
+    pa_assert(a);
+    pa_assert(b);
 
-    oil_scaleconv_f32_u8(b, ca, n, &add, &factor);
+    oil_scaleconv_f32_u8(b, a, n, &add, &factor);
 }
 
-static void u8_from_float32ne(unsigned n, const float *a, void *b) {
-    uint8_t *cb = b;
-    static const double add = 128.0, factor = 127.0;
+static void u8_from_float32ne(unsigned n, const float *a, uint8_t *b) {
+    static const double add = 128, factor = 127.0;
 
-    assert(a);
-    assert(b);
+    pa_assert(a);
+    pa_assert(b);
 
-    oil_scaleconv_u8_f32(cb, a, n, &add, &factor);
+    oil_scaleconv_u8_f32(b, a, n, &add, &factor);
 }
 
-static void float32ne_to_float32ne(unsigned n, const void *a, float *b) {
-    assert(a);
-    assert(b);
+static void u8_to_s16ne(unsigned n, const uint8_t *a, int16_t *b) {
+    static const int16_t add = -0x80, factor = 0x100;
 
-    oil_memcpy(b, a, sizeof(float) * n);
+    pa_assert(a);
+    pa_assert(b);
+
+    oil_conv_s16_u8(b, 2, a, 1, n);
+    oil_scalaradd_s16(b, 2, b, 2, &add, n);
+    oil_scalarmult_s16(b, 2, b, 2, &factor, n);
+}
+
+static void u8_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) {
+
+    pa_assert(a);
+    pa_assert(b);
+
+    for (; n > 0; n--, a++, b++)
+        *b = (uint8_t) (*a / 0x100 + 0x80);
 }
 
-static void float32ne_from_float32ne(unsigned n, const float *a, void *b) {
-    assert(a);
-    assert(b);
+/* float32 */
+
+static void float32ne_to_float32ne(unsigned n, const float *a, float *b) {
+    pa_assert(a);
+    pa_assert(b);
 
     oil_memcpy(b, a, sizeof(float) * n);
 }
 
-static void float32re_to_float32ne(unsigned n, const void *a, float *b) {
-    assert(a);
-    assert(b);
+static void float32re_to_float32ne(unsigned n, const float *a, float *b) {
+    pa_assert(a);
+    pa_assert(b);
+
+    for (; n > 0; n--, a++, b++)
+        *((uint32_t *) b) = PA_UINT32_SWAP(*((uint32_t *) a));
+}
+
+/* s16 */
 
-    while (n-- > 0)
-        ((uint32_t *)b)[n] = UINT32_SWAP (((uint32_t *)a)[n]);
+static void s16ne_to_s16ne(unsigned n, const int16_t *a, int16_t *b) {
+    pa_assert(a);
+    pa_assert(b);
+
+    oil_memcpy(b, a, sizeof(int16_t) * n);
 }
 
-static void float32re_from_float32ne(unsigned n, const float *a, void *b) {
-    assert(a);
-    assert(b);
+static void s16re_to_s16ne(unsigned n, const int16_t *a, int16_t *b) {
+    pa_assert(a);
+    pa_assert(b);
 
-    while (n-- > 0)
-        ((uint32_t *)b)[n] = UINT32_SWAP (((uint32_t *)a)[n]);
+    for (; n > 0; n--, a++, b++)
+        *b = PA_UINT16_SWAP(*a);
 }
 
-static void ulaw_to_float32ne(unsigned n, const void *a, float *b) {
-    const uint8_t *ca = a;
+/* ulaw */
 
-    assert(a);
-    assert(b);
+static void ulaw_to_float32ne(unsigned n, const uint8_t *a, float *b) {
+    pa_assert(a);
+    pa_assert(b);
 
     for (; n > 0; n--)
-        *(b++) = st_ulaw2linear16(*(ca++)) * 1.0F / 0x7FFF;
+        *(b++) = (float) st_ulaw2linear16(*(a++)) / 0x8000;
 }
 
-static void ulaw_from_float32ne(unsigned n, const float *a, void *b) {
-    uint8_t *cb = b;
-
-    assert(a);
-    assert(b);
+static void ulaw_from_float32ne(unsigned n, const float *a, uint8_t *b) {
+    pa_assert(a);
+    pa_assert(b);
 
     for (; n > 0; n--) {
         float v = *(a++);
+        v = CLAMP(v, -1, 1);
+        v *= 0x1FFF;
+        *(b++) = st_14linear2ulaw((int16_t) v);
+    }
+}
+
+static void ulaw_to_s16ne(unsigned n, const uint8_t *a, int16_t *b) {
+    pa_assert(a);
+    pa_assert(b);
+
+    for (; n > 0; n--, a++, b++)
+        *b = st_ulaw2linear16(*a);
+}
+
+static void ulaw_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) {
+    pa_assert(a);
+    pa_assert(b);
+
+    for (; n > 0; n--, a++, b++)
+        *b = st_14linear2ulaw(*a >> 2);
+}
 
-        if (v > 1)
-            v = 1;
+/* alaw */
 
-        if (v < -1)
-            v = -1;
+static void alaw_to_float32ne(unsigned n, const uint8_t *a, float *b) {
+    pa_assert(a);
+    pa_assert(b);
 
-        *(cb++) = st_14linear2ulaw((int16_t) (v * 0x1FFF));
+    for (; n > 0; n--, a++, b++)
+        *b = (float) st_alaw2linear16(*a) / 0x8000;
+}
+
+static void alaw_from_float32ne(unsigned n, const float *a, uint8_t *b) {
+    pa_assert(a);
+    pa_assert(b);
+
+    for (; n > 0; n--, a++, b++) {
+        float v = *a;
+        v = CLAMP(v, -1, 1);
+        v *= 0xFFF;
+        *b = st_13linear2alaw((int16_t) v);
     }
 }
 
-static void alaw_to_float32ne(unsigned n, const void *a, float *b) {
-    const uint8_t *ca = a;
+static void alaw_to_s16ne(unsigned n, const int8_t *a, int16_t *b) {
+    pa_assert(a);
+    pa_assert(b);
 
-    assert(a);
-    assert(b);
+    for (; n > 0; n--, a++, b++)
+        *b = st_alaw2linear16(*a);
+}
 
-    for (; n > 0; n--)
-        *(b++) = st_alaw2linear16(*(ca++)) * 1.0F / 0x7FFF;
+static void alaw_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) {
+    pa_assert(a);
+    pa_assert(b);
+
+    for (; n > 0; n--, a++, b++)
+        *b = st_13linear2alaw(*a >> 3);
 }
 
-static void alaw_from_float32ne(unsigned n, const float *a, void *b) {
-    uint8_t *cb = b;
+pa_convert_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) {
 
-    assert(a);
-    assert(b);
+    static const pa_convert_func_t table[] = {
+        [PA_SAMPLE_U8]        = (pa_convert_func_t) u8_to_float32ne,
+        [PA_SAMPLE_ALAW]      = (pa_convert_func_t) alaw_to_float32ne,
+        [PA_SAMPLE_ULAW]      = (pa_convert_func_t) ulaw_to_float32ne,
+        [PA_SAMPLE_S16LE]     = (pa_convert_func_t) pa_sconv_s16le_to_float32ne,
+        [PA_SAMPLE_S16BE]     = (pa_convert_func_t) pa_sconv_s16be_to_float32ne,
+        [PA_SAMPLE_FLOAT32NE] = (pa_convert_func_t) float32ne_to_float32ne,
+        [PA_SAMPLE_FLOAT32RE] = (pa_convert_func_t) float32re_to_float32ne,
+    };
 
-    for (; n > 0; n--) {
-        float v = *(a++);
+    pa_assert(f >= 0);
+    pa_assert(f < PA_SAMPLE_MAX);
 
-        if (v > 1)
-            v = 1;
+    return table[f];
+}
 
-        if (v < -1)
-            v = -1;
+pa_convert_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) {
 
-        *(cb++) = st_13linear2alaw((int16_t) (v * 0xFFF));
-    }
+    static const pa_convert_func_t table[] = {
+        [PA_SAMPLE_U8]        = (pa_convert_func_t) u8_from_float32ne,
+        [PA_SAMPLE_S16LE]     = (pa_convert_func_t) pa_sconv_s16le_from_float32ne,
+        [PA_SAMPLE_S16BE]     = (pa_convert_func_t) pa_sconv_s16be_from_float32ne,
+        [PA_SAMPLE_FLOAT32NE] = (pa_convert_func_t) float32ne_to_float32ne,
+        [PA_SAMPLE_FLOAT32RE] = (pa_convert_func_t) float32re_to_float32ne,
+        [PA_SAMPLE_ALAW]      = (pa_convert_func_t) alaw_from_float32ne,
+        [PA_SAMPLE_ULAW]      = (pa_convert_func_t) ulaw_from_float32ne
+    };
+
+    pa_assert(f >= 0);
+    pa_assert(f < PA_SAMPLE_MAX);
+
+    return table[f];
 }
 
-pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) {
-    switch(f) {
-        case PA_SAMPLE_U8:
-            return u8_to_float32ne;
-        case PA_SAMPLE_S16LE:
-            return pa_sconv_s16le_to_float32ne;
-        case PA_SAMPLE_S16BE:
-            return pa_sconv_s16be_to_float32ne;
-        case PA_SAMPLE_FLOAT32NE:
-            return float32ne_to_float32ne;
-        case PA_SAMPLE_FLOAT32RE:
-            return float32re_to_float32ne;
-        case PA_SAMPLE_ALAW:
-            return alaw_to_float32ne;
-        case PA_SAMPLE_ULAW:
-            return ulaw_to_float32ne;
-        default:
-            return NULL;
-    }
+pa_convert_func_t pa_get_convert_to_s16ne_function(pa_sample_format_t f) {
+
+    static const pa_convert_func_t table[] = {
+        [PA_SAMPLE_U8]        = (pa_convert_func_t) u8_to_s16ne,
+        [PA_SAMPLE_S16NE]     = (pa_convert_func_t) s16ne_to_s16ne,
+        [PA_SAMPLE_S16RE]     = (pa_convert_func_t) s16re_to_s16ne,
+        [PA_SAMPLE_FLOAT32BE] = (pa_convert_func_t) pa_sconv_float32be_to_s16ne,
+        [PA_SAMPLE_FLOAT32LE] = (pa_convert_func_t) pa_sconv_float32le_to_s16ne,
+        [PA_SAMPLE_ALAW]      = (pa_convert_func_t) alaw_to_s16ne,
+        [PA_SAMPLE_ULAW]      = (pa_convert_func_t) ulaw_to_s16ne
+    };
+
+    pa_assert(f >= 0);
+    pa_assert(f < PA_SAMPLE_MAX);
+
+    return table[f];
 }
 
-pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) {
-    switch(f) {
-        case PA_SAMPLE_U8:
-            return u8_from_float32ne;
-        case PA_SAMPLE_S16LE:
-            return pa_sconv_s16le_from_float32ne;
-        case PA_SAMPLE_S16BE:
-            return pa_sconv_s16be_from_float32ne;
-        case PA_SAMPLE_FLOAT32NE:
-            return float32ne_from_float32ne;
-        case PA_SAMPLE_FLOAT32RE:
-            return float32re_from_float32ne;
-        case PA_SAMPLE_ALAW:
-            return alaw_from_float32ne;
-        case PA_SAMPLE_ULAW:
-            return ulaw_from_float32ne;
-        default:
-            return NULL;
-    }
+pa_convert_func_t pa_get_convert_from_s16ne_function(pa_sample_format_t f) {
+
+    static const pa_convert_func_t table[] = {
+        [PA_SAMPLE_U8]        = (pa_convert_func_t) u8_from_s16ne,
+        [PA_SAMPLE_S16NE]     = (pa_convert_func_t) s16ne_to_s16ne,
+        [PA_SAMPLE_S16RE]     = (pa_convert_func_t) s16re_to_s16ne,
+        [PA_SAMPLE_FLOAT32BE] = (pa_convert_func_t) pa_sconv_float32be_from_s16ne,
+        [PA_SAMPLE_FLOAT32LE] = (pa_convert_func_t) pa_sconv_float32le_from_s16ne,
+        [PA_SAMPLE_ALAW]      = (pa_convert_func_t) alaw_from_s16ne,
+        [PA_SAMPLE_ULAW]      = (pa_convert_func_t) ulaw_from_s16ne,
+    };
+
+    pa_assert(f >= 0);
+    pa_assert(f < PA_SAMPLE_MAX);
+
+    return table[f];
 }
index 1e97aad9d7e9827afaacbee615f8fa77db6830df..901f50a3040d6b05e16c1b2cfca7052a2b86faa2 100644 (file)
 
 #include <pulse/sample.h>
 
-typedef void (*pa_convert_to_float32ne_func_t)(unsigned n, const void *a, float *b);
-typedef void (*pa_convert_from_float32ne_func_t)(unsigned n, const float *a, void *b);
+typedef void (*pa_convert_func_t)(unsigned n, const void *a, void *b);
 
-pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f);
-pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f);
+pa_convert_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) PA_GCC_PURE;
+pa_convert_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) PA_GCC_PURE;
+
+pa_convert_func_t pa_get_convert_to_s16ne_function(pa_sample_format_t f) PA_GCC_PURE;
+pa_convert_func_t pa_get_convert_from_s16ne_function(pa_sample_format_t f) PA_GCC_PURE;
 
 #endif
diff --git a/src/pulsecore/semaphore-posix.c b/src/pulsecore/semaphore-posix.c
new file mode 100644 (file)
index 0000000..750c2af
--- /dev/null
@@ -0,0 +1,69 @@
+/* $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 <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
+
+#include "semaphore.h"
+
+struct pa_semaphore {
+    sem_t sem;
+};
+
+pa_semaphore* pa_semaphore_new(unsigned value) {
+    pa_semaphore *s;
+
+    s = pa_xnew(pa_semaphore, 1);
+    pa_assert_se(sem_init(&s->sem, 0, value) == 0);
+    return s;
+}
+
+void pa_semaphore_free(pa_semaphore *s) {
+    pa_assert(s);
+    pa_assert_se(sem_destroy(&s->sem) == 0);
+    pa_xfree(s);
+}
+
+void pa_semaphore_post(pa_semaphore *s) {
+    pa_assert(s);
+    pa_assert_se(sem_post(&s->sem) == 0);
+}
+
+void pa_semaphore_wait(pa_semaphore *s) {
+    int ret;
+    pa_assert(s);
+
+    do {
+        ret = sem_wait(&s->sem);
+    } while (ret < 0 && errno == EINTR);
+
+    pa_assert(ret == 0);
+}
diff --git a/src/pulsecore/semaphore-win32.c b/src/pulsecore/semaphore-win32.c
new file mode 100644 (file)
index 0000000..f657634
--- /dev/null
@@ -0,0 +1,65 @@
+/* $Id: mutex-win32.c 1426 2007-02-13 15:35:19Z ossman $ */
+
+/***
+  This file is part of PulseAudio.
+
+  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 <windows.h>
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
+
+#include "semaphore.h"
+
+struct pa_semaphore
+{
+    HANDLE sema;
+};
+
+pa_semaphore* pa_semaphore_new(unsigned value) {
+    pa_semaphore *s;
+
+    s = pa_xnew(pa_semaphore, 1);
+
+    s->sema = CreateSemaphore(NULL, value, 32767, NULL);
+    pa_assert(s->sema != NULL);
+
+    return s;
+}
+
+void pa_semaphore_free(pa_semaphore *s) {
+    pa_assert(s);
+    CloseHandle(s->sema);
+    pa_xfree(s);
+}
+
+void pa_semaphore_post(pa_semaphore *s) {
+    pa_assert(s);
+    ReleaseSemaphore(s->sema, 1, NULL);
+}
+
+void pa_semaphore_wait(pa_semaphore *s) {
+    pa_assert(s);
+    WaitForSingleObject(s->sema, INFINITE);
+}
similarity index 64%
rename from src/pulsecore/anotify.h
rename to src/pulsecore/semaphore.h
index b3f75b7e88e27df98443bfd34c0563ba73b7874d..c394e0f2f5ccfdae266bcdb8575183f66ff7ef42 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef foopulseanotifyhfoo
-#define foopulseanotifyhfoo
+#ifndef foopulsesemaphorehfoo
+#define foopulsesemaphorehfoo
 
 /* $Id$ */
 
   USA.
 ***/
 
-/* Asynchronous thread-safe notification of mainloops */
+typedef struct pa_semaphore pa_semaphore;
 
+pa_semaphore* pa_semaphore_new(unsigned value);
+void pa_semaphore_free(pa_semaphore *m);
 
-#include <inttypes.h>
-#include <pulse/mainloop-api.h>
-
-typedef struct pa_anotify pa_anotify;
-typedef void (*pa_anotify_cb_t)(uint8_t event, void *userdata);
-
-pa_anotify *pa_anotify_new(pa_mainloop_api*api, pa_anotify_cb_t cb, void *userdata);
-void pa_anotify_free(pa_anotify *a);
-int pa_anotify_signal(pa_anotify *a, uint8_t event);
+void pa_semaphore_post(pa_semaphore *m);
+void pa_semaphore_wait(pa_semaphore *m);
 
 #endif
index 444d4010e13a476f30f8839f2927c28e0ce7b4b8..6882e7f8586ac547d3e271fa9dff45ba727d2cfb 100644 (file)
@@ -1,32 +1,31 @@
 /* $Id$ */
 
 /***
-  This file is part of PulseAudio.
+    This file is part of PulseAudio.
 
-  Copyright 2006 Lennart Poettering
-  Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
+    Copyright 2006 Lennart Poettering
+    Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
 
-  PulseAudio is free software; you can redistribute it and/or modify
-  it under the terms of the GNU Lesser General Public License as
-  published by the Free Software Foundation; either version 2.1 of the
-  License, or (at your option) any later version.
+    PulseAudio is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as
+    published by the Free Software Foundation; either version 2.1 of the
+    License, or (at your option) any later version.
 
-  PulseAudio is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
+    PulseAudio is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    Lesser General Public License for more details.
 
-  You should have received a copy of the GNU Lesser General Public
-  License along with PulseAudio; if not, write to the Free Software
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-  USA.
+    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 <assert.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <signal.h>
 
 #ifdef HAVE_SYS_MMAN_H
 #include <sys/mman.h>
 #endif
 
+#include <pulse/xmalloc.h>
+
 #include <pulsecore/core-error.h>
 #include <pulsecore/log.h>
 #include <pulsecore/random.h>
-#include <pulse/xmalloc.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/atomic.h>
 
 #include "shm.h"
 
 #define MADV_REMOVE 9
 #endif
 
-#define MAX_SHM_SIZE (1024*1024*20)
+#define MAX_SHM_SIZE (PA_ALIGN(1024*1024*20))
+
+#ifdef __linux__
+/* On Linux we know that the shared memory blocks are files in
+ * /dev/shm. We can use that information to list all blocks and
+ * cleanup unused ones */
+#define SHM_PATH "/dev/shm/"
+#else
+#undef SHM_PATH
+#endif
+
+#define SHM_MARKER ((int) 0xbeefcafe)
+
+/* We now put this SHM marker at the end of each segment. It's optional to not require a reboot when upgrading, though */
+struct shm_marker {
+    pa_atomic_t marker; /* 0xbeefcafe */
+    pa_atomic_t pid;
+    void *_reserverd1;
+    void *_reserverd2;
+    void *_reserverd3;
+    void *_reserverd4;
+};
 
 static char *segment_name(char *fn, size_t l, unsigned id) {
-    snprintf(fn, l, "/pulse-shm-%u", id);
+    pa_snprintf(fn, l, "/pulse-shm-%u", id);
     return fn;
 }
 
@@ -61,10 +88,17 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
     char fn[32];
     int fd = -1;
 
-    assert(m);
-    assert(size > 0);
-    assert(size < MAX_SHM_SIZE);
-    assert(mode >= 0600);
+    pa_assert(m);
+    pa_assert(size > 0);
+    pa_assert(size < MAX_SHM_SIZE);
+    pa_assert(mode >= 0600);
+
+    /* Each time we create a new SHM area, let's first drop all stale
+     * ones */
+    pa_shm_cleanup();
+
+    /* Round up to make it aligned */
+    size = PA_ALIGN(size);
 
     if (!shared) {
         m->id = 0;
@@ -79,7 +113,7 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
         {
             int r;
 
-            if ((r = posix_memalign(&m->ptr, sysconf(_SC_PAGESIZE), size)) < 0) {
+            if ((r = posix_memalign(&m->ptr, PA_PAGE_SIZE, size)) < 0) {
                 pa_log("posix_memalign() failed: %s", pa_cstrerror(r));
                 goto fail;
             }
@@ -92,6 +126,8 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
 
     } else {
 #ifdef HAVE_SHM_OPEN
+        struct shm_marker *marker;
+
         pa_random(&m->id, sizeof(m->id));
         segment_name(fn, sizeof(fn), m->id);
 
@@ -100,7 +136,9 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
             goto fail;
         }
 
-        if (ftruncate(fd, m->size = size) < 0) {
+        m->size = size + PA_ALIGN(sizeof(struct shm_marker));
+
+        if (ftruncate(fd, m->size) < 0) {
             pa_log("ftruncate() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
@@ -110,10 +148,16 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
             goto fail;
         }
 
-        close(fd);
+        /* We store our PID at the end of the shm block, so that we
+         * can check for dead shm segments later */
+        marker = (struct shm_marker*) ((uint8_t*) m->ptr + m->size - PA_ALIGN(sizeof(struct shm_marker)));
+        pa_atomic_store(&marker->pid, (int) getpid());
+        pa_atomic_store(&marker->marker, SHM_MARKER);
+
+        pa_assert_se(close(fd) == 0);
         m->do_unlink = 1;
 #else
-               return -1;
+        return -1;
 #endif
     }
 
@@ -126,7 +170,7 @@ fail:
 #ifdef HAVE_SHM_OPEN
     if (fd >= 0) {
         shm_unlink(fn);
-        close(fd);
+        pa_close(fd);
     }
 #endif
 
@@ -134,76 +178,70 @@ fail:
 }
 
 void pa_shm_free(pa_shm *m) {
-    assert(m);
-    assert(m->ptr);
-    assert(m->size > 0);
+    pa_assert(m);
+    pa_assert(m->ptr);
+    pa_assert(m->size > 0);
 
 #ifdef MAP_FAILED
-       assert(m->ptr != MAP_FAILED);
+    pa_assert(m->ptr != MAP_FAILED);
 #endif
 
-       if (!m->shared) {
+    if (!m->shared) {
 #ifdef MAP_ANONYMOUS
-           if (munmap(m->ptr, m->size) < 0)
-               pa_log("munmap() failed: %s", pa_cstrerror(errno));
+        if (munmap(m->ptr, m->size) < 0)
+            pa_log("munmap() failed: %s", pa_cstrerror(errno));
 #elif defined(HAVE_POSIX_MEMALIGN)
         free(m->ptr);
 #else
         pa_xfree(m->ptr);
 #endif
-       } else {
+    } else {
 #ifdef HAVE_SHM_OPEN
-           if (munmap(m->ptr, m->size) < 0)
-               pa_log("munmap() failed: %s", pa_cstrerror(errno));
+        if (munmap(m->ptr, m->size) < 0)
+            pa_log("munmap() failed: %s", pa_cstrerror(errno));
 
-           if (m->do_unlink) {
-                   char fn[32];
+        if (m->do_unlink) {
+            char fn[32];
 
-                    segment_name(fn, sizeof(fn), m->id);
+            segment_name(fn, sizeof(fn), m->id);
 
-                    if (shm_unlink(fn) < 0)
-                        pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno));
-           }
+            if (shm_unlink(fn) < 0)
+                pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno));
+        }
 #else
-               /* We shouldn't be here without shm support */
-               assert(0);
+        /* We shouldn't be here without shm support */
+        pa_assert_not_reached();
 #endif
-       }
+    }
 
     memset(m, 0, sizeof(*m));
 }
 
 void pa_shm_punch(pa_shm *m, size_t offset, size_t size) {
     void *ptr;
+    size_t o, ps;
 
-    assert(m);
-    assert(m->ptr);
-    assert(m->size > 0);
-    assert(offset+size <= m->size);
+    pa_assert(m);
+    pa_assert(m->ptr);
+    pa_assert(m->size > 0);
+    pa_assert(offset+size <= m->size);
 
 #ifdef MAP_FAILED
-       assert(m->ptr != MAP_FAILED);
+    pa_assert(m->ptr != MAP_FAILED);
 #endif
 
     /* You're welcome to implement this as NOOP on systems that don't
      * support it */
 
+    /* Align this to multiples of the page size */
     ptr = (uint8_t*) m->ptr + offset;
-
-#ifdef __linux__
-{
-    /* On Linux ptr must be page aligned */
-    long psz = sysconf(_SC_PAGESIZE);
-    unsigned o;
-
-    o = ((unsigned long) ptr) - ((((unsigned long) ptr)/psz) * psz);
+    o = (uint8_t*) ptr - (uint8_t*) PA_PAGE_ALIGN_PTR(ptr);
 
     if (o > 0) {
-        ptr = (uint8_t*) ptr + (psz - o);
-        size -= psz - o;
+        ps = PA_PAGE_SIZE;
+        ptr = (uint8_t*) ptr + (ps - o);
+        size -= ps - o;
     }
-}
-#endif
 
 #ifdef MADV_REMOVE
     if (madvise(ptr, size, MADV_REMOVE) >= 0)
@@ -216,7 +254,9 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size) {
 #endif
 
 #ifdef MADV_DONTNEED
-    madvise(ptr, size, MADV_DONTNEED);
+    pa_assert_se(madvise(ptr, size, MADV_DONTNEED) == 0);
+#elif defined(POSIX_MADV_DONTNEED)
+    pa_assert_se(posix_madvise(ptr, size, POSIX_MADV_DONTNEED) == 0);
 #endif
 }
 
@@ -227,12 +267,13 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) {
     int fd = -1;
     struct stat st;
 
-    assert(m);
+    pa_assert(m);
 
     segment_name(fn, sizeof(fn), m->id = id);
 
     if ((fd = shm_open(fn, O_RDONLY, 0)) < 0) {
-        pa_log("shm_open() failed: %s", pa_cstrerror(errno));
+        if (errno != EACCES)
+            pa_log("shm_open() failed: %s", pa_cstrerror(errno));
         goto fail;
     }
 
@@ -241,7 +282,7 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) {
         goto fail;
     }
 
-    if (st.st_size <= 0 || st.st_size > MAX_SHM_SIZE) {
+    if (st.st_size <= 0 || st.st_size > MAX_SHM_SIZE+PA_ALIGN(sizeof(struct shm_marker)) || PA_ALIGN(st.st_size) != st.st_size) {
         pa_log("Invalid shared memory segment size");
         goto fail;
     }
@@ -256,13 +297,13 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) {
     m->do_unlink = 0;
     m->shared = 1;
 
-    close(fd);
+    pa_assert_se(pa_close(fd) == 0);
 
     return 0;
 
 fail:
     if (fd >= 0)
-        close(fd);
+        pa_close(fd);
 
     return -1;
 }
@@ -270,7 +311,71 @@ fail:
 #else /* HAVE_SHM_OPEN */
 
 int pa_shm_attach_ro(pa_shm *m, unsigned id) {
-       return -1;
+    return -1;
 }
 
 #endif /* HAVE_SHM_OPEN */
+
+int pa_shm_cleanup(void) {
+
+#ifdef SHM_PATH
+    DIR *d;
+    struct dirent *de;
+
+    if (!(d = opendir(SHM_PATH))) {
+        pa_log_warn("Failed to read "SHM_PATH": %s", pa_cstrerror(errno));
+        return -1;
+    }
+
+    while ((de = readdir(d))) {
+        pa_shm seg;
+        unsigned id;
+        pid_t pid;
+        char fn[128];
+        struct shm_marker *m;
+
+        if (strncmp(de->d_name, "pulse-shm-", 10))
+            continue;
+
+        if (pa_atou(de->d_name + 10, &id) < 0)
+            continue;
+
+        if (pa_shm_attach_ro(&seg, id) < 0)
+            continue;
+
+        if (seg.size < PA_ALIGN(sizeof(struct shm_marker))) {
+            pa_shm_free(&seg);
+            continue;
+        }
+
+        m = (struct shm_marker*) ((uint8_t*) seg.ptr + seg.size - PA_ALIGN(sizeof(struct shm_marker)));
+
+        if (pa_atomic_load(&m->marker) != SHM_MARKER) {
+            pa_shm_free(&seg);
+            continue;
+        }
+
+        if (!(pid = (pid_t) pa_atomic_load(&m->pid))) {
+            pa_shm_free(&seg);
+            continue;
+        }
+
+        if (kill(pid, 0) == 0 || errno != ESRCH) {
+            pa_shm_free(&seg);
+            continue;
+        }
+
+        pa_shm_free(&seg);
+
+        /* Ok, the owner of this shms segment is dead, so, let's remove the segment */
+        segment_name(fn, sizeof(fn), id);
+
+        if (shm_unlink(fn) < 0 && errno != EACCES)
+            pa_log_warn("Failed to remove SHM segment %s: %s\n", fn, pa_cstrerror(errno));
+    }
+
+    closedir(d);
+#endif
+
+    return 0;
+}
index e695a2a193c3243ef913cee81032db9fa28bb478..270591dec28e4a9242ceb9128b25d468b9ae64da 100644 (file)
@@ -41,4 +41,6 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size);
 
 void pa_shm_free(pa_shm *m);
 
+int pa_shm_cleanup(void);
+
 #endif
index 3ddd74350acfba85cc97d36d9d57881c6f3f0605..6f654b6169ced4a5078b9efe0c45abb709c837b5 100644 (file)
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
 
 #include "sink-input.h"
 
-#define CONVERT_BUFFER_LENGTH 4096
-#define MOVE_BUFFER_LENGTH (1024*1024)
-#define SILENCE_BUFFER_LENGTH (64*1024)
+#define CONVERT_BUFFER_LENGTH (PA_PAGE_SIZE)
+#define SILENCE_BUFFER_LENGTH (PA_PAGE_SIZE*12)
+#define MOVE_BUFFER_LENGTH (PA_PAGE_SIZE*256)
 
-#define CHECK_VALIDITY_RETURN_NULL(condition) \
-do {\
-if (!(condition)) \
-    return NULL; \
-} while (0)
+static PA_DEFINE_CHECK_TYPE(pa_sink_input, pa_msgobject);
+
+static void sink_input_free(pa_object *o);
 
 pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data) {
-    assert(data);
+    pa_assert(data);
 
     memset(data, 0, sizeof(*data));
     data->resample_method = PA_RESAMPLER_INVALID;
+
     return data;
 }
 
 void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map) {
-    assert(data);
+    pa_assert(data);
 
     if ((data->channel_map_is_set = !!map))
         data->channel_map = *map;
 }
 
 void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume) {
-    assert(data);
+    pa_assert(data);
 
     if ((data->volume_is_set = !!volume))
         data->volume = *volume;
 }
 
 void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const pa_sample_spec *spec) {
-    assert(data);
+    pa_assert(data);
 
     if ((data->sample_spec_is_set = !!spec))
         data->sample_spec = *spec;
 }
 
+void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) {
+    pa_assert(data);
+
+    data->muted_is_set = TRUE;
+    data->muted = !!mute;
+}
+
 pa_sink_input* pa_sink_input_new(
         pa_core *core,
         pa_sink_input_new_data *data,
@@ -88,46 +93,52 @@ pa_sink_input* pa_sink_input_new(
 
     pa_sink_input *i;
     pa_resampler *resampler = NULL;
-    int r;
     char st[PA_SAMPLE_SPEC_SNPRINT_MAX];
 
-    assert(core);
-    assert(data);
+    pa_assert(core);
+    pa_assert(data);
 
-    if (!(flags & PA_SINK_INPUT_NO_HOOKS))
-        if (pa_hook_fire(&core->hook_sink_input_new, data) < 0)
-            return NULL;
+    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data) < 0)
+        return NULL;
 
-    CHECK_VALIDITY_RETURN_NULL(!data->driver || pa_utf8_valid(data->driver));
-    CHECK_VALIDITY_RETURN_NULL(!data->name || pa_utf8_valid(data->name));
+    pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
+    pa_return_null_if_fail(!data->name || pa_utf8_valid(data->name));
 
     if (!data->sink)
         data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK, 1);
 
-    CHECK_VALIDITY_RETURN_NULL(data->sink);
-    CHECK_VALIDITY_RETURN_NULL(data->sink->state == PA_SINK_RUNNING);
+    pa_return_null_if_fail(data->sink);
+    pa_return_null_if_fail(pa_sink_get_state(data->sink) != PA_SINK_UNLINKED);
+    pa_return_null_if_fail(!data->sync_base || (data->sync_base->sink == data->sink && pa_sink_input_get_state(data->sync_base) == PA_SINK_INPUT_CORKED));
 
     if (!data->sample_spec_is_set)
         data->sample_spec = data->sink->sample_spec;
 
-    CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(&data->sample_spec));
+    pa_return_null_if_fail(pa_sample_spec_valid(&data->sample_spec));
 
-    if (!data->channel_map_is_set)
-        pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
+    if (!data->channel_map_is_set) {
+        if (data->sink->channel_map.channels == data->sample_spec.channels)
+            data->channel_map = data->sink->channel_map;
+        else
+            pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
+    }
 
-    CHECK_VALIDITY_RETURN_NULL(pa_channel_map_valid(&data->channel_map));
-    CHECK_VALIDITY_RETURN_NULL(data->channel_map.channels == data->sample_spec.channels);
+    pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
+    pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
 
     if (!data->volume_is_set)
         pa_cvolume_reset(&data->volume, data->sample_spec.channels);
 
-    CHECK_VALIDITY_RETURN_NULL(pa_cvolume_valid(&data->volume));
-    CHECK_VALIDITY_RETURN_NULL(data->volume.channels == data->sample_spec.channels);
+    pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
+    pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels);
+
+    if (!data->muted_is_set)
+        data->muted = 0;
 
     if (data->resample_method == PA_RESAMPLER_INVALID)
         data->resample_method = core->resample_method;
 
-    CHECK_VALIDITY_RETURN_NULL(data->resample_method < PA_RESAMPLER_MAX);
+    pa_return_null_if_fail(data->resample_method < PA_RESAMPLER_MAX);
 
     if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) {
         pa_log_warn("Failed to create sink input: too many inputs per sink.");
@@ -136,20 +147,27 @@ pa_sink_input* pa_sink_input_new(
 
     if ((flags & PA_SINK_INPUT_VARIABLE_RATE) ||
         !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec) ||
-        !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map))
+        !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) {
 
         if (!(resampler = pa_resampler_new(
                       core->mempool,
                       &data->sample_spec, &data->channel_map,
                       &data->sink->sample_spec, &data->sink->channel_map,
-                      data->resample_method))) {
+                      data->resample_method,
+                      !!(flags & PA_SINK_INPUT_VARIABLE_RATE)))) {
             pa_log_warn("Unsupported resampling operation.");
             return NULL;
         }
 
-    i = pa_xnew(pa_sink_input, 1);
-    i->ref = 1;
-    i->state = PA_SINK_INPUT_DRAINED;
+        data->resample_method = pa_resampler_get_method(resampler);
+    }
+
+    i = pa_msgobject_new(pa_sink_input);
+    i->parent.parent.free = sink_input_free;
+    i->parent.process_msg = pa_sink_input_process_msg;
+
+    i->core = core;
+    i->state = PA_SINK_INPUT_INIT;
     i->flags = flags;
     i->name = pa_xstrdup(data->name);
     i->driver = pa_xstrdup(data->driver);
@@ -157,105 +175,203 @@ pa_sink_input* pa_sink_input_new(
     i->sink = data->sink;
     i->client = data->client;
 
+    i->resample_method = data->resample_method;
     i->sample_spec = data->sample_spec;
     i->channel_map = data->channel_map;
+
     i->volume = data->volume;
+    i->muted = data->muted;
+
+    if (data->sync_base) {
+        i->sync_next = data->sync_base->sync_next;
+        i->sync_prev = data->sync_base;
+
+        if (data->sync_base->sync_next)
+            data->sync_base->sync_next->sync_prev = i;
+        data->sync_base->sync_next = i;
+    } else
+        i->sync_next = i->sync_prev = NULL;
 
     i->peek = NULL;
     i->drop = NULL;
     i->kill = NULL;
     i->get_latency = NULL;
-    i->underrun = NULL;
+    i->attach = NULL;
+    i->detach = NULL;
+    i->suspend = NULL;
     i->userdata = NULL;
 
-    i->move_silence = 0;
-
-    pa_memchunk_reset(&i->resampled_chunk);
-    i->resampler = resampler;
-    i->resample_method = data->resample_method;
-    i->silence_memblock = NULL;
-
-    r = pa_idxset_put(core->sink_inputs, i, &i->index);
-    assert(r == 0);
-    r = pa_idxset_put(i->sink->inputs, i, NULL);
-    assert(r == 0);
-
-    pa_log_info("created %u \"%s\" on %s with sample spec %s",
+    i->thread_info.state = i->state;
+    pa_atomic_store(&i->thread_info.drained, 1);
+    i->thread_info.sample_spec = i->sample_spec;
+    i->thread_info.silence_memblock = NULL;
+    i->thread_info.move_silence = 0;
+    pa_memchunk_reset(&i->thread_info.resampled_chunk);
+    i->thread_info.resampler = resampler;
+    i->thread_info.volume = i->volume;
+    i->thread_info.muted = i->muted;
+    i->thread_info.attached = FALSE;
+
+    pa_assert_se(pa_idxset_put(core->sink_inputs, pa_sink_input_ref(i), &i->index) == 0);
+    pa_assert_se(pa_idxset_put(i->sink->inputs, i, NULL) == 0);
+
+    pa_log_info("Created input %u \"%s\" on %s with sample spec %s",
                 i->index,
                 i->name,
                 i->sink->name,
                 pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec));
 
-    pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
-
-    /* We do not call pa_sink_notify() here, because the virtual
-     * functions have not yet been initialized */
+    /* Don't forget to call pa_sink_input_put! */
 
     return i;
 }
 
-void pa_sink_input_disconnect(pa_sink_input *i) {
-    assert(i);
-    assert(i->state != PA_SINK_INPUT_DISCONNECTED);
-    assert(i->sink);
-    assert(i->sink->core);
+static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
+    pa_assert(i);
+
+    if (i->state == PA_SINK_INPUT_CORKED && state != PA_SINK_INPUT_CORKED)
+        pa_assert_se(i->sink->n_corked -- >= 1);
+    else if (i->state != PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_CORKED)
+        i->sink->n_corked++;
+
+    pa_sink_update_status(i->sink);
+}
+
+static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
+    pa_sink_input *ssync;
+    pa_assert(i);
+
+    if (state == PA_SINK_INPUT_DRAINED)
+        state = PA_SINK_INPUT_RUNNING;
+
+    if (i->state == state)
+        return 0;
+
+    if (pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0)
+        return -1;
+
+    update_n_corked(i, state);
+    i->state = state;
+
+    for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev) {
+        update_n_corked(ssync, state);
+        ssync->state = state;
+    }
+    for (ssync = i->sync_next; ssync; ssync = ssync->sync_next) {
+        update_n_corked(ssync, state);
+        ssync->state = state;
+    }
+
+    if (state != PA_SINK_INPUT_UNLINKED)
+        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], i);
+
+    return 0;
+}
+
+void pa_sink_input_unlink(pa_sink_input *i) {
+    pa_bool_t linked;
+    pa_assert(i);
+
+    /* See pa_sink_unlink() for a couple of comments how this function
+     * works */
+
+    pa_sink_input_ref(i);
+
+    linked = PA_SINK_INPUT_LINKED(i->state);
+
+    if (linked)
+        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i);
+
+    if (i->sync_prev)
+        i->sync_prev->sync_next = i->sync_next;
+    if (i->sync_next)
+        i->sync_next->sync_prev = i->sync_prev;
+
+    i->sync_prev = i->sync_next = NULL;
 
     pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL);
-    pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
+    if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
+        pa_sink_input_unref(i);
 
-    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
-    i->sink = NULL;
+    if (linked) {
+        pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL);
+        sink_input_set_state(i, PA_SINK_INPUT_UNLINKED);
+        pa_sink_update_status(i->sink);
+    } else
+        i->state = PA_SINK_INPUT_UNLINKED;
 
     i->peek = NULL;
     i->drop = NULL;
     i->kill = NULL;
     i->get_latency = NULL;
-    i->underrun = NULL;
+    i->attach = NULL;
+    i->detach = NULL;
+    i->suspend = NULL;
+
+    if (linked) {
+        pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
+        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i);
+    }
 
-    i->state = PA_SINK_INPUT_DISCONNECTED;
+    i->sink = NULL;
+    pa_sink_input_unref(i);
 }
 
-static void sink_input_free(pa_sink_input* i) {
-    assert(i);
+static void sink_input_free(pa_object *o) {
+    pa_sink_input* i = PA_SINK_INPUT(o);
 
-    if (i->state != PA_SINK_INPUT_DISCONNECTED)
-        pa_sink_input_disconnect(i);
+    pa_assert(i);
+    pa_assert(pa_sink_input_refcnt(i) == 0);
 
-    pa_log_info("freed %u \"%s\"", i->index, i->name);
+    if (PA_SINK_INPUT_LINKED(i->state))
+        pa_sink_input_unlink(i);
 
-    if (i->resampled_chunk.memblock)
-        pa_memblock_unref(i->resampled_chunk.memblock);
+    pa_log_info("Freeing output %u \"%s\"", i->index, i->name);
 
-    if (i->resampler)
-        pa_resampler_free(i->resampler);
+    pa_assert(!i->thread_info.attached);
 
-    if (i->silence_memblock)
-        pa_memblock_unref(i->silence_memblock);
+    if (i->thread_info.resampled_chunk.memblock)
+        pa_memblock_unref(i->thread_info.resampled_chunk.memblock);
+
+    if (i->thread_info.resampler)
+        pa_resampler_free(i->thread_info.resampler);
+
+    if (i->thread_info.silence_memblock)
+        pa_memblock_unref(i->thread_info.silence_memblock);
 
     pa_xfree(i->name);
     pa_xfree(i->driver);
     pa_xfree(i);
 }
 
-void pa_sink_input_unref(pa_sink_input *i) {
-    assert(i);
-    assert(i->ref >= 1);
+void pa_sink_input_put(pa_sink_input *i) {
+    pa_sink_input_assert_ref(i);
 
-    if (!(--i->ref))
-        sink_input_free(i);
-}
+    pa_assert(i->state == PA_SINK_INPUT_INIT);
+    pa_assert(i->peek);
+    pa_assert(i->drop);
 
-pa_sink_input* pa_sink_input_ref(pa_sink_input *i) {
-    assert(i);
-    assert(i->ref >= 1);
+    i->thread_info.state = i->state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
+    i->thread_info.volume = i->volume;
+    i->thread_info.muted = i->muted;
 
-    i->ref++;
-    return i;
+    if (i->state == PA_SINK_INPUT_CORKED)
+        i->sink->n_corked++;
+
+    pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL);
+    pa_sink_update_status(i->sink);
+
+    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
+    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i);
+
+    /* Please note that if you change something here, you have to
+       change something in pa_sink_input_move() with the ghost stream
+       registration too. */
 }
 
 void pa_sink_input_kill(pa_sink_input*i) {
-    assert(i);
-    assert(i->ref >= 1);
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
     if (i->kill)
         i->kill(i);
@@ -264,108 +380,127 @@ void pa_sink_input_kill(pa_sink_input*i) {
 pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
     pa_usec_t r = 0;
 
-    assert(i);
-    assert(i->ref >= 1);
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
+
+    if (pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, &r, 0, NULL) < 0)
+        r = 0;
 
     if (i->get_latency)
         r += i->get_latency(i);
 
-    if (i->resampled_chunk.memblock)
-        r += pa_bytes_to_usec(i->resampled_chunk.length, &i->sink->sample_spec);
-
-    if (i->move_silence)
-        r += pa_bytes_to_usec(i->move_silence, &i->sink->sample_spec);
-
     return r;
 }
 
-int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) {
+/* Called from thread context */
+int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_cvolume *volume) {
     int ret = -1;
     int do_volume_adj_here;
     int volume_is_norm;
+    size_t block_size_max;
 
-    assert(i);
-    assert(i->ref >= 1);
-    assert(chunk);
-    assert(volume);
-
-    pa_sink_input_ref(i);
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
+    pa_assert(pa_frame_aligned(length, &i->sink->sample_spec));
+    pa_assert(chunk);
+    pa_assert(volume);
 
-    if (!i->peek || !i->drop || i->state == PA_SINK_INPUT_CORKED)
+    if (!i->peek || !i->drop || i->thread_info.state == PA_SINK_INPUT_CORKED)
         goto finish;
 
-    assert(i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED);
+    pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING || i->thread_info.state == PA_SINK_INPUT_DRAINED);
 
-    if (i->move_silence > 0) {
+    /* Default buffer size */
+    if (length <= 0)
+        length = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sink->sample_spec);
+
+    /* Make sure the buffer fits in the mempool tile */
+    block_size_max = pa_mempool_block_size_max(i->sink->core->mempool);
+    if (length > block_size_max)
+        length = pa_frame_align(block_size_max, &i->sink->sample_spec);
+
+    if (i->thread_info.move_silence > 0) {
+        size_t l;
 
         /* We have just been moved and shall play some silence for a
          * while until the old sink has drained its playback buffer */
 
-        if (!i->silence_memblock)
-            i->silence_memblock = pa_silence_memblock_new(i->sink->core->mempool, &i->sink->sample_spec, SILENCE_BUFFER_LENGTH);
+        if (!i->thread_info.silence_memblock)
+            i->thread_info.silence_memblock = pa_silence_memblock_new(
+                    i->sink->core->mempool,
+                    &i->sink->sample_spec,
+                    pa_frame_align(SILENCE_BUFFER_LENGTH, &i->sink->sample_spec));
 
-        chunk->memblock = pa_memblock_ref(i->silence_memblock);
+        chunk->memblock = pa_memblock_ref(i->thread_info.silence_memblock);
         chunk->index = 0;
-        chunk->length = i->move_silence < chunk->memblock->length ? i->move_silence : chunk->memblock->length;
+        l = pa_memblock_get_length(chunk->memblock);
+        chunk->length = i->thread_info.move_silence < l ? i->thread_info.move_silence : l;
 
         ret = 0;
         do_volume_adj_here = 1;
         goto finish;
     }
 
-    if (!i->resampler) {
-        do_volume_adj_here = 0;
-        ret = i->peek(i, chunk);
+    if (!i->thread_info.resampler) {
+        do_volume_adj_here = 0; /* FIXME??? */
+        ret = i->peek(i, length, chunk);
         goto finish;
     }
 
     do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
-    volume_is_norm = pa_cvolume_is_norm(&i->volume);
+    volume_is_norm = pa_cvolume_is_norm(&i->thread_info.volume) && !i->thread_info.muted;
 
-    while (!i->resampled_chunk.memblock) {
+    while (!i->thread_info.resampled_chunk.memblock) {
         pa_memchunk tchunk;
-        size_t l;
+        size_t l, rmbs;
 
-        if ((ret = i->peek(i, &tchunk)) < 0)
-            goto finish;
+        l = pa_resampler_request(i->thread_info.resampler, length);
 
-        assert(tchunk.length);
+        if (l <= 0)
+            l = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec);
 
-        l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH);
+        rmbs = pa_resampler_max_block_size(i->thread_info.resampler);
+        if (l > rmbs)
+            l = rmbs;
 
-        if (l > tchunk.length)
-            l = tchunk.length;
+        if ((ret = i->peek(i, l, &tchunk)) < 0)
+            goto finish;
+
+        pa_assert(tchunk.length > 0);
+
+        if (tchunk.length > l)
+            tchunk.length = l;
 
-        i->drop(i, &tchunk, l);
-        tchunk.length = l;
+        i->drop(i, tchunk.length);
 
         /* It might be necessary to adjust the volume here */
         if (do_volume_adj_here && !volume_is_norm) {
             pa_memchunk_make_writable(&tchunk, 0);
-            pa_volume_memchunk(&tchunk, &i->sample_spec, &i->volume);
+
+            if (i->thread_info.muted)
+                pa_silence_memchunk(&tchunk, &i->thread_info.sample_spec);
+            else
+                pa_volume_memchunk(&tchunk, &i->thread_info.sample_spec, &i->thread_info.volume);
         }
 
-        pa_resampler_run(i->resampler, &tchunk, &i->resampled_chunk);
+        pa_resampler_run(i->thread_info.resampler, &tchunk, &i->thread_info.resampled_chunk);
         pa_memblock_unref(tchunk.memblock);
     }
 
-    assert(i->resampled_chunk.memblock);
-    assert(i->resampled_chunk.length);
+    pa_assert(i->thread_info.resampled_chunk.memblock);
+    pa_assert(i->thread_info.resampled_chunk.length > 0);
 
-    *chunk = i->resampled_chunk;
-    pa_memblock_ref(i->resampled_chunk.memblock);
+    *chunk = i->thread_info.resampled_chunk;
+    pa_memblock_ref(i->thread_info.resampled_chunk.memblock);
 
     ret = 0;
 
 finish:
 
-    if (ret < 0 && i->state == PA_SINK_INPUT_RUNNING && i->underrun)
-        i->underrun(i);
-
     if (ret >= 0)
-        i->state = PA_SINK_INPUT_RUNNING;
-    else if (ret < 0 && i->state == PA_SINK_INPUT_RUNNING)
-        i->state = PA_SINK_INPUT_DRAINED;
+        pa_atomic_store(&i->thread_info.drained, 0);
+    else if (ret < 0)
+        pa_atomic_store(&i->thread_info.drained, 1);
 
     if (ret >= 0) {
         /* Let's see if we had to apply the volume adjustment
@@ -374,120 +509,179 @@ finish:
         if (do_volume_adj_here)
             /* We had different channel maps, so we already did the adjustment */
             pa_cvolume_reset(volume, i->sink->sample_spec.channels);
-        else
+        else if (i->thread_info.muted)
             /* We've both the same channel map, so let's have the sink do the adjustment for us*/
-            *volume = i->volume;
+            pa_cvolume_mute(volume, i->sink->sample_spec.channels);
+        else
+            *volume = i->thread_info.volume;
     }
 
-    pa_sink_input_unref(i);
-
     return ret;
 }
 
-void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
-    assert(i);
-    assert(i->ref >= 1);
-    assert(length > 0);
+/* Called from thread context */
+void pa_sink_input_drop(pa_sink_input *i, size_t length) {
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
+    pa_assert(pa_frame_aligned(length, &i->sink->sample_spec));
+    pa_assert(length > 0);
 
-    if (i->move_silence > 0) {
+    if (!i->peek || !i->drop || i->thread_info.state == PA_SINK_INPUT_CORKED)
+        return;
 
-        if (chunk) {
+    if (i->thread_info.move_silence > 0) {
 
-            if (chunk->memblock != i->silence_memblock ||
-                chunk->index != 0 ||
-                (chunk->memblock && (chunk->length != (i->silence_memblock->length < i->move_silence ? i->silence_memblock->length : i->move_silence))))
-                return;
+        if (i->thread_info.move_silence >= length) {
+            i->thread_info.move_silence -= length;
+            length = 0;
+        } else {
+            length -= i->thread_info.move_silence;
+            i->thread_info.move_silence = 0;
+        }
 
+        if (i->thread_info.move_silence <= 0) {
+            if (i->thread_info.silence_memblock) {
+                pa_memblock_unref(i->thread_info.silence_memblock);
+                i->thread_info.silence_memblock = NULL;
+            }
         }
 
-        assert(i->move_silence >= length);
+        if (length <= 0)
+            return;
+    }
+
+    if (i->thread_info.resampled_chunk.memblock) {
+        size_t l = length;
+
+        if (l > i->thread_info.resampled_chunk.length)
+            l = i->thread_info.resampled_chunk.length;
 
-        i->move_silence -= length;
+        i->thread_info.resampled_chunk.index += l;
+        i->thread_info.resampled_chunk.length -= l;
 
-        if (i->move_silence <= 0) {
-            assert(i->silence_memblock);
-            pa_memblock_unref(i->silence_memblock);
-            i->silence_memblock = NULL;
+        if (i->thread_info.resampled_chunk.length <= 0) {
+            pa_memblock_unref(i->thread_info.resampled_chunk.memblock);
+            pa_memchunk_reset(&i->thread_info.resampled_chunk);
         }
 
-        return;
+        length -= l;
     }
 
-    if (!i->resampler) {
-        if (i->drop)
-            i->drop(i, chunk, length);
-        return;
-    }
+    if (length > 0) {
+
+        if (i->thread_info.resampler) {
+            /* So, we have a resampler. To avoid discontinuities we
+             * have to actually read all data that could be read and
+             * pass it through the resampler. */
+
+            while (length > 0) {
+                pa_memchunk chunk;
+                pa_cvolume volume;
+
+                if (pa_sink_input_peek(i, length, &chunk, &volume) >= 0) {
+                    size_t l;
+
+                    pa_memblock_unref(chunk.memblock);
+
+                    l = chunk.length;
+                    if (l > length)
+                        l = length;
+
+                    pa_sink_input_drop(i, l);
+                    length -= l;
 
-    assert(i->resampled_chunk.memblock);
-    assert(i->resampled_chunk.length >= length);
+                } else {
+                    size_t l;
 
-    i->resampled_chunk.index += length;
-    i->resampled_chunk.length -= length;
+                    l = pa_resampler_request(i->thread_info.resampler, length);
+
+                    /* Hmmm, peeking failed, so let's at least drop
+                     * the right amount of data */
+
+                    if (l > 0)
+                        if (i->drop)
+                            i->drop(i, l);
+
+                    break;
+                }
+            }
 
-    if (i->resampled_chunk.length <= 0) {
-        pa_memblock_unref(i->resampled_chunk.memblock);
-        i->resampled_chunk.memblock = NULL;
-        i->resampled_chunk.index = i->resampled_chunk.length = 0;
+        } else {
+
+            /* We have no resampler, hence let's just drop the data */
+
+            if (i->drop)
+                i->drop(i, length);
+        }
     }
 }
 
 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
-    assert(i);
-    assert(i->ref >= 1);
-    assert(i->sink);
-    assert(i->sink->core);
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
     if (pa_cvolume_equal(&i->volume, volume))
         return;
 
     i->volume = *volume;
+
+    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), 0, NULL, pa_xfree);
     pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
 }
 
-const pa_cvolume * pa_sink_input_get_volume(pa_sink_input *i) {
-    assert(i);
-    assert(i->ref >= 1);
+const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i) {
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
     return &i->volume;
 }
 
-void pa_sink_input_cork(pa_sink_input *i, int b) {
-    int n;
+void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute) {
+    pa_assert(i);
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
-    assert(i);
-    assert(i->ref >= 1);
+    if (!i->muted == !mute)
+        return;
 
-    assert(i->state != PA_SINK_INPUT_DISCONNECTED);
+    i->muted = mute;
 
-    n = i->state == PA_SINK_INPUT_CORKED && !b;
+    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), 0, NULL, NULL);
+    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+}
+
+int pa_sink_input_get_mute(pa_sink_input *i) {
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
+
+    return !!i->muted;
+}
 
-    if (b)
-        i->state = PA_SINK_INPUT_CORKED;
-    else if (i->state == PA_SINK_INPUT_CORKED)
-        i->state = PA_SINK_INPUT_DRAINED;
+void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b) {
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
-    if (n)
-        pa_sink_notify(i->sink);
+    sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
 }
 
-void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
-    assert(i);
-    assert(i->resampler);
-    assert(i->ref >= 1);
+int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
+    pa_return_val_if_fail(i->thread_info.resampler, -1);
 
     if (i->sample_spec.rate == rate)
-        return;
+        return 0;
 
     i->sample_spec.rate = rate;
-    pa_resampler_set_input_rate(i->resampler, rate);
+
+    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL);
 
     pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+    return 0;
 }
 
 void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
-    assert(i);
-    assert(i->ref >= 1);
+    pa_sink_input_assert_ref(i);
 
     if (!i->name && !name)
         return;
@@ -498,47 +692,56 @@ void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
     pa_xfree(i->name);
     i->name = pa_xstrdup(name);
 
-    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+    if (PA_SINK_INPUT_LINKED(i->state)) {
+        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_NAME_CHANGED], i);
+        pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+    }
 }
 
 pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
-    assert(i);
-    assert(i->ref >= 1);
+    pa_sink_input_assert_ref(i);
 
-    if (!i->resampler)
-        return i->resample_method;
-
-    return pa_resampler_get_method(i->resampler);
+    return i->resample_method;
 }
 
 int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
-    pa_resampler *new_resampler = NULL;
-    pa_memblockq *buffer = NULL;
+    pa_resampler *new_resampler;
     pa_sink *origin;
+    pa_usec_t silence_usec = 0;
+    pa_sink_input_move_info info;
 
-    assert(i);
-    assert(dest);
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
+    pa_sink_assert_ref(dest);
 
     origin = i->sink;
 
     if (dest == origin)
         return 0;
 
+    if (i->flags & PA_SINK_INPUT_DONT_MOVE)
+        return -1;
+
+    if (i->sync_next || i->sync_prev) {
+        pa_log_warn("Moving synchronised streams not supported.");
+        return -1;
+    }
+
     if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) {
         pa_log_warn("Failed to move sink input: too many inputs per sink.");
         return -1;
     }
 
-    if (i->resampler &&
+    if (i->thread_info.resampler &&
         pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) &&
         pa_channel_map_equal(&origin->channel_map, &dest->channel_map))
 
         /* Try to reuse the old resampler if possible */
-        new_resampler = i->resampler;
+        new_resampler = i->thread_info.resampler;
 
     else if ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
-        !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) ||
-        !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) {
+             !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) ||
+             !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) {
 
         /* Okey, we need a new resampler for the new sink */
 
@@ -546,20 +749,26 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
                       dest->core->mempool,
                       &i->sample_spec, &i->channel_map,
                       &dest->sample_spec, &dest->channel_map,
-                      i->resample_method))) {
+                      i->resample_method,
+                      !!(i->flags & PA_SINK_INPUT_VARIABLE_RATE)))) {
             pa_log_warn("Unsupported resampling operation.");
             return -1;
         }
-    }
+    } else
+        new_resampler = NULL;
+
+    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE], i);
+
+    memset(&info, 0, sizeof(info));
+    info.sink_input = i;
 
     if (!immediately) {
         pa_usec_t old_latency, new_latency;
-        pa_usec_t silence_usec = 0;
-
-        buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, NULL);
 
         /* Let's do a little bit of Voodoo for compensating latency
-         * differences */
+         * differences. We assume that the accuracy for our
+         * estimations is still good enough, even though we do these
+         * operations non-atomic. */
 
         old_latency = pa_sink_get_latency(origin);
         new_latency = pa_sink_get_latency(dest);
@@ -576,8 +785,6 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
             silence_usec = old_latency - new_latency;
 
         } else {
-            size_t l;
-            int volume_is_norm;
 
             /* The latency of new sink is larger than the latency of
              * the old sink. Therefore we have to precompute a little
@@ -585,87 +792,164 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
              * sink, until we can play the first sample on the new
              * sink.*/
 
-            l = pa_usec_to_bytes(new_latency - old_latency, &origin->sample_spec);
+            info.buffer_bytes = pa_usec_to_bytes(new_latency - old_latency, &origin->sample_spec);
+        }
 
-            volume_is_norm = pa_cvolume_is_norm(&i->volume);
+        /* Okey, let's move it */
 
-            while (l > 0) {
-                pa_memchunk chunk;
-                pa_cvolume volume;
-                size_t n;
+        if (info.buffer_bytes > 0) {
 
-                if (pa_sink_input_peek(i, &chunk, &volume) < 0)
-                    break;
+            info.ghost_sink_input = pa_memblockq_sink_input_new(
+                    origin,
+                    "Ghost Stream",
+                    &origin->sample_spec,
+                    &origin->channel_map,
+                    NULL,
+                    NULL);
 
-                n = chunk.length > l ? l : chunk.length;
-                pa_sink_input_drop(i, &chunk, n);
-                chunk.length = n;
+            info.ghost_sink_input->thread_info.state = info.ghost_sink_input->state = PA_SINK_INPUT_RUNNING;
+            info.ghost_sink_input->thread_info.volume = info.ghost_sink_input->volume;
+            info.ghost_sink_input->thread_info.muted = info.ghost_sink_input->muted;
 
-                if (!volume_is_norm) {
-                    pa_memchunk_make_writable(&chunk, 0);
-                    pa_volume_memchunk(&chunk, &origin->sample_spec, &volume);
-                }
-
-                if (pa_memblockq_push(buffer, &chunk) < 0) {
-                    pa_memblock_unref(chunk.memblock);
-                    break;
-                }
-
-                pa_memblock_unref(chunk.memblock);
-                l -= n;
-            }
+            info.buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, NULL);
         }
+    }
 
-        if (i->resampled_chunk.memblock) {
-
-            /* There is still some data left in the already resampled
-             * memory block. Hence, let's output it on the old sink
-             * and sleep so long on the new sink */
+    pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, &info, 0, NULL);
 
-            pa_memblockq_push(buffer, &i->resampled_chunk);
-            silence_usec += pa_bytes_to_usec(i->resampled_chunk.length, &origin->sample_spec);
-        }
+    if (info.ghost_sink_input) {
+        /* Basically, do what pa_sink_input_put() does ...*/
 
-        /* Calculate the new sleeping time */
-        i->move_silence = pa_usec_to_bytes(
-                pa_bytes_to_usec(i->move_silence, &i->sample_spec) +
-                silence_usec,
-                &i->sample_spec);
+        pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, info.ghost_sink_input->index);
+        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], info.ghost_sink_input);
+        pa_sink_input_unref(info.ghost_sink_input);
     }
 
-    /* Okey, let's move it */
     pa_idxset_remove_by_data(origin->inputs, i, NULL);
     pa_idxset_put(dest->inputs, i, NULL);
     i->sink = dest;
 
+    if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED) {
+        pa_assert_se(origin->n_corked-- >= 1);
+        dest->n_corked++;
+    }
+
     /* Replace resampler */
-    if (new_resampler != i->resampler) {
-        if (i->resampler)
-            pa_resampler_free(i->resampler);
-        i->resampler = new_resampler;
+    if (new_resampler != i->thread_info.resampler) {
+        if (i->thread_info.resampler)
+            pa_resampler_free(i->thread_info.resampler);
+        i->thread_info.resampler = new_resampler;
 
         /* if the resampler changed, the silence memblock is
          * probably invalid now, too */
-        if (i->silence_memblock) {
-            pa_memblock_unref(i->silence_memblock);
-            i->silence_memblock = NULL;
+        if (i->thread_info.silence_memblock) {
+            pa_memblock_unref(i->thread_info.silence_memblock);
+            i->thread_info.silence_memblock = NULL;
         }
     }
 
     /* Dump already resampled data */
-    if (i->resampled_chunk.memblock) {
-        pa_memblock_unref(i->resampled_chunk.memblock);
-        i->resampled_chunk.memblock = NULL;
-        i->resampled_chunk.index = i->resampled_chunk.length = 0;
+    if (i->thread_info.resampled_chunk.memblock) {
+        /* Hmm, this data has already been added to the ghost queue, presumably, hence let's sleep a little bit longer */
+        silence_usec += pa_bytes_to_usec(i->thread_info.resampled_chunk.length, &origin->sample_spec);
+        pa_memblock_unref(i->thread_info.resampled_chunk.memblock);
+        pa_memchunk_reset(&i->thread_info.resampled_chunk);
     }
 
+    /* Calculate the new sleeping time */
+    if (immediately)
+        i->thread_info.move_silence = 0;
+    else
+        i->thread_info.move_silence = pa_usec_to_bytes(
+                pa_bytes_to_usec(i->thread_info.move_silence, &origin->sample_spec) +
+                silence_usec,
+                &dest->sample_spec);
+
+    pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL);
+
+    pa_sink_update_status(origin);
+    pa_sink_update_status(dest);
+
+    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_POST], i);
+
+    pa_log_debug("Successfully moved sink input %i from %s to %s.", i->index, origin->name, dest->name);
+
     /* Notify everyone */
     pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
-    pa_sink_notify(i->sink);
-
-    /* Ok, no let's feed the precomputed buffer to the old sink */
-    if (buffer)
-        pa_play_memblockq(origin, "Ghost Stream", &origin->sample_spec, &origin->channel_map, buffer, NULL);
 
     return 0;
 }
+
+/* Called from thread context */
+int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
+    pa_sink_input *i = PA_SINK_INPUT(o);
+
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
+
+    switch (code) {
+        case PA_SINK_INPUT_MESSAGE_SET_VOLUME:
+            i->thread_info.volume = *((pa_cvolume*) userdata);
+            return 0;
+
+        case PA_SINK_INPUT_MESSAGE_SET_MUTE:
+            i->thread_info.muted = PA_PTR_TO_UINT(userdata);
+            return 0;
+
+        case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
+            pa_usec_t *r = userdata;
+
+            if (i->thread_info.resampled_chunk.memblock)
+                *r += pa_bytes_to_usec(i->thread_info.resampled_chunk.length, &i->sink->sample_spec);
+
+            if (i->thread_info.move_silence)
+                *r += pa_bytes_to_usec(i->thread_info.move_silence, &i->sink->sample_spec);
+
+            return 0;
+        }
+
+        case PA_SINK_INPUT_MESSAGE_SET_RATE:
+
+            i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
+            pa_resampler_set_input_rate(i->thread_info.resampler, PA_PTR_TO_UINT(userdata));
+
+            return 0;
+
+        case PA_SINK_INPUT_MESSAGE_SET_STATE: {
+            pa_sink_input *ssync;
+
+            if ((PA_PTR_TO_UINT(userdata) == PA_SINK_INPUT_DRAINED || PA_PTR_TO_UINT(userdata) == PA_SINK_INPUT_RUNNING) &&
+                (i->thread_info.state != PA_SINK_INPUT_DRAINED) && (i->thread_info.state != PA_SINK_INPUT_RUNNING))
+                pa_atomic_store(&i->thread_info.drained, 1);
+
+            i->thread_info.state = PA_PTR_TO_UINT(userdata);
+
+            for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev) {
+                if ((PA_PTR_TO_UINT(userdata) == PA_SINK_INPUT_DRAINED || PA_PTR_TO_UINT(userdata) == PA_SINK_INPUT_RUNNING) &&
+                    (ssync->thread_info.state != PA_SINK_INPUT_DRAINED) && (ssync->thread_info.state != PA_SINK_INPUT_RUNNING))
+                    pa_atomic_store(&ssync->thread_info.drained, 1);
+                ssync->thread_info.state = PA_PTR_TO_UINT(userdata);
+            }
+
+            for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next) {
+                if ((PA_PTR_TO_UINT(userdata) == PA_SINK_INPUT_DRAINED || PA_PTR_TO_UINT(userdata) == PA_SINK_INPUT_RUNNING) &&
+                    (ssync->thread_info.state != PA_SINK_INPUT_DRAINED) && (ssync->thread_info.state != PA_SINK_INPUT_RUNNING))
+                    pa_atomic_store(&ssync->thread_info.drained, 1);
+                ssync->thread_info.state = PA_PTR_TO_UINT(userdata);
+            }
+
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
+pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i) {
+    pa_sink_input_assert_ref(i);
+
+    if (i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED)
+        return pa_atomic_load(&i->thread_info.drained) ? PA_SINK_INPUT_DRAINED : PA_SINK_INPUT_RUNNING;
+
+    return i->state;
+}
index 51d9ec788cd6b25ec88697516abd1a431f660023..3f8e20390279f856ddc0874969f1210700f46d9b 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef foosinkinputhfoo
-#define foosinkinputhfoo
+#ifndef foopulsesinkinputhfoo
+#define foopulsesinkinputhfoo
 
 /* $Id$ */
 
@@ -39,20 +39,32 @@ typedef struct pa_sink_input pa_sink_input;
 #include <pulsecore/core.h>
 
 typedef enum pa_sink_input_state {
-    PA_SINK_INPUT_RUNNING,      /*< The stream is alive and kicking */
+    PA_SINK_INPUT_INIT,         /*< The stream is not active yet, because pa_sink_put() has not been called yet */
     PA_SINK_INPUT_DRAINED,      /*< The stream stopped playing because there was no data to play */
+    PA_SINK_INPUT_RUNNING,      /*< The stream is alive and kicking */
     PA_SINK_INPUT_CORKED,       /*< The stream was corked on user request */
-    PA_SINK_INPUT_DISCONNECTED  /*< The stream is dead */
+    PA_SINK_INPUT_UNLINKED      /*< The stream is dead */
 } pa_sink_input_state_t;
 
+static inline pa_bool_t PA_SINK_INPUT_LINKED(pa_sink_input_state_t x) {
+    return x == PA_SINK_INPUT_DRAINED || x == PA_SINK_INPUT_RUNNING || x == PA_SINK_INPUT_CORKED;
+}
+
 typedef enum pa_sink_input_flags {
     PA_SINK_INPUT_VARIABLE_RATE = 1,
-    PA_SINK_INPUT_NO_HOOKS = 2
+    PA_SINK_INPUT_DONT_MOVE = 2,
+    PA_SINK_INPUT_START_CORKED = 4
 } pa_sink_input_flags_t;
 
 struct pa_sink_input {
-    int ref;
+    pa_msgobject parent;
+
     uint32_t index;
+    pa_core *core;
+
+    /* Please note that this state should only be read with
+     * pa_sink_input_get_state(). That function will transparently
+     * merge the thread_info.drained value in. */
     pa_sink_input_state_t state;
     pa_sink_input_flags_t flags;
 
@@ -64,27 +76,87 @@ struct pa_sink_input {
 
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
-    pa_cvolume volume;
 
-    /* Some silence to play before the actual data. This is used to
-     * compensate for latency differences when moving a sink input
-     * "hot" between sinks. */
-    size_t move_silence;
+    pa_sink_input *sync_prev, *sync_next;
 
-    int (*peek) (pa_sink_input *i, pa_memchunk *chunk);
-    void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length);
+    pa_cvolume volume;
+    pa_bool_t muted;
+
+    /* Returns the chunk of audio data (but doesn't drop it
+     * yet!). Returns -1 on failure. Called from IO thread context. If
+     * data needs to be generated from scratch then please in the
+     * specified length. This is an optimization only. If less data is
+     * available, it's fine to return a smaller block. If more data is
+     * already ready, it is better to return the full block.*/
+    int (*peek) (pa_sink_input *i, size_t length, pa_memchunk *chunk);
+
+    /* Drops the specified number of bytes, usually called right after
+     * peek(), but not necessarily. Called from IO thread context. */
+    void (*drop) (pa_sink_input *i, size_t length);
+
+    /* If non-NULL this function is called when the input is first
+     * connected to a sink or when the rtpoll/asyncmsgq fields
+     * change. You usually don't need to implement this function
+     * unless you rewrite a sink that is piggy-backed onto
+     * another. Called from IO thread context */
+    void (*attach) (pa_sink_input *i);           /* may be NULL */
+
+    /* If non-NULL this function is called when the output is
+     * disconnected from its sink. Called from IO thread context */
+    void (*detach) (pa_sink_input *i);           /* may be NULL */
+
+    /* If non-NULL called whenever the the sink this input is attached
+     * to suspends or resumes. Called from main context */
+    void (*suspend) (pa_sink_input *i, int b);   /* may be NULL */
+
+    /* Supposed to unlink and destroy this stream. Called from main
+     * context. */
     void (*kill) (pa_sink_input *i);             /* may be NULL */
+
+    /* Return the current latency (i.e. length of bufferd audio) of
+    this stream. Called from main context. If NULL a
+    PA_SINK_INPUT_MESSAGE_GET_LATENCY message is sent to the IO thread
+    instead. */
     pa_usec_t (*get_latency) (pa_sink_input *i); /* may be NULL */
-    void (*underrun) (pa_sink_input *i);         /* may be NULL */
 
-    void *userdata;
+    pa_resample_method_t resample_method;
 
-    pa_memchunk resampled_chunk;
-    pa_resampler *resampler;                     /* may be NULL */
+    struct {
+        pa_sink_input_state_t state;
+        pa_atomic_t drained;
 
-    pa_resample_method_t resample_method;
+        pa_bool_t attached; /* True only between ->attach() and ->detach() calls */
+
+        pa_sample_spec sample_spec;
+
+        pa_memchunk resampled_chunk;
+        pa_resampler *resampler;                     /* may be NULL */
+
+        /* Some silence to play before the actual data. This is used to
+         * compensate for latency differences when moving a sink input
+         * "hot" between sinks. */
+        size_t move_silence;
+        pa_memblock *silence_memblock;               /* may be NULL */
+
+        pa_sink_input *sync_prev, *sync_next;
+
+        pa_cvolume volume;
+        pa_bool_t muted;
+    } thread_info;
+
+    void *userdata;
+};
+
+PA_DECLARE_CLASS(pa_sink_input);
+#define PA_SINK_INPUT(o) pa_sink_input_cast(o)
 
-    pa_memblock *silence_memblock;               /* may be NULL */
+enum {
+    PA_SINK_INPUT_MESSAGE_SET_VOLUME,
+    PA_SINK_INPUT_MESSAGE_SET_MUTE,
+    PA_SINK_INPUT_MESSAGE_GET_LATENCY,
+    PA_SINK_INPUT_MESSAGE_SET_RATE,
+    PA_SINK_INPUT_MESSAGE_SET_STATE,
+    PA_SINK_INPUT_MESSAGE_MAX
 };
 
 typedef struct pa_sink_input_new_data {
@@ -95,50 +167,71 @@ typedef struct pa_sink_input_new_data {
     pa_sink *sink;
 
     pa_sample_spec sample_spec;
-    int sample_spec_is_set;
+    pa_bool_t sample_spec_is_set;
     pa_channel_map channel_map;
-    int channel_map_is_set;
+    pa_bool_t channel_map_is_set;
+
     pa_cvolume volume;
-    int volume_is_set;
+    pa_bool_t volume_is_set;
+    pa_bool_t muted;
+    pa_bool_t muted_is_set;
 
     pa_resample_method_t resample_method;
+
+    pa_sink_input *sync_base;
 } pa_sink_input_new_data;
 
 pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data);
 void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const pa_sample_spec *spec);
 void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map);
 void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume);
+void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute);
+
+/* To be called by the implementing module only */
 
 pa_sink_input* pa_sink_input_new(
         pa_core *core,
         pa_sink_input_new_data *data,
         pa_sink_input_flags_t flags);
 
-void pa_sink_input_unref(pa_sink_input* i);
-pa_sink_input* pa_sink_input_ref(pa_sink_input* i);
+void pa_sink_input_put(pa_sink_input *i);
+void pa_sink_input_unlink(pa_sink_input* i);
 
-/* To be called by the implementing module only */
-void pa_sink_input_disconnect(pa_sink_input* i);
+void pa_sink_input_set_name(pa_sink_input *i, const char *name);
 
-/* External code may request disconnection with this funcion */
+/* Callable by everyone */
+
+/* External code may request disconnection with this function */
 void pa_sink_input_kill(pa_sink_input*i);
 
 pa_usec_t pa_sink_input_get_latency(pa_sink_input *i);
 
-int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume);
-void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length);
-
 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume);
-const pa_cvolume * pa_sink_input_get_volume(pa_sink_input *i);
+const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i);
+void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute);
+int pa_sink_input_get_mute(pa_sink_input *i);
 
-void pa_sink_input_cork(pa_sink_input *i, int b);
+void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b);
 
-void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate);
-
-void pa_sink_input_set_name(pa_sink_input *i, const char *name);
+int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate);
 
 pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i);
 
 int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately);
 
+pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i);
+
+/* To be used exclusively by the sink driver thread */
+
+int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_cvolume *volume);
+void pa_sink_input_drop(pa_sink_input *i, size_t length);
+int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
+
+typedef struct pa_sink_input_move_info {
+    pa_sink_input *sink_input;
+    pa_sink_input *ghost_sink_input;
+    pa_memblockq *buffer;
+    size_t buffer_bytes;
+} pa_sink_input_move_info;
+
 #endif
index 9588c2c3d72caee5119535ef7f507c18a529c69d..dccb34cc022e49d2dd9a785c4bce8759b4381a75 100644 (file)
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 
 #include <pulsecore/sample-util.h>
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/play-memblockq.h>
 
 #include "sink.h"
 
 #define MAX_MIX_CHANNELS 32
+#define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
+#define SILENCE_BUFFER_LENGTH (PA_PAGE_SIZE*12)
 
-#define CHECK_VALIDITY_RETURN_NULL(condition) \
-do {\
-if (!(condition)) \
-    return NULL; \
-} while (0)
+static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
+
+static void sink_free(pa_object *s);
 
 pa_sink* pa_sink_new(
         pa_core *core,
@@ -63,68 +64,71 @@ pa_sink* pa_sink_new(
     pa_sink *s;
     char *n = NULL;
     char st[256];
-    int r;
     pa_channel_map tmap;
 
-    assert(core);
-    assert(name);
-    assert(spec);
+    pa_assert(core);
+    pa_assert(name);
+    pa_assert(spec);
 
-    CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec));
+    pa_return_null_if_fail(pa_sample_spec_valid(spec));
 
     if (!map)
         map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT);
 
-    CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map));
-    CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels);
-    CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver));
-    CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name) && *name);
+    pa_return_null_if_fail(map && pa_channel_map_valid(map));
+    pa_return_null_if_fail(map->channels == spec->channels);
+    pa_return_null_if_fail(!driver || pa_utf8_valid(driver));
+    pa_return_null_if_fail(name && pa_utf8_valid(name) && *name);
 
-    s = pa_xnew(pa_sink, 1);
+    s = pa_msgobject_new(pa_sink);
 
     if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) {
         pa_xfree(s);
         return NULL;
     }
 
-    s->ref = 1;
+    s->parent.parent.free = sink_free;
+    s->parent.process_msg = pa_sink_process_msg;
+
     s->core = core;
-    s->state = PA_SINK_RUNNING;
+    s->state = PA_SINK_INIT;
+    s->flags = 0;
     s->name = pa_xstrdup(name);
     s->description = NULL;
     s->driver = pa_xstrdup(driver);
-    s->owner = NULL;
+    s->module = NULL;
 
     s->sample_spec = *spec;
     s->channel_map = *map;
 
     s->inputs = pa_idxset_new(NULL, NULL);
+    s->n_corked = 0;
 
-    pa_cvolume_reset(&s->sw_volume, spec->channels);
-    pa_cvolume_reset(&s->hw_volume, spec->channels);
-    s->sw_muted = 0;
-    s->hw_muted = 0;
-
-    s->is_hardware = 0;
+    pa_cvolume_reset(&s->volume, spec->channels);
+    s->muted = FALSE;
+    s->refresh_volume = s->refresh_mute = FALSE;
 
     s->get_latency = NULL;
-    s->notify = NULL;
-    s->set_hw_volume = NULL;
-    s->get_hw_volume = NULL;
-    s->set_hw_mute = NULL;
-    s->get_hw_mute = NULL;
+    s->set_volume = NULL;
+    s->get_volume = NULL;
+    s->set_mute = NULL;
+    s->get_mute = NULL;
+    s->set_state = NULL;
     s->userdata = NULL;
 
-    r = pa_idxset_put(core->sinks, s, &s->index);
-    assert(s->index != PA_IDXSET_INVALID && r >= 0);
+    s->asyncmsgq = NULL;
+    s->rtpoll = NULL;
+    s->silence = NULL;
+
+    pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
 
     pa_sample_spec_snprint(st, sizeof(st), spec);
-    pa_log_info("created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st);
+    pa_log_info("Created sink %u \"%s\" with sample spec \"%s\"", s->index, s->name, st);
 
     n = pa_sprintf_malloc("%s.monitor", name);
 
     if (!(s->monitor_source = pa_source_new(core, driver, n, 0, spec, map)))
-        pa_log_warn("failed to create monitor source.");
+        pa_log_warn("Failed to create monitor source.");
     else {
         char *d;
         s->monitor_source->monitor_of = s;
@@ -135,51 +139,124 @@ pa_sink* pa_sink_new(
 
     pa_xfree(n);
 
-    pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
+    s->thread_info.inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+    s->thread_info.soft_volume = s->volume;
+    s->thread_info.soft_muted = s->muted;
+    s->thread_info.state = s->state;
 
     return s;
 }
 
-void pa_sink_disconnect(pa_sink* s) {
+static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
+    int ret;
+
+    pa_assert(s);
+
+    if (s->state == state)
+        return 0;
+
+    if ((s->state == PA_SINK_SUSPENDED && PA_SINK_OPENED(state)) ||
+        (PA_SINK_OPENED(s->state) && state == PA_SINK_SUSPENDED)) {
+        pa_sink_input *i;
+        uint32_t idx;
+
+        /* We're suspending or resuming, tell everyone about it */
+
+        for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx)))
+            if (i->suspend)
+                i->suspend(i, state == PA_SINK_SUSPENDED);
+    }
+
+    if (s->set_state)
+        if ((ret = s->set_state(s, state)) < 0)
+            return -1;
+
+    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0)
+        return -1;
+
+    s->state = state;
+
+    if (state != PA_SINK_UNLINKED) /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
+        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
+    return 0;
+}
+
+void pa_sink_put(pa_sink* s) {
+    pa_sink_assert_ref(s);
+
+    pa_assert(s->state == PA_SINK_INIT);
+    pa_assert(s->asyncmsgq);
+    pa_assert(s->rtpoll);
+
+    pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
+
+    pa_source_put(s->monitor_source);
+
+    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_NEW_POST], s);
+}
+
+void pa_sink_unlink(pa_sink* s) {
+    pa_bool_t linked;
     pa_sink_input *i, *j = NULL;
 
-    assert(s);
-    assert(s->state == PA_SINK_RUNNING);
+    pa_assert(s);
+
+    /* Please note that pa_sink_unlink() does more than simply
+     * reversing pa_sink_put(). It also undoes the registrations
+     * already done in pa_sink_new()! */
 
-    s->state = PA_SINK_DISCONNECTED;
-    pa_namereg_unregister(s->core, s->name);
+    /* All operations here shall be idempotent, i.e. pa_sink_unlink()
+     * may be called multiple times on the same sink without bad
+     * effects. */
 
-    pa_hook_fire(&s->core->hook_sink_disconnect, s);
+    linked = PA_SINK_LINKED(s->state);
+
+    if (linked)
+        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
+
+    if (s->state != PA_SINK_UNLINKED)
+        pa_namereg_unregister(s->core, s->name);
+    pa_idxset_remove_by_data(s->core->sinks, s, NULL);
 
     while ((i = pa_idxset_first(s->inputs, NULL))) {
-        assert(i != j);
+        pa_assert(i != j);
         pa_sink_input_kill(i);
         j = i;
     }
 
-    if (s->monitor_source)
-        pa_source_disconnect(s->monitor_source);
-
-    pa_idxset_remove_by_data(s->core->sinks, s, NULL);
+    if (linked)
+        sink_set_state(s, PA_SINK_UNLINKED);
+    else
+        s->state = PA_SINK_UNLINKED;
 
     s->get_latency = NULL;
-    s->notify = NULL;
-    s->get_hw_volume = NULL;
-    s->set_hw_volume = NULL;
-    s->set_hw_mute = NULL;
-    s->get_hw_mute = NULL;
+    s->get_volume = NULL;
+    s->set_volume = NULL;
+    s->set_mute = NULL;
+    s->get_mute = NULL;
+    s->set_state = NULL;
 
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
+    if (s->monitor_source)
+        pa_source_unlink(s->monitor_source);
+
+    if (linked) {
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
+        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s);
+    }
 }
 
-static void sink_free(pa_sink *s) {
-    assert(s);
-    assert(!s->ref);
+static void sink_free(pa_object *o) {
+    pa_sink *s = PA_SINK(o);
+    pa_sink_input *i;
+
+    pa_assert(s);
+    pa_assert(pa_sink_refcnt(s) == 0);
 
-    if (s->state != PA_SINK_DISCONNECTED)
-        pa_sink_disconnect(s);
+    if (PA_SINK_LINKED(s->state))
+        pa_sink_unlink(s);
 
-    pa_log_info("freed %u \"%s\"", s->index, s->name);
+    pa_log_info("Freeing sink %u \"%s\"", s->index, s->name);
 
     if (s->monitor_source) {
         pa_source_unref(s->monitor_source);
@@ -188,108 +265,192 @@ static void sink_free(pa_sink *s) {
 
     pa_idxset_free(s->inputs, NULL, NULL);
 
+    while ((i = pa_hashmap_steal_first(s->thread_info.inputs)))
+        pa_sink_input_unref(i);
+
+    pa_hashmap_free(s->thread_info.inputs, NULL, NULL);
+
+    if (s->silence)
+        pa_memblock_unref(s->silence);
+
     pa_xfree(s->name);
     pa_xfree(s->description);
     pa_xfree(s->driver);
     pa_xfree(s);
 }
 
-void pa_sink_unref(pa_sink*s) {
-    assert(s);
-    assert(s->ref >= 1);
+void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
+    pa_sink_assert_ref(s);
+    pa_assert(q);
+
+    s->asyncmsgq = q;
 
-    if (!(--s->ref))
-        sink_free(s);
+    if (s->monitor_source)
+        pa_source_set_asyncmsgq(s->monitor_source, q);
 }
 
-pa_sink* pa_sink_ref(pa_sink *s) {
-    assert(s);
-    assert(s->ref >= 1);
+void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
+    pa_sink_assert_ref(s);
+    pa_assert(p);
 
-    s->ref++;
-    return s;
+    s->rtpoll = p;
+    if (s->monitor_source)
+        pa_source_set_rtpoll(s->monitor_source, p);
+}
+
+int pa_sink_update_status(pa_sink*s) {
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
+
+    if (s->state == PA_SINK_SUSPENDED)
+        return 0;
+
+    return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
+}
+
+int pa_sink_suspend(pa_sink *s, pa_bool_t suspend) {
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
+
+    if (suspend)
+        return sink_set_state(s, PA_SINK_SUSPENDED);
+    else
+        return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
 }
 
-void pa_sink_notify(pa_sink*s) {
-    assert(s);
-    assert(s->ref >= 1);
+void pa_sink_ping(pa_sink *s) {
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
 
-    if (s->notify)
-        s->notify(s);
+    pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_PING, NULL, 0, NULL, NULL);
 }
 
-static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) {
-    uint32_t idx = PA_IDXSET_INVALID;
+static unsigned fill_mix_info(pa_sink *s, size_t length, pa_mix_info *info, unsigned maxinfo) {
     pa_sink_input *i;
     unsigned n = 0;
+    void *state = NULL;
 
-    assert(s);
-    assert(s->ref >= 1);
-    assert(info);
+    pa_sink_assert_ref(s);
+    pa_assert(info);
 
-    for (i = pa_idxset_first(s->inputs, &idx); maxinfo > 0 && i; i = pa_idxset_next(s->inputs, &idx)) {
-        /* Increase ref counter, to make sure that this input doesn't
-         * vanish while we still need it */
-        pa_sink_input_ref(i);
+    while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxinfo > 0) {
+        pa_sink_input_assert_ref(i);
 
-        if (pa_sink_input_peek(i, &info->chunk, &info->volume) < 0) {
-            pa_sink_input_unref(i);
+        if (pa_sink_input_peek(i, length, &info->chunk, &info->volume) < 0)
             continue;
-        }
 
-        info->userdata = i;
+        info->userdata = pa_sink_input_ref(i);
 
-        assert(info->chunk.memblock);
-        assert(info->chunk.memblock->data);
-        assert(info->chunk.length);
+        pa_assert(info->chunk.memblock);
+        pa_assert(info->chunk.length > 0);
 
         info++;
-        maxinfo--;
         n++;
+        maxinfo--;
     }
 
     return n;
 }
 
-static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned maxinfo, size_t length) {
-    assert(s);
-    assert(s->ref >= 1);
-    assert(info);
+static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length) {
+    pa_sink_input *i;
+    void *state = NULL;
+    unsigned p = 0;
+    unsigned n_unreffed = 0;
+
+    pa_sink_assert_ref(s);
+
+    /* We optimize for the case where the order of the inputs has not changed */
+
+    while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
+        unsigned j;
+        pa_mix_info* m;
+
+        pa_sink_input_assert_ref(i);
 
-    for (; maxinfo > 0; maxinfo--, info++) {
-        pa_sink_input *i = info->userdata;
+        m = NULL;
 
-        assert(i);
-        assert(info->chunk.memblock);
+        /* Let's try to find the matching entry info the pa_mix_info array */
+        for (j = 0; j < n; j ++) {
+
+            if (info[p].userdata == i) {
+                m = info + p;
+                break;
+            }
+
+            p++;
+            if (p >= n)
+                p = 0;
+        }
 
         /* Drop read data */
-        pa_sink_input_drop(i, &info->chunk, length);
-        pa_memblock_unref(info->chunk.memblock);
+        pa_sink_input_drop(i, length);
 
-        /* Decrease ref counter */
-        pa_sink_input_unref(i);
-        info->userdata = NULL;
+        if (m) {
+            pa_sink_input_unref(m->userdata);
+            m->userdata = NULL;
+            if (m->chunk.memblock)
+                pa_memblock_unref(m->chunk.memblock);
+            pa_memchunk_reset(&m->chunk);
+
+            n_unreffed += 1;
+        }
+    }
+
+    /* Now drop references to entries that are included in the
+     * pa_mix_info array but don't exist anymore */
+
+    if (n_unreffed < n) {
+        for (; n > 0; info++, n--) {
+            if (info->userdata)
+                pa_sink_input_unref(info->userdata);
+            if (info->chunk.memblock)
+                pa_memblock_unref(info->chunk.memblock);
+        }
     }
 }
 
-int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
+void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
     pa_mix_info info[MAX_MIX_CHANNELS];
     unsigned n;
-    int r = -1;
+    size_t block_size_max;
 
-    assert(s);
-    assert(s->ref >= 1);
-    assert(length);
-    assert(result);
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_OPENED(s->thread_info.state));
+    pa_assert(pa_frame_aligned(length, &s->sample_spec));
+    pa_assert(result);
 
     pa_sink_ref(s);
 
-    n = fill_mix_info(s, info, MAX_MIX_CHANNELS);
+    if (length <= 0)
+        length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
+
+    block_size_max = pa_mempool_block_size_max(s->core->mempool);
+    if (length > block_size_max)
+        length = pa_frame_align(block_size_max, &s->sample_spec);
+
+    pa_assert(length > 0);
+
+    n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, length, info, MAX_MIX_CHANNELS) : 0;
+
+    if (n == 0) {
+
+        if (length > SILENCE_BUFFER_LENGTH)
+            length = pa_frame_align(SILENCE_BUFFER_LENGTH, &s->sample_spec);
 
-    if (n <= 0)
-        goto finish;
+        pa_assert(length > 0);
 
-    if (n == 1) {
+        if (!s->silence || pa_memblock_get_length(s->silence) < length) {
+            if (s->silence)
+                pa_memblock_unref(s->silence);
+            s->silence = pa_silence_memblock_new(s->core->mempool, &s->sample_spec, length);
+        }
+
+        result->memblock = pa_memblock_ref(s->silence);
+        result->length = length;
+        result->index = 0;
+
+    } else if (n == 1) {
         pa_cvolume volume;
 
         *result = info[0].chunk;
@@ -298,105 +459,112 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
         if (result->length > length)
             result->length = length;
 
-        pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume);
+        pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
 
-        if (s->sw_muted || !pa_cvolume_is_norm(&volume)) {
+        if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) {
             pa_memchunk_make_writable(result, 0);
-            if (s->sw_muted)
+            if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
                 pa_silence_memchunk(result, &s->sample_spec);
             else
                 pa_volume_memchunk(result, &s->sample_spec, &volume);
         }
     } else {
+        void *ptr;
         result->memblock = pa_memblock_new(s->core->mempool, length);
-        assert(result->memblock);
 
-/*          pa_log("mixing %i", n);  */
+        ptr = pa_memblock_acquire(result->memblock);
+        result->length = pa_mix(info, n, ptr, length, &s->sample_spec, &s->thread_info.soft_volume, s->thread_info.soft_muted);
+        pa_memblock_release(result->memblock);
 
-        result->length = pa_mix(info, n, result->memblock->data, length,
-            &s->sample_spec, &s->sw_volume, s->sw_muted);
         result->index = 0;
     }
 
-    inputs_drop(s, info, n, result->length);
+    if (s->thread_info.state == PA_SINK_RUNNING)
+        inputs_drop(s, info, n, result->length);
 
-    if (s->monitor_source)
+    if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source)))
         pa_source_post(s->monitor_source, result);
 
-    r = 0;
-
-finish:
     pa_sink_unref(s);
-
-    return r;
 }
 
-int pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
+void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
     pa_mix_info info[MAX_MIX_CHANNELS];
     unsigned n;
-    int r = -1;
 
-    assert(s);
-    assert(s->ref >= 1);
-    assert(target);
-    assert(target->memblock);
-    assert(target->length);
-    assert(target->memblock->data);
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_OPENED(s->thread_info.state));
+    pa_assert(target);
+    pa_assert(target->memblock);
+    pa_assert(target->length > 0);
+    pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
 
     pa_sink_ref(s);
 
-    n = fill_mix_info(s, info, MAX_MIX_CHANNELS);
-
-    if (n <= 0)
-        goto finish;
-
-    if (n == 1) {
-        pa_cvolume volume;
+    n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, target->length, info, MAX_MIX_CHANNELS) : 0;
 
+    if (n == 0) {
+        pa_silence_memchunk(target, &s->sample_spec);
+    } else if (n == 1) {
         if (target->length > info[0].chunk.length)
             target->length = info[0].chunk.length;
 
-        memcpy((uint8_t*) target->memblock->data + target->index,
-               (uint8_t*) info[0].chunk.memblock->data + info[0].chunk.index,
-               target->length);
+        if (s->thread_info.soft_muted)
+            pa_silence_memchunk(target, &s->sample_spec);
+        else {
+            void *src, *ptr;
+            pa_cvolume volume;
 
-        pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume);
+            ptr = pa_memblock_acquire(target->memblock);
+            src = pa_memblock_acquire(info[0].chunk.memblock);
+
+            memcpy((uint8_t*) ptr + target->index,
+                   (uint8_t*) src + info[0].chunk.index,
+                   target->length);
+
+            pa_memblock_release(target->memblock);
+            pa_memblock_release(info[0].chunk.memblock);
+
+            pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
+
+            if (!pa_cvolume_is_norm(&volume))
+                pa_volume_memchunk(target, &s->sample_spec, &volume);
+        }
+
+    } else {
+        void *ptr;
+
+        ptr = pa_memblock_acquire(target->memblock);
 
-        if (s->sw_muted)
-            pa_silence_memchunk(target, &s->sample_spec);
-        else if (!pa_cvolume_is_norm(&volume))
-            pa_volume_memchunk(target, &s->sample_spec, &volume);
-    } else
         target->length = pa_mix(info, n,
-                                (uint8_t*) target->memblock->data + target->index,
+                                (uint8_t*) ptr + target->index,
                                 target->length,
                                 &s->sample_spec,
-                                &s->sw_volume,
-                                s->sw_muted);
+                                &s->thread_info.soft_volume,
+                                s->thread_info.soft_muted);
 
-    inputs_drop(s, info, n, target->length);
+        pa_memblock_release(target->memblock);
+    }
 
-    if (s->monitor_source)
-        pa_source_post(s->monitor_source, target);
+    if (s->thread_info.state == PA_SINK_RUNNING)
+        inputs_drop(s, info, n, target->length);
 
-    r = 0;
+    if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source)))
+        pa_source_post(s->monitor_source, target);
 
-finish:
     pa_sink_unref(s);
-
-    return r;
 }
 
 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
     pa_memchunk chunk;
     size_t l, d;
 
-    assert(s);
-    assert(s->ref >= 1);
-    assert(target);
-    assert(target->memblock);
-    assert(target->length);
-    assert(target->memblock->data);
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_OPENED(s->thread_info.state));
+    pa_assert(target);
+    pa_assert(target->memblock);
+    pa_assert(target->length > 0);
+    pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
 
     pa_sink_ref(s);
 
@@ -407,140 +575,177 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
         chunk.index += d;
         chunk.length -= d;
 
-        if (pa_sink_render_into(s, &chunk) < 0)
-            break;
+        pa_sink_render_into(s, &chunk);
 
         d += chunk.length;
         l -= chunk.length;
     }
 
-    if (l > 0) {
-        chunk = *target;
-        chunk.index += d;
-        chunk.length -= d;
-        pa_silence_memchunk(&chunk, &s->sample_spec);
-    }
-
     pa_sink_unref(s);
 }
 
 void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
-    assert(s);
-    assert(s->ref >= 1);
-    assert(length);
-    assert(result);
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_OPENED(s->thread_info.state));
+    pa_assert(length > 0);
+    pa_assert(pa_frame_aligned(length, &s->sample_spec));
+    pa_assert(result);
 
     /*** This needs optimization ***/
 
-    result->memblock = pa_memblock_new(s->core->mempool, result->length = length);
     result->index = 0;
+    result->length = length;
+    result->memblock = pa_memblock_new(s->core->mempool, length);
 
     pa_sink_render_into_full(s, result);
 }
 
+void pa_sink_skip(pa_sink *s, size_t length) {
+    pa_sink_input *i;
+    void *state = NULL;
+
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_OPENED(s->thread_info.state));
+    pa_assert(length > 0);
+    pa_assert(pa_frame_aligned(length, &s->sample_spec));
+
+    if (pa_source_used_by(s->monitor_source)) {
+        pa_memchunk chunk;
+
+        /* If something is connected to our monitor source, we have to
+         * pass valid data to it */
+
+        while (length > 0) {
+            pa_sink_render(s, length, &chunk);
+            pa_memblock_unref(chunk.memblock);
+
+            pa_assert(chunk.length <= length);
+            length -= chunk.length;
+        }
+
+    } else {
+        /* Ok, noone cares about the rendered data, so let's not even render it */
+
+        while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
+            pa_sink_input_assert_ref(i);
+            pa_sink_input_drop(i, length);
+        }
+    }
+}
+
 pa_usec_t pa_sink_get_latency(pa_sink *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_usec_t usec = 0;
 
-    if (!s->get_latency)
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
+
+    if (!PA_SINK_OPENED(s->state))
+        return 0;
+
+    if (s->get_latency)
+        return s->get_latency(s);
+
+    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
         return 0;
 
-    return s->get_latency(s);
+    return usec;
 }
 
-void pa_sink_set_owner(pa_sink *s, pa_module *m) {
-    assert(s);
-    assert(s->ref >= 1);
+void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume) {
+    int changed;
 
-    if (s->owner == m)
-        return;
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
+    pa_assert(volume);
 
-    s->owner = m;
+    changed = !pa_cvolume_equal(volume, &s->volume);
+    s->volume = *volume;
 
-    if (s->monitor_source)
-        pa_source_set_owner(s->monitor_source, m);
+    if (s->set_volume && s->set_volume(s) < 0)
+        s->set_volume = NULL;
 
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    if (!s->set_volume)
+        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), 0, NULL, pa_xfree);
+
+    if (changed)
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 }
 
-void pa_sink_set_volume(pa_sink *s, pa_mixer_t m, const pa_cvolume *volume) {
-    pa_cvolume *v;
+const pa_cvolume *pa_sink_get_volume(pa_sink *s) {
+    struct pa_cvolume old_volume;
 
-    assert(s);
-    assert(s->ref >= 1);
-    assert(volume);
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
 
-    if (m == PA_MIXER_HARDWARE && s->set_hw_volume)
-        v = &s->hw_volume;
-    else
-        v = &s->sw_volume;
+    old_volume = s->volume;
 
-    if (pa_cvolume_equal(v, volume))
-        return;
+    if (s->get_volume && s->get_volume(s) < 0)
+        s->get_volume = NULL;
 
-    *v = *volume;
+    if (!s->get_volume && s->refresh_volume)
+        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, &s->volume, 0, NULL);
 
-    if (v == &s->hw_volume)
-        if (s->set_hw_volume(s) < 0)
-            s->sw_volume =  *volume;
+    if (!pa_cvolume_equal(&old_volume, &s->volume))
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    return &s->volume;
 }
 
-const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_mixer_t m) {
-    assert(s);
-    assert(s->ref >= 1);
+void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) {
+    int changed;
+
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
 
-    if (m == PA_MIXER_HARDWARE && s->set_hw_volume) {
+    changed = s->muted != mute;
+    s->muted = mute;
 
-        if (s->get_hw_volume)
-            s->get_hw_volume(s);
+    if (s->set_mute && s->set_mute(s) < 0)
+        s->set_mute = NULL;
 
-        return &s->hw_volume;
-    } else
-        return &s->sw_volume;
+    if (!s->set_mute)
+        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), 0, NULL, NULL);
+
+    if (changed)
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 }
 
-void pa_sink_set_mute(pa_sink *s, pa_mixer_t m, int mute) {
-    int *t;
+pa_bool_t pa_sink_get_mute(pa_sink *s) {
+    pa_bool_t old_muted;
 
-    assert(s);
-    assert(s->ref >= 1);
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
 
-    if (m == PA_MIXER_HARDWARE && s->set_hw_mute)
-        t = &s->hw_muted;
-    else
-        t = &s->sw_muted;
+    old_muted = s->muted;
 
-    if (!!*t == !!mute)
-        return;
+    if (s->get_mute && s->get_mute(s) < 0)
+        s->get_mute = NULL;
 
-    *t = !!mute;
+    if (!s->get_mute && s->refresh_mute)
+        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, &s->muted, 0, NULL);
 
-    if (t == &s->hw_muted)
-        if (s->set_hw_mute(s) < 0)
-            s->sw_muted = !!mute;
+    if (old_muted != s->muted)
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    return s->muted;
 }
 
-int pa_sink_get_mute(pa_sink *s, pa_mixer_t m) {
-    assert(s);
-    assert(s->ref >= 1);
+void pa_sink_set_module(pa_sink *s, pa_module *m) {
+    pa_sink_assert_ref(s);
 
-    if (m == PA_MIXER_HARDWARE && s->set_hw_mute) {
+    if (s->module == m)
+        return;
+
+    s->module = m;
 
-        if (s->get_hw_mute)
-            s->get_hw_mute(s);
+    if (s->monitor_source)
+        pa_source_set_module(s->monitor_source, m);
 
-        return s->hw_muted;
-    } else
-        return s->sw_muted;
+    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 }
 
 void pa_sink_set_description(pa_sink *s, const char *description) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_sink_assert_ref(s);
 
     if (!description && !s->description)
         return;
@@ -559,19 +764,298 @@ void pa_sink_set_description(pa_sink *s, const char *description) {
         pa_xfree(n);
     }
 
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    if (PA_SINK_LINKED(s->state)) {
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_DESCRIPTION_CHANGED], s);
+    }
 }
 
-unsigned pa_sink_used_by(pa_sink *s) {
+unsigned pa_sink_linked_by(pa_sink *s) {
     unsigned ret;
 
-    assert(s);
-    assert(s->ref >= 1);
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
 
     ret = pa_idxset_size(s->inputs);
 
+    /* We add in the number of streams connected to us here. Please
+     * not the asymmmetry to pa_sink_used_by()! */
+
     if (s->monitor_source)
-        ret += pa_source_used_by(s->monitor_source);
+        ret += pa_source_linked_by(s->monitor_source);
 
     return ret;
 }
+
+unsigned pa_sink_used_by(pa_sink *s) {
+    unsigned ret;
+
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
+
+    ret = pa_idxset_size(s->inputs);
+    pa_assert(ret >= s->n_corked);
+    ret -= s->n_corked;
+
+    /* Streams connected to our monitor source do not matter for
+     * pa_sink_used_by()!.*/
+
+    return ret;
+}
+
+int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
+    pa_sink *s = PA_SINK(o);
+    pa_sink_assert_ref(s);
+    pa_assert(s->thread_info.state != PA_SINK_UNLINKED);
+
+    switch ((pa_sink_message_t) code) {
+
+        case PA_SINK_MESSAGE_ADD_INPUT: {
+            pa_sink_input *i = PA_SINK_INPUT(userdata);
+            pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
+
+            /* Since the caller sleeps in pa_sink_input_put(), we can
+             * safely access data outside of thread_info even though
+             * it is mutable */
+
+            if ((i->thread_info.sync_prev = i->sync_prev)) {
+                pa_assert(i->sink == i->thread_info.sync_prev->sink);
+                pa_assert(i->sync_prev->sync_next == i);
+                i->thread_info.sync_prev->thread_info.sync_next = i;
+            }
+
+            if ((i->thread_info.sync_next = i->sync_next)) {
+                pa_assert(i->sink == i->thread_info.sync_next->sink);
+                pa_assert(i->sync_next->sync_prev == i);
+                i->thread_info.sync_next->thread_info.sync_prev = i;
+            }
+
+            pa_assert(!i->thread_info.attached);
+            i->thread_info.attached = TRUE;
+
+            if (i->attach)
+                i->attach(i);
+
+            /* If you change anything here, make sure to change the
+             * ghost sink input handling a few lines down at
+             * PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, too. */
+
+            return 0;
+        }
+
+        case PA_SINK_MESSAGE_REMOVE_INPUT: {
+            pa_sink_input *i = PA_SINK_INPUT(userdata);
+
+            /* If you change anything here, make sure to change the
+             * sink input handling a few lines down at
+             * PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, too. */
+
+            if (i->detach)
+                i->detach(i);
+
+            pa_assert(i->thread_info.attached);
+            i->thread_info.attached = FALSE;
+
+            /* Since the caller sleeps in pa_sink_input_unlink(),
+             * we can safely access data outside of thread_info even
+             * though it is mutable */
+
+            pa_assert(!i->thread_info.sync_prev);
+            pa_assert(!i->thread_info.sync_next);
+
+            if (i->thread_info.sync_prev) {
+                i->thread_info.sync_prev->thread_info.sync_next = i->thread_info.sync_prev->sync_next;
+                i->thread_info.sync_prev = NULL;
+            }
+
+            if (i->thread_info.sync_next) {
+                i->thread_info.sync_next->thread_info.sync_prev = i->thread_info.sync_next->sync_prev;
+                i->thread_info.sync_next = NULL;
+            }
+
+            if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
+                pa_sink_input_unref(i);
+
+            return 0;
+        }
+
+        case PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER: {
+            pa_sink_input_move_info *info = userdata;
+            int volume_is_norm;
+
+            /* We don't support moving synchronized streams. */
+            pa_assert(!info->sink_input->sync_prev);
+            pa_assert(!info->sink_input->sync_next);
+            pa_assert(!info->sink_input->thread_info.sync_next);
+            pa_assert(!info->sink_input->thread_info.sync_prev);
+
+            if (info->sink_input->detach)
+                info->sink_input->detach(info->sink_input);
+
+            pa_assert(info->sink_input->thread_info.attached);
+            info->sink_input->thread_info.attached = FALSE;
+
+            if (info->ghost_sink_input) {
+                pa_assert(info->buffer_bytes > 0);
+                pa_assert(info->buffer);
+
+                volume_is_norm = pa_cvolume_is_norm(&info->sink_input->thread_info.volume);
+
+                pa_log_debug("Buffering %lu bytes ...", (unsigned long) info->buffer_bytes);
+
+                while (info->buffer_bytes > 0) {
+                    pa_memchunk memchunk;
+                    pa_cvolume volume;
+                    size_t n;
+
+                    if (pa_sink_input_peek(info->sink_input, info->buffer_bytes, &memchunk, &volume) < 0)
+                        break;
+
+                    n = memchunk.length > info->buffer_bytes ? info->buffer_bytes : memchunk.length;
+                    pa_sink_input_drop(info->sink_input, n);
+                    memchunk.length = n;
+
+                    if (!volume_is_norm) {
+                        pa_memchunk_make_writable(&memchunk, 0);
+                        pa_volume_memchunk(&memchunk, &s->sample_spec, &volume);
+                    }
+
+                    if (pa_memblockq_push(info->buffer, &memchunk) < 0) {
+                        pa_memblock_unref(memchunk.memblock);
+                        break;
+                    }
+
+                    pa_memblock_unref(memchunk.memblock);
+                    info->buffer_bytes -= n;
+                }
+
+                /* Add the remaining already resampled chunk to the buffer */
+                if (info->sink_input->thread_info.resampled_chunk.memblock)
+                    pa_memblockq_push(info->buffer, &info->sink_input->thread_info.resampled_chunk);
+
+                pa_memblockq_sink_input_set_queue(info->ghost_sink_input, info->buffer);
+
+                pa_log_debug("Buffered %lu bytes ...", (unsigned long) pa_memblockq_get_length(info->buffer));
+            }
+
+            /* Let's remove the sink input ...*/
+            if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(info->sink_input->index)))
+                pa_sink_input_unref(info->sink_input);
+
+            /* .. and add the ghost sink input instead */
+            if (info->ghost_sink_input) {
+                pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(info->ghost_sink_input->index), pa_sink_input_ref(info->ghost_sink_input));
+                info->ghost_sink_input->thread_info.sync_prev = info->ghost_sink_input->thread_info.sync_next = NULL;
+
+                pa_assert(!info->ghost_sink_input->thread_info.attached);
+                info->ghost_sink_input->thread_info.attached = TRUE;
+
+                if (info->ghost_sink_input->attach)
+                    info->ghost_sink_input->attach(info->ghost_sink_input);
+            }
+
+            return 0;
+        }
+
+        case PA_SINK_MESSAGE_SET_VOLUME:
+            s->thread_info.soft_volume = *((pa_cvolume*) userdata);
+            return 0;
+
+        case PA_SINK_MESSAGE_SET_MUTE:
+            s->thread_info.soft_muted = PA_PTR_TO_UINT(userdata);
+            return 0;
+
+        case PA_SINK_MESSAGE_GET_VOLUME:
+            *((pa_cvolume*) userdata) = s->thread_info.soft_volume;
+            return 0;
+
+        case PA_SINK_MESSAGE_GET_MUTE:
+            *((pa_bool_t*) userdata) = s->thread_info.soft_muted;
+            return 0;
+
+        case PA_SINK_MESSAGE_PING:
+            return 0;
+
+        case PA_SINK_MESSAGE_SET_STATE:
+
+            s->thread_info.state = PA_PTR_TO_UINT(userdata);
+            return 0;
+
+        case PA_SINK_MESSAGE_DETACH:
+
+            /* We're detaching all our input streams so that the
+             * asyncmsgq and rtpoll fields can be changed without
+             * problems */
+            pa_sink_detach_within_thread(s);
+            break;
+
+        case PA_SINK_MESSAGE_ATTACH:
+
+            /* Reattach all streams */
+            pa_sink_attach_within_thread(s);
+            break;
+
+        case PA_SINK_MESSAGE_GET_LATENCY:
+        case PA_SINK_MESSAGE_MAX:
+            ;
+    }
+
+    return -1;
+}
+
+int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend) {
+    pa_sink *sink;
+    uint32_t idx;
+    int ret = 0;
+
+    pa_core_assert_ref(c);
+
+    for (sink = PA_SINK(pa_idxset_first(c->sinks, &idx)); sink; sink = PA_SINK(pa_idxset_next(c->sinks, &idx)))
+        ret -= pa_sink_suspend(sink, suspend) < 0;
+
+    return ret;
+}
+
+void pa_sink_detach(pa_sink *s) {
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
+
+    pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_DETACH, NULL, 0, NULL);
+}
+
+void pa_sink_attach(pa_sink *s) {
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
+
+    pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_ATTACH, NULL, 0, NULL);
+}
+
+void pa_sink_detach_within_thread(pa_sink *s) {
+    pa_sink_input *i;
+    void *state = NULL;
+
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->thread_info.state));
+
+    while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
+        if (i->detach)
+            i->detach(i);
+
+    if (s->monitor_source)
+        pa_source_detach_within_thread(s->monitor_source);
+}
+
+void pa_sink_attach_within_thread(pa_sink *s) {
+    pa_sink_input *i;
+    void *state = NULL;
+
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->thread_info.state));
+
+    while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
+        if (i->attach)
+            i->attach(i);
+
+    if (s->monitor_source)
+        pa_source_attach_within_thread(s->monitor_source);
+}
index ef73f67d24db703299a757d45aa45a9021a28056..e9969309b4410e6cf7f0a88419e1fd551a75efb3 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef foosinkhfoo
-#define foosinkhfoo
+#ifndef foopulsesinkhfoo
+#define foopulsesinkhfoo
 
 /* $Id$ */
 
   USA.
 ***/
 
-#include <inttypes.h>
-
 typedef struct pa_sink pa_sink;
 
+#include <inttypes.h>
+
 #include <pulse/sample.h>
 #include <pulse/channelmap.h>
 #include <pulse/volume.h>
+
 #include <pulsecore/core-def.h>
 #include <pulsecore/core.h>
 #include <pulsecore/idxset.h>
 #include <pulsecore/source.h>
 #include <pulsecore/module.h>
+#include <pulsecore/refcnt.h>
+#include <pulsecore/msgobject.h>
+#include <pulsecore/rtpoll.h>
 
 #define PA_MAX_INPUTS_PER_SINK 32
 
 typedef enum pa_sink_state {
+    PA_SINK_INIT,
     PA_SINK_RUNNING,
-    PA_SINK_DISCONNECTED
+    PA_SINK_SUSPENDED,
+    PA_SINK_IDLE,
+    PA_SINK_UNLINKED
 } pa_sink_state_t;
 
+static inline pa_bool_t PA_SINK_OPENED(pa_sink_state_t x) {
+    return x == PA_SINK_RUNNING || x == PA_SINK_IDLE;
+}
+
+static inline pa_bool_t PA_SINK_LINKED(pa_sink_state_t x) {
+    return x == PA_SINK_RUNNING || x == PA_SINK_IDLE || x == PA_SINK_SUSPENDED;
+}
+
 struct pa_sink {
-    int ref;
+    pa_msgobject parent;
+
     uint32_t index;
     pa_core *core;
     pa_sink_state_t state;
+    pa_sink_flags_t flags;
 
     char *name;
     char *description, *driver;            /* may be NULL */
-    int is_hardware;
 
-    pa_module *owner;                      /* may be NULL */
+    pa_module *module;                      /* may be NULL */
 
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
 
     pa_idxset *inputs;
-    pa_source *monitor_source;             /* may be NULL */
-
-    pa_cvolume hw_volume, sw_volume;
-    int hw_muted, sw_muted;
-
-    void (*notify)(pa_sink*sink);          /* may be NULL */
-    pa_usec_t (*get_latency)(pa_sink *s);  /* dito */
-    int (*set_hw_volume)(pa_sink *s);      /* dito */
-    int (*get_hw_volume)(pa_sink *s);      /* dito */
-    int (*set_hw_mute)(pa_sink *s);        /* dito */
-    int (*get_hw_mute)(pa_sink *s);        /* dito */
+    unsigned n_corked;
+    pa_source *monitor_source;
+
+    pa_cvolume volume;
+    pa_bool_t muted;
+    pa_bool_t refresh_volume;
+    pa_bool_t refresh_mute;
+
+    int (*set_state)(pa_sink *s, pa_sink_state_t state); /* may be NULL */
+    int (*set_volume)(pa_sink *s);           /* dito */
+    int (*get_volume)(pa_sink *s);           /* dito */
+    int (*get_mute)(pa_sink *s);             /* dito */
+    int (*set_mute)(pa_sink *s);             /* dito */
+    pa_usec_t (*get_latency)(pa_sink *s);    /* dito */
+
+    pa_asyncmsgq *asyncmsgq;
+    pa_rtpoll *rtpoll;
+
+    /* Contains copies of the above data so that the real-time worker
+     * thread can work without access locking */
+    struct {
+        pa_sink_state_t state;
+        pa_hashmap *inputs;
+        pa_cvolume soft_volume;
+        pa_bool_t soft_muted;
+    } thread_info;
+
+    pa_memblock *silence;
 
     void *userdata;
 };
 
+PA_DECLARE_CLASS(pa_sink);
+#define PA_SINK(s) (pa_sink_cast(s))
+
+typedef enum pa_sink_message {
+    PA_SINK_MESSAGE_ADD_INPUT,
+    PA_SINK_MESSAGE_REMOVE_INPUT,
+    PA_SINK_MESSAGE_GET_VOLUME,
+    PA_SINK_MESSAGE_SET_VOLUME,
+    PA_SINK_MESSAGE_GET_MUTE,
+    PA_SINK_MESSAGE_SET_MUTE,
+    PA_SINK_MESSAGE_GET_LATENCY,
+    PA_SINK_MESSAGE_SET_STATE,
+    PA_SINK_MESSAGE_PING,
+    PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER,
+    PA_SINK_MESSAGE_ATTACH,
+    PA_SINK_MESSAGE_DETACH,
+    PA_SINK_MESSAGE_MAX
+} pa_sink_message_t;
+
+/* To be called exclusively by the sink driver, from main context */
+
 pa_sink* pa_sink_new(
-    pa_core *core,
-    const char *driver,
-    const char *name,
-    int namereg_fail,
-    const pa_sample_spec *spec,
-    const pa_channel_map *map);
-
-void pa_sink_disconnect(pa_sink* s);
-void pa_sink_unref(pa_sink*s);
-pa_sink* pa_sink_ref(pa_sink *s);
-
-int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result);
-void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result);
-int pa_sink_render_into(pa_sink*s, pa_memchunk *target);
-void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target);
+        pa_core *core,
+        const char *driver,
+        const char *name,
+        int namereg_fail,
+        const pa_sample_spec *spec,
+        const pa_channel_map *map);
+
+void pa_sink_put(pa_sink *s);
+void pa_sink_unlink(pa_sink* s);
+
+void pa_sink_set_module(pa_sink *sink, pa_module *m);
+void pa_sink_set_description(pa_sink *s, const char *description);
+void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q);
+void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p);
+
+void pa_sink_detach(pa_sink *s);
+void pa_sink_attach(pa_sink *s);
+
+/* May be called by everyone, from main context */
 
 pa_usec_t pa_sink_get_latency(pa_sink *s);
 
-void pa_sink_notify(pa_sink*s);
+int pa_sink_update_status(pa_sink*s);
+int pa_sink_suspend(pa_sink *s, pa_bool_t suspend);
+int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend);
 
-void pa_sink_set_owner(pa_sink *sink, pa_module *m);
+/* Sends a ping message to the sink thread, to make it wake up and
+ * check for data to process even if there is no real message is
+ * sent */
+void pa_sink_ping(pa_sink *s);
 
-void pa_sink_set_volume(pa_sink *sink, pa_mixer_t m, const pa_cvolume *volume);
-const pa_cvolume *pa_sink_get_volume(pa_sink *sink, pa_mixer_t m);
-void pa_sink_set_mute(pa_sink *sink, pa_mixer_t m, int mute);
-int pa_sink_get_mute(pa_sink *sink, pa_mixer_t m);
+void pa_sink_set_volume(pa_sink *sink, const pa_cvolume *volume);
+const pa_cvolume *pa_sink_get_volume(pa_sink *sink);
+void pa_sink_set_mute(pa_sink *sink, pa_bool_t mute);
+pa_bool_t pa_sink_get_mute(pa_sink *sink);
 
-void pa_sink_set_description(pa_sink *s, const char *description);
+unsigned pa_sink_linked_by(pa_sink *s); /* Number of connected streams */
+unsigned pa_sink_used_by(pa_sink *s); /* Number of connected streams which are not corked */
+#define pa_sink_get_state(s) ((s)->state)
+
+/* To be called exclusively by the sink driver, from IO context */
+
+void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result);
+void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result);
+void pa_sink_render_into(pa_sink*s, pa_memchunk *target);
+void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target);
+
+void pa_sink_skip(pa_sink *s, size_t length);
+
+int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
 
-unsigned pa_sink_used_by(pa_sink *s);
+void pa_sink_attach_within_thread(pa_sink *s);
+void pa_sink_detach_within_thread(pa_sink *s);
 
 #endif
index d3d7538efeeed98088ee20a8a8133e0d8a0e96b5..8d4c6fa7c46896285560b30c63da3e0269571e25 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/atomic.h>
 
 #include "sioman.h"
 
-static int stdio_inuse = 0;
+static pa_atomic_t stdio_inuse = PA_ATOMIC_INIT(0);
 
 int pa_stdio_acquire(void) {
-    if (stdio_inuse)
-        return -1;
-
-    stdio_inuse = 1;
-    return 0;
+    return pa_atomic_cmpxchg(&stdio_inuse, 0, 1) ? 0 : -1;
 }
 
 void pa_stdio_release(void) {
-    assert(stdio_inuse);
-    stdio_inuse = 0;
+    pa_assert_se(pa_atomic_cmpxchg(&stdio_inuse, 1, 0));
 }
index b99c8025d3584057c539516d0bfd406b8ea34106..5b5bc5cacf0c25e004f040e090fc7ca69718bddf 100644 (file)
@@ -1,25 +1,25 @@
 /* $Id$ */
 
 /***
-  This file is part of PulseAudio.
+    This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
-  Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
+    Copyright 2004-2006 Lennart Poettering
+    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 by the Free Software Foundation; either version 2.1 of the
-  License, or (at your option) any later version.
+    PulseAudio is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as
+    published by the Free Software Foundation; either version 2.1 of the
+    License, or (at your option) any later version.
 
-  PulseAudio is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
+    PulseAudio is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    Lesser General Public License for more details.
 
-  You should have received a copy of the GNU Lesser General Public
-  License along with PulseAudio; if not, write to the Free Software
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-  USA.
+    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
@@ -32,7 +32,6 @@
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
-#include <assert.h>
 #include <stdlib.h>
 
 #ifdef HAVE_SYS_SOCKET_H
 #include <asyncns.h>
 #endif
 
-#include "winsock.h"
-
 #include <pulse/timeval.h>
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/winsock.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/socket-util.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
 #include <pulsecore/parseaddr.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/refcnt.h>
 
 #include "socket-client.h"
 
 #define CONNECT_TIMEOUT 5
 
 struct pa_socket_client {
-    int ref;
+    PA_REFCNT_DECLARE;
     pa_mainloop_api *mainloop;
     int fd;
     pa_io_event *io_event;
@@ -89,10 +89,10 @@ struct pa_socket_client {
 
 static pa_socket_client*pa_socket_client_new(pa_mainloop_api *m) {
     pa_socket_client *c;
-    assert(m);
+    pa_assert(m);
 
-    c = pa_xmalloc(sizeof(pa_socket_client));
-    c->ref = 1;
+    c = pa_xnew(pa_socket_client, 1);
+    PA_REFCNT_INIT(c);
     c->mainloop = m;
     c->fd = -1;
     c->io_event = NULL;
@@ -112,7 +112,7 @@ static pa_socket_client*pa_socket_client_new(pa_mainloop_api *m) {
 }
 
 static void free_events(pa_socket_client *c) {
-    assert(c);
+    pa_assert(c);
 
     if (c->io_event) {
         c->mainloop->io_free(c->io_event);
@@ -134,7 +134,10 @@ static void do_call(pa_socket_client *c) {
     pa_iochannel *io = NULL;
     int error;
     socklen_t lerror;
-    assert(c && c->callback);
+
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(c->callback);
 
     pa_socket_client_ref(c);
 
@@ -153,13 +156,13 @@ static void do_call(pa_socket_client *c) {
     }
 
     if (error != 0) {
-        pa_log_debug("connect(): %s", pa_cstrerror(errno));
+        pa_log_debug("connect(): %s", pa_cstrerror(error));
         errno = error;
         goto finish;
     }
 
     io = pa_iochannel_new(c->mainloop, c->fd, c->fd);
-    assert(io);
+    pa_assert(io);
 
 finish:
     if (!io && c->fd >= 0)
@@ -168,7 +171,7 @@ finish:
 
     free_events(c);
 
-    assert(c->callback);
+    pa_assert(c->callback);
     c->callback(c, io, c->userdata);
 
     pa_socket_client_unref(c);
@@ -176,21 +179,36 @@ finish:
 
 static void connect_fixed_cb(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
     pa_socket_client *c = userdata;
-    assert(m && c && c->defer_event == e);
+
+    pa_assert(m);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(c->defer_event == e);
+
     do_call(c);
 }
 
 static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
     pa_socket_client *c = userdata;
-    assert(m && c && c->io_event == e && fd >= 0);
+
+    pa_assert(m);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(c->io_event == e);
+    pa_assert(fd >= 0);
+
     do_call(c);
 }
 
 static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t len) {
     int r;
-    assert(c && sa && len);
 
-    pa_make_nonblock_fd(c->fd);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(sa);
+    pa_assert(len > 0);
+
+    pa_make_fd_nonblock(c->fd);
 
     if ((r = connect(c->fd, sa, len)) < 0) {
 #ifdef OS_IS_WIN32
@@ -203,19 +221,18 @@ static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t
             return -1;
         }
 
-        c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c);
-        assert(c->io_event);
-    } else {
-        c->defer_event = c->mainloop->defer_new(c->mainloop, connect_fixed_cb, c);
-        assert(c->defer_event);
-    }
+        pa_assert_se(c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c));
+    } else
+        pa_assert_se(c->defer_event = c->mainloop->defer_new(c->mainloop, connect_fixed_cb, c));
 
     return 0;
 }
 
 pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port) {
     struct sockaddr_in sa;
-    assert(m && port > 0);
+
+    pa_assert(m);
+    pa_assert(port > 0);
 
     memset(&sa, 0, sizeof(sa));
     sa.sin_family = AF_INET;
@@ -229,7 +246,9 @@ pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address
 
 pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
     struct sockaddr_un sa;
-    assert(m && filename);
+
+    pa_assert(m);
+    pa_assert(filename);
 
     memset(&sa, 0, sizeof(sa));
     sa.sun_family = AF_UNIX;
@@ -248,9 +267,9 @@ pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *file
 #endif /* HAVE_SYS_UN_H */
 
 static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size_t salen) {
-    assert(c);
-    assert(sa);
-    assert(salen);
+    pa_assert(c);
+    pa_assert(sa);
+    pa_assert(salen);
 
     switch (sa->sa_family) {
         case AF_UNIX:
@@ -274,11 +293,11 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size
         return -1;
     }
 
-    pa_fd_set_cloexec(c->fd, 1);
+    pa_make_fd_cloexec(c->fd);
     if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)
-        pa_socket_tcp_low_delay(c->fd);
+        pa_make_tcp_socket_low_delay(c->fd);
     else
-        pa_socket_low_delay(c->fd);
+        pa_make_socket_low_delay(c->fd);
 
     if (do_connect(c, sa, salen) < 0)
         return -1;
@@ -288,9 +307,12 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size
 
 pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) {
     pa_socket_client *c;
-    assert(m && sa);
-    c = pa_socket_client_new(m);
-    assert(c);
+
+    pa_assert(m);
+    pa_assert(sa);
+    pa_assert(salen > 0);
+
+    pa_assert_se(c = pa_socket_client_new(m));
 
     if (sockaddr_prepare(c, sa, salen) < 0)
         goto fail;
@@ -300,12 +322,11 @@ pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct
 fail:
     pa_socket_client_unref(c);
     return NULL;
-
 }
 
 static void socket_client_free(pa_socket_client *c) {
-    assert(c && c->mainloop);
-
+    pa_assert(c);
+    pa_assert(c->mainloop);
 
     free_events(c);
 
@@ -325,20 +346,25 @@ static void socket_client_free(pa_socket_client *c) {
 }
 
 void pa_socket_client_unref(pa_socket_client *c) {
-    assert(c && c->ref >= 1);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
-    if (!(--(c->ref)))
+    if (PA_REFCNT_DEC(c) <= 0)
         socket_client_free(c);
 }
 
 pa_socket_client* pa_socket_client_ref(pa_socket_client *c) {
-    assert(c && c->ref >= 1);
-    c->ref++;
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    PA_REFCNT_INC(c);
     return c;
 }
 
 void pa_socket_client_set_callback(pa_socket_client *c, void (*on_connection)(pa_socket_client *c, pa_iochannel*io, void *userdata), void *userdata) {
-    assert(c);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
     c->callback = on_connection;
     c->userdata = userdata;
 }
@@ -346,6 +372,10 @@ void pa_socket_client_set_callback(pa_socket_client *c, void (*on_connection)(pa
 pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) {
     struct sockaddr_in6 sa;
 
+    pa_assert(m);
+    pa_assert(address);
+    pa_assert(port > 0);
+
     memset(&sa, 0, sizeof(sa));
     sa.sin6_family = AF_INET6;
     sa.sin6_port = htons(port);
@@ -360,7 +390,12 @@ static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED
     pa_socket_client *c = userdata;
     struct addrinfo *res = NULL;
     int ret;
-    assert(m && c && c->asyncns_io_event == e && fd >= 0);
+
+    pa_assert(m);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(c->asyncns_io_event == e);
+    pa_assert(fd >= 0);
 
     if (asyncns_wait(c->asyncns, 0) < 0)
         goto fail;
@@ -397,10 +432,11 @@ fail:
 
 static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *tv, void *userdata) {
     pa_socket_client *c = userdata;
-    assert(m);
-    assert(e);
-    assert(tv);
-    assert(c);
+
+    pa_assert(m);
+    pa_assert(e);
+    pa_assert(tv);
+    pa_assert(c);
 
     if (c->fd >= 0) {
         pa_close(c->fd);
@@ -413,8 +449,8 @@ static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeva
 
 static void start_timeout(pa_socket_client *c) {
     struct timeval tv;
-    assert(c);
-    assert(!c->timeout_event);
+    pa_assert(c);
+    pa_assert(!c->timeout_event);
 
     pa_gettimeofday(&tv);
     pa_timeval_add(&tv, CONNECT_TIMEOUT * 1000000);
@@ -424,7 +460,9 @@ static void start_timeout(pa_socket_client *c) {
 pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*name, uint16_t default_port) {
     pa_socket_client *c = NULL;
     pa_parsed_address a;
-    assert(m && name);
+
+    pa_assert(m);
+    pa_assert(name);
 
     if (pa_parse_address(name, &a) < 0)
         return NULL;
@@ -435,7 +473,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam
     switch (a.type) {
         case PA_PARSED_ADDRESS_UNIX:
             if ((c = pa_socket_client_new_unix(m, a.path_or_host)))
-               start_timeout(c);
+                start_timeout(c);
             break;
 
         case PA_PARSED_ADDRESS_TCP4:  /* Fallthrough */
@@ -445,7 +483,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam
             struct addrinfo hints;
             char port[12];
 
-            snprintf(port, sizeof(port), "%u", (unsigned) a.port);
+            pa_snprintf(port, sizeof(port), "%u", (unsigned) a.port);
 
             memset(&hints, 0, sizeof(hints));
             hints.ai_family = a.type == PA_PARSED_ADDRESS_TCP4 ? PF_INET : (a.type == PA_PARSED_ADDRESS_TCP6 ? PF_INET6 : PF_UNSPEC);
@@ -462,7 +500,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam
                 c->asyncns = asyncns;
                 c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c);
                 c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints);
-                assert(c->asyncns_query);
+                pa_assert(c->asyncns_query);
                 start_timeout(c);
             }
 #else /* HAVE_LIBASYNCNS */
@@ -479,7 +517,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam
                 if (res->ai_addr) {
                     if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen)))
                         start_timeout(c);
-                               }
+                }
 
                 freeaddrinfo(res);
 #else /* HAVE_GETADDRINFO */
@@ -507,7 +545,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam
                 s.sin_port = htons(a.port);
 
                 if ((c = pa_socket_client_new_sockaddr(m, (struct sockaddr*)&s, sizeof(s))))
-                       start_timeout(c);
+                    start_timeout(c);
 #endif /* HAVE_GETADDRINFO */
             }
 #endif /* HAVE_LIBASYNCNS */
@@ -524,6 +562,8 @@ finish:
    local. "local" means UNIX socket or TCP socket on localhost. Other
    local IP addresses are not considered local. */
 int pa_socket_client_is_local(pa_socket_client *c) {
-    assert(c);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
     return c->local;
 }
index b5a6dc3177ba083a670ff3aba040cf70ca9d1013..162a1aac2f8f9e7cf802d9e846ffb800550b1a70 100644 (file)
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/types.h>
 #include <pulsecore/socket-util.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 #include <pulsecore/core-error.h>
+#include <pulsecore/refcnt.h>
 
 #include "socket-server.h"
 
 struct pa_socket_server {
-    int ref;
+    PA_REFCNT_DECLARE;
     int fd;
     char *filename;
     char *tcpwrap_service;
@@ -94,7 +95,14 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U
     pa_socket_server *s = userdata;
     pa_iochannel *io;
     int nfd;
-    assert(s && s->mainloop == mainloop && s->io_event == e && e && fd >= 0 && fd == s->fd);
+
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(s->mainloop == mainloop);
+    pa_assert(s->io_event == e);
+    pa_assert(e);
+    pa_assert(fd >= 0);
+    pa_assert(fd == s->fd);
 
     pa_socket_server_ref(s);
 
@@ -103,7 +111,7 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U
         goto finish;
     }
 
-    pa_fd_set_cloexec(nfd, 1);
+    pa_make_fd_cloexec(nfd);
 
     if (!s->on_connection) {
         pa_close(nfd);
@@ -129,12 +137,11 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U
 
     /* There should be a check for socket type here */
     if (s->type == SOCKET_SERVER_IPV4)
-        pa_socket_tcp_low_delay(fd);
+        pa_make_tcp_socket_low_delay(fd);
     else
-        pa_socket_low_delay(fd);
+        pa_make_socket_low_delay(fd);
 
-    io = pa_iochannel_new(s->mainloop, nfd, nfd);
-    assert(io);
+    pa_assert_se(io = pa_iochannel_new(s->mainloop, nfd, nfd));
     s->on_connection(s, io, s->userdata);
 
 finish:
@@ -143,10 +150,12 @@ finish:
 
 pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd) {
     pa_socket_server *s;
-    assert(m && fd >= 0);
 
-    s = pa_xmalloc(sizeof(pa_socket_server));
-    s->ref = 1;
+    pa_assert(m);
+    pa_assert(fd >= 0);
+
+    s = pa_xnew(pa_socket_server, 1);
+    PA_REFCNT_INIT(s);
     s->fd = fd;
     s->filename = NULL;
     s->on_connection = NULL;
@@ -154,8 +163,7 @@ pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd) {
     s->tcpwrap_service = NULL;
 
     s->mainloop = m;
-    s->io_event = m->io_new(m, fd, PA_IO_EVENT_INPUT, callback, s);
-    assert(s->io_event);
+    pa_assert_se(s->io_event = m->io_new(m, fd, PA_IO_EVENT_INPUT, callback, s));
 
     s->type = SOCKET_SERVER_GENERIC;
 
@@ -163,8 +171,10 @@ pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd) {
 }
 
 pa_socket_server* pa_socket_server_ref(pa_socket_server *s) {
-    assert(s && s->ref >= 1);
-    s->ref++;
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+
+    PA_REFCNT_INC(s);
     return s;
 }
 
@@ -175,20 +185,21 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file
     struct sockaddr_un sa;
     pa_socket_server *s;
 
-    assert(m && filename);
+    pa_assert(m);
+    pa_assert(filename);
 
     if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
         pa_log("socket(): %s", pa_cstrerror(errno));
         goto fail;
     }
 
-    pa_fd_set_cloexec(fd, 1);
+    pa_make_fd_cloexec(fd);
 
     sa.sun_family = AF_UNIX;
     strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1);
     sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
 
-    pa_socket_low_delay(fd);
+    pa_make_socket_low_delay(fd);
 
     if (bind(fd, (struct sockaddr*) &sa, SUN_LEN(&sa)) < 0) {
         pa_log("bind(): %s", pa_cstrerror(errno));
@@ -206,8 +217,7 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file
         goto fail;
     }
 
-    s = pa_socket_server_new(m, fd);
-    assert(s);
+    pa_assert_se(s = pa_socket_server_new(m, fd));
 
     s->filename = pa_xstrdup(filename);
     s->type = SOCKET_SERVER_UNIX;
@@ -235,21 +245,22 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address
     struct sockaddr_in sa;
     int on = 1;
 
-    assert(m && port);
+    pa_assert(m);
+    pa_assert(port);
 
     if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
         pa_log("socket(PF_INET): %s", pa_cstrerror(errno));
         goto fail;
     }
 
-    pa_fd_set_cloexec(fd, 1);
+    pa_make_fd_cloexec(fd);
 
 #ifdef SO_REUSEADDR
     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
         pa_log("setsockopt(): %s", pa_cstrerror(errno));
 #endif
 
-    pa_socket_tcp_low_delay(fd);
+    pa_make_tcp_socket_low_delay(fd);
 
     memset(&sa, 0, sizeof(sa));
     sa.sin_family = AF_INET;
@@ -286,14 +297,15 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad
     struct sockaddr_in6 sa;
     int on = 1;
 
-    assert(m && port);
+    pa_assert(m);
+    pa_assert(port > 0);
 
     if ((fd = socket(PF_INET6, SOCK_STREAM, 0)) < 0) {
         pa_log("socket(PF_INET6): %s", pa_cstrerror(errno));
         goto fail;
     }
 
-    pa_fd_set_cloexec(fd, 1);
+    pa_make_fd_cloexec(fd);
 
 #ifdef IPV6_V6ONLY
     if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0)
@@ -305,7 +317,7 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad
         pa_log("setsockopt(SOL_SOCKET, SO_REUSEADDR, 1): %s", pa_cstrerror(errno));
 #endif
 
-    pa_socket_tcp_low_delay(fd);
+    pa_make_tcp_socket_low_delay(fd);
 
     memset(&sa, 0, sizeof(sa));
     sa.sin6_family = AF_INET6;
@@ -337,29 +349,29 @@ fail:
 }
 
 pa_socket_server* pa_socket_server_new_ipv4_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) {
-    assert(m);
-    assert(port > 0);
+    pa_assert(m);
+    pa_assert(port > 0);
 
     return pa_socket_server_new_ipv4(m, INADDR_LOOPBACK, port, tcpwrap_service);
 }
 
 pa_socket_server* pa_socket_server_new_ipv6_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) {
-    assert(m);
-    assert(port > 0);
+    pa_assert(m);
+    pa_assert(port > 0);
 
     return pa_socket_server_new_ipv6(m, in6addr_loopback.s6_addr, port, tcpwrap_service);
 }
 
 pa_socket_server* pa_socket_server_new_ipv4_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) {
-    assert(m);
-    assert(port > 0);
+    pa_assert(m);
+    pa_assert(port > 0);
 
     return pa_socket_server_new_ipv4(m, INADDR_ANY, port, tcpwrap_service);
 }
 
 pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) {
-    assert(m);
-    assert(port > 0);
+    pa_assert(m);
+    pa_assert(port > 0);
 
     return pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, tcpwrap_service);
 }
@@ -367,9 +379,9 @@ pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t por
 pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) {
     struct in_addr ipv4;
 
-    assert(m);
-    assert(name);
-    assert(port > 0);
+    pa_assert(m);
+    pa_assert(name);
+    pa_assert(port > 0);
 
     if (inet_pton(AF_INET, name, &ipv4) > 0)
         return pa_socket_server_new_ipv4(m, ntohl(ipv4.s_addr), port, tcpwrap_service);
@@ -380,9 +392,9 @@ pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const cha
 pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) {
     struct in6_addr ipv6;
 
-    assert(m);
-    assert(name);
-    assert(port > 0);
+    pa_assert(m);
+    pa_assert(name);
+    pa_assert(port > 0);
 
     if (inet_pton(AF_INET6, name, &ipv6) > 0)
         return pa_socket_server_new_ipv6(m, ipv6.s6_addr, port, tcpwrap_service);
@@ -391,7 +403,7 @@ pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const cha
 }
 
 static void socket_server_free(pa_socket_server*s) {
-    assert(s);
+    pa_assert(s);
 
     if (s->filename) {
         unlink(s->filename);
@@ -407,21 +419,26 @@ static void socket_server_free(pa_socket_server*s) {
 }
 
 void pa_socket_server_unref(pa_socket_server *s) {
-    assert(s && s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
-    if (!(--(s->ref)))
+    if (PA_REFCNT_DEC(s) <= 0)
         socket_server_free(s);
 }
 
 void pa_socket_server_set_callback(pa_socket_server*s, void (*on_connection)(pa_socket_server*s, pa_iochannel *io, void *userdata), void *userdata) {
-    assert(s && s->ref >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->on_connection = on_connection;
     s->userdata = userdata;
 }
 
 char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) {
-    assert(s && c && l > 0);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(c);
+    pa_assert(l > 0);
 
     switch (s->type) {
         case SOCKET_SERVER_IPV6: {
@@ -438,14 +455,14 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) {
                 if (!pa_get_fqdn(fqdn, sizeof(fqdn)))
                     return NULL;
 
-                snprintf(c, l, "tcp6:%s:%u", fqdn, (unsigned) ntohs(sa.sin6_port));
+                pa_snprintf(c, l, "tcp6:%s:%u", fqdn, (unsigned) ntohs(sa.sin6_port));
 
             } else if (memcmp(&in6addr_loopback, &sa.sin6_addr, sizeof(in6addr_loopback)) == 0) {
                 char hn[256];
                 if (!pa_get_host_name(hn, sizeof(hn)))
                     return NULL;
 
-                snprintf(c, l, "{%s}tcp6:localhost:%u", hn, (unsigned) ntohs(sa.sin6_port));
+                pa_snprintf(c, l, "{%s}tcp6:localhost:%u", hn, (unsigned) ntohs(sa.sin6_port));
             } else {
                 char ip[INET6_ADDRSTRLEN];
 
@@ -454,7 +471,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) {
                     return NULL;
                 }
 
-                snprintf(c, l, "tcp6:[%s]:%u", ip, (unsigned) ntohs(sa.sin6_port));
+                pa_snprintf(c, l, "tcp6:[%s]:%u", ip, (unsigned) ntohs(sa.sin6_port));
             }
 
             return c;
@@ -474,13 +491,13 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) {
                 if (!pa_get_fqdn(fqdn, sizeof(fqdn)))
                     return NULL;
 
-                snprintf(c, l, "tcp:%s:%u", fqdn, (unsigned) ntohs(sa.sin_port));
+                pa_snprintf(c, l, "tcp:%s:%u", fqdn, (unsigned) ntohs(sa.sin_port));
             } else if (sa.sin_addr.s_addr == INADDR_LOOPBACK) {
                 char hn[256];
                 if (!pa_get_host_name(hn, sizeof(hn)))
                     return NULL;
 
-                snprintf(c, l, "{%s}tcp:localhost:%u", hn, (unsigned) ntohs(sa.sin_port));
+                pa_snprintf(c, l, "{%s}tcp:localhost:%u", hn, (unsigned) ntohs(sa.sin_port));
             } else {
                 char ip[INET_ADDRSTRLEN];
 
@@ -489,7 +506,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) {
                     return NULL;
                 }
 
-                snprintf(c, l, "tcp:[%s]:%u", ip, (unsigned) ntohs(sa.sin_port));
+                pa_snprintf(c, l, "tcp:[%s]:%u", ip, (unsigned) ntohs(sa.sin_port));
 
             }
 
@@ -505,7 +522,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) {
             if (!pa_get_host_name(hn, sizeof(hn)))
                 return NULL;
 
-            snprintf(c, l, "{%s}unix:%s", hn, s->filename);
+            pa_snprintf(c, l, "{%s}unix:%s", hn, s->filename);
             return c;
         }
 
index 673058e2a994638922a94ebbac23f4c74a9bbc56..456accb82c9e8f79c13611b962650351bf0f4c6a 100644 (file)
@@ -31,7 +31,6 @@
 #include <stdlib.h>
 #include <signal.h>
 #include <errno.h>
-#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "socket-util.h"
 
 void pa_socket_peer_to_string(int fd, char *c, size_t l) {
     struct stat st;
 
-    assert(c && l && fd >= 0);
+    pa_assert(fd >= 0);
+    pa_assert(c);
+    pa_assert(l > 0);
 
 #ifndef OS_IS_WIN32
-    if (fstat(fd, &st) < 0) {
-        snprintf(c, l, "Invalid client fd");
-        return;
-    }
+    pa_assert_se(fstat(fd, &st) == 0);
 #endif
 
 #ifndef OS_IS_WIN32
@@ -108,12 +107,12 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
             if (sa.sa.sa_family == AF_INET) {
                 uint32_t ip = ntohl(sa.in.sin_addr.s_addr);
 
-                snprintf(c, l, "TCP/IP client from %i.%i.%i.%i:%u",
-                         ip >> 24,
-                         (ip >> 16) & 0xFF,
-                         (ip >> 8) & 0xFF,
-                         ip & 0xFF,
-                         ntohs(sa.in.sin_port));
+                pa_snprintf(c, l, "TCP/IP client from %i.%i.%i.%i:%u",
+                            ip >> 24,
+                            (ip >> 16) & 0xFF,
+                            (ip >> 8) & 0xFF,
+                            ip & 0xFF,
+                            ntohs(sa.in.sin_port));
                 return;
             } else if (sa.sa.sa_family == AF_INET6) {
                 char buf[INET6_ADDRSTRLEN];
@@ -121,94 +120,107 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
 
                 res = inet_ntop(AF_INET6, &sa.in6.sin6_addr, buf, sizeof(buf));
                 if (res) {
-                    snprintf(c, l, "TCP/IP client from [%s]:%u", buf, ntohs(sa.in6.sin6_port));
+                    pa_snprintf(c, l, "TCP/IP client from [%s]:%u", buf, ntohs(sa.in6.sin6_port));
                     return;
                 }
 #ifdef HAVE_SYS_UN_H
             } else if (sa.sa.sa_family == AF_UNIX) {
-                snprintf(c, l, "UNIX socket client");
+                pa_snprintf(c, l, "UNIX socket client");
                 return;
 #endif
             }
 
         }
 #ifndef OS_IS_WIN32
-        snprintf(c, l, "Unknown network client");
+        pa_snprintf(c, l, "Unknown network client");
         return;
     } else if (S_ISCHR(st.st_mode) && (fd == 0 || fd == 1)) {
-        snprintf(c, l, "STDIN/STDOUT client");
+        pa_snprintf(c, l, "STDIN/STDOUT client");
         return;
     }
 #endif /* OS_IS_WIN32 */
 
-    snprintf(c, l, "Unknown client");
+    pa_snprintf(c, l, "Unknown client");
 }
 
-int pa_socket_low_delay(int fd) {
+void pa_make_socket_low_delay(int fd) {
+
 #ifdef SO_PRIORITY
     int priority;
-    assert(fd >= 0);
+    pa_assert(fd >= 0);
 
-    priority = 7;
+    priority = 6;
     if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, sizeof(priority)) < 0)
-        return -1;
+        pa_log_warn("SO_PRIORITY failed: %s", pa_cstrerror(errno));
 #endif
-
-    return 0;
 }
 
-int pa_socket_tcp_low_delay(int fd) {
-    int ret, tos, on;
+void pa_make_tcp_socket_low_delay(int fd) {
+    pa_assert(fd >= 0);
 
-    assert(fd >= 0);
-
-    ret = pa_socket_low_delay(fd);
-
-    on = 1;
-    tos = 0;
+    pa_make_socket_low_delay(fd);
 
 #if defined(SOL_TCP) || defined(IPPROTO_TCP)
+    {
+        int on = 1;
 #if defined(SOL_TCP)
-    if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0)
+        if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0)
 #else
-    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0)
+        if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0)
 #endif
-        ret = -1;
+            pa_log_warn("TCP_NODELAY failed: %s", pa_cstrerror(errno));
+    }
 #endif
 
-#if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || \
-       defined(IPPROTO_IP))
-    tos = IPTOS_LOWDELAY;
+#if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP))
+    {
+        int tos = IPTOS_LOWDELAY;
 #ifdef SOL_IP
-    if (setsockopt(fd, SOL_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
+        if (setsockopt(fd, SOL_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
 #else
-    if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
+        if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
 #endif
-        ret = -1;
+            pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno));
+    }
 #endif
+}
 
-    return ret;
+void pa_make_udp_socket_low_delay(int fd) {
+    pa_assert(fd >= 0);
 
+    pa_make_socket_low_delay(fd);
+
+#if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP))
+    {
+        int tos = IPTOS_LOWDELAY;
+#ifdef SOL_IP
+        if (setsockopt(fd, SOL_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
+#else
+        if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
+#endif
+            pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno));
+    }
+#endif
 }
 
 int pa_socket_set_rcvbuf(int fd, size_t l) {
-    assert(fd >= 0);
+    pa_assert(fd >= 0);
 
-/*     if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void*)&l, sizeof(l)) < 0) { */
-/*         pa_log("SO_RCVBUF: %s", strerror(errno)); */
-/*         return -1; */
-/*     } */
+    if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void*)&l, sizeof(l)) < 0) {
+        pa_log_warn("SO_RCVBUF: %s", pa_cstrerror(errno));
+        return -1;
+    }
 
     return 0;
 }
 
 int pa_socket_set_sndbuf(int fd, size_t l) {
-    assert(fd >= 0);
+    pa_assert(fd >= 0);
 
-/*     if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void*)&l, sizeof(l)) < 0) { */
-/*         pa_log("SO_SNDBUF: %s", strerror(errno)); */
-/*         return -1; */
-/*     } */
+    if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void*)&l, sizeof(l)) < 0) {
+        pa_log("SO_SNDBUF: %s", pa_cstrerror(errno));
+        return -1;
+    }
 
     return 0;
 }
@@ -219,6 +231,8 @@ int pa_unix_socket_is_stale(const char *fn) {
     struct sockaddr_un sa;
     int fd = -1, ret = -1;
 
+    pa_assert(fn);
+
     if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
         pa_log("socket(): %s", pa_cstrerror(errno));
         goto finish;
@@ -244,6 +258,8 @@ finish:
 int pa_unix_socket_remove_stale(const char *fn) {
     int r;
 
+    pa_assert(fn);
+
     if ((r = pa_unix_socket_is_stale(fn)) < 0)
         return errno != ENOENT ? -1 : 0;
 
index 616c40acd00b31cc403bebe03dc1dfd45f11c10c..a0344c68f90d87870463005e64e1106f72e92858 100644 (file)
@@ -29,8 +29,9 @@
 
 void pa_socket_peer_to_string(int fd, char *c, size_t l);
 
-int pa_socket_low_delay(int fd);
-int pa_socket_tcp_low_delay(int fd);
+void pa_make_socket_low_delay(int fd);
+void pa_make_tcp_socket_low_delay(int fd);
+void pa_make_udp_socket_low_delay(int fd);
 
 int pa_socket_set_sndbuf(int fd, size_t l);
 int pa_socket_set_rcvbuf(int fd, size_t l);
index 7a43c74331d3fcd07fb94a759bbf20bbeee5050e..bb1f3e9a8d6652cca1fe78eac471537fc28e3554 100644 (file)
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
 
 #include <sndfile.h>
 
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/core-error.h>
 #include <pulsecore/sink-input.h>
 #include <pulsecore/log.h>
+#include <pulsecore/thread-mq.h>
+#include <pulsecore/core-util.h>
 
 #include "sound-file-stream.h"
 
-#define BUF_SIZE (1024*10)
-
-struct userdata {
+typedef struct file_stream {
+    pa_msgobject parent;
+    pa_core *core;
     SNDFILE *sndfile;
     pa_sink_input *sink_input;
     pa_memchunk memchunk;
     sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames);
+    size_t drop;
+} file_stream;
+
+enum {
+    FILE_STREAM_MESSAGE_UNLINK
 };
 
-static void free_userdata(struct userdata *u) {
-    assert(u);
-    if (u->sink_input) {
-        pa_sink_input_disconnect(u->sink_input);
-        pa_sink_input_unref(u->sink_input);
-    }
+PA_DECLARE_CLASS(file_stream);
+#define FILE_STREAM(o) (file_stream_cast(o))
+static PA_DEFINE_CHECK_TYPE(file_stream, pa_msgobject);
+
+static void file_stream_unlink(file_stream *u) {
+    pa_assert(u);
+
+    if (!u->sink_input)
+        return;
+
+    pa_sink_input_unlink(u->sink_input);
+
+    pa_sink_input_unref(u->sink_input);
+    u->sink_input = NULL;
+
+    /* Make sure we don't decrease the ref count twice. */
+    file_stream_unref(u);
+}
+
+static void file_stream_free(pa_object *o) {
+    file_stream *u = FILE_STREAM(o);
+    pa_assert(u);
+
+    file_stream_unlink(u);
 
     if (u->memchunk.memblock)
         pa_memblock_unref(u->memchunk.memblock);
+
     if (u->sndfile)
         sf_close(u->sndfile);
 
     pa_xfree(u);
 }
 
-static void sink_input_kill(pa_sink_input *i) {
-    assert(i && i->userdata);
-    free_userdata(i->userdata);
+static int file_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
+    file_stream *u = FILE_STREAM(o);
+    file_stream_assert_ref(u);
+
+    switch (code) {
+        case FILE_STREAM_MESSAGE_UNLINK:
+            file_stream_unlink(u);
+            break;
+    }
+
+    return 0;
+}
+
+static void sink_input_kill_cb(pa_sink_input *i) {
+    pa_sink_input_assert_ref(i);
+
+    file_stream_unlink(FILE_STREAM(i->userdata));
 }
 
-static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
-    struct userdata *u;
-    assert(i && chunk && i->userdata);
-    u = i->userdata;
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+    file_stream *u;
+
+    pa_assert(i);
+    pa_assert(chunk);
+    u = FILE_STREAM(i->userdata);
+    file_stream_assert_ref(u);
+
+    if (!u->sndfile)
+        return -1;
+
+    for (;;) {
+
+        if (!u->memchunk.memblock) {
+
+            u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, length);
+            u->memchunk.index = 0;
+
+            if (u->readf_function) {
+                sf_count_t n;
+                void *p;
+                size_t fs = pa_frame_size(&i->sample_spec);
+
+                p = pa_memblock_acquire(u->memchunk.memblock);
+                n = u->readf_function(u->sndfile, p, length/fs);
+                pa_memblock_release(u->memchunk.memblock);
 
-    if (!u->memchunk.memblock) {
-        uint32_t fs = pa_frame_size(&i->sample_spec);
-        sf_count_t n;
+                if (n <= 0)
+                    n = 0;
 
-        u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, BUF_SIZE);
-        u->memchunk.index = 0;
+                u->memchunk.length = n * fs;
+            } else {
+                sf_count_t n;
+                void *p;
 
-        if (u->readf_function) {
-            if ((n = u->readf_function(u->sndfile, u->memchunk.memblock->data, BUF_SIZE/fs)) <= 0)
-                n = 0;
+                p = pa_memblock_acquire(u->memchunk.memblock);
+                n = sf_read_raw(u->sndfile, p, length);
+                pa_memblock_release(u->memchunk.memblock);
 
-            u->memchunk.length = n * fs;
-        } else {
-            if ((n = sf_read_raw(u->sndfile, u->memchunk.memblock->data, BUF_SIZE)) <= 0)
-                n = 0;
+                if (n <= 0)
+                    n = 0;
 
-            u->memchunk.length = n;
+                u->memchunk.length = n;
+            }
+
+            if (u->memchunk.length <= 0) {
+
+                pa_memblock_unref(u->memchunk.memblock);
+                pa_memchunk_reset(&u->memchunk);
+
+                pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), FILE_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
+
+                sf_close(u->sndfile);
+                u->sndfile = NULL;
+
+                return -1;
+            }
         }
 
-        if (!u->memchunk.length) {
-            free_userdata(u);
-            return -1;
+        pa_assert(u->memchunk.memblock);
+        pa_assert(u->memchunk.length > 0);
+
+        if (u->drop < u->memchunk.length) {
+            u->memchunk.index += u->drop;
+            u->memchunk.length -= u->drop;
+            u->drop = 0;
+            break;
         }
+
+        u->drop -= u->memchunk.length;
+        pa_memblock_unref(u->memchunk.memblock);
+        pa_memchunk_reset(&u->memchunk);
     }
 
     *chunk = u->memchunk;
     pa_memblock_ref(chunk->memblock);
-    assert(chunk->length);
+
+    pa_assert(chunk->length > 0);
+    pa_assert(u->drop <= 0);
+
     return 0;
 }
 
-static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t length) {
-    struct userdata *u;
-    assert(i && chunk && length && i->userdata);
-    u = i->userdata;
+static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
+    file_stream *u;
 
-    assert(!memcmp(chunk, &u->memchunk, sizeof(chunk)));
-    assert(length <= u->memchunk.length);
+    pa_assert(i);
+    pa_assert(length > 0);
+    u = FILE_STREAM(i->userdata);
+    file_stream_assert_ref(u);
 
-    u->memchunk.index += length;
-    u->memchunk.length -= length;
+    if (u->memchunk.memblock) {
 
-    if (u->memchunk.length <= 0) {
+        if (length < u->memchunk.length) {
+            u->memchunk.index += length;
+            u->memchunk.length -= length;
+            return;
+        }
+
+        length -= u->memchunk.length;
         pa_memblock_unref(u->memchunk.memblock);
-        u->memchunk.memblock = NULL;
-        u->memchunk.index = u->memchunk.length = 0;
+        pa_memchunk_reset(&u->memchunk);
     }
+
+    u->drop += length;
 }
 
 int pa_play_file(
@@ -127,28 +223,60 @@ int pa_play_file(
         const char *fname,
         const pa_cvolume *volume) {
 
-    struct userdata *u = NULL;
+    file_stream *u = NULL;
     SF_INFO sfinfo;
     pa_sample_spec ss;
     pa_sink_input_new_data data;
+    int fd;
 
-    assert(sink);
-    assert(fname);
+    pa_assert(sink);
+    pa_assert(fname);
 
-    u = pa_xnew(struct userdata, 1);
+    u = pa_msgobject_new(file_stream);
+    u->parent.parent.free = file_stream_free;
+    u->parent.process_msg = file_stream_process_msg;
+    u->core = sink->core;
     u->sink_input = NULL;
-    u->memchunk.memblock = NULL;
-    u->memchunk.index = u->memchunk.length = 0;
+    pa_memchunk_reset(&u->memchunk);
     u->sndfile = NULL;
+    u->readf_function = NULL;
+    u->drop = 0;
 
     memset(&sfinfo, 0, sizeof(sfinfo));
 
-    if (!(u->sndfile = sf_open(fname, SFM_READ, &sfinfo))) {
-        pa_log("Failed to open file %s", fname);
+    if ((fd = open(fname, O_RDONLY
+#ifdef O_NOCTTY
+                   |O_NOCTTY
+#endif
+                   )) < 0) {
+        pa_log("Failed to open file %s: %s", fname, pa_cstrerror(errno));
         goto fail;
     }
 
-    u->readf_function = NULL;
+    /* FIXME: For now we just use posix_fadvise to avoid page faults
+     * when accessing the file data. Eventually we should move the
+     * file reader into the main event loop and pass the data over the
+     * asyncmsgq. */
+
+#ifdef HAVE_POSIX_FADVISE
+    if (posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL) < 0) {
+        pa_log_warn("POSIX_FADV_SEQUENTIAL failed: %s", pa_cstrerror(errno));
+        goto fail;
+    } else
+        pa_log_debug("POSIX_FADV_SEQUENTIAL succeeded.");
+
+    if (posix_fadvise(fd, 0, 0, POSIX_FADV_WILLNEED) < 0) {
+        pa_log_warn("POSIX_FADV_WILLNEED failed: %s", pa_cstrerror(errno));
+        goto fail;
+    } else
+        pa_log_debug("POSIX_FADV_WILLNEED succeeded.");
+#endif
+
+    if (!(u->sndfile = sf_open_fd(fd, SFM_READ, &sfinfo, 1))) {
+        pa_log("Failed to open file %s", fname);
+        pa_close(fd);
+        goto fail;
+    }
 
     switch (sfinfo.format & 0xFF) {
         case SF_FORMAT_PCM_16:
@@ -191,18 +319,21 @@ int pa_play_file(
     if (!(u->sink_input = pa_sink_input_new(sink->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;
 
-    pa_sink_notify(u->sink_input->sink);
+    pa_sink_input_put(u->sink_input);
+
+    /* The reference to u is dangling here, because we want to keep
+     * this stream around until it is fully played. */
 
     return 0;
 
 fail:
     if (u)
-        free_userdata(u);
+        file_stream_unref(u);
 
     return -1;
 }
index 69b543ab175f0b706b5200b02672f15e3b250329..7e88734c270fcff9a684c680401f6bd37ee1a4e2 100644 (file)
 #endif
 
 #include <string.h>
-#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
 
 #include <sndfile.h>
 
 #include <pulse/sample.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/core-error.h>
+#include <pulsecore/core-util.h>
 
 #include "sound-file.h"
 #include "core-scache.h"
 
-int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, pa_channel_map *map, pa_memchunk *chunk) {
-    SNDFILE*sf = NULL;
+int pa_sound_file_load(
+        pa_mempool *pool,
+        const char *fname,
+        pa_sample_spec *ss,
+        pa_channel_map *map,
+        pa_memchunk *chunk) {
+
+    SNDFILE *sf = NULL;
     SF_INFO sfinfo;
     int ret = -1;
     size_t l;
     sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames) = NULL;
-    assert(fname && ss && chunk);
+    void *ptr = NULL;
+    int fd;
 
-    chunk->memblock = NULL;
-    chunk->index = chunk->length = 0;
+    pa_assert(fname);
+    pa_assert(ss);
+    pa_assert(chunk);
 
+    pa_memchunk_reset(chunk);
     memset(&sfinfo, 0, sizeof(sfinfo));
 
-    if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) {
+    if ((fd = open(fname, O_RDONLY
+#ifdef O_NOCTTY
+                   |O_NOCTTY
+#endif
+                   )) < 0) {
+        pa_log("Failed to open file %s: %s", fname, pa_cstrerror(errno));
+        goto finish;
+    }
+
+#ifdef HAVE_POSIX_FADVISE
+    if (posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL) < 0) {
+        pa_log_warn("POSIX_FADV_SEQUENTIAL failed: %s", pa_cstrerror(errno));
+        goto finish;
+    } else
+        pa_log_debug("POSIX_FADV_SEQUENTIAL succeeded.");
+#endif
+
+    if (!(sf = sf_open_fd(fd, SFM_READ, &sfinfo, 1))) {
         pa_log("Failed to open file %s", fname);
+        pa_close(fd);
         goto finish;
     }
 
@@ -89,18 +121,19 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss,
     if (map)
         pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_DEFAULT);
 
-    if ((l = pa_frame_size(ss)*sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
+    if ((l = pa_frame_size(ss) * sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
         pa_log("File too large");
         goto finish;
     }
 
     chunk->memblock = pa_memblock_new(pool, l);
-    assert(chunk->memblock);
     chunk->index = 0;
     chunk->length = l;
 
-    if ((readf_function && readf_function(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) ||
-        (!readf_function && sf_read_raw(sf, chunk->memblock->data, l) != l)) {
+    ptr = pa_memblock_acquire(chunk->memblock);
+
+    if ((readf_function && readf_function(sf, ptr, sfinfo.frames) != sfinfo.frames) ||
+        (!readf_function && sf_read_raw(sf, ptr, l) != (sf_count_t) l)) {
         pa_log("Premature file end");
         goto finish;
     }
@@ -112,21 +145,26 @@ finish:
     if (sf)
         sf_close(sf);
 
+    if (ptr)
+        pa_memblock_release(chunk->memblock);
+
     if (ret != 0 && chunk->memblock)
         pa_memblock_unref(chunk->memblock);
 
     return ret;
-
 }
 
 int pa_sound_file_too_big_to_cache(const char *fname) {
+
     SNDFILE*sf = NULL;
     SF_INFO sfinfo;
     pa_sample_spec ss;
 
+    pa_assert(fname);
+
     if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) {
         pa_log("Failed to open file %s", fname);
-        return 0;
+        return -1;
     }
 
     sf_close(sf);
@@ -156,8 +194,13 @@ int pa_sound_file_too_big_to_cache(const char *fname) {
     ss.rate = sfinfo.samplerate;
     ss.channels = sfinfo.channels;
 
+    if (!pa_sample_spec_valid(&ss)) {
+        pa_log("Unsupported sample format in file %s", fname);
+        return -1;
+    }
+
     if ((pa_frame_size(&ss) * sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
-        pa_log("File too large %s", fname);
+        pa_log("File too large: %s", fname);
         return 1;
     }
 
index c7a9858c49b66283aae4414c8ab635b50686d7b2..2a902dc2bbaf8f08037d9ab56a49ba343096fa61 100644 (file)
@@ -26,7 +26,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
 
 #include "source-output.h"
 
-#define CHECK_VALIDITY_RETURN_NULL(condition) \
-do {\
-if (!(condition)) \
-    return NULL; \
-} while (0)
+static PA_DEFINE_CHECK_TYPE(pa_source_output, pa_msgobject);
+
+static void source_output_free(pa_object* mo);
 
 pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data) {
-    assert(data);
+    pa_assert(data);
 
     memset(data, 0, sizeof(*data));
     data->resample_method = PA_RESAMPLER_INVALID;
@@ -54,14 +51,14 @@ pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_d
 }
 
 void pa_source_output_new_data_set_channel_map(pa_source_output_new_data *data, const pa_channel_map *map) {
-    assert(data);
+    pa_assert(data);
 
     if ((data->channel_map_is_set = !!map))
         data->channel_map = *map;
 }
 
 void pa_source_output_new_data_set_sample_spec(pa_source_output_new_data *data, const pa_sample_spec *spec) {
-    assert(data);
+    pa_assert(data);
 
     if ((data->sample_spec_is_set = !!spec))
         data->sample_spec = *spec;
@@ -74,288 +71,415 @@ pa_source_output* pa_source_output_new(
 
     pa_source_output *o;
     pa_resampler *resampler = NULL;
-    int r;
     char st[PA_SAMPLE_SPEC_SNPRINT_MAX];
 
-    assert(core);
-    assert(data);
+    pa_assert(core);
+    pa_assert(data);
 
-    if (!(flags & PA_SOURCE_OUTPUT_NO_HOOKS))
-        if (pa_hook_fire(&core->hook_source_output_new, data) < 0)
-            return NULL;
+    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], data) < 0)
+        return NULL;
 
-    CHECK_VALIDITY_RETURN_NULL(!data->driver || pa_utf8_valid(data->driver));
-    CHECK_VALIDITY_RETURN_NULL(!data->name || pa_utf8_valid(data->name));
+    pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
+    pa_return_null_if_fail(!data->name || pa_utf8_valid(data->name));
 
     if (!data->source)
         data->source = pa_namereg_get(core, NULL, PA_NAMEREG_SOURCE, 1);
 
-    CHECK_VALIDITY_RETURN_NULL(data->source);
-    CHECK_VALIDITY_RETURN_NULL(data->source->state == PA_SOURCE_RUNNING);
+    pa_return_null_if_fail(data->source);
+    pa_return_null_if_fail(pa_source_get_state(data->source) != PA_SOURCE_UNLINKED);
 
     if (!data->sample_spec_is_set)
         data->sample_spec = data->source->sample_spec;
 
-    CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(&data->sample_spec));
+    pa_return_null_if_fail(pa_sample_spec_valid(&data->sample_spec));
 
-    if (!data->channel_map_is_set)
-        pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
+    if (!data->channel_map_is_set) {
+        if (data->source->channel_map.channels == data->sample_spec.channels)
+            data->channel_map = data->source->channel_map;
+        else
+            pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
+    }
 
-    CHECK_VALIDITY_RETURN_NULL(pa_channel_map_valid(&data->channel_map));
-    CHECK_VALIDITY_RETURN_NULL(data->channel_map.channels == data->sample_spec.channels);
+    pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
+    pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
 
     if (data->resample_method == PA_RESAMPLER_INVALID)
         data->resample_method = core->resample_method;
 
-    CHECK_VALIDITY_RETURN_NULL(data->resample_method < PA_RESAMPLER_MAX);
+    pa_return_null_if_fail(data->resample_method < PA_RESAMPLER_MAX);
 
     if (pa_idxset_size(data->source->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) {
         pa_log("Failed to create source output: too many outputs per source.");
         return NULL;
     }
 
-    if (!pa_sample_spec_equal(&data->sample_spec, &data->source->sample_spec) ||
-        !pa_channel_map_equal(&data->channel_map, &data->source->channel_map))
+    if ((flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ||
+        !pa_sample_spec_equal(&data->sample_spec, &data->source->sample_spec) ||
+        !pa_channel_map_equal(&data->channel_map, &data->source->channel_map)) {
+
         if (!(resampler = pa_resampler_new(
                       core->mempool,
                       &data->source->sample_spec, &data->source->channel_map,
                       &data->sample_spec, &data->channel_map,
-                      data->resample_method))) {
+                      data->resample_method,
+                      !!(flags & PA_SOURCE_OUTPUT_VARIABLE_RATE)))) {
             pa_log_warn("Unsupported resampling operation.");
             return NULL;
         }
 
-    o = pa_xnew(pa_source_output, 1);
-    o->ref = 1;
-    o->state = PA_SOURCE_OUTPUT_RUNNING;
+        data->resample_method = pa_resampler_get_method(resampler);
+    }
+
+    o = pa_msgobject_new(pa_source_output);
+    o->parent.parent.free = source_output_free;
+    o->parent.process_msg = pa_source_output_process_msg;
+
+    o->core = core;
+    o->state = PA_SOURCE_OUTPUT_INIT;
+    o->flags = flags;
     o->name = pa_xstrdup(data->name);
     o->driver = pa_xstrdup(data->driver);
     o->module = data->module;
     o->source = data->source;
     o->client = data->client;
 
+    o->resample_method = data->resample_method;
     o->sample_spec = data->sample_spec;
     o->channel_map = data->channel_map;
 
     o->push = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
+    o->detach = NULL;
+    o->attach = NULL;
+    o->suspend = NULL;
     o->userdata = NULL;
 
-    o->resampler = resampler;
-    o->resample_method = data->resample_method;
+    o->thread_info.state = o->state;
+    o->thread_info.attached = FALSE;
+    o->thread_info.sample_spec = o->sample_spec;
+    o->thread_info.resampler = resampler;
 
-    r = pa_idxset_put(core->source_outputs, o, &o->index);
-    assert(r == 0);
-    r = pa_idxset_put(o->source->outputs, o, NULL);
-    assert(r == 0);
+    pa_assert_se(pa_idxset_put(core->source_outputs, o, &o->index) == 0);
+    pa_assert_se(pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL) == 0);
 
-    pa_log_info("created %u \"%s\" on %s with sample spec %s",
+    pa_log_info("Created output %u \"%s\" on %s with sample spec %s",
                 o->index,
                 o->name,
                 o->source->name,
                 pa_sample_spec_snprint(st, sizeof(st), &o->sample_spec));
 
-    pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index);
-
-    /* We do not call pa_source_notify() here, because the virtual
-     * functions have not yet been initialized */
+    /* Don't forget to call pa_source_output_put! */
 
     return o;
 }
 
-void pa_source_output_disconnect(pa_source_output*o) {
-    assert(o);
-    assert(o->state != PA_SOURCE_OUTPUT_DISCONNECTED);
-    assert(o->source);
-    assert(o->source->core);
+static int source_output_set_state(pa_source_output *o, pa_source_output_state_t state) {
+    pa_assert(o);
+
+    if (o->state == state)
+        return 0;
+
+    if (pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0)
+        return -1;
+
+    if (o->state == PA_SOURCE_OUTPUT_CORKED && state != PA_SOURCE_OUTPUT_CORKED)
+        pa_assert_se(o->source->n_corked -- >= 1);
+    else if (o->state != PA_SOURCE_OUTPUT_CORKED && state == PA_SOURCE_OUTPUT_CORKED)
+        o->source->n_corked++;
+
+    pa_source_update_status(o->source);
+
+    o->state = state;
+
+    if (state != PA_SOURCE_OUTPUT_UNLINKED)
+        pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED], o);
+
+    return 0;
+}
+
+void pa_source_output_unlink(pa_source_output*o) {
+    pa_bool_t linked;
+    pa_assert(o);
+
+    /* See pa_sink_unlink() for a couple of comments how this function
+     * works */
+
+    pa_source_output_ref(o);
+
+    linked = PA_SOURCE_OUTPUT_LINKED(o->state);
+
+    if (linked)
+        pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], o);
 
     pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
-    pa_idxset_remove_by_data(o->source->outputs, o, NULL);
+    if (pa_idxset_remove_by_data(o->source->outputs, o, NULL))
+        pa_source_output_unref(o);
 
-    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index);
-    o->source = NULL;
+    if (linked) {
+        pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
+        source_output_set_state(o, PA_SOURCE_OUTPUT_UNLINKED);
+        pa_source_update_status(o->source);
+    } else
+        o->state = PA_SOURCE_OUTPUT_UNLINKED;
 
     o->push = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
+    o->attach = NULL;
+    o->detach = NULL;
+    o->suspend = NULL;
+
+    if (linked) {
+        pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index);
+        pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], o);
+    }
 
-    o->state = PA_SOURCE_OUTPUT_DISCONNECTED;
+    o->source = NULL;
+    pa_source_output_unref(o);
 }
 
-static void source_output_free(pa_source_output* o) {
-    assert(o);
+static void source_output_free(pa_object* mo) {
+    pa_source_output *o = PA_SOURCE_OUTPUT(mo);
+
+    pa_assert(pa_source_output_refcnt(o) == 0);
+
+    if (PA_SOURCE_OUTPUT_LINKED(o->state))
+        pa_source_output_unlink(o);
 
-    if (o->state != PA_SOURCE_OUTPUT_DISCONNECTED)
-        pa_source_output_disconnect(o);
+    pa_log_info("Freeing output %u \"%s\"", o->index, o->name);
 
-    pa_log_info("freed %u \"%s\"", o->index, o->name);
+    pa_assert(!o->thread_info.attached);
 
-    if (o->resampler)
-        pa_resampler_free(o->resampler);
+    if (o->thread_info.resampler)
+        pa_resampler_free(o->thread_info.resampler);
 
     pa_xfree(o->name);
     pa_xfree(o->driver);
     pa_xfree(o);
 }
 
-void pa_source_output_unref(pa_source_output* o) {
-    assert(o);
-    assert(o->ref >= 1);
+void pa_source_output_put(pa_source_output *o) {
+    pa_source_output_assert_ref(o);
 
-    if (!(--o->ref))
-        source_output_free(o);
-}
+    pa_assert(o->state == PA_SOURCE_OUTPUT_INIT);
+    pa_assert(o->push);
 
-pa_source_output* pa_source_output_ref(pa_source_output *o) {
-    assert(o);
-    assert(o->ref >= 1);
+    o->thread_info.state = o->state = o->flags & PA_SOURCE_OUTPUT_START_CORKED ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
 
-    o->ref++;
-    return o;
+    if (o->state == PA_SOURCE_OUTPUT_CORKED)
+        o->source->n_corked++;
+
+    pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL);
+    pa_source_update_status(o->source);
+
+    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index);
+
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], o);
 }
 
 void pa_source_output_kill(pa_source_output*o) {
-    assert(o);
-    assert(o->ref >= 1);
+    pa_source_output_assert_ref(o);
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
 
     if (o->kill)
         o->kill(o);
 }
 
+pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
+    pa_usec_t r = 0;
+
+    pa_source_output_assert_ref(o);
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
+
+    if (pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY, &r, 0, NULL) < 0)
+        r = 0;
+
+    if (o->get_latency)
+        r += o->get_latency(o);
+
+    return r;
+}
+
+/* Called from thread context */
 void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     pa_memchunk rchunk;
 
-    assert(o);
-    assert(chunk);
-    assert(chunk->length);
-    assert(o->push);
+    pa_source_output_assert_ref(o);
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->thread_info.state));
+    pa_assert(chunk);
+    pa_assert(chunk->length);
 
-    if (o->state == PA_SOURCE_OUTPUT_CORKED)
+    if (!o->push || o->state == PA_SOURCE_OUTPUT_CORKED)
         return;
 
-    if (!o->resampler) {
+    pa_assert(o->state == PA_SOURCE_OUTPUT_RUNNING);
+
+    if (!o->thread_info.resampler) {
         o->push(o, chunk);
         return;
     }
 
-    pa_resampler_run(o->resampler, chunk, &rchunk);
+    pa_resampler_run(o->thread_info.resampler, chunk, &rchunk);
     if (!rchunk.length)
         return;
 
-    assert(rchunk.memblock);
+    pa_assert(rchunk.memblock);
     o->push(o, &rchunk);
     pa_memblock_unref(rchunk.memblock);
 }
 
-void pa_source_output_set_name(pa_source_output *o, const char *name) {
-    assert(o);
-    assert(o->ref >= 1);
-
-    if (!o->name && !name)
-        return;
+void pa_source_output_cork(pa_source_output *o, pa_bool_t b) {
+    pa_source_output_assert_ref(o);
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
 
-    if (o->name && name && !strcmp(o->name, name))
-        return;
+    source_output_set_state(o, b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING);
+}
 
-    pa_xfree(o->name);
-    o->name = pa_xstrdup(name);
+int pa_source_output_set_rate(pa_source_output *o, uint32_t rate) {
+    pa_source_output_assert_ref(o);
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
+    pa_return_val_if_fail(o->thread_info.resampler, -1);
 
-    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
-}
+    if (o->sample_spec.rate == rate)
+        return 0;
 
-pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
-    assert(o);
-    assert(o->ref >= 1);
+    o->sample_spec.rate = rate;
 
-    if (o->get_latency)
-        return o->get_latency(o);
+    pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL);
 
+    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
     return 0;
 }
 
-void pa_source_output_cork(pa_source_output *o, int b) {
-    int n;
-
-    assert(o);
-    assert(o->ref >= 1);
+void pa_source_output_set_name(pa_source_output *o, const char *name) {
+    pa_source_output_assert_ref(o);
 
-    if (o->state == PA_SOURCE_OUTPUT_DISCONNECTED)
+    if (!o->name && !name)
         return;
 
-    n = o->state == PA_SOURCE_OUTPUT_CORKED && !b;
+    if (o->name && name && !strcmp(o->name, name))
+        return;
 
-    o->state = b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
+    pa_xfree(o->name);
+    o->name = pa_xstrdup(name);
 
-    if (n)
-        pa_source_notify(o->source);
+    if (PA_SOURCE_OUTPUT_LINKED(o->state)) {
+        pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NAME_CHANGED], o);
+        pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
+    }
 }
 
 pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) {
-    assert(o);
-    assert(o->ref >= 1);
+    pa_source_output_assert_ref(o);
 
-    if (!o->resampler)
-        return o->resample_method;
-
-    return pa_resampler_get_method(o->resampler);
+    return o->resample_method;
 }
 
 int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
     pa_source *origin;
     pa_resampler *new_resampler = NULL;
 
-    assert(o);
-    assert(o->ref >= 1);
-    assert(dest);
+    pa_source_output_assert_ref(o);
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
+    pa_source_assert_ref(dest);
 
     origin = o->source;
 
     if (dest == origin)
         return 0;
 
+    if (o->flags & PA_SOURCE_OUTPUT_DONT_MOVE)
+        return -1;
+
     if (pa_idxset_size(dest->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) {
         pa_log_warn("Failed to move source output: too many outputs per source.");
         return -1;
     }
 
-    if (o->resampler &&
+    if (o->thread_info.resampler &&
         pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) &&
         pa_channel_map_equal(&origin->channel_map, &dest->channel_map))
 
         /* Try to reuse the old resampler if possible */
-        new_resampler = o->resampler;
+        new_resampler = o->thread_info.resampler;
 
-    else if (!pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) ||
-        !pa_channel_map_equal(&o->channel_map, &dest->channel_map)) {
+    else if ((o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ||
+             !pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) ||
+             !pa_channel_map_equal(&o->channel_map, &dest->channel_map)) {
 
-        /* Okey, we need a new resampler for the new sink */
+        /* Okey, we need a new resampler for the new source */
 
         if (!(new_resampler = pa_resampler_new(
                       dest->core->mempool,
                       &dest->sample_spec, &dest->channel_map,
                       &o->sample_spec, &o->channel_map,
-                      o->resample_method))) {
+                      o->resample_method,
+                      !!(o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE)))) {
             pa_log_warn("Unsupported resampling operation.");
             return -1;
         }
     }
 
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE], o);
+
     /* Okey, let's move it */
+    pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
+
     pa_idxset_remove_by_data(origin->outputs, o, NULL);
     pa_idxset_put(dest->outputs, o, NULL);
     o->source = dest;
 
+    if (pa_source_output_get_state(o) == PA_SOURCE_OUTPUT_CORKED) {
+        pa_assert_se(origin->n_corked-- >= 1);
+        dest->n_corked++;
+    }
+
     /* Replace resampler */
-    if (new_resampler != o->resampler) {
-        if (o->resampler)
-            pa_resampler_free(o->resampler);
-        o->resampler = new_resampler;
+    if (new_resampler != o->thread_info.resampler) {
+        if (o->thread_info.resampler)
+            pa_resampler_free(o->thread_info.resampler);
+        o->thread_info.resampler = new_resampler;
     }
 
+    pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL);
+
+    pa_source_update_status(origin);
+    pa_source_update_status(dest);
+
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST], o);
+
+    pa_log_debug("Successfully moved source output %i from %s to %s.", o->index, origin->name, dest->name);
+
     /* Notify everyone */
     pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
-    pa_source_notify(o->source);
 
     return 0;
 }
+
+/* Called from thread context */
+int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int64_t offset, pa_memchunk* chunk) {
+    pa_source_output *o = PA_SOURCE_OUTPUT(mo);
+
+    pa_source_output_assert_ref(o);
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->thread_info.state));
+
+    switch (code) {
+
+        case PA_SOURCE_OUTPUT_MESSAGE_SET_RATE: {
+
+            o->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
+            pa_resampler_set_output_rate(o->thread_info.resampler, PA_PTR_TO_UINT(userdata));
+
+            return 0;
+        }
+
+        case PA_SOURCE_OUTPUT_MESSAGE_SET_STATE: {
+            o->thread_info.state = PA_PTR_TO_UINT(userdata);
+
+            return 0;
+        }
+    }
+
+    return -1;
+}
index 3da6caacdee9731886630864b5f0b9f74fd913ed..e38a1e5a1d7b24dd28de55a1a9bc4ee7786681b6 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef foosourceoutputhfoo
-#define foosourceoutputhfoo
+#ifndef foopulsesourceoutputhfoo
+#define foopulsesourceoutputhfoo
 
 /* $Id$ */
 
@@ -35,40 +35,91 @@ typedef struct pa_source_output pa_source_output;
 #include <pulsecore/module.h>
 #include <pulsecore/client.h>
 
-typedef enum {
+typedef enum pa_source_output_state {
+    PA_SOURCE_OUTPUT_INIT,
     PA_SOURCE_OUTPUT_RUNNING,
     PA_SOURCE_OUTPUT_CORKED,
-    PA_SOURCE_OUTPUT_DISCONNECTED
+    PA_SOURCE_OUTPUT_UNLINKED
 } pa_source_output_state_t;
 
+static inline pa_bool_t PA_SOURCE_OUTPUT_LINKED(pa_source_output_state_t x) {
+    return x == PA_SOURCE_OUTPUT_RUNNING || x == PA_SOURCE_OUTPUT_CORKED;
+}
+
 typedef enum pa_source_output_flags {
-    PA_SOURCE_OUTPUT_NO_HOOKS = 1
+    PA_SOURCE_OUTPUT_VARIABLE_RATE = 1,
+    PA_SOURCE_OUTPUT_DONT_MOVE = 2,
+    PA_SOURCE_OUTPUT_START_CORKED = 4
 } pa_source_output_flags_t;
 
 struct pa_source_output {
-    int ref;
+    pa_msgobject parent;
+
     uint32_t index;
+    pa_core *core;
     pa_source_output_state_t state;
+    pa_source_output_flags_t flags;
 
     char *name, *driver;                  /* may be NULL */
     pa_module *module;                    /* may be NULL */
+    pa_client *client;                    /* may be NULL */
 
     pa_source *source;
-    pa_client *client;                    /* may be NULL */
 
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
 
+    /* Pushes a new memchunk into the output. Called from IO thread
+     * context. */
     void (*push)(pa_source_output *o, const pa_memchunk *chunk);
+
+    /* If non-NULL this function is called when the output is first
+     * connected to a source. Called from IO thread context */
+    void (*attach) (pa_source_output *o);           /* may be NULL */
+
+    /* If non-NULL this function is called when the output is
+     * disconnected from its source. Called from IO thread context */
+    void (*detach) (pa_source_output *o);           /* may be NULL */
+
+    /* If non-NULL called whenever the the source this output is attached
+     * to suspends or resumes. Called from main context */
+    void (*suspend) (pa_source_output *o, int b);   /* may be NULL */
+
+    /* Supposed to unlink and destroy this stream. Called from main
+     * context. */
     void (*kill)(pa_source_output* o);              /* may be NULL */
+
+    /* Return the current latency (i.e. length of bufferd audio) of
+    this stream. Called from main context. If NULL a
+    PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY message is sent to the IO
+    thread instead. */
     pa_usec_t (*get_latency) (pa_source_output *o); /* may be NULL */
 
-    pa_resampler* resampler;              /* may be NULL */
     pa_resample_method_t resample_method;
 
+    struct {
+        pa_source_output_state_t state;
+
+        pa_bool_t attached; /* True only between ->attach() and ->detach() calls */
+
+        pa_sample_spec sample_spec;
+
+        pa_resampler* resampler;              /* may be NULL */
+    } thread_info;
+
     void *userdata;
 };
 
+PA_DECLARE_CLASS(pa_source_output);
+#define PA_SOURCE_OUTPUT(o) pa_source_output_cast(o)
+
+enum {
+    PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY,
+    PA_SOURCE_OUTPUT_MESSAGE_SET_RATE,
+    PA_SOURCE_OUTPUT_MESSAGE_SET_STATE,
+    PA_SOURCE_OUTPUT_MESSAGE_MAX
+};
+
 typedef struct pa_source_output_new_data {
     const char *name, *driver;
     pa_module *module;
@@ -77,9 +128,9 @@ typedef struct pa_source_output_new_data {
     pa_source *source;
 
     pa_sample_spec sample_spec;
-    int sample_spec_is_set;
+    pa_bool_t sample_spec_is_set;
     pa_channel_map channel_map;
-    int channel_map_is_set;
+    pa_bool_t channel_map_is_set;
 
     pa_resample_method_t resample_method;
 } pa_source_output_new_data;
@@ -89,30 +140,38 @@ void pa_source_output_new_data_set_sample_spec(pa_source_output_new_data *data,
 void pa_source_output_new_data_set_channel_map(pa_source_output_new_data *data, const pa_channel_map *map);
 void pa_source_output_new_data_set_volume(pa_source_output_new_data *data, const pa_cvolume *volume);
 
+/* To be called by the implementing module only */
+
 pa_source_output* pa_source_output_new(
         pa_core *core,
         pa_source_output_new_data *data,
         pa_source_output_flags_t flags);
 
-void pa_source_output_unref(pa_source_output* o);
-pa_source_output* pa_source_output_ref(pa_source_output *o);
+void pa_source_output_put(pa_source_output *o);
+void pa_source_output_unlink(pa_source_output*o);
 
-/* To be called by the implementing module only */
-void pa_source_output_disconnect(pa_source_output*o);
+void pa_source_output_set_name(pa_source_output *i, const char *name);
+
+/* Callable by everyone */
 
 /* External code may request disconnection with this funcion */
 void pa_source_output_kill(pa_source_output*o);
 
-void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk);
-
-void pa_source_output_set_name(pa_source_output *i, const char *name);
-
 pa_usec_t pa_source_output_get_latency(pa_source_output *i);
 
-void pa_source_output_cork(pa_source_output *i, int b);
+void pa_source_output_cork(pa_source_output *i, pa_bool_t b);
+
+int pa_source_output_set_rate(pa_source_output *o, uint32_t rate);
 
 pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o);
 
 int pa_source_output_move_to(pa_source_output *o, pa_source *dest);
 
+#define pa_source_output_get_state(o) ((o)->state)
+
+/* To be used exclusively by the source driver thread */
+
+void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk);
+int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
+
 #endif
index 9bb2d342d8d2ec3efcc39987d9f525f8c81980aa..9a6902ae6afd7fd3532505260f69fffb20012fd6 100644 (file)
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
 
 #include "source.h"
 
-#define CHECK_VALIDITY_RETURN_NULL(condition) \
-do {\
-if (!(condition)) \
-    return NULL; \
-} while (0)
+static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
+
+static void source_free(pa_object *o);
 
 pa_source* pa_source_new(
         pa_core *core,
@@ -58,274 +55,359 @@ pa_source* pa_source_new(
 
     pa_source *s;
     char st[256];
-    int r;
     pa_channel_map tmap;
 
-    assert(core);
-    assert(name);
-    assert(spec);
+    pa_assert(core);
+    pa_assert(name);
+    pa_assert(spec);
 
-    CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec));
+    pa_return_null_if_fail(pa_sample_spec_valid(spec));
 
     if (!map)
         map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT);
 
-    CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map));
-    CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels);
-    CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver));
-    CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name) && *name);
+    pa_return_null_if_fail(map && pa_channel_map_valid(map));
+    pa_return_null_if_fail(map->channels == spec->channels);
+    pa_return_null_if_fail(!driver || pa_utf8_valid(driver));
+    pa_return_null_if_fail(pa_utf8_valid(name) && *name);
 
-    s = pa_xnew(pa_source, 1);
+    s = pa_msgobject_new(pa_source);
 
     if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) {
         pa_xfree(s);
         return NULL;
     }
 
-    s->ref = 1;
+    s->parent.parent.free = source_free;
+    s->parent.process_msg = pa_source_process_msg;
+
     s->core = core;
-    s->state = PA_SOURCE_RUNNING;
+    s->state = PA_SOURCE_INIT;
+    s->flags = 0;
     s->name = pa_xstrdup(name);
     s->description = NULL;
     s->driver = pa_xstrdup(driver);
-    s->owner = NULL;
+    s->module = NULL;
 
     s->sample_spec = *spec;
     s->channel_map = *map;
 
     s->outputs = pa_idxset_new(NULL, NULL);
+    s->n_corked = 0;
     s->monitor_of = NULL;
 
-    pa_cvolume_reset(&s->sw_volume, spec->channels);
-    pa_cvolume_reset(&s->hw_volume, spec->channels);
-    s->sw_muted = 0;
-    s->hw_muted = 0;
-
-    s->is_hardware = 0;
+    pa_cvolume_reset(&s->volume, spec->channels);
+    s->muted = FALSE;
+    s->refresh_volume = s->refresh_muted = FALSE;
 
     s->get_latency = NULL;
-    s->notify = NULL;
-    s->set_hw_volume = NULL;
-    s->get_hw_volume = NULL;
-    s->set_hw_mute = NULL;
-    s->get_hw_mute = NULL;
+    s->set_volume = NULL;
+    s->get_volume = NULL;
+    s->set_mute = NULL;
+    s->get_mute = NULL;
+    s->set_state = NULL;
     s->userdata = NULL;
 
-    r = pa_idxset_put(core->sources, s, &s->index);
-    assert(s->index != PA_IDXSET_INVALID && r >= 0);
+    s->asyncmsgq = NULL;
+    s->rtpoll = NULL;
+
+    pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
 
     pa_sample_spec_snprint(st, sizeof(st), spec);
-    pa_log_info("created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st);
+    pa_log_info("Created source %u \"%s\" with sample spec \"%s\"", s->index, s->name, st);
 
-    pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
+    s->thread_info.outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+    s->thread_info.soft_volume = s->volume;
+    s->thread_info.soft_muted = s->muted;
+    s->thread_info.state = s->state;
 
     return s;
 }
 
-void pa_source_disconnect(pa_source *s) {
+static int source_set_state(pa_source *s, pa_source_state_t state) {
+    int ret;
+
+    pa_assert(s);
+
+    if (s->state == state)
+        return 0;
+
+    if ((s->state == PA_SOURCE_SUSPENDED && PA_SOURCE_OPENED(state)) ||
+        (PA_SOURCE_OPENED(s->state) && state == PA_SOURCE_SUSPENDED)) {
+        pa_source_output *o;
+        uint32_t idx;
+
+        /* We're suspending or resuming, tell everyone about it */
+
+        for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx)))
+            if (o->suspend)
+                o->suspend(o, state == PA_SINK_SUSPENDED);
+    }
+
+    if (s->set_state)
+        if ((ret = s->set_state(s, state)) < 0)
+            return -1;
+
+    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0)
+        return -1;
+
+    s->state = state;
+
+    if (state != PA_SOURCE_UNLINKED) /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */
+        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s);
+    return 0;
+}
+
+void pa_source_put(pa_source *s) {
+    pa_source_assert_ref(s);
+
+    pa_assert(s->state == PA_SINK_INIT);
+    pa_assert(s->rtpoll);
+    pa_assert(s->asyncmsgq);
+
+    pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
+
+    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_NEW_POST], s);
+}
+
+void pa_source_unlink(pa_source *s) {
+    pa_bool_t linked;
     pa_source_output *o, *j = NULL;
 
-    assert(s);
-    assert(s->state == PA_SOURCE_RUNNING);
+    pa_assert(s);
+
+    /* See pa_sink_unlink() for a couple of comments how this function
+     * works. */
 
-    s->state = PA_SOURCE_DISCONNECTED;
-    pa_namereg_unregister(s->core, s->name);
+    linked = PA_SOURCE_LINKED(s->state);
 
-    pa_hook_fire(&s->core->hook_source_disconnect, s);
+    if (linked)
+        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);
+
+    if (s->state != PA_SOURCE_UNLINKED)
+        pa_namereg_unregister(s->core, s->name);
+    pa_idxset_remove_by_data(s->core->sources, s, NULL);
 
     while ((o = pa_idxset_first(s->outputs, NULL))) {
-        assert(o != j);
+        pa_assert(o != j);
         pa_source_output_kill(o);
         j = o;
     }
 
-    pa_idxset_remove_by_data(s->core->sources, s, NULL);
+    if (linked)
+        source_set_state(s, PA_SOURCE_UNLINKED);
+    else
+        s->state = PA_SOURCE_UNLINKED;
 
     s->get_latency = NULL;
-    s->notify = NULL;
-    s->get_hw_volume = NULL;
-    s->set_hw_volume = NULL;
-    s->set_hw_mute = NULL;
-    s->get_hw_mute = NULL;
-
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
+    s->get_volume = NULL;
+    s->set_volume = NULL;
+    s->set_mute = NULL;
+    s->get_mute = NULL;
+    s->set_state = NULL;
+
+    if (linked) {
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
+        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], s);
+    }
 }
 
-static void source_free(pa_source *s) {
-    assert(s);
-    assert(!s->ref);
+static void source_free(pa_object *o) {
+    pa_source_output *so;
+    pa_source *s = PA_SOURCE(o);
 
-    if (s->state != PA_SOURCE_DISCONNECTED)
-        pa_source_disconnect(s);
+    pa_assert(s);
+    pa_assert(pa_source_refcnt(s) == 0);
 
-    pa_log_info("freed %u \"%s\"", s->index, s->name);
+    if (PA_SOURCE_LINKED(s->state))
+        pa_source_unlink(s);
+
+    pa_log_info("Freeing source %u \"%s\"", s->index, s->name);
 
     pa_idxset_free(s->outputs, NULL, NULL);
 
+    while ((so = pa_hashmap_steal_first(s->thread_info.outputs)))
+        pa_source_output_unref(so);
+
+    pa_hashmap_free(s->thread_info.outputs, NULL, NULL);
+
     pa_xfree(s->name);
     pa_xfree(s->description);
     pa_xfree(s->driver);
     pa_xfree(s);
 }
 
-void pa_source_unref(pa_source *s) {
-    assert(s);
-    assert(s->ref >= 1);
-
-    if (!(--s->ref))
-        source_free(s);
-}
+int pa_source_update_status(pa_source*s) {
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
 
-pa_source* pa_source_ref(pa_source *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    if (s->state == PA_SOURCE_SUSPENDED)
+        return 0;
 
-    s->ref++;
-    return s;
+    return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
 }
 
-void pa_source_notify(pa_source*s) {
-    assert(s);
-    assert(s->ref >= 1);
+int pa_source_suspend(pa_source *s, pa_bool_t suspend) {
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
 
-    if (s->notify)
-        s->notify(s);
+    if (suspend)
+        return source_set_state(s, PA_SOURCE_SUSPENDED);
+    else
+        return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
 }
 
-static int do_post(void *p, PA_GCC_UNUSED uint32_t idx, PA_GCC_UNUSED int *del, void*userdata) {
-    pa_source_output *o = p;
-    const pa_memchunk *chunk = userdata;
+void pa_source_ping(pa_source *s) {
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
 
-    assert(o);
-    assert(chunk);
-
-    pa_source_output_push(o, chunk);
-    return 0;
+    pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_PING, NULL, 0, NULL, NULL);
 }
 
 void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
-    assert(s);
-    assert(s->ref >= 1);
-    assert(chunk);
+    pa_source_output *o;
+    void *state = NULL;
 
-    pa_source_ref(s);
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_OPENED(s->thread_info.state));
+    pa_assert(chunk);
 
-    if (s->sw_muted || !pa_cvolume_is_norm(&s->sw_volume)) {
+    if (s->thread_info.state != PA_SOURCE_RUNNING)
+        return;
+
+    if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
         pa_memchunk vchunk = *chunk;
 
         pa_memblock_ref(vchunk.memblock);
         pa_memchunk_make_writable(&vchunk, 0);
-        if (s->sw_muted)
+
+        if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
             pa_silence_memchunk(&vchunk, &s->sample_spec);
         else
-            pa_volume_memchunk(&vchunk, &s->sample_spec, &s->sw_volume);
-        pa_idxset_foreach(s->outputs, do_post, &vchunk);
+            pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
+
+        while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+            pa_source_output_push(o, &vchunk);
+
         pa_memblock_unref(vchunk.memblock);
-    } else
-        pa_idxset_foreach(s->outputs, do_post, (void*) chunk);
+    } else {
 
-    pa_source_unref(s);
+        while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+            pa_source_output_push(o, chunk);
+    }
 }
 
-void pa_source_set_owner(pa_source *s, pa_module *m) {
-    assert(s);
-    assert(s->ref >= 1);
+pa_usec_t pa_source_get_latency(pa_source *s) {
+    pa_usec_t usec;
 
-    if (m == s->owner)
-        return;
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
 
-    s->owner = m;
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
-}
+    if (!PA_SOURCE_OPENED(s->state))
+        return 0;
 
-pa_usec_t pa_source_get_latency(pa_source *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    if (s->get_latency)
+        return s->get_latency(s);
 
-    if (!s->get_latency)
+    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
         return 0;
 
-    return s->get_latency(s);
+    return usec;
 }
 
-void pa_source_set_volume(pa_source *s, pa_mixer_t m, const pa_cvolume *volume) {
-    pa_cvolume *v;
+void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
+    int changed;
 
-    assert(s);
-    assert(s->ref >= 1);
-    assert(volume);
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
+    pa_assert(volume);
 
-    if (m == PA_MIXER_HARDWARE && s->set_hw_volume)
-        v = &s->hw_volume;
-    else
-        v = &s->sw_volume;
+    changed = !pa_cvolume_equal(volume, &s->volume);
+    s->volume = *volume;
 
-    if (pa_cvolume_equal(v, volume))
-        return;
+    if (s->set_volume && s->set_volume(s) < 0)
+        s->set_volume = NULL;
 
-    *v = *volume;
+    if (!s->set_volume)
+        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), 0, NULL, pa_xfree);
 
-    if (v == &s->hw_volume)
-        if (s->set_hw_volume(s) < 0)
-            s->sw_volume =  *volume;
+    if (changed)
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+}
 
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+const pa_cvolume *pa_source_get_volume(pa_source *s) {
+    pa_cvolume old_volume;
+
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
+
+    old_volume = s->volume;
+
+    if (s->get_volume && s->get_volume(s) < 0)
+        s->get_volume = NULL;
+
+    if (!s->get_volume && s->refresh_volume)
+        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_VOLUME, &s->volume, 0, NULL);
+
+    if (!pa_cvolume_equal(&old_volume, &s->volume))
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+
+    return &s->volume;
 }
 
-const pa_cvolume *pa_source_get_volume(pa_source *s, pa_mixer_t m) {
-    assert(s);
-    assert(s->ref >= 1);
+void pa_source_set_mute(pa_source *s, pa_bool_t mute) {
+    int changed;
+
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
+
+    changed = s->muted != mute;
+    s->muted = mute;
 
-    if (m == PA_MIXER_HARDWARE && s->set_hw_volume) {
+    if (s->set_mute && s->set_mute(s) < 0)
+        s->set_mute = NULL;
 
-        if (s->get_hw_volume)
-            s->get_hw_volume(s);
+    if (!s->set_mute)
+        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), 0, NULL, NULL);
 
-        return &s->hw_volume;
-    } else
-        return &s->sw_volume;
+    if (changed)
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 }
 
-void pa_source_set_mute(pa_source *s, pa_mixer_t m, int mute) {
-    int *t;
+pa_bool_t pa_source_get_mute(pa_source *s) {
+    pa_bool_t old_muted;
 
-    assert(s);
-    assert(s->ref >= 1);
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
 
-    if (m == PA_MIXER_HARDWARE && s->set_hw_mute)
-        t = &s->hw_muted;
-    else
-        t = &s->sw_muted;
+    old_muted = s->muted;
 
-    if (!!*t == !!mute)
-        return;
+    if (s->get_mute && s->get_mute(s) < 0)
+        s->get_mute = NULL;
 
-    *t = !!mute;
+    if (!s->get_mute && s->refresh_muted)
+        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, &s->muted, 0, NULL);
 
-    if (t == &s->hw_muted)
-        if (s->set_hw_mute(s) < 0)
-            s->sw_muted = !!mute;
+    if (old_muted != s->muted)
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    return s->muted;
 }
 
-int pa_source_get_mute(pa_source *s, pa_mixer_t m) {
-    assert(s);
-    assert(s->ref >= 1);
+void pa_source_set_module(pa_source *s, pa_module *m) {
+    pa_source_assert_ref(s);
 
-    if (m == PA_MIXER_HARDWARE && s->set_hw_mute) {
+    if (m == s->module)
+        return;
 
-        if (s->get_hw_mute)
-            s->get_hw_mute(s);
+    s->module = m;
 
-        return s->hw_muted;
-    } else
-        return s->sw_muted;
+    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 }
 
 void pa_source_set_description(pa_source *s, const char *description) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_source_assert_ref(s);
 
     if (!description && !s->description)
         return;
@@ -336,12 +418,172 @@ void pa_source_set_description(pa_source *s, const char *description) {
     pa_xfree(s->description);
     s->description = pa_xstrdup(description);
 
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    if (PA_SOURCE_LINKED(s->state)) {
+        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_DESCRIPTION_CHANGED], s);
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    }
 }
 
-unsigned pa_source_used_by(pa_source *s) {
-    assert(s);
-    assert(s->ref >= 1);
+void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q) {
+    pa_source_assert_ref(s);
+    pa_assert(q);
+
+    s->asyncmsgq = q;
+}
+
+void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p) {
+    pa_source_assert_ref(s);
+    pa_assert(p);
+
+    s->rtpoll = p;
+}
+
+unsigned pa_source_linked_by(pa_source *s) {
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
 
     return pa_idxset_size(s->outputs);
 }
+
+unsigned pa_source_used_by(pa_source *s) {
+    unsigned ret;
+
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
+
+    ret = pa_idxset_size(s->outputs);
+    pa_assert(ret >= s->n_corked);
+
+    return ret - s->n_corked;
+}
+
+int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
+    pa_source *s = PA_SOURCE(object);
+    pa_source_assert_ref(s);
+    pa_assert(s->thread_info.state != PA_SOURCE_UNLINKED);
+
+    switch ((pa_source_message_t) code) {
+        case PA_SOURCE_MESSAGE_ADD_OUTPUT: {
+            pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
+            pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o));
+
+            pa_assert(!o->thread_info.attached);
+            o->thread_info.attached = TRUE;
+
+            if (o->attach)
+                o->attach(o);
+
+            return 0;
+        }
+
+        case PA_SOURCE_MESSAGE_REMOVE_OUTPUT: {
+            pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
+
+            if (o->detach)
+                o->detach(o);
+
+            pa_assert(o->thread_info.attached);
+            o->thread_info.attached = FALSE;
+
+            if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
+                pa_source_output_unref(o);
+
+            return 0;
+        }
+
+        case PA_SOURCE_MESSAGE_SET_VOLUME:
+            s->thread_info.soft_volume = *((pa_cvolume*) userdata);
+            return 0;
+
+        case PA_SOURCE_MESSAGE_SET_MUTE:
+            s->thread_info.soft_muted = PA_PTR_TO_UINT(userdata);
+            return 0;
+
+        case PA_SOURCE_MESSAGE_GET_VOLUME:
+            *((pa_cvolume*) userdata) = s->thread_info.soft_volume;
+            return 0;
+
+        case PA_SOURCE_MESSAGE_GET_MUTE:
+            *((pa_bool_t*) userdata) = s->thread_info.soft_muted;
+            return 0;
+
+        case PA_SOURCE_MESSAGE_PING:
+            return 0;
+
+        case PA_SOURCE_MESSAGE_SET_STATE:
+            s->thread_info.state = PA_PTR_TO_UINT(userdata);
+            return 0;
+
+        case PA_SOURCE_MESSAGE_DETACH:
+
+            /* We're detaching all our output streams so that the
+             * asyncmsgq and rtpoll fields can be changed without
+             * problems */
+            pa_source_detach_within_thread(s);
+            break;
+
+        case PA_SOURCE_MESSAGE_ATTACH:
+
+            /* Reattach all streams */
+            pa_source_attach_within_thread(s);
+            break;
+
+        case PA_SOURCE_MESSAGE_GET_LATENCY:
+        case PA_SOURCE_MESSAGE_MAX:
+            ;
+    }
+
+    return -1;
+}
+
+int pa_source_suspend_all(pa_core *c, pa_bool_t suspend) {
+    uint32_t idx;
+    pa_source *source;
+    int ret = 0;
+
+    pa_core_assert_ref(c);
+
+    for (source = PA_SOURCE(pa_idxset_first(c->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(c->sources, &idx)))
+        ret -= pa_source_suspend(source, suspend) < 0;
+
+    return ret;
+}
+
+void pa_source_detach(pa_source *s) {
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
+
+    pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_DETACH, NULL, 0, NULL);
+}
+
+void pa_source_attach(pa_source *s) {
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
+
+    pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_ATTACH, NULL, 0, NULL);
+}
+
+void pa_source_detach_within_thread(pa_source *s) {
+    pa_source_output *o;
+    void *state = NULL;
+
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->thread_info.state));
+
+    while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+        if (o->detach)
+            o->detach(o);
+}
+
+void pa_source_attach_within_thread(pa_source *s) {
+    pa_source_output *o;
+    void *state = NULL;
+
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->thread_info.state));
+
+    while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+        if (o->attach)
+            o->attach(o);
+
+}
index 5a28cf4b7f4edd2d330cc7f463c46ebbd0c00661..bd0a91228e79fb6a552038ca349c88d74daf22d5 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef foosourcehfoo
-#define foosourcehfoo
+#ifndef foopulsesourcehfoo
+#define foopulsesourcehfoo
 
 /* $Id$ */
 
@@ -32,6 +32,7 @@ typedef struct pa_source pa_source;
 #include <pulse/sample.h>
 #include <pulse/channelmap.h>
 #include <pulse/volume.h>
+
 #include <pulsecore/core-def.h>
 #include <pulsecore/core.h>
 #include <pulsecore/idxset.h>
@@ -39,73 +40,140 @@ typedef struct pa_source pa_source;
 #include <pulsecore/memchunk.h>
 #include <pulsecore/sink.h>
 #include <pulsecore/module.h>
+#include <pulsecore/asyncmsgq.h>
+#include <pulsecore/msgobject.h>
+#include <pulsecore/rtpoll.h>
 
-#define PA_MAX_OUTPUTS_PER_SOURCE 16
+#define PA_MAX_OUTPUTS_PER_SOURCE 32
 
 typedef enum pa_source_state {
+    PA_SOURCE_INIT,
     PA_SOURCE_RUNNING,
-    PA_SOURCE_DISCONNECTED
+    PA_SOURCE_SUSPENDED,
+    PA_SOURCE_IDLE,
+    PA_SOURCE_UNLINKED
 } pa_source_state_t;
 
+static inline pa_bool_t PA_SOURCE_OPENED(pa_source_state_t x) {
+    return x == PA_SOURCE_RUNNING || x == PA_SOURCE_IDLE;
+}
+
+static inline pa_bool_t PA_SOURCE_LINKED(pa_source_state_t x) {
+    return x == PA_SOURCE_RUNNING || x == PA_SOURCE_IDLE || x == PA_SOURCE_SUSPENDED;
+}
+
 struct pa_source {
-    int ref;
+    pa_msgobject parent;
+
     uint32_t index;
     pa_core *core;
     pa_source_state_t state;
+    pa_source_flags_t flags;
 
     char *name;
     char *description, *driver;              /* may be NULL */
 
-    pa_module *owner;                        /* may be NULL */
+    pa_module *module;                        /* may be NULL */
 
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
 
     pa_idxset *outputs;
+    unsigned n_corked;
     pa_sink *monitor_of;                     /* may be NULL */
 
-    pa_cvolume hw_volume, sw_volume;
-    int hw_muted, sw_muted;
-
-    int is_hardware;
+    pa_cvolume volume;
+    pa_bool_t muted;
+    pa_bool_t refresh_volume;
+    pa_bool_t refresh_muted;
 
-    void (*notify)(pa_source*source);        /* may be NULL */
+    int (*set_state)(pa_source*source, pa_source_state_t state); /* may be NULL */
+    int (*set_volume)(pa_source *s);         /* dito */
+    int (*get_volume)(pa_source *s);         /* dito */
+    int (*set_mute)(pa_source *s);           /* dito */
+    int (*get_mute)(pa_source *s);           /* dito */
     pa_usec_t (*get_latency)(pa_source *s);  /* dito */
-    int (*set_hw_volume)(pa_source *s);      /* dito */
-    int (*get_hw_volume)(pa_source *s);      /* dito */
-    int (*set_hw_mute)(pa_source *s);        /* dito */
-    int (*get_hw_mute)(pa_source *s);        /* dito */
+
+    pa_asyncmsgq *asyncmsgq;
+    pa_rtpoll *rtpoll;
+
+    /* Contains copies of the above data so that the real-time worker
+     * thread can work without access locking */
+    struct {
+        pa_source_state_t state;
+        pa_hashmap *outputs;
+        pa_cvolume soft_volume;
+        pa_bool_t soft_muted;
+    } thread_info;
 
     void *userdata;
 };
 
+PA_DECLARE_CLASS(pa_source);
+#define PA_SOURCE(s) pa_source_cast(s)
+
+typedef enum pa_source_message {
+    PA_SOURCE_MESSAGE_ADD_OUTPUT,
+    PA_SOURCE_MESSAGE_REMOVE_OUTPUT,
+    PA_SOURCE_MESSAGE_GET_VOLUME,
+    PA_SOURCE_MESSAGE_SET_VOLUME,
+    PA_SOURCE_MESSAGE_GET_MUTE,
+    PA_SOURCE_MESSAGE_SET_MUTE,
+    PA_SOURCE_MESSAGE_GET_LATENCY,
+    PA_SOURCE_MESSAGE_SET_STATE,
+    PA_SOURCE_MESSAGE_PING,
+    PA_SOURCE_MESSAGE_ATTACH,
+    PA_SOURCE_MESSAGE_DETACH,
+    PA_SOURCE_MESSAGE_MAX
+} pa_source_message_t;
+
+/* To be called exclusively by the source driver, from main context */
+
 pa_source* pa_source_new(
-    pa_core *core,
-    const char *driver,
-    const char *name,
-    int namereg_fail,
-    const pa_sample_spec *spec,
-    const pa_channel_map *map);
-
-void pa_source_disconnect(pa_source *s);
-void pa_source_unref(pa_source *s);
-pa_source* pa_source_ref(pa_source *c);
-
-/* Pass a new memory block to all output streams */
-void pa_source_post(pa_source*s, const pa_memchunk *b);
+        pa_core *core,
+        const char *driver,
+        const char *name,
+        int namereg_fail,
+        const pa_sample_spec *spec,
+        const pa_channel_map *map);
+
+void pa_source_put(pa_source *s);
+void pa_source_unlink(pa_source *s);
 
-void pa_source_notify(pa_source *s);
+void pa_source_set_module(pa_source *s, pa_module *m);
+void pa_source_set_description(pa_source *s, const char *description);
+void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q);
+void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p);
+
+void pa_source_detach(pa_source *s);
+void pa_source_attach(pa_source *s);
 
-void pa_source_set_owner(pa_source *s, pa_module *m);
+/* May be called by everyone, from main context */
 
 pa_usec_t pa_source_get_latency(pa_source *s);
 
-void pa_source_set_volume(pa_source *source, pa_mixer_t m, const pa_cvolume *volume);
-const pa_cvolume *pa_source_get_volume(pa_source *source, pa_mixer_t m);
-void pa_source_set_mute(pa_source *source, pa_mixer_t m, int mute);
-int pa_source_get_mute(pa_source *source, pa_mixer_t m);
+int pa_source_update_status(pa_source*s);
+int pa_source_suspend(pa_source *s, pa_bool_t suspend);
+int pa_source_suspend_all(pa_core *c, pa_bool_t suspend);
 
-void pa_source_set_description(pa_source *s, const char *description);
+void pa_source_ping(pa_source *s);
+
+void pa_source_set_volume(pa_source *source, const pa_cvolume *volume);
+const pa_cvolume *pa_source_get_volume(pa_source *source);
+void pa_source_set_mute(pa_source *source, pa_bool_t mute);
+pa_bool_t pa_source_get_mute(pa_source *source);
+
+unsigned pa_source_linked_by(pa_source *s); /* Number of connected streams */
+unsigned pa_source_used_by(pa_source *s); /* Number of connected streams that are not corked */
+#define pa_source_get_state(s) ((pa_source_state_t) (s)->state)
+
+/* To be called exclusively by the source driver, from IO context */
+
+void pa_source_post(pa_source*s, const pa_memchunk *b);
+
+int pa_source_process_msg(pa_msgobject *o, int code, void *userdata, int64_t, pa_memchunk *chunk);
+
+void pa_source_attach_within_thread(pa_source *s);
+void pa_source_detach_within_thread(pa_source *s);
 
-unsigned pa_source_used_by(pa_source *s);
 #endif
diff --git a/src/pulsecore/speex/Makefile b/src/pulsecore/speex/Makefile
new file mode 100644 (file)
index 0000000..316beb7
--- /dev/null
@@ -0,0 +1,13 @@
+# This is a dirty trick just to ease compilation with emacs
+#
+# This file is not intended to be distributed or anything
+#
+# So: don't touch it, even better ignore it!
+
+all:
+       $(MAKE) -C ../..
+
+clean:
+       $(MAKE) -C ../.. clean
+
+.PHONY: all clean
diff --git a/src/pulsecore/speex/arch.h b/src/pulsecore/speex/arch.h
new file mode 100644 (file)
index 0000000..4be693c
--- /dev/null
@@ -0,0 +1,197 @@
+/* Copyright (C) 2003 Jean-Marc Valin */
+/**
+   @file arch.h
+   @brief Various architecture definitions Speex
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef ARCH_H
+#define ARCH_H
+
+#ifndef OUTSIDE_SPEEX
+#include "speex/speex_types.h"
+#endif
+
+#define ABS(x) ((x) < 0 ? (-(x)) : (x))      /**< Absolute integer value. */
+#define ABS16(x) ((x) < 0 ? (-(x)) : (x))    /**< Absolute 16-bit value.  */
+#define MIN16(a,b) ((a) < (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
+#define MAX16(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
+#define ABS32(x) ((x) < 0 ? (-(x)) : (x))    /**< Absolute 32-bit value.  */
+#define MIN32(a,b) ((a) < (b) ? (a) : (b))   /**< Maximum 32-bit value.   */
+#define MAX32(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 32-bit value.   */
+
+#ifdef FIXED_POINT
+
+typedef spx_int16_t spx_word16_t;
+typedef spx_int32_t   spx_word32_t;
+typedef spx_word32_t spx_mem_t;
+typedef spx_word16_t spx_coef_t;
+typedef spx_word16_t spx_lsp_t;
+typedef spx_word32_t spx_sig_t;
+
+#define Q15ONE 32767
+
+#define LPC_SCALING  8192
+#define SIG_SCALING  16384
+#define LSP_SCALING  8192.
+#define GAMMA_SCALING 32768.
+#define GAIN_SCALING 64
+#define GAIN_SCALING_1 0.015625
+
+#define LPC_SHIFT    13
+#define LSP_SHIFT    13
+#define SIG_SHIFT    14
+
+#define VERY_SMALL 0
+#define VERY_LARGE32 ((spx_word32_t)2147483647)
+#define VERY_LARGE16 ((spx_word16_t)32767)
+#define Q15_ONE ((spx_word16_t)32767)
+
+
+#ifdef FIXED_DEBUG
+#include "fixed_debug.h"
+#else
+
+#include "fixed_generic.h"
+
+#ifdef ARM5E_ASM
+#include "fixed_arm5e.h"
+#elif defined (ARM4_ASM)
+#include "fixed_arm4.h"
+#elif defined (ARM5E_ASM)
+#include "fixed_arm5e.h"
+#elif defined (BFIN_ASM)
+#include "fixed_bfin.h"
+#endif
+
+#endif
+
+
+#else
+
+typedef float spx_mem_t;
+typedef float spx_coef_t;
+typedef float spx_lsp_t;
+typedef float spx_sig_t;
+typedef float spx_word16_t;
+typedef float spx_word32_t;
+
+#define Q15ONE 1.0f
+#define LPC_SCALING  1.f
+#define SIG_SCALING  1.f
+#define LSP_SCALING  1.f
+#define GAMMA_SCALING 1.f
+#define GAIN_SCALING 1.f
+#define GAIN_SCALING_1 1.f
+
+#define LPC_SHIFT    0
+#define LSP_SHIFT    0
+#define SIG_SHIFT    0
+
+#define VERY_SMALL 1e-15f
+#define VERY_LARGE32 1e15f
+#define VERY_LARGE16 1e15f
+#define Q15_ONE ((spx_word16_t)1.f)
+
+#define QCONST16(x,bits) (x)
+#define QCONST32(x,bits) (x)
+
+#define NEG16(x) (-(x))
+#define NEG32(x) (-(x))
+#define EXTRACT16(x) (x)
+#define EXTEND32(x) (x)
+#define SHR16(a,shift) (a)
+#define SHL16(a,shift) (a)
+#define SHR32(a,shift) (a)
+#define SHL32(a,shift) (a)
+#define PSHR16(a,shift) (a)
+#define PSHR32(a,shift) (a)
+#define VSHR32(a,shift) (a)
+#define SATURATE16(x,a) (x)
+#define SATURATE32(x,a) (x)
+
+#define PSHR(a,shift)       (a)
+#define SHR(a,shift)       (a)
+#define SHL(a,shift)       (a)
+#define SATURATE(x,a) (x)
+
+#define ADD16(a,b) ((a)+(b))
+#define SUB16(a,b) ((a)-(b))
+#define ADD32(a,b) ((a)+(b))
+#define SUB32(a,b) ((a)-(b))
+#define MULT16_16_16(a,b)     ((a)*(b))
+#define MULT16_16(a,b)     ((spx_word32_t)(a)*(spx_word32_t)(b))
+#define MAC16_16(c,a,b)     ((c)+(spx_word32_t)(a)*(spx_word32_t)(b))
+
+#define MULT16_32_Q11(a,b)     ((a)*(b))
+#define MULT16_32_Q13(a,b)     ((a)*(b))
+#define MULT16_32_Q14(a,b)     ((a)*(b))
+#define MULT16_32_Q15(a,b)     ((a)*(b))
+#define MULT16_32_P15(a,b)     ((a)*(b))
+
+#define MAC16_32_Q11(c,a,b)     ((c)+(a)*(b))
+#define MAC16_32_Q15(c,a,b)     ((c)+(a)*(b))
+
+#define MAC16_16_Q11(c,a,b)     ((c)+(a)*(b))
+#define MAC16_16_Q13(c,a,b)     ((c)+(a)*(b))
+#define MAC16_16_P13(c,a,b)     ((c)+(a)*(b))
+#define MULT16_16_Q11_32(a,b)     ((a)*(b))
+#define MULT16_16_Q13(a,b)     ((a)*(b))
+#define MULT16_16_Q14(a,b)     ((a)*(b))
+#define MULT16_16_Q15(a,b)     ((a)*(b))
+#define MULT16_16_P15(a,b)     ((a)*(b))
+#define MULT16_16_P13(a,b)     ((a)*(b))
+#define MULT16_16_P14(a,b)     ((a)*(b))
+
+#define DIV32_16(a,b)     (((spx_word32_t)(a))/(spx_word16_t)(b))
+#define PDIV32_16(a,b)     (((spx_word32_t)(a))/(spx_word16_t)(b))
+#define DIV32(a,b)     (((spx_word32_t)(a))/(spx_word32_t)(b))
+#define PDIV32(a,b)     (((spx_word32_t)(a))/(spx_word32_t)(b))
+
+
+#endif
+
+
+#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
+
+/* 2 on TI C5x DSP */
+#define BYTES_PER_CHAR 2
+#define BITS_PER_CHAR 16
+#define LOG2_BITS_PER_CHAR 4
+
+#else
+
+#define BYTES_PER_CHAR 1
+#define BITS_PER_CHAR 8
+#define LOG2_BITS_PER_CHAR 3
+
+#endif
+
+#endif
diff --git a/src/pulsecore/speex/fixed_generic.h b/src/pulsecore/speex/fixed_generic.h
new file mode 100644 (file)
index 0000000..547e22c
--- /dev/null
@@ -0,0 +1,106 @@
+/* Copyright (C) 2003 Jean-Marc Valin */
+/**
+   @file fixed_generic.h
+   @brief Generic fixed-point operations
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef FIXED_GENERIC_H
+#define FIXED_GENERIC_H
+
+#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
+#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
+
+#define NEG16(x) (-(x))
+#define NEG32(x) (-(x))
+#define EXTRACT16(x) ((spx_word16_t)(x))
+#define EXTEND32(x) ((spx_word32_t)(x))
+#define SHR16(a,shift) ((a) >> (shift))
+#define SHL16(a,shift) ((a) << (shift))
+#define SHR32(a,shift) ((a) >> (shift))
+#define SHL32(a,shift) ((a) << (shift))
+#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift))
+#define PSHR32(a,shift) (SHR32((a)+((1<<((shift))>>1)),shift))
+#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
+#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+
+#define SHR(a,shift) ((a) >> (shift))
+#define SHL(a,shift) ((spx_word32_t)(a) << (shift))
+#define PSHR(a,shift) (SHR((a)+((1<<((shift))>>1)),shift))
+#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+
+
+#define ADD16(a,b) ((spx_word16_t)((spx_word16_t)(a)+(spx_word16_t)(b)))
+#define SUB16(a,b) ((spx_word16_t)(a)-(spx_word16_t)(b))
+#define ADD32(a,b) ((spx_word32_t)(a)+(spx_word32_t)(b))
+#define SUB32(a,b) ((spx_word32_t)(a)-(spx_word32_t)(b))
+
+
+/* result fits in 16 bits */
+#define MULT16_16_16(a,b)     ((((spx_word16_t)(a))*((spx_word16_t)(b))))
+
+/* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */
+#define MULT16_16(a,b)     (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b)))
+
+#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
+#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12))
+#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13))
+#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14))
+
+#define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))
+#define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)))
+
+#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15))
+#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))
+#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
+
+
+#define MAC16_16_Q11(c,a,b)     (ADD32((c),SHR(MULT16_16((a),(b)),11)))
+#define MAC16_16_Q13(c,a,b)     (ADD32((c),SHR(MULT16_16((a),(b)),13)))
+#define MAC16_16_P13(c,a,b)     (ADD32((c),SHR(ADD32(4096,MULT16_16((a),(b))),13)))
+
+#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11))
+#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13))
+#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14))
+#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15))
+
+#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13))
+#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14))
+#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15))
+
+#define MUL_16_32_R15(a,bh,bl) ADD32(MULT16_16((a),(bh)), SHR(MULT16_16((a),(bl)),15))
+
+#define DIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a))/((spx_word16_t)(b))))
+#define PDIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word16_t)(b))))
+#define DIV32(a,b) (((spx_word32_t)(a))/((spx_word32_t)(b)))
+#define PDIV32(a,b) (((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word32_t)(b)))
+
+#endif
diff --git a/src/pulsecore/speex/resample.c b/src/pulsecore/speex/resample.c
new file mode 100644 (file)
index 0000000..bf1f88b
--- /dev/null
@@ -0,0 +1,1114 @@
+/* Copyright (C) 2007 Jean-Marc Valin
+
+   File: resample.c
+   Arbitrary resampling code
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+   The design goals of this code are:
+      - Very fast algorithm
+      - SIMD-friendly algorithm
+      - Low memory requirement
+      - Good *perceptual* quality (and not best SNR)
+
+   The code is working, but it's in a very early stage, so it may have
+   artifacts, noise or subliminal messages from satan. Also, the API
+   isn't stable and I can actually promise that I *will* change the API
+   some time in the future.
+
+TODO list:
+      - Variable calculation resolution depending on quality setting
+         - Single vs double in float mode
+         - 16-bit vs 32-bit (sinc only) in fixed-point mode
+      - Make sure the filter update works even when changing params
+             after only a few samples procesed
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef OUTSIDE_SPEEX
+#include <stdlib.h>
+static void *speex_alloc (int size) {return calloc(size,1);}
+static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}
+static void speex_free (void *ptr) {free(ptr);}
+#include "speex_resampler.h"
+#include "arch.h"
+#else /* OUTSIDE_SPEEX */
+
+#include "speex/speex_resampler.h"
+#include "misc.h"
+#endif /* OUTSIDE_SPEEX */
+
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.14159263
+#endif
+
+#ifdef FIXED_POINT
+#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
+#else
+#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
+#endif
+
+/*#define float double*/
+#define FILTER_SIZE 64
+#define OVERSAMPLE 8
+
+#define IMAX(a,b) ((a) > (b) ? (a) : (b))
+#define IMIN(a,b) ((a) < (b) ? (a) : (b))
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
+
+struct SpeexResamplerState_ {
+   spx_uint32_t in_rate;
+   spx_uint32_t out_rate;
+   spx_uint32_t num_rate;
+   spx_uint32_t den_rate;
+
+   int    quality;
+   spx_uint32_t nb_channels;
+   spx_uint32_t filt_len;
+   spx_uint32_t mem_alloc_size;
+   int          int_advance;
+   int          frac_advance;
+   float  cutoff;
+   spx_uint32_t oversample;
+   int          initialised;
+   int          started;
+
+   /* These are per-channel */
+   spx_int32_t  *last_sample;
+   spx_uint32_t *samp_frac_num;
+   spx_uint32_t *magic_samples;
+
+   spx_word16_t *mem;
+   spx_word16_t *sinc_table;
+   spx_uint32_t sinc_table_length;
+   resampler_basic_func resampler_ptr;
+
+   int    in_stride;
+   int    out_stride;
+} ;
+
+static double kaiser12_table[68] = {
+   0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
+   0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
+   0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
+   0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014,
+   0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490,
+   0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546,
+   0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178,
+   0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947,
+   0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058,
+   0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438,
+   0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
+   0.00001000, 0.00000000};
+/*
+static double kaiser12_table[36] = {
+   0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
+   0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
+   0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
+   0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466,
+   0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
+   0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
+*/
+static double kaiser10_table[36] = {
+   0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
+   0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
+   0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
+   0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451,
+   0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
+   0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000};
+
+static double kaiser8_table[36] = {
+   0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
+   0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
+   0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
+   0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758,
+   0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
+   0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000};
+
+static double kaiser6_table[36] = {
+   0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
+   0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
+   0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
+   0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058,
+   0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600,
+   0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000};
+
+struct FuncDef {
+   double *table;
+   int oversample;
+};
+
+static struct FuncDef _KAISER12 = {kaiser12_table, 64};
+#define KAISER12 (&_KAISER12)
+/*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
+#define KAISER12 (&_KAISER12)*/
+static struct FuncDef _KAISER10 = {kaiser10_table, 32};
+#define KAISER10 (&_KAISER10)
+static struct FuncDef _KAISER8 = {kaiser8_table, 32};
+#define KAISER8 (&_KAISER8)
+static struct FuncDef _KAISER6 = {kaiser6_table, 32};
+#define KAISER6 (&_KAISER6)
+
+struct QualityMapping {
+   int base_length;
+   int oversample;
+   float downsample_bandwidth;
+   float upsample_bandwidth;
+   struct FuncDef *window_func;
+};
+
+
+/* This table maps conversion quality to internal parameters. There are two
+   reasons that explain why the up-sampling bandwidth is larger than the
+   down-sampling bandwidth:
+   1) When up-sampling, we can assume that the spectrum is already attenuated
+      close to the Nyquist rate (from an A/D or a previous resampling filter)
+   2) Any aliasing that occurs very close to the Nyquist rate will be masked
+      by the sinusoids/noise just below the Nyquist rate (guaranteed only for
+      up-sampling).
+*/
+static const struct QualityMapping quality_map[11] = {
+   {  8,  4, 0.830f, 0.860f, KAISER6 }, /* Q0 */
+   { 16,  4, 0.850f, 0.880f, KAISER6 }, /* Q1 */
+   { 32,  4, 0.882f, 0.910f, KAISER6 }, /* Q2 */  /* 82.3% cutoff ( ~60 dB stop) 6  */
+   { 48,  8, 0.895f, 0.917f, KAISER8 }, /* Q3 */  /* 84.9% cutoff ( ~80 dB stop) 8  */
+   { 64,  8, 0.921f, 0.940f, KAISER8 }, /* Q4 */  /* 88.7% cutoff ( ~80 dB stop) 8  */
+   { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */  /* 89.1% cutoff (~100 dB stop) 10 */
+   { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */  /* 91.5% cutoff (~100 dB stop) 10 */
+   {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */  /* 93.1% cutoff (~100 dB stop) 10 */
+   {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */  /* 94.5% cutoff (~100 dB stop) 10 */
+   {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */  /* 95.5% cutoff (~100 dB stop) 10 */
+   {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */
+};
+/*8,24,40,56,80,104,128,160,200,256,320*/
+static double compute_func(float x, struct FuncDef *func)
+{
+   float y, frac;
+   double interp[4];
+   int ind;
+   y = x*func->oversample;
+   ind = (int)floor(y);
+   frac = (y-ind);
+   /* CSE with handle the repeated powers */
+   interp[3] =  -0.1666666667*frac + 0.1666666667*(frac*frac*frac);
+   interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac);
+   /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
+   interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac);
+   /* Just to make sure we don't have rounding problems */
+   interp[1] = 1.f-interp[3]-interp[2]-interp[0];
+
+   /*sum = frac*accum[1] + (1-frac)*accum[2];*/
+   return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3];
+}
+
+#if 0
+#include <stdio.h>
+int main(int argc, char **argv)
+{
+   int i;
+   for (i=0;i<256;i++)
+   {
+      printf ("%f\n", compute_func(i/256., KAISER12));
+   }
+   return 0;
+}
+#endif
+
+#ifdef FIXED_POINT
+/* The slow way of computing a sinc for the table. Should improve that some day */
+static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
+{
+   /*fprintf (stderr, "%f ", x);*/
+   float xx = x * cutoff;
+   if (fabs(x)<1e-6f)
+      return WORD2INT(32768.*cutoff);
+   else if (fabs(x) > .5f*N)
+      return 0;
+   /*FIXME: Can it really be any slower than this? */
+   return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func));
+}
+#else
+/* The slow way of computing a sinc for the table. Should improve that some day */
+static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
+{
+   /*fprintf (stderr, "%f ", x);*/
+   float xx = x * cutoff;
+   if (fabs(x)<1e-6)
+      return cutoff;
+   else if (fabs(x) > .5*N)
+      return 0;
+   /*FIXME: Can it really be any slower than this? */
+   return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func);
+}
+#endif
+
+#ifdef FIXED_POINT
+static void cubic_coef(spx_word16_t x, spx_word16_t interp[4])
+{
+   /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
+   but I know it's MMSE-optimal on a sinc */
+   spx_word16_t x2, x3;
+   x2 = MULT16_16_P15(x, x);
+   x3 = MULT16_16_P15(x, x2);
+   interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15);
+   interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1));
+   interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15);
+   /* Just to make sure we don't have rounding problems */
+   interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3];
+   if (interp[2]<32767)
+      interp[2]+=1;
+}
+#else
+static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4])
+{
+   /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
+   but I know it's MMSE-optimal on a sinc */
+   interp[0] =  -0.16667f*frac + 0.16667f*frac*frac*frac;
+   interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac;
+   /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
+   interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac;
+   /* Just to make sure we don't have rounding problems */
+   interp[2] = 1.-interp[0]-interp[1]-interp[3];
+}
+#endif
+
+static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
+{
+   int N = st->filt_len;
+   int out_sample = 0;
+   spx_word16_t *mem;
+   int last_sample = st->last_sample[channel_index];
+   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+   mem = st->mem + channel_index * st->mem_alloc_size;
+   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
+   {
+      int j;
+      spx_word32_t sum=0;
+
+      /* We already have all the filter coefficients pre-computed in the table */
+      const spx_word16_t *ptr;
+      /* Do the memory part */
+      for (j=0;last_sample-N+1+j < 0;j++)
+      {
+         sum += MULT16_16(mem[last_sample+j],st->sinc_table[samp_frac_num*st->filt_len+j]);
+      }
+
+      /* Do the new part */
+      ptr = in+st->in_stride*(last_sample-N+1+j);
+      for (;j<N;j++)
+      {
+         sum += MULT16_16(*ptr,st->sinc_table[samp_frac_num*st->filt_len+j]);
+         ptr += st->in_stride;
+      }
+
+      *out = PSHR32(sum,15);
+      out += st->out_stride;
+      out_sample++;
+      last_sample += st->int_advance;
+      samp_frac_num += st->frac_advance;
+      if (samp_frac_num >= st->den_rate)
+      {
+         samp_frac_num -= st->den_rate;
+         last_sample++;
+      }
+   }
+   st->last_sample[channel_index] = last_sample;
+   st->samp_frac_num[channel_index] = samp_frac_num;
+   return out_sample;
+}
+
+#ifdef FIXED_POINT
+#else
+/* This is the same as the previous function, except with a double-precision accumulator */
+static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
+{
+   int N = st->filt_len;
+   int out_sample = 0;
+   spx_word16_t *mem;
+   int last_sample = st->last_sample[channel_index];
+   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+   mem = st->mem + channel_index * st->mem_alloc_size;
+   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
+   {
+      int j;
+      double sum=0;
+
+      /* We already have all the filter coefficients pre-computed in the table */
+      const spx_word16_t *ptr;
+      /* Do the memory part */
+      for (j=0;last_sample-N+1+j < 0;j++)
+      {
+         sum += MULT16_16(mem[last_sample+j],(double)st->sinc_table[samp_frac_num*st->filt_len+j]);
+      }
+
+      /* Do the new part */
+      ptr = in+st->in_stride*(last_sample-N+1+j);
+      for (;j<N;j++)
+      {
+         sum += MULT16_16(*ptr,(double)st->sinc_table[samp_frac_num*st->filt_len+j]);
+         ptr += st->in_stride;
+      }
+
+      *out = sum;
+      out += st->out_stride;
+      out_sample++;
+      last_sample += st->int_advance;
+      samp_frac_num += st->frac_advance;
+      if (samp_frac_num >= st->den_rate)
+      {
+         samp_frac_num -= st->den_rate;
+         last_sample++;
+      }
+   }
+   st->last_sample[channel_index] = last_sample;
+   st->samp_frac_num[channel_index] = samp_frac_num;
+   return out_sample;
+}
+#endif
+
+static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
+{
+   int N = st->filt_len;
+   int out_sample = 0;
+   spx_word16_t *mem;
+   int last_sample = st->last_sample[channel_index];
+   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+   mem = st->mem + channel_index * st->mem_alloc_size;
+   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
+   {
+      int j;
+      spx_word32_t sum=0;
+
+      /* We need to interpolate the sinc filter */
+      spx_word32_t accum[4] = {0.f,0.f, 0.f, 0.f};
+      spx_word16_t interp[4];
+      const spx_word16_t *ptr;
+      int offset;
+      spx_word16_t frac;
+      offset = samp_frac_num*st->oversample/st->den_rate;
+#ifdef FIXED_POINT
+      frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
+#else
+      frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
+#endif
+         /* This code is written like this to make it easy to optimise with SIMD.
+      For most DSPs, it would be best to split the loops in two because most DSPs
+      have only two accumulators */
+      for (j=0;last_sample-N+1+j < 0;j++)
+      {
+         spx_word16_t curr_mem = mem[last_sample+j];
+         accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
+         accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
+         accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]);
+         accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
+      }
+      ptr = in+st->in_stride*(last_sample-N+1+j);
+      /* Do the new part */
+      for (;j<N;j++)
+      {
+         spx_word16_t curr_in = *ptr;
+         ptr += st->in_stride;
+         accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
+         accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
+         accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
+         accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
+      }
+      cubic_coef(frac, interp);
+      sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
+
+      *out = PSHR32(sum,15);
+      out += st->out_stride;
+      out_sample++;
+      last_sample += st->int_advance;
+      samp_frac_num += st->frac_advance;
+      if (samp_frac_num >= st->den_rate)
+      {
+         samp_frac_num -= st->den_rate;
+         last_sample++;
+      }
+   }
+   st->last_sample[channel_index] = last_sample;
+   st->samp_frac_num[channel_index] = samp_frac_num;
+   return out_sample;
+}
+
+#ifdef FIXED_POINT
+#else
+/* This is the same as the previous function, except with a double-precision accumulator */
+static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
+{
+   int N = st->filt_len;
+   int out_sample = 0;
+   spx_word16_t *mem;
+   int last_sample = st->last_sample[channel_index];
+   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
+   mem = st->mem + channel_index * st->mem_alloc_size;
+   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
+   {
+      int j;
+      spx_word32_t sum=0;
+
+      /* We need to interpolate the sinc filter */
+      double accum[4] = {0.f,0.f, 0.f, 0.f};
+      float interp[4];
+      const spx_word16_t *ptr;
+      float alpha = ((float)samp_frac_num)/st->den_rate;
+      int offset = samp_frac_num*st->oversample/st->den_rate;
+      float frac = alpha*st->oversample - offset;
+         /* This code is written like this to make it easy to optimise with SIMD.
+      For most DSPs, it would be best to split the loops in two because most DSPs
+      have only two accumulators */
+      for (j=0;last_sample-N+1+j < 0;j++)
+      {
+         double curr_mem = mem[last_sample+j];
+         accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
+         accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
+         accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]);
+         accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
+      }
+      ptr = in+st->in_stride*(last_sample-N+1+j);
+      /* Do the new part */
+      for (;j<N;j++)
+      {
+         double curr_in = *ptr;
+         ptr += st->in_stride;
+         accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
+         accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
+         accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
+         accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
+      }
+      cubic_coef(frac, interp);
+      sum = interp[0]*accum[0] + interp[1]*accum[1] + interp[2]*accum[2] + interp[3]*accum[3];
+
+      *out = PSHR32(sum,15);
+      out += st->out_stride;
+      out_sample++;
+      last_sample += st->int_advance;
+      samp_frac_num += st->frac_advance;
+      if (samp_frac_num >= st->den_rate)
+      {
+         samp_frac_num -= st->den_rate;
+         last_sample++;
+      }
+   }
+   st->last_sample[channel_index] = last_sample;
+   st->samp_frac_num[channel_index] = samp_frac_num;
+   return out_sample;
+}
+#endif
+
+static void update_filter(SpeexResamplerState *st)
+{
+   spx_uint32_t old_length;
+
+   old_length = st->filt_len;
+   st->oversample = quality_map[st->quality].oversample;
+   st->filt_len = quality_map[st->quality].base_length;
+
+   if (st->num_rate > st->den_rate)
+   {
+      /* down-sampling */
+      st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate;
+      /* FIXME: divide the numerator and denominator by a certain amount if they're too large */
+      st->filt_len = st->filt_len*st->num_rate / st->den_rate;
+      /* Round down to make sure we have a multiple of 4 */
+      st->filt_len &= (~0x3);
+      if (2*st->den_rate < st->num_rate)
+         st->oversample >>= 1;
+      if (4*st->den_rate < st->num_rate)
+         st->oversample >>= 1;
+      if (8*st->den_rate < st->num_rate)
+         st->oversample >>= 1;
+      if (16*st->den_rate < st->num_rate)
+         st->oversample >>= 1;
+      if (st->oversample < 1)
+         st->oversample = 1;
+   } else {
+      /* up-sampling */
+      st->cutoff = quality_map[st->quality].upsample_bandwidth;
+   }
+
+   /* Choose the resampling type that requires the least amount of memory */
+   if (st->den_rate <= st->oversample)
+   {
+      spx_uint32_t i;
+      if (!st->sinc_table)
+         st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t));
+      else if (st->sinc_table_length < st->filt_len*st->den_rate)
+      {
+         st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t));
+         st->sinc_table_length = st->filt_len*st->den_rate;
+      }
+      for (i=0;i<st->den_rate;i++)
+      {
+         spx_int32_t j;
+         for (j=0;j<st->filt_len;j++)
+         {
+            st->sinc_table[i*st->filt_len+j] = sinc(st->cutoff,((j-(spx_int32_t)st->filt_len/2+1)-((float)i)/st->den_rate), st->filt_len, quality_map[st->quality].window_func);
+         }
+      }
+#ifdef FIXED_POINT
+      st->resampler_ptr = resampler_basic_direct_single;
+#else
+      if (st->quality>8)
+         st->resampler_ptr = resampler_basic_direct_double;
+      else
+         st->resampler_ptr = resampler_basic_direct_single;
+#endif
+      /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/
+   } else {
+      spx_int32_t i;
+      if (!st->sinc_table)
+         st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
+      else if (st->sinc_table_length < st->filt_len*st->oversample+8)
+      {
+         st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
+         st->sinc_table_length = st->filt_len*st->oversample+8;
+      }
+      for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++)
+         st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func);
+#ifdef FIXED_POINT
+      st->resampler_ptr = resampler_basic_interpolate_single;
+#else
+      if (st->quality>8)
+         st->resampler_ptr = resampler_basic_interpolate_double;
+      else
+         st->resampler_ptr = resampler_basic_interpolate_single;
+#endif
+      /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/
+   }
+   st->int_advance = st->num_rate/st->den_rate;
+   st->frac_advance = st->num_rate%st->den_rate;
+
+
+   /* Here's the place where we update the filter memory to take into account
+      the change in filter length. It's probably the messiest part of the code
+      due to handling of lots of corner cases. */
+   if (!st->mem)
+   {
+      spx_uint32_t i;
+      st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
+      for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
+         st->mem[i] = 0;
+      st->mem_alloc_size = st->filt_len-1;
+      /*speex_warning("init filter");*/
+   } else if (!st->started)
+   {
+      spx_uint32_t i;
+      st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
+      for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
+         st->mem[i] = 0;
+      st->mem_alloc_size = st->filt_len-1;
+      /*speex_warning("reinit filter");*/
+   } else if (st->filt_len > old_length)
+   {
+      spx_int32_t i;
+      /* Increase the filter length */
+      /*speex_warning("increase filter size");*/
+      int old_alloc_size = st->mem_alloc_size;
+      if (st->filt_len-1 > st->mem_alloc_size)
+      {
+         st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
+         st->mem_alloc_size = st->filt_len-1;
+      }
+      for (i=st->nb_channels-1;i>=0;i--)
+      {
+         spx_int32_t j;
+         spx_uint32_t olen = old_length;
+         /*if (st->magic_samples[i])*/
+         {
+            /* Try and remove the magic samples as if nothing had happened */
+
+            /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
+            olen = old_length + 2*st->magic_samples[i];
+            for (j=old_length-2+st->magic_samples[i];j>=0;j--)
+               st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j];
+            for (j=0;j<st->magic_samples[i];j++)
+               st->mem[i*st->mem_alloc_size+j] = 0;
+            st->magic_samples[i] = 0;
+         }
+         if (st->filt_len > olen)
+         {
+            /* If the new filter length is still bigger than the "augmented" length */
+            /* Copy data going backward */
+            for (j=0;j<olen-1;j++)
+               st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)];
+            /* Then put zeros for lack of anything better */
+            for (;j<st->filt_len-1;j++)
+               st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0;
+            /* Adjust last_sample */
+            st->last_sample[i] += (st->filt_len - olen)/2;
+         } else {
+            /* Put back some of the magic! */
+            st->magic_samples[i] = (olen - st->filt_len)/2;
+            for (j=0;j<st->filt_len-1+st->magic_samples[i];j++)
+               st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
+         }
+      }
+   } else if (st->filt_len < old_length)
+   {
+      spx_uint32_t i;
+      /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
+         samples so they can be used directly as input the next time(s) */
+      for (i=0;i<st->nb_channels;i++)
+      {
+         spx_uint32_t j;
+         spx_uint32_t old_magic = st->magic_samples[i];
+         st->magic_samples[i] = (old_length - st->filt_len)/2;
+         /* We must copy some of the memory that's no longer used */
+         /* Copy data going backward */
+         for (j=0;j<st->filt_len-1+st->magic_samples[i]+old_magic;j++)
+            st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
+         st->magic_samples[i] += old_magic;
+      }
+   }
+
+}
+
+SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
+{
+   return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
+}
+
+SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
+{
+   spx_uint32_t i;
+   SpeexResamplerState *st;
+   if (quality > 10 || quality < 0)
+   {
+      if (err)
+         *err = RESAMPLER_ERR_INVALID_ARG;
+      return NULL;
+   }
+   st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState));
+   st->initialised = 0;
+   st->started = 0;
+   st->in_rate = 0;
+   st->out_rate = 0;
+   st->num_rate = 0;
+   st->den_rate = 0;
+   st->quality = -1;
+   st->sinc_table_length = 0;
+   st->mem_alloc_size = 0;
+   st->filt_len = 0;
+   st->mem = 0;
+   st->resampler_ptr = 0;
+
+   st->cutoff = 1.f;
+   st->nb_channels = nb_channels;
+   st->in_stride = 1;
+   st->out_stride = 1;
+
+   /* Per channel data */
+   st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int));
+   st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
+   st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
+   for (i=0;i<nb_channels;i++)
+   {
+      st->last_sample[i] = 0;
+      st->magic_samples[i] = 0;
+      st->samp_frac_num[i] = 0;
+   }
+
+   speex_resampler_set_quality(st, quality);
+   speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);
+
+
+   update_filter(st);
+
+   st->initialised = 1;
+   if (err)
+      *err = RESAMPLER_ERR_SUCCESS;
+
+   return st;
+}
+
+void speex_resampler_destroy(SpeexResamplerState *st)
+{
+   speex_free(st->mem);
+   speex_free(st->sinc_table);
+   speex_free(st->last_sample);
+   speex_free(st->magic_samples);
+   speex_free(st->samp_frac_num);
+   speex_free(st);
+}
+
+
+
+static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
+{
+   int j=0;
+   int N = st->filt_len;
+   int out_sample = 0;
+   spx_word16_t *mem;
+   spx_uint32_t tmp_out_len = 0;
+   mem = st->mem + channel_index * st->mem_alloc_size;
+   st->started = 1;
+
+   /* Handle the case where we have samples left from a reduction in filter length */
+   if (st->magic_samples[channel_index])
+   {
+      int istride_save;
+      spx_uint32_t tmp_in_len;
+      spx_uint32_t tmp_magic;
+
+      istride_save = st->in_stride;
+      tmp_in_len = st->magic_samples[channel_index];
+      tmp_out_len = *out_len;
+      /* magic_samples needs to be set to zero to avoid infinite recursion */
+      tmp_magic = st->magic_samples[channel_index];
+      st->magic_samples[channel_index] = 0;
+      st->in_stride = 1;
+      speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len);
+      st->in_stride = istride_save;
+      /*speex_warning_int("extra samples:", tmp_out_len);*/
+      /* If we couldn't process all "magic" input samples, save the rest for next time */
+      if (tmp_in_len < tmp_magic)
+      {
+         spx_uint32_t i;
+         st->magic_samples[channel_index] = tmp_magic-tmp_in_len;
+         for (i=0;i<st->magic_samples[channel_index];i++)
+            mem[N-1+i]=mem[N-1+i+tmp_in_len];
+      }
+      out += tmp_out_len*st->out_stride;
+      *out_len -= tmp_out_len;
+   }
+
+   /* Call the right resampler through the function ptr */
+   out_sample = st->resampler_ptr(st, channel_index, in, in_len, out, out_len);
+
+   if (st->last_sample[channel_index] < (spx_int32_t)*in_len)
+      *in_len = st->last_sample[channel_index];
+   *out_len = out_sample+tmp_out_len;
+   st->last_sample[channel_index] -= *in_len;
+
+   for (j=0;j<N-1-(spx_int32_t)*in_len;j++)
+      mem[j] = mem[j+*in_len];
+   for (;j<N-1;j++)
+      mem[j] = in[st->in_stride*(j+*in_len-N+1)];
+
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+#define FIXED_STACK_ALLOC 1024
+
+#ifdef FIXED_POINT
+int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
+{
+   spx_uint32_t i;
+   int istride_save, ostride_save;
+#ifdef VAR_ARRAYS
+   spx_word16_t x[*in_len];
+   spx_word16_t y[*out_len];
+   /*VARDECL(spx_word16_t *x);
+   VARDECL(spx_word16_t *y);
+   ALLOC(x, *in_len, spx_word16_t);
+   ALLOC(y, *out_len, spx_word16_t);*/
+   istride_save = st->in_stride;
+   ostride_save = st->out_stride;
+   for (i=0;i<*in_len;i++)
+      x[i] = WORD2INT(in[i*st->in_stride]);
+   st->in_stride = st->out_stride = 1;
+   speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
+   st->in_stride = istride_save;
+   st->out_stride = ostride_save;
+   for (i=0;i<*out_len;i++)
+      out[i*st->out_stride] = y[i];
+#else
+   spx_word16_t x[FIXED_STACK_ALLOC];
+   spx_word16_t y[FIXED_STACK_ALLOC];
+   spx_uint32_t ilen=*in_len, olen=*out_len;
+   istride_save = st->in_stride;
+   ostride_save = st->out_stride;
+   while (ilen && olen)
+   {
+      spx_uint32_t ichunk, ochunk;
+      ichunk = ilen;
+      ochunk = olen;
+      if (ichunk>FIXED_STACK_ALLOC)
+         ichunk=FIXED_STACK_ALLOC;
+      if (ochunk>FIXED_STACK_ALLOC)
+         ochunk=FIXED_STACK_ALLOC;
+      for (i=0;i<ichunk;i++)
+         x[i] = WORD2INT(in[i*st->in_stride]);
+      st->in_stride = st->out_stride = 1;
+      speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk);
+      st->in_stride = istride_save;
+      st->out_stride = ostride_save;
+      for (i=0;i<ochunk;i++)
+         out[i*st->out_stride] = y[i];
+      out += ochunk;
+      in += ichunk;
+      ilen -= ichunk;
+      olen -= ochunk;
+   }
+   *in_len -= ilen;
+   *out_len -= olen;
+#endif
+   return RESAMPLER_ERR_SUCCESS;
+}
+int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
+{
+   return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
+}
+#else
+int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
+{
+   return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
+}
+int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
+{
+   spx_uint32_t i;
+   int istride_save, ostride_save;
+#ifdef VAR_ARRAYS
+   spx_word16_t x[*in_len];
+   spx_word16_t y[*out_len];
+   /*VARDECL(spx_word16_t *x);
+   VARDECL(spx_word16_t *y);
+   ALLOC(x, *in_len, spx_word16_t);
+   ALLOC(y, *out_len, spx_word16_t);*/
+   istride_save = st->in_stride;
+   ostride_save = st->out_stride;
+   for (i=0;i<*in_len;i++)
+      x[i] = in[i*st->in_stride];
+   st->in_stride = st->out_stride = 1;
+   speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
+   st->in_stride = istride_save;
+   st->out_stride = ostride_save;
+   for (i=0;i<*out_len;i++)
+      out[i*st->out_stride] = WORD2INT(y[i]);
+#else
+   spx_word16_t x[FIXED_STACK_ALLOC];
+   spx_word16_t y[FIXED_STACK_ALLOC];
+   spx_uint32_t ilen=*in_len, olen=*out_len;
+   istride_save = st->in_stride;
+   ostride_save = st->out_stride;
+   while (ilen && olen)
+   {
+      spx_uint32_t ichunk, ochunk;
+      ichunk = ilen;
+      ochunk = olen;
+      if (ichunk>FIXED_STACK_ALLOC)
+         ichunk=FIXED_STACK_ALLOC;
+      if (ochunk>FIXED_STACK_ALLOC)
+         ochunk=FIXED_STACK_ALLOC;
+      for (i=0;i<ichunk;i++)
+         x[i] = in[i*st->in_stride];
+      st->in_stride = st->out_stride = 1;
+      speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk);
+      st->in_stride = istride_save;
+      st->out_stride = ostride_save;
+      for (i=0;i<ochunk;i++)
+         out[i*st->out_stride] = WORD2INT(y[i]);
+      out += ochunk;
+      in += ichunk;
+      ilen -= ichunk;
+      olen -= ochunk;
+   }
+   *in_len -= ilen;
+   *out_len -= olen;
+#endif
+   return RESAMPLER_ERR_SUCCESS;
+}
+#endif
+
+int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
+{
+   spx_uint32_t i;
+   int istride_save, ostride_save;
+   spx_uint32_t bak_len = *out_len;
+   istride_save = st->in_stride;
+   ostride_save = st->out_stride;
+   st->in_stride = st->out_stride = st->nb_channels;
+   for (i=0;i<st->nb_channels;i++)
+   {
+      *out_len = bak_len;
+      speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
+   }
+   st->in_stride = istride_save;
+   st->out_stride = ostride_save;
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+
+int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
+{
+   spx_uint32_t i;
+   int istride_save, ostride_save;
+   spx_uint32_t bak_len = *out_len;
+   istride_save = st->in_stride;
+   ostride_save = st->out_stride;
+   st->in_stride = st->out_stride = st->nb_channels;
+   for (i=0;i<st->nb_channels;i++)
+   {
+      *out_len = bak_len;
+      speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
+   }
+   st->in_stride = istride_save;
+   st->out_stride = ostride_save;
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
+{
+   return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
+}
+
+void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
+{
+   *in_rate = st->in_rate;
+   *out_rate = st->out_rate;
+}
+
+int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
+{
+   spx_uint32_t fact;
+   spx_uint32_t old_den;
+   spx_uint32_t i;
+   if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den)
+      return RESAMPLER_ERR_SUCCESS;
+
+   old_den = st->den_rate;
+   st->in_rate = in_rate;
+   st->out_rate = out_rate;
+   st->num_rate = ratio_num;
+   st->den_rate = ratio_den;
+   /* FIXME: This is terribly inefficient, but who cares (at least for now)? */
+   for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++)
+   {
+      while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0))
+      {
+         st->num_rate /= fact;
+         st->den_rate /= fact;
+      }
+   }
+
+   if (old_den > 0)
+   {
+      for (i=0;i<st->nb_channels;i++)
+      {
+         st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den;
+         /* Safety net */
+         if (st->samp_frac_num[i] >= st->den_rate)
+            st->samp_frac_num[i] = st->den_rate-1;
+      }
+   }
+
+   if (st->initialised)
+      update_filter(st);
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
+{
+   *ratio_num = st->num_rate;
+   *ratio_den = st->den_rate;
+}
+
+int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
+{
+   if (quality > 10 || quality < 0)
+      return RESAMPLER_ERR_INVALID_ARG;
+   if (st->quality == quality)
+      return RESAMPLER_ERR_SUCCESS;
+   st->quality = quality;
+   if (st->initialised)
+      update_filter(st);
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
+{
+   *quality = st->quality;
+}
+
+void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
+{
+   st->in_stride = stride;
+}
+
+void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
+{
+   *stride = st->in_stride;
+}
+
+void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
+{
+   st->out_stride = stride;
+}
+
+void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
+{
+   *stride = st->out_stride;
+}
+
+int speex_resampler_skip_zeros(SpeexResamplerState *st)
+{
+   spx_uint32_t i;
+   for (i=0;i<st->nb_channels;i++)
+      st->last_sample[i] = st->filt_len/2;
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+int speex_resampler_reset_mem(SpeexResamplerState *st)
+{
+   spx_uint32_t i;
+   for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
+      st->mem[i] = 0;
+   return RESAMPLER_ERR_SUCCESS;
+}
+
+const char *speex_resampler_strerror(int err)
+{
+   switch (err)
+   {
+      case RESAMPLER_ERR_SUCCESS:
+         return "Success.";
+      case RESAMPLER_ERR_ALLOC_FAILED:
+         return "Memory allocation failed.";
+      case RESAMPLER_ERR_BAD_STATE:
+         return "Bad resampler state.";
+      case RESAMPLER_ERR_INVALID_ARG:
+         return "Invalid argument.";
+      case RESAMPLER_ERR_PTR_OVERLAP:
+         return "Input and output buffers overlap.";
+      default:
+         return "Unknown error. Bad error code or strange version mismatch.";
+   }
+}
diff --git a/src/pulsecore/speex/speex_resampler.h b/src/pulsecore/speex/speex_resampler.h
new file mode 100644 (file)
index 0000000..8629eeb
--- /dev/null
@@ -0,0 +1,328 @@
+/* Copyright (C) 2007 Jean-Marc Valin
+
+   File: speex_resampler.h
+   Resampling code
+
+   The design goals of this code are:
+      - Very fast algorithm
+      - Low memory requirement
+      - Good *perceptual* quality (and not best SNR)
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef SPEEX_RESAMPLER_H
+#define SPEEX_RESAMPLER_H
+
+#ifdef OUTSIDE_SPEEX
+
+/********* WARNING: MENTAL SANITY ENDS HERE *************/
+
+/* If the resampler is defined outside of Speex, we change the symbol names so that
+   there won't be any clash if linking with Speex later on. */
+
+/* #define RANDOM_PREFIX your software name here */
+#ifndef RANDOM_PREFIX
+#error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes"
+#endif
+
+#define CAT_PREFIX2(a,b) a ## b
+#define CAT_PREFIX(a,b) CAT_PREFIX2(a, b)
+
+#define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init)
+#define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac)
+#define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy)
+#define speex_resampler_process_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_float)
+#define speex_resampler_process_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_int)
+#define speex_resampler_process_interleaved_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_float)
+#define speex_resampler_process_interleaved_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_int)
+#define speex_resampler_set_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate)
+#define speex_resampler_get_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_get_rate)
+#define speex_resampler_set_rate_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate_frac)
+#define speex_resampler_get_ratio CAT_PREFIX(RANDOM_PREFIX,_resampler_get_ratio)
+#define speex_resampler_set_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_set_quality)
+#define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality)
+#define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride)
+#define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride)
+#define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride)
+#define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride)
+#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros)
+#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem)
+#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror)
+
+#define spx_int16_t short
+#define spx_int32_t int
+#define spx_uint16_t unsigned short
+#define spx_uint32_t unsigned int
+
+#else /* OUTSIDE_SPEEX */
+
+#include "speex/speex_types.h"
+
+#endif /* OUTSIDE_SPEEX */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SPEEX_RESAMPLER_QUALITY_MAX 10
+#define SPEEX_RESAMPLER_QUALITY_MIN 0
+#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4
+#define SPEEX_RESAMPLER_QUALITY_VOIP 3
+#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5
+
+enum {
+   RESAMPLER_ERR_SUCCESS         = 0,
+   RESAMPLER_ERR_ALLOC_FAILED    = 1,
+   RESAMPLER_ERR_BAD_STATE       = 2,
+   RESAMPLER_ERR_INVALID_ARG     = 3,
+   RESAMPLER_ERR_PTR_OVERLAP     = 4,
+
+   RESAMPLER_ERR_MAX_ERROR
+};
+
+struct SpeexResamplerState_;
+typedef struct SpeexResamplerState_ SpeexResamplerState;
+
+/** Create a new resampler with integer input and output rates.
+ * @param nb_channels Number of channels to be processed
+ * @param in_rate Input sampling rate (integer number of Hz).
+ * @param out_rate Output sampling rate (integer number of Hz).
+ * @param quality Resampling quality between 0 and 10, where 0 has poor quality
+ * and 10 has very high quality.
+ * @return Newly created resampler state
+ * @retval NULL Error: not enough memory
+ */
+SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels,
+                                          spx_uint32_t in_rate,
+                                          spx_uint32_t out_rate,
+                                          int quality,
+                                          int *err);
+
+/** Create a new resampler with fractional input/output rates. The sampling
+ * rate ratio is an arbitrary rational number with both the numerator and
+ * denominator being 32-bit integers.
+ * @param nb_channels Number of channels to be processed
+ * @param ratio_num Numerator of the sampling rate ratio
+ * @param ratio_den Denominator of the sampling rate ratio
+ * @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
+ * @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
+ * @param quality Resampling quality between 0 and 10, where 0 has poor quality
+ * and 10 has very high quality.
+ * @return Newly created resampler state
+ * @retval NULL Error: not enough memory
+ */
+SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
+                                               spx_uint32_t ratio_num,
+                                               spx_uint32_t ratio_den,
+                                               spx_uint32_t in_rate,
+                                               spx_uint32_t out_rate,
+                                               int quality,
+                                               int *err);
+
+/** Destroy a resampler state.
+ * @param st Resampler state
+ */
+void speex_resampler_destroy(SpeexResamplerState *st);
+
+/** Resample a float array. The input and output buffers must *not* overlap.
+ * @param st Resampler state
+ * @param channel_index Index of the channel to process for the multi-channel
+ * base (0 otherwise)
+ * @param in Input buffer
+ * @param in_len Number of input samples in the input buffer. Returns the
+ * number of samples processed
+ * @param out Output buffer
+ * @param out_len Size of the output buffer. Returns the number of samples written
+ */
+int speex_resampler_process_float(SpeexResamplerState *st,
+                                   spx_uint32_t channel_index,
+                                   const float *in,
+                                   spx_uint32_t *in_len,
+                                   float *out,
+                                   spx_uint32_t *out_len);
+
+/** Resample an int array. The input and output buffers must *not* overlap.
+ * @param st Resampler state
+ * @param channel_index Index of the channel to process for the multi-channel
+ * base (0 otherwise)
+ * @param in Input buffer
+ * @param in_len Number of input samples in the input buffer. Returns the number
+ * of samples processed
+ * @param out Output buffer
+ * @param out_len Size of the output buffer. Returns the number of samples written
+ */
+int speex_resampler_process_int(SpeexResamplerState *st,
+                                 spx_uint32_t channel_index,
+                                 const spx_int16_t *in,
+                                 spx_uint32_t *in_len,
+                                 spx_int16_t *out,
+                                 spx_uint32_t *out_len);
+
+/** Resample an interleaved float array. The input and output buffers must *not* overlap.
+ * @param st Resampler state
+ * @param in Input buffer
+ * @param in_len Number of input samples in the input buffer. Returns the number
+ * of samples processed. This is all per-channel.
+ * @param out Output buffer
+ * @param out_len Size of the output buffer. Returns the number of samples written.
+ * This is all per-channel.
+ */
+int speex_resampler_process_interleaved_float(SpeexResamplerState *st,
+                                               const float *in,
+                                               spx_uint32_t *in_len,
+                                               float *out,
+                                               spx_uint32_t *out_len);
+
+/** Resample an interleaved int array. The input and output buffers must *not* overlap.
+ * @param st Resampler state
+ * @param in Input buffer
+ * @param in_len Number of input samples in the input buffer. Returns the number
+ * of samples processed. This is all per-channel.
+ * @param out Output buffer
+ * @param out_len Size of the output buffer. Returns the number of samples written.
+ * This is all per-channel.
+ */
+int speex_resampler_process_interleaved_int(SpeexResamplerState *st,
+                                             const spx_int16_t *in,
+                                             spx_uint32_t *in_len,
+                                             spx_int16_t *out,
+                                             spx_uint32_t *out_len);
+
+/** Set (change) the input/output sampling rates (integer value).
+ * @param st Resampler state
+ * @param in_rate Input sampling rate (integer number of Hz).
+ * @param out_rate Output sampling rate (integer number of Hz).
+ */
+int speex_resampler_set_rate(SpeexResamplerState *st,
+                              spx_uint32_t in_rate,
+                              spx_uint32_t out_rate);
+
+/** Get the current input/output sampling rates (integer value).
+ * @param st Resampler state
+ * @param in_rate Input sampling rate (integer number of Hz) copied.
+ * @param out_rate Output sampling rate (integer number of Hz) copied.
+ */
+void speex_resampler_get_rate(SpeexResamplerState *st,
+                              spx_uint32_t *in_rate,
+                              spx_uint32_t *out_rate);
+
+/** Set (change) the input/output sampling rates and resampling ratio
+ * (fractional values in Hz supported).
+ * @param st Resampler state
+ * @param ratio_num Numerator of the sampling rate ratio
+ * @param ratio_den Denominator of the sampling rate ratio
+ * @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
+ * @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
+ */
+int speex_resampler_set_rate_frac(SpeexResamplerState *st,
+                                   spx_uint32_t ratio_num,
+                                   spx_uint32_t ratio_den,
+                                   spx_uint32_t in_rate,
+                                   spx_uint32_t out_rate);
+
+/** Get the current resampling ratio. This will be reduced to the least
+ * common denominator.
+ * @param st Resampler state
+ * @param ratio_num Numerator of the sampling rate ratio copied
+ * @param ratio_den Denominator of the sampling rate ratio copied
+ */
+void speex_resampler_get_ratio(SpeexResamplerState *st,
+                               spx_uint32_t *ratio_num,
+                               spx_uint32_t *ratio_den);
+
+/** Set (change) the conversion quality.
+ * @param st Resampler state
+ * @param quality Resampling quality between 0 and 10, where 0 has poor
+ * quality and 10 has very high quality.
+ */
+int speex_resampler_set_quality(SpeexResamplerState *st,
+                                 int quality);
+
+/** Get the conversion quality.
+ * @param st Resampler state
+ * @param quality Resampling quality between 0 and 10, where 0 has poor
+ * quality and 10 has very high quality.
+ */
+void speex_resampler_get_quality(SpeexResamplerState *st,
+                                 int *quality);
+
+/** Set (change) the input stride.
+ * @param st Resampler state
+ * @param stride Input stride
+ */
+void speex_resampler_set_input_stride(SpeexResamplerState *st,
+                                      spx_uint32_t stride);
+
+/** Get the input stride.
+ * @param st Resampler state
+ * @param stride Input stride copied
+ */
+void speex_resampler_get_input_stride(SpeexResamplerState *st,
+                                      spx_uint32_t *stride);
+
+/** Set (change) the output stride.
+ * @param st Resampler state
+ * @param stride Output stride
+ */
+void speex_resampler_set_output_stride(SpeexResamplerState *st,
+                                      spx_uint32_t stride);
+
+/** Get the output stride.
+ * @param st Resampler state copied
+ * @param stride Output stride
+ */
+void speex_resampler_get_output_stride(SpeexResamplerState *st,
+                                      spx_uint32_t *stride);
+
+/** Make sure that the first samples to go out of the resamplers don't have
+ * leading zeros. This is only useful before starting to use a newly created
+ * resampler. It is recommended to use that when resampling an audio file, as
+ * it will generate a file with the same length. For real-time processing,
+ * it is probably easier not to use this call (so that the output duration
+ * is the same for the first frame).
+ * @param st Resampler state
+ */
+int speex_resampler_skip_zeros(SpeexResamplerState *st);
+
+/** Reset a resampler so a new (unrelated) stream can be processed.
+ * @param st Resampler state
+ */
+int speex_resampler_reset_mem(SpeexResamplerState *st);
+
+/** Returns the English meaning for an error code
+ * @param err Error code
+ * @return English string
+ */
+const char *speex_resampler_strerror(int err);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/pulsecore/speexwrap.h b/src/pulsecore/speexwrap.h
new file mode 100644 (file)
index 0000000..c0d5c0c
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef foopulsespeexwraphfoo
+#define foopulsespeexwraphfoo
+
+/* $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.
+***/
+
+/* We define a minimal version of speex_resampler.h however define one
+ * version for fixed and another one for float. Yes, somewhat ugly */
+
+#define spx_int16_t short
+#define spx_int32_t int
+#define spx_uint16_t unsigned short
+#define spx_uint32_t unsigned int
+
+typedef struct SpeexResamplerState_ SpeexResamplerState;
+
+SpeexResamplerState *paspfx_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate,  int quality, int *err);
+void paspfx_resampler_destroy(SpeexResamplerState *st);
+int paspfx_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in,  spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len);
+int paspfx_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate);
+
+SpeexResamplerState *paspfl_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate,  int quality, int *err);
+void paspfl_resampler_destroy(SpeexResamplerState *st);
+int paspfl_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in,  spx_uint32_t *in_len, float *out, spx_uint32_t *out_len);
+int paspfl_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate);
+
+#endif
index a3ddc1144c3cae330722668ab68418cdd072d59c..7c576c672d4685eeeb3b010652bc82ead350640d 100644 (file)
 
 #include <sys/types.h>
 #include <stdlib.h>
-#include <assert.h>
 #include <string.h>
 #include <stdarg.h>
 #include <stdio.h>
 
 #include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
 
 #include "strbuf.h"
 
@@ -42,7 +42,7 @@ struct chunk {
     size_t length;
 };
 
-#define CHUNK_TO_TEXT(c) ((char*) (c) + sizeof(struct chunk))
+#define CHUNK_TO_TEXT(c) ((char*) (c) + PA_ALIGN(sizeof(struct chunk)))
 
 struct pa_strbuf {
     size_t length;
@@ -50,14 +50,18 @@ struct pa_strbuf {
 };
 
 pa_strbuf *pa_strbuf_new(void) {
-    pa_strbuf *sb = pa_xmalloc(sizeof(pa_strbuf));
+    pa_strbuf *sb;
+
+    sb = pa_xnew(pa_strbuf, 1);
     sb->length = 0;
     sb->head = sb->tail = NULL;
+
     return sb;
 }
 
 void pa_strbuf_free(pa_strbuf *sb) {
-    assert(sb);
+    pa_assert(sb);
+
     while (sb->head) {
         struct chunk *c = sb->head;
         sb->head = sb->head->next;
@@ -72,12 +76,13 @@ void pa_strbuf_free(pa_strbuf *sb) {
 char *pa_strbuf_tostring(pa_strbuf *sb) {
     char *t, *e;
     struct chunk *c;
-    assert(sb);
 
-    e = t = pa_xmalloc(sb->length+1);
+    pa_assert(sb);
+
+    e = t = pa_xnew(char, sb->length+1);
 
     for (c = sb->head; c; c = c->next) {
-        assert((size_t) (e-t) <= sb->length);
+        pa_assert((size_t) (e-t) <= sb->length);
         memcpy(e, CHUNK_TO_TEXT(c), c->length);
         e += c->length;
     }
@@ -85,7 +90,7 @@ char *pa_strbuf_tostring(pa_strbuf *sb) {
     /* Trailing NUL */
     *e = 0;
 
-    assert(e == t+sb->length);
+    pa_assert(e == t+sb->length);
 
     return t;
 }
@@ -93,27 +98,33 @@ char *pa_strbuf_tostring(pa_strbuf *sb) {
 /* Combination of pa_strbuf_free() and pa_strbuf_tostring() */
 char *pa_strbuf_tostring_free(pa_strbuf *sb) {
     char *t;
-    assert(sb);
+
+    pa_assert(sb);
     t = pa_strbuf_tostring(sb);
     pa_strbuf_free(sb);
+
     return t;
 }
 
 /* Append a string to the string buffer */
 void pa_strbuf_puts(pa_strbuf *sb, const char *t) {
-    assert(sb && t);
+
+    pa_assert(sb);
+    pa_assert(t);
+
     pa_strbuf_putsn(sb, t, strlen(t));
 }
 
 /* Append a new chunk to the linked list */
 static void append(pa_strbuf *sb, struct chunk *c) {
-    assert(sb && c);
+    pa_assert(sb);
+    pa_assert(c);
 
     if (sb->tail) {
-        assert(sb->head);
+        pa_assert(sb->head);
         sb->tail->next = c;
     } else {
-        assert(!sb->head);
+        pa_assert(!sb->head);
         sb->head = c;
     }
 
@@ -125,12 +136,14 @@ static void append(pa_strbuf *sb, struct chunk *c) {
 /* Append up to l bytes of a string to the string buffer */
 void pa_strbuf_putsn(pa_strbuf *sb, const char *t, size_t l) {
     struct chunk *c;
-    assert(sb && t);
+
+    pa_assert(sb);
+    pa_assert(t);
 
     if (!l)
        return;
 
-    c = pa_xmalloc(sizeof(struct chunk)+l);
+    c = pa_xmalloc(PA_ALIGN(sizeof(struct chunk)) + l);
     c->length = l;
     memcpy(CHUNK_TO_TEXT(c), t, l);
 
@@ -143,16 +156,18 @@ int pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) {
     int size = 100;
     struct chunk *c = NULL;
 
-    assert(sb);
+    pa_assert(sb);
+    pa_assert(format);
 
     for(;;) {
         va_list ap;
         int r;
 
-        c = pa_xrealloc(c, sizeof(struct chunk)+size);
+        c = pa_xrealloc(c, PA_ALIGN(sizeof(struct chunk)) + size);
 
         va_start(ap, format);
         r = vsnprintf(CHUNK_TO_TEXT(c), size, format, ap);
+        CHUNK_TO_TEXT(c)[size-1] = 0;
         va_end(ap);
 
         if (r > -1 && r < size) {
index 955b78e419613394b0433218322af4cb4153517b..792af0ff897121cf1d797a23092ba13085046cec 100644 (file)
 #endif
 
 #include <string.h>
-#include <assert.h>
 
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/strbuf.h>
+#include <pulsecore/macro.h>
 #include <pulsecore/core-util.h>
 
 #include "strlist.h"
 
 struct pa_strlist {
     pa_strlist *next;
-    char *str;
 };
 
+#define ITEM_TO_TEXT(c) ((char*) (c) + PA_ALIGN(sizeof(pa_strlist)))
+
 pa_strlist* pa_strlist_prepend(pa_strlist *l, const char *s) {
     pa_strlist *n;
-    assert(s);
-    n = pa_xmalloc(sizeof(pa_strlist));
-    n->str = pa_xstrdup(s);
+    size_t size;
+
+    pa_assert(s);
+    size = strlen(s);
+    n = pa_xmalloc(PA_ALIGN(sizeof(pa_strlist)) + size + 1);
+    memcpy(ITEM_TO_TEXT(n), s, size + 1);
     n->next = l;
+
     return  n;
 }
 
@@ -58,7 +63,7 @@ char *pa_strlist_tostring(pa_strlist *l) {
         if (!first)
             pa_strbuf_puts(b, " ");
         first = 0;
-        pa_strbuf_puts(b, l->str);
+        pa_strbuf_puts(b, ITEM_TO_TEXT(l));
     }
 
     return pa_strbuf_tostring_free(b);
@@ -66,19 +71,20 @@ char *pa_strlist_tostring(pa_strlist *l) {
 
 pa_strlist* pa_strlist_remove(pa_strlist *l, const char *s) {
     pa_strlist *ret = l, *prev = NULL;
-    assert(l && s);
+
+    pa_assert(l);
+    pa_assert(s);
 
     while (l) {
-        if (!strcmp(l->str, s)) {
+        if (!strcmp(ITEM_TO_TEXT(l), s)) {
             pa_strlist *n = l->next;
 
             if (!prev) {
-                assert(ret == l);
+                pa_assert(ret == l);
                 ret = n;
             } else
                 prev->next = n;
 
-            pa_xfree(l->str);
             pa_xfree(l);
 
             l = n;
@@ -96,22 +102,21 @@ void pa_strlist_free(pa_strlist *l) {
     while (l) {
         pa_strlist *c = l;
         l = l->next;
-
-        pa_xfree(c->str);
         pa_xfree(c);
     }
 }
 
 pa_strlist* pa_strlist_pop(pa_strlist *l, char **s) {
     pa_strlist *r;
-    assert(s);
+
+    pa_assert(s);
 
     if (!l) {
         *s = NULL;
         return NULL;
     }
 
-    *s = l->str;
+    *s = pa_xstrdup(ITEM_TO_TEXT(l));
     r = l->next;
     pa_xfree(l);
     return r;
@@ -124,10 +129,12 @@ pa_strlist* pa_strlist_parse(const char *s) {
 
     while ((r = pa_split_spaces(s, &state))) {
         pa_strlist *n;
+        size_t size = strlen(r);
 
-        n = pa_xmalloc(sizeof(pa_strlist));
-        n->str = r;
+        n = pa_xmalloc(PA_ALIGN(sizeof(pa_strlist)) + size + 1);
         n->next = NULL;
+        memcpy(ITEM_TO_TEXT(n), r, size+1);
+        pa_xfree(r);
 
         if (p)
             p->next = n;
index ac7ae1ab8b514634f1fce5305b53da33498d105d..556fe80676dc8a836ac2c02c03a68b1ca3293afe 100644 (file)
 #include <string.h>
 #include <unistd.h>
 #include <sys/time.h>
-#include <assert.h>
 #include <stdarg.h>
 
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
 
-#include "winsock.h"
-
 #include <pulse/xmalloc.h>
 
-#include "tagstruct.h"
+#include <pulsecore/winsock.h>
+#include <pulsecore/macro.h>
 
+#include "tagstruct.h"
 
 struct pa_tagstruct {
     uint8_t *data;
@@ -54,18 +53,20 @@ struct pa_tagstruct {
 pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) {
     pa_tagstruct*t;
 
-    assert(!data || (data && length));
+    pa_assert(!data || (data && length));
 
-    t = pa_xmalloc(sizeof(pa_tagstruct));
+    t = pa_xnew(pa_tagstruct, 1);
     t->data = (uint8_t*) data;
     t->allocated = t->length = data ? length : 0;
     t->rindex = 0;
     t->dynamic = !data;
+
     return t;
 }
 
 void pa_tagstruct_free(pa_tagstruct*t) {
-    assert(t);
+    pa_assert(t);
+
     if (t->dynamic)
         pa_xfree(t->data);
     pa_xfree(t);
@@ -73,7 +74,11 @@ void pa_tagstruct_free(pa_tagstruct*t) {
 
 uint8_t* pa_tagstruct_free_data(pa_tagstruct*t, size_t *l) {
     uint8_t *p;
-    assert(t && t->dynamic && l);
+
+    pa_assert(t);
+    pa_assert(t->dynamic);
+    pa_assert(l);
+
     p = t->data;
     *l = t->length;
     pa_xfree(t);
@@ -81,8 +86,8 @@ uint8_t* pa_tagstruct_free_data(pa_tagstruct*t, size_t *l) {
 }
 
 static void extend(pa_tagstruct*t, size_t l) {
-    assert(t);
-    assert(t->dynamic);
+    pa_assert(t);
+    pa_assert(t->dynamic);
 
     if (t->length+l <= t->allocated)
         return;
@@ -92,7 +97,8 @@ static void extend(pa_tagstruct*t, size_t l) {
 
 void pa_tagstruct_puts(pa_tagstruct*t, const char *s) {
     size_t l;
-    assert(t);
+    pa_assert(t);
+
     if (s) {
         l = strlen(s)+2;
         extend(t, l);
@@ -107,7 +113,8 @@ void pa_tagstruct_puts(pa_tagstruct*t, const char *s) {
 }
 
 void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i) {
-    assert(t);
+    pa_assert(t);
+
     extend(t, 5);
     t->data[t->length] = PA_TAG_U32;
     i = htonl(i);
@@ -116,7 +123,8 @@ void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i) {
 }
 
 void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c) {
-    assert(t);
+    pa_assert(t);
+
     extend(t, 2);
     t->data[t->length] = PA_TAG_U8;
     *(t->data+t->length+1) = c;
@@ -125,7 +133,10 @@ void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c) {
 
 void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss) {
     uint32_t rate;
-    assert(t && ss);
+
+    pa_assert(t);
+    pa_assert(ss);
+
     extend(t, 7);
     t->data[t->length] = PA_TAG_SAMPLE_SPEC;
     t->data[t->length+1] = (uint8_t) ss->format;
@@ -137,7 +148,9 @@ void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss) {
 
 void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) {
     uint32_t tmp;
-    assert(t && p);
+
+    pa_assert(t);
+    pa_assert(p);
 
     extend(t, 5+length);
     t->data[t->length] = PA_TAG_ARBITRARY;
@@ -149,7 +162,8 @@ void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) {
 }
 
 void pa_tagstruct_put_boolean(pa_tagstruct*t, int b) {
-    assert(t);
+    pa_assert(t);
+
     extend(t, 1);
     t->data[t->length] = b ? PA_TAG_BOOLEAN_TRUE : PA_TAG_BOOLEAN_FALSE;
     t->length += 1;
@@ -157,7 +171,8 @@ void pa_tagstruct_put_boolean(pa_tagstruct*t, int b) {
 
 void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv) {
     uint32_t tmp;
-    assert(t);
+    pa_assert(t);
+
     extend(t, 9);
     t->data[t->length] = PA_TAG_TIMEVAL;
     tmp = htonl(tv->tv_sec);
@@ -169,7 +184,9 @@ void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv) {
 
 void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u) {
     uint32_t tmp;
-    assert(t);
+
+    pa_assert(t);
+
     extend(t, 9);
     t->data[t->length] = PA_TAG_USEC;
     tmp = htonl((uint32_t) (u >> 32));
@@ -181,7 +198,9 @@ void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u) {
 
 void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t u) {
     uint32_t tmp;
-    assert(t);
+
+    pa_assert(t);
+
     extend(t, 9);
     t->data[t->length] = PA_TAG_U64;
     tmp = htonl((uint32_t) (u >> 32));
@@ -193,7 +212,9 @@ void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t u) {
 
 void pa_tagstruct_puts64(pa_tagstruct*t, int64_t u) {
     uint32_t tmp;
-    assert(t);
+
+    pa_assert(t);
+
     extend(t, 9);
     t->data[t->length] = PA_TAG_S64;
     tmp = htonl((uint32_t) ((uint64_t) u >> 32));
@@ -206,7 +227,7 @@ void pa_tagstruct_puts64(pa_tagstruct*t, int64_t u) {
 void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) {
     unsigned i;
 
-    assert(t);
+    pa_assert(t);
     extend(t, 2 + map->channels);
 
     t->data[t->length++] = PA_TAG_CHANNEL_MAP;
@@ -220,7 +241,7 @@ void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) {
     unsigned i;
     pa_volume_t vol;
 
-    assert(t);
+    pa_assert(t);
     extend(t, 2 + cvolume->channels * sizeof(pa_volume_t));
 
     t->data[t->length++] = PA_TAG_CVOLUME;
@@ -237,7 +258,9 @@ int pa_tagstruct_gets(pa_tagstruct*t, const char **s) {
     int error = 0;
     size_t n;
     char *c;
-    assert(t && s);
+
+    pa_assert(t);
+    pa_assert(s);
 
     if (t->rindex+1 > t->length)
         return -1;
@@ -271,7 +294,8 @@ int pa_tagstruct_gets(pa_tagstruct*t, const char **s) {
 }
 
 int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i) {
-    assert(t && i);
+    pa_assert(t);
+    pa_assert(i);
 
     if (t->rindex+5 > t->length)
         return -1;
@@ -286,7 +310,8 @@ int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i) {
 }
 
 int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c) {
-    assert(t && c);
+    pa_assert(t);
+    pa_assert(c);
 
     if (t->rindex+2 > t->length)
         return -1;
@@ -300,7 +325,8 @@ int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c) {
 }
 
 int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) {
-    assert(t && ss);
+    pa_assert(t);
+    pa_assert(ss);
 
     if (t->rindex+7 > t->length)
         return -1;
@@ -319,7 +345,9 @@ int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) {
 
 int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length) {
     uint32_t len;
-    assert(t && p);
+
+    pa_assert(t);
+    pa_assert(p);
 
     if (t->rindex+5+length > t->length)
         return -1;
@@ -337,18 +365,23 @@ int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length) {
 }
 
 int pa_tagstruct_eof(pa_tagstruct*t) {
-    assert(t);
+    pa_assert(t);
+
     return t->rindex >= t->length;
 }
 
 const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l) {
-    assert(t && t->dynamic && l);
+    pa_assert(t);
+    pa_assert(t->dynamic);
+    pa_assert(l);
+
     *l = t->length;
     return t->data;
 }
 
 int pa_tagstruct_get_boolean(pa_tagstruct*t, int *b) {
-    assert(t && b);
+    pa_assert(t);
+    pa_assert(b);
 
     if (t->rindex+1 > t->length)
         return -1;
@@ -366,6 +399,9 @@ int pa_tagstruct_get_boolean(pa_tagstruct*t, int *b) {
 
 int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv) {
 
+    pa_assert(t);
+    pa_assert(tv);
+
     if (t->rindex+9 > t->length)
         return -1;
 
@@ -382,7 +418,9 @@ int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv) {
 
 int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u) {
     uint32_t tmp;
-    assert(t && u);
+
+    pa_assert(t);
+    pa_assert(u);
 
     if (t->rindex+9 > t->length)
         return -1;
@@ -400,7 +438,9 @@ int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u) {
 
 int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) {
     uint32_t tmp;
-    assert(t && u);
+
+    pa_assert(t);
+    pa_assert(u);
 
     if (t->rindex+9 > t->length)
         return -1;
@@ -418,7 +458,9 @@ int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) {
 
 int pa_tagstruct_gets64(pa_tagstruct*t, int64_t *u) {
     uint32_t tmp;
-    assert(t && u);
+
+    pa_assert(t);
+    pa_assert(u);
 
     if (t->rindex+9 > t->length)
         return -1;
@@ -437,8 +479,8 @@ int pa_tagstruct_gets64(pa_tagstruct*t, int64_t *u) {
 int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) {
     unsigned i;
 
-    assert(t);
-    assert(map);
+    pa_assert(t);
+    pa_assert(map);
 
     if (t->rindex+2 > t->length)
         return -1;
@@ -463,8 +505,8 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) {
     unsigned i;
     pa_volume_t vol;
 
-    assert(t);
-    assert(cvolume);
+    pa_assert(t);
+    pa_assert(cvolume);
 
     if (t->rindex+2 > t->length)
         return -1;
@@ -489,7 +531,7 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) {
 
 void pa_tagstruct_put(pa_tagstruct *t, ...) {
     va_list va;
-    assert(t);
+    pa_assert(t);
 
     va_start(va, t);
 
@@ -550,7 +592,7 @@ void pa_tagstruct_put(pa_tagstruct *t, ...) {
                 break;
 
             default:
-                abort();
+                pa_assert_not_reached();
         }
     }
 
@@ -561,7 +603,7 @@ int pa_tagstruct_get(pa_tagstruct *t, ...) {
     va_list va;
     int ret = 0;
 
-    assert(t);
+    pa_assert(t);
 
     va_start(va, t);
     while (ret == 0) {
@@ -620,9 +662,8 @@ int pa_tagstruct_get(pa_tagstruct *t, ...) {
                 ret = pa_tagstruct_get_cvolume(t, va_arg(va, pa_cvolume *));
                 break;
 
-
             default:
-                abort();
+                pa_assert_not_reached();
         }
 
     }
diff --git a/src/pulsecore/thread-mq.c b/src/pulsecore/thread-mq.c
new file mode 100644 (file)
index 0000000..9b87942
--- /dev/null
@@ -0,0 +1,112 @@
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, 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 <unistd.h>
+#include <errno.h>
+
+#include <pulse/xmalloc.h>
+
+#include <pulsecore/atomic.h>
+#include <pulsecore/once.h>
+#include <pulsecore/log.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/semaphore.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/flist.h>
+
+#include "thread-mq.h"
+
+PA_STATIC_TLS_DECLARE_NO_FREE(thread_mq);
+
+static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
+    pa_thread_mq *q = userdata;
+    pa_asyncmsgq *aq;
+
+    pa_assert(pa_asyncmsgq_get_fd(q->outq) == fd);
+    pa_assert(events == PA_IO_EVENT_INPUT);
+
+    pa_asyncmsgq_ref(aq = q->outq);
+    pa_asyncmsgq_after_poll(aq);
+
+    for (;;) {
+        pa_msgobject *object;
+        int code;
+        void *data;
+        int64_t offset;
+        pa_memchunk chunk;
+
+        /* Check whether there is a message for us to process */
+        while (pa_asyncmsgq_get(aq, &object, &code, &data, &offset, &chunk, 0) == 0) {
+            int ret;
+
+            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
+            pa_asyncmsgq_done(aq, ret);
+        }
+
+        if (pa_asyncmsgq_before_poll(aq) == 0)
+            break;
+    }
+
+    pa_asyncmsgq_unref(aq);
+}
+
+void pa_thread_mq_init(pa_thread_mq *q, pa_mainloop_api *mainloop) {
+    pa_assert(q);
+    pa_assert(mainloop);
+
+    q->mainloop = mainloop;
+    pa_assert_se(q->inq = pa_asyncmsgq_new(0));
+    pa_assert_se(q->outq = pa_asyncmsgq_new(0));
+
+    pa_assert_se(pa_asyncmsgq_before_poll(q->outq) == 0);
+    pa_assert_se(q->io_event = mainloop->io_new(mainloop, pa_asyncmsgq_get_fd(q->outq), PA_IO_EVENT_INPUT, asyncmsgq_cb, q));
+}
+
+void pa_thread_mq_done(pa_thread_mq *q) {
+    pa_assert(q);
+
+    q->mainloop->io_free(q->io_event);
+    q->io_event = NULL;
+
+    pa_asyncmsgq_unref(q->inq);
+    pa_asyncmsgq_unref(q->outq);
+    q->inq = q->outq = NULL;
+
+    q->mainloop = NULL;
+}
+
+void pa_thread_mq_install(pa_thread_mq *q) {
+    pa_assert(q);
+
+    pa_assert(!(PA_STATIC_TLS_GET(thread_mq)));
+    PA_STATIC_TLS_SET(thread_mq, q);
+}
+
+pa_thread_mq *pa_thread_mq_get(void) {
+    return PA_STATIC_TLS_GET(thread_mq);
+}
diff --git a/src/pulsecore/thread-mq.h b/src/pulsecore/thread-mq.h
new file mode 100644 (file)
index 0000000..13b6e01
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef foopulsethreadmqhfoo
+#define foopulsethreadmqhfoo
+
+/* $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.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#include <pulse/mainloop-api.h>
+#include <pulsecore/asyncmsgq.h>
+
+/* Two way communication between a thread and a mainloop. Before the
+ * thread is started a pa_pthread_mq should be initialized and than
+ * attached to the thread using pa_thread_mq_install(). */
+
+typedef struct pa_thread_mq {
+    pa_mainloop_api *mainloop;
+    pa_asyncmsgq *inq, *outq;
+    pa_io_event *io_event;
+} pa_thread_mq;
+
+void pa_thread_mq_init(pa_thread_mq *q, pa_mainloop_api *mainloop);
+void pa_thread_mq_done(pa_thread_mq *q);
+
+/* Install the specified pa_thread_mq object for the current thread */
+void pa_thread_mq_install(pa_thread_mq *q);
+
+/* Return the pa_thread_mq object that is set for the current thread */
+pa_thread_mq *pa_thread_mq_get(void);
+
+#endif
index 4271fa42f06a84692d44a9f1a35097ea4ec5570e..7f43f43e75288949bf5ee73f4402a9bdb6067f46 100644 (file)
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <pthread.h>
 #include <sched.h>
 #include <errno.h>
 #include <pulsecore/mutex.h>
 #include <pulsecore/once.h>
 #include <pulsecore/atomic.h>
+#include <pulsecore/macro.h>
 
 #include "thread.h"
 
-#define ASSERT_SUCCESS(x) do { \
-    int _r = (x); \
-    assert(_r == 0); \
-} while(0)
-
 struct pa_thread {
     pthread_t id;
     pa_thread_func_t thread_func;
     void *userdata;
-    pa_atomic_int_t running;
+    pa_atomic_t running;
 };
 
 struct pa_tls {
     pthread_key_t key;
 };
 
-static pa_tls *thread_tls;
-static pa_once_t thread_tls_once = PA_ONCE_INIT;
-
-static void tls_free_cb(void *p) {
+static void thread_free_cb(void *p) {
     pa_thread *t = p;
 
-    assert(t);
+    pa_assert(t);
 
     if (!t->thread_func)
         /* This is a foreign thread, we need to free the struct */
         pa_xfree(t);
 }
 
-static void thread_tls_once_func(void) {
-    thread_tls = pa_tls_new(tls_free_cb);
-    assert(thread_tls);
-}
+PA_STATIC_TLS_DECLARE(current_thread, thread_free_cb);
 
 static void* internal_thread_func(void *userdata) {
     pa_thread *t = userdata;
-    assert(t);
+    pa_assert(t);
 
     t->id = pthread_self();
 
-    pa_once(&thread_tls_once, thread_tls_once_func);
-
-    pa_tls_set(thread_tls, t);
+    PA_STATIC_TLS_SET(current_thread, t);
 
     pa_atomic_inc(&t->running);
     t->thread_func(t->userdata);
-    pa_atomic_add(&t->running, -2);
+    pa_atomic_sub(&t->running, 2);
 
     return NULL;
 }
@@ -92,7 +79,7 @@ static void* internal_thread_func(void *userdata) {
 pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) {
     pa_thread *t;
 
-    assert(thread_func);
+    pa_assert(thread_func);
 
     t = pa_xnew(pa_thread, 1);
     t->thread_func = thread_func;
@@ -110,26 +97,26 @@ pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) {
 }
 
 int pa_thread_is_running(pa_thread *t) {
-    assert(t);
+    pa_assert(t);
 
     /* Unfortunately there is no way to tell whether a "foreign"
      * thread is still running. See
      * http://udrepper.livejournal.com/16844.html for more
      * information */
-    assert(t->thread_func);
+    pa_assert(t->thread_func);
 
     return pa_atomic_load(&t->running) > 0;
 }
 
 void pa_thread_free(pa_thread *t) {
-    assert(t);
+    pa_assert(t);
 
     pa_thread_join(t);
     pa_xfree(t);
 }
 
 int pa_thread_join(pa_thread *t) {
-    assert(t);
+    pa_assert(t);
 
     return pthread_join(t->id, NULL);
 }
@@ -137,9 +124,7 @@ int pa_thread_join(pa_thread *t) {
 pa_thread* pa_thread_self(void) {
     pa_thread *t;
 
-    pa_once(&thread_tls_once, thread_tls_once_func);
-
-    if ((t = pa_tls_get(thread_tls)))
+    if ((t = PA_STATIC_TLS_GET(current_thread)))
         return t;
 
     /* This is a foreign thread, let's create a pthread structure to
@@ -151,19 +136,19 @@ pa_thread* pa_thread_self(void) {
     t->userdata = NULL;
     pa_atomic_store(&t->running, 2);
 
-    pa_tls_set(thread_tls, t);
+    PA_STATIC_TLS_SET(current_thread, t);
 
     return t;
 }
 
 void* pa_thread_get_data(pa_thread *t) {
-    assert(t);
+    pa_assert(t);
 
     return t->userdata;
 }
 
 void pa_thread_set_data(pa_thread *t, void *userdata) {
-    assert(t);
+    pa_assert(t);
 
     t->userdata = userdata;
 }
@@ -172,7 +157,7 @@ void pa_thread_yield(void) {
 #ifdef HAVE_PTHREAD_YIELD
     pthread_yield();
 #else
-    ASSERT_SUCCESS(sched_yield());
+    pa_assert_se(sched_yield() == 0);
 #endif
 }
 
@@ -190,14 +175,14 @@ pa_tls* pa_tls_new(pa_free_cb_t free_cb) {
 }
 
 void pa_tls_free(pa_tls *t) {
-    assert(t);
+    pa_assert(t);
 
-    ASSERT_SUCCESS(pthread_key_delete(t->key));
+    pa_assert_se(pthread_key_delete(t->key) == 0);
     pa_xfree(t);
 }
 
 void *pa_tls_get(pa_tls *t) {
-    assert(t);
+    pa_assert(t);
 
     return pthread_getspecific(t->key);
 }
@@ -206,7 +191,7 @@ void *pa_tls_set(pa_tls *t, void *userdata) {
     void *r;
 
     r = pthread_getspecific(t->key);
-    ASSERT_SUCCESS(pthread_setspecific(t->key, userdata));
+    pa_assert_se(pthread_setspecific(t->key, userdata) == 0);
     return r;
 }
 
index 46d273b4148bdf455ae3a551092c5a70bd3fdbfb..cad1420a783e177f9287614041759f5cceb775c8 100644 (file)
@@ -53,9 +53,8 @@ struct pa_tls_monitor {
 };
 
 static pa_tls *thread_tls;
-static pa_once_t thread_tls_once = PA_ONCE_INIT;
+static pa_once thread_tls_once = PA_ONCE_INIT;
 static pa_tls *monitor_tls;
-static pa_once_t monitor_tls_once = PA_ONCE_INIT;
 
 static void thread_tls_once_func(void) {
     thread_tls = pa_tls_new(NULL);
@@ -66,7 +65,7 @@ static DWORD WINAPI internal_thread_func(LPVOID param) {
     pa_thread *t = param;
     assert(t);
 
-    pa_once(&thread_tls_once, thread_tls_once_func);
+    pa_run_once(&thread_tls_once, thread_tls_once_func);
     pa_tls_set(thread_tls, t);
 
     t->thread_func(t->userdata);
@@ -122,7 +121,7 @@ int pa_thread_join(pa_thread *t) {
 }
 
 pa_thread* pa_thread_self(void) {
-    pa_once(&thread_tls_once, thread_tls_once_func);
+    pa_run_once(&thread_tls_once, thread_tls_once_func);
     return pa_tls_get(thread_tls);
 }
 
@@ -130,12 +129,6 @@ void pa_thread_yield(void) {
     Sleep(0);
 }
 
-static void monitor_tls_once_func(void) {
-    monitor_tls = pa_tls_new(NULL);
-    assert(monitor_tls);
-    pa_tls_set(monitor_tls, NULL);
-}
-
 static DWORD WINAPI monitor_thread_func(LPVOID param) {
     struct pa_tls_monitor *m = param;
     assert(m);
@@ -191,7 +184,11 @@ void *pa_tls_set(pa_tls *t, void *userdata) {
     if (t->free_func) {
         struct pa_tls_monitor *m;
 
-        pa_once(&monitor_tls_once, monitor_tls_once_func);
+        PA_ONCE_BEGIN {
+            monitor_tls = pa_tls_new(NULL);
+            assert(monitor_tls);
+            pa_tls_set(monitor_tls, NULL);
+        } PA_ONCE_END;
 
         m = pa_tls_get(monitor_tls);
         if (!m) {
index ca1fe4da84f4373ee82add93f94eba830c45093e..54ef320e13631bec9fadba05f4d99caf746c4c26 100644 (file)
 ***/
 
 #include <pulse/def.h>
+#include <pulsecore/once.h>
+
+#ifndef PACKAGE
+#error "Please include config.h before including this file!"
+#endif
 
 typedef struct pa_thread pa_thread;
 
@@ -48,4 +53,60 @@ void pa_tls_free(pa_tls *t);
 void * pa_tls_get(pa_tls *t);
 void *pa_tls_set(pa_tls *t, void *userdata);
 
+#define PA_STATIC_TLS_DECLARE(name, free_cb)                            \
+    static struct {                                                     \
+        pa_once once;                                                   \
+        pa_tls *tls;                                                    \
+    } name##_tls = {                                                    \
+        .once = PA_ONCE_INIT,                                           \
+        .tls = NULL                                                     \
+    };                                                                  \
+    static void name##_tls_init(void) {                                 \
+        name##_tls.tls = pa_tls_new(free_cb);                           \
+    }                                                                   \
+    static inline pa_tls* name##_tls_obj(void) {                        \
+        pa_run_once(&name##_tls.once, name##_tls_init);                 \
+        return name##_tls.tls;                                          \
+    }                                                                   \
+    static void name##_tls_destructor(void) PA_GCC_DESTRUCTOR;          \
+    static void name##_tls_destructor(void) {                           \
+        static void (*_free_cb)(void*) = free_cb;                       \
+        if (!name##_tls.tls)                                            \
+            return;                                                     \
+        if (_free_cb) {                                                 \
+            void *p;                                                    \
+            if ((p = pa_tls_get(name##_tls.tls)))                       \
+                _free_cb(p);                                            \
+        }                                                               \
+        pa_tls_free(name##_tls.tls);                                    \
+    }                                                                   \
+    static inline void* name##_tls_get(void) {                          \
+        return pa_tls_get(name##_tls_obj());                            \
+    }                                                                   \
+    static inline void* name##_tls_set(void *p) {                       \
+        return pa_tls_set(name##_tls_obj(), p);                         \
+    }                                                                   \
+    struct __stupid_useless_struct_to_allow_trailing_semicolon
+
+#ifdef HAVE_TLS_BUILTIN
+/* An optimized version of the above that requires no dynamic
+ * allocation if the compiler supports __thread */
+#define PA_STATIC_TLS_DECLARE_NO_FREE(name)                             \
+    static __thread void *name##_tls = NULL;                            \
+    static inline void* name##_tls_get(void) {                          \
+        return name##_tls;                                              \
+    }                                                                   \
+    static inline void* name##_tls_set(void *p) {                       \
+        void *r = name##_tls;                                           \
+        name##_tls = p;                                                 \
+        return r;                                                       \
+    }                                                                   \
+    struct __stupid_useless_struct_to_allow_trailing_semicolon
+#else
+#define PA_STATIC_TLS_DECLARE_NO_FREE(name) PA_STATIC_TLS_DECLARE(name, NULL)
+#endif
+
+#define PA_STATIC_TLS_GET(name) (name##_tls_get())
+#define PA_STATIC_TLS_SET(name, p) (name##_tls_set(p))
+
 #endif
diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
new file mode 100644 (file)
index 0000000..6bda3df
--- /dev/null
@@ -0,0 +1,378 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2007 Lennart Poettering
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, 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 <pulse/sample.h>
+#include <pulse/xmalloc.h>
+
+#include <pulsecore/macro.h>
+
+#include "time-smoother.h"
+
+#define HISTORY_MAX 50
+
+/*
+ * Implementation of a time smoothing algorithm to synchronize remote
+ * clocks to a local one. Evens out noise, adjusts to clock skew and
+ * allows cheap estimations of the remote time while clock updates may
+ * be seldom and recieved in non-equidistant intervals.
+ *
+ * Basically, we estimate the gradient of received clock samples in a
+ * certain history window (of size 'history_time') with linear
+ * regression. With that info we estimate the remote time in
+ * 'adjust_time' ahead and smoothen our current estimation function
+ * towards that point with a 3rd order polynomial interpolation with
+ * fitting derivatives. (more or less a b-spline)
+ *
+ * The larger 'history_time' is chosen the better we will surpress
+ * noise -- but we'll adjust to clock skew slower..
+ *
+ * The larger 'adjust_time' is chosen the smoother our estimation
+ * function will be -- but we'll adjust to clock skew slower, too.
+ *
+ * If 'monotonic' is TRUE the resulting estimation function is
+ * guaranteed to be monotonic.
+ */
+
+struct pa_smoother {
+    pa_usec_t adjust_time, history_time;
+    pa_bool_t monotonic;
+
+    pa_usec_t time_offset;
+
+    pa_usec_t px, py;     /* Point p, where we want to reach stability */
+    double dp;            /* Gradient we want at point p */
+
+    pa_usec_t ex, ey;     /* Point e, which we estimated before and need to smooth to */
+    double de;            /* Gradient we estimated for point e */
+
+                          /* History of last measurements */
+    pa_usec_t history_x[HISTORY_MAX], history_y[HISTORY_MAX];
+    unsigned history_idx, n_history;
+
+    /* To even out for monotonicity */
+    pa_usec_t last_y;
+
+    /* Cached parameters for our interpolation polynomial y=ax^3+b^2+cx */
+    double a, b, c;
+    pa_bool_t abc_valid;
+
+    pa_bool_t paused;
+    pa_usec_t pause_time;
+};
+
+pa_smoother* pa_smoother_new(pa_usec_t adjust_time, pa_usec_t history_time, pa_bool_t monotonic) {
+    pa_smoother *s;
+
+    pa_assert(adjust_time > 0);
+    pa_assert(history_time > 0);
+
+    s = pa_xnew(pa_smoother, 1);
+    s->adjust_time = adjust_time;
+    s->history_time = history_time;
+    s->time_offset = 0;
+    s->monotonic = monotonic;
+
+    s->px = s->py = 0;
+    s->dp = 1;
+
+    s->ex = s->ey = 0;
+    s->de = 1;
+
+    s->history_idx = 0;
+    s->n_history = 0;
+
+    s->last_y = 0;
+
+    s->abc_valid = FALSE;
+
+    s->paused = FALSE;
+
+    return s;
+}
+
+void pa_smoother_free(pa_smoother* s) {
+    pa_assert(s);
+
+    pa_xfree(s);
+}
+
+static void drop_old(pa_smoother *s, pa_usec_t x) {
+    unsigned j;
+
+    /* First drop items from history which are too old, but make sure
+     * to always keep two entries in the history */
+
+    for (j = s->n_history; j > 2; j--) {
+
+        if (s->history_x[s->history_idx] + s->history_time >= x) {
+            /* This item is still valid, and thus all following ones
+             * are too, so let's quit this loop */
+            break;
+        }
+
+        /* Item is too old, let's drop it */
+        s->history_idx ++;
+        while (s->history_idx >= HISTORY_MAX)
+            s->history_idx -= HISTORY_MAX;
+
+        s->n_history --;
+    }
+}
+
+static void add_to_history(pa_smoother *s, pa_usec_t x, pa_usec_t y) {
+    unsigned j;
+    pa_assert(s);
+
+    drop_old(s, x);
+
+    /* Calculate position for new entry */
+    j = s->history_idx + s->n_history;
+    while (j >= HISTORY_MAX)
+        j -= HISTORY_MAX;
+
+    /* Fill in entry */
+    s->history_x[j] = x;
+    s->history_y[j] = y;
+
+    /* Adjust counter */
+    s->n_history ++;
+
+    /* And make sure we don't store more entries than fit in */
+    if (s->n_history >= HISTORY_MAX) {
+        s->history_idx += s->n_history - HISTORY_MAX;
+        s->n_history = HISTORY_MAX;
+    }
+}
+
+static double avg_gradient(pa_smoother *s, pa_usec_t x) {
+    unsigned i, j, c = 0;
+    int64_t ax = 0, ay = 0, k, t;
+    double r;
+
+    drop_old(s, x);
+
+    /* First, calculate average of all measurements */
+    i = s->history_idx;
+    for (j = s->n_history; j > 0; j--) {
+
+        ax += s->history_x[i];
+        ay += s->history_y[i];
+        c++;
+
+        i++;
+        while (i >= HISTORY_MAX)
+            i -= HISTORY_MAX;
+    }
+
+    /* Too few measurements, assume gradient of 1 */
+    if (c < 2)
+        return 1;
+
+    ax /= c;
+    ay /= c;
+
+    /* Now, do linear regression */
+    k = t = 0;
+
+    i = s->history_idx;
+    for (j = s->n_history; j > 0; j--) {
+        int64_t dx, dy;
+
+        dx = (int64_t) s->history_x[i] - ax;
+        dy = (int64_t) s->history_y[i] - ay;
+
+        k += dx*dy;
+        t += dx*dx;
+
+        i++;
+        while (i >= HISTORY_MAX)
+            i -= HISTORY_MAX;
+    }
+
+    r = (double) k / t;
+
+    return s->monotonic && r < 0 ? 0 : r;
+}
+
+static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) {
+    pa_assert(s);
+    pa_assert(y);
+
+    if (x >= s->px) {
+        int64_t t;
+
+        /* The requested point is right of the point where we wanted
+         * to be on track again, thus just linearly estimate */
+
+        t = (int64_t) s->py + (int64_t) (s->dp * (x - s->px));
+
+        if (t < 0)
+            t = 0;
+
+        *y = (pa_usec_t) t;
+
+        if (deriv)
+            *deriv = s->dp;
+
+    } else {
+
+        if (!s->abc_valid) {
+            pa_usec_t ex, ey, px, py;
+            int64_t kx, ky;
+            double de, dp;
+
+            /* Ok, we're not yet on track, thus let's interpolate, and
+             * make sure that the first derivative is smooth */
+
+            /* We have two points: (ex|ey) and (px|py) with two gradients
+             * at these points de and dp. We do a polynomial interpolation
+             * of degree 3 with these 6 values */
+
+            ex = s->ex; ey = s->ey;
+            px = s->px; py = s->py;
+            de = s->de; dp = s->dp;
+
+            pa_assert(ex < px);
+
+            /* To increase the dynamic range and symplify calculation, we
+             * move these values to the origin */
+            kx = (int64_t) px - (int64_t) ex;
+            ky = (int64_t) py - (int64_t) ey;
+
+            /* Calculate a, b, c for y=ax^3+b^2+cx */
+            s->c = de;
+            s->b = (((double) (3*ky)/kx - dp - 2*de)) / kx;
+            s->a = (dp/kx - 2*s->b - de/kx) / (3*kx);
+
+            s->abc_valid = TRUE;
+        }
+
+        /* Move to origin */
+        x -= s->ex;
+
+        /* Horner scheme */
+        *y = (pa_usec_t) ((double) x * (s->c + (double) x * (s->b + (double) x * s->a)));
+
+        /* Move back from origin */
+        *y += s->ey;
+
+        /* Horner scheme */
+        if (deriv)
+            *deriv = s->c + ((double) x * (s->b*2 + (double) x * s->a*3));
+    }
+
+    /* Guarantee monotonicity */
+    if (s->monotonic) {
+
+        if (*y < s->last_y)
+            *y = s->last_y;
+        else
+            s->last_y = *y;
+
+        if (deriv && *deriv < 0)
+            *deriv = 0;
+    }
+}
+
+void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) {
+    pa_usec_t ney;
+    double nde;
+
+    pa_assert(s);
+    pa_assert(x >= s->time_offset);
+
+    /* Fix up x value */
+    if (s->paused)
+        x = s->pause_time;
+    else
+        x -= s->time_offset;
+
+    pa_assert(x >= s->ex);
+
+    /* First, we calculate the position we'd estimate for x, so that
+     * we can adjust our position smoothly from this one */
+    estimate(s, x, &ney, &nde);
+    s->ex = x; s->ey = ney; s->de = nde;
+
+    /* Then, we add the new measurement to our history */
+    add_to_history(s, x, y);
+
+    /* And determine the average gradient of the history */
+    s->dp = avg_gradient(s, x);
+
+    /* And calculate when we want to be on track again */
+    s->px = x + s->adjust_time;
+    s->py = y + s->dp *s->adjust_time;
+
+    s->abc_valid = FALSE;
+}
+
+pa_usec_t pa_smoother_get(pa_smoother *s, pa_usec_t x) {
+    pa_usec_t y;
+
+    pa_assert(s);
+    pa_assert(x >= s->time_offset);
+
+    /* Fix up x value */
+    if (s->paused)
+        x = s->pause_time;
+    else
+        x -= s->time_offset;
+
+    pa_assert(x >= s->ex);
+
+    estimate(s, x, &y, NULL);
+    return y;
+}
+
+void pa_smoother_set_time_offset(pa_smoother *s, pa_usec_t offset) {
+    pa_assert(s);
+
+    s->time_offset = offset;
+}
+
+void pa_smoother_pause(pa_smoother *s, pa_usec_t x) {
+    pa_assert(s);
+
+    if (s->paused)
+        return;
+
+    s->paused = TRUE;
+    s->pause_time = x;
+}
+
+void pa_smoother_resume(pa_smoother *s, pa_usec_t x) {
+    pa_assert(s);
+
+    if (!s->paused)
+        return;
+
+    s->paused = FALSE;
+    s->time_offset += x - s->pause_time;
+}
diff --git a/src/pulsecore/time-smoother.h b/src/pulsecore/time-smoother.h
new file mode 100644 (file)
index 0000000..8b8512e
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef foopulsetimesmootherhfoo
+#define foopulsetimesmootherhfoo
+
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2007 Lennart Poettering
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#include <pulsecore/macro.h>
+#include <pulse/sample.h>
+
+typedef struct pa_smoother pa_smoother;
+
+pa_smoother* pa_smoother_new(pa_usec_t adjust_time, pa_usec_t history_time, pa_bool_t monotonic);
+void pa_smoother_free(pa_smoother* s);
+
+void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y);
+pa_usec_t pa_smoother_get(pa_smoother *s, pa_usec_t x);
+
+void pa_smoother_set_time_offset(pa_smoother *s, pa_usec_t offset);
+
+void pa_smoother_pause(pa_smoother *s, pa_usec_t x);
+void pa_smoother_resume(pa_smoother *s, pa_usec_t x);
+
+#endif
index 117c7f881f87373c49b1c88778fa3c3efdc5d6ee..f79c19c5418b34a4cfe4b6d848e5679b065ea7a3 100644 (file)
 #endif
 
 #include <string.h>
-#include <assert.h>
 #include <stdlib.h>
 
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/dynarray.h>
 #include <pulsecore/gccmacro.h>
+#include <pulsecore/macro.h>
 
 #include "tokenizer.h"
 
-struct pa_tokenizer {
-    pa_dynarray *dynarray;
-};
-
 static void token_free(void *p, PA_GCC_UNUSED void *userdata) {
     pa_xfree(p);
 }
@@ -48,7 +44,9 @@ static void parse(pa_dynarray*a, const char *s, unsigned args) {
     int infty = 0;
     const char delimiter[] = " \t\n\r";
     const char *p;
-    assert(a && s);
+
+    pa_assert(a);
+    pa_assert(s);
 
     if (args == 0)
         infty = 1;
@@ -70,23 +68,23 @@ static void parse(pa_dynarray*a, const char *s, unsigned args) {
 }
 
 pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args) {
-    pa_tokenizer *t;
-
-    t = pa_xmalloc(sizeof(pa_tokenizer));
-    t->dynarray = pa_dynarray_new();
-    assert(t->dynarray);
+    pa_dynarray *a;
 
-    parse(t->dynarray, s, args);
-    return t;
+    a = pa_dynarray_new();
+    parse(a, s, args);
+    return (pa_tokenizer*) a;
 }
 
 void pa_tokenizer_free(pa_tokenizer *t) {
-    assert(t);
-    pa_dynarray_free(t->dynarray, token_free, NULL);
-    pa_xfree(t);
+    pa_dynarray *a = (pa_dynarray*) t;
+
+    pa_assert(a);
+    pa_dynarray_free(a, token_free, NULL);
 }
 
 const char *pa_tokenizer_get(pa_tokenizer *t, unsigned i) {
-    assert(t);
-    return pa_dynarray_get(t->dynarray, i);
+    pa_dynarray *a = (pa_dynarray*) t;
+
+    pa_assert(a);
+    return pa_dynarray_get(a, i);
 }
index ae868b384767ae5ba33f3abf1dad2e979bae74e6..0352bf4d42d7162a9795ca86c96740ac3a726ab1 100644 (file)
@@ -15,6 +15,8 @@
 #define EHOSTUNREACH    WSAEHOSTUNREACH
 #define EWOULDBLOCK     WSAEWOULDBLOCK
 
+typedef long suseconds_t;
+
 #endif
 
 #ifdef HAVE_WS2TCPIP_H
index 5b85ea426acf258d91a98efa94c9514fbeca2da3..a740e39b4a1bf9018a192d535478e8236b066aa3 100644 (file)
@@ -32,7 +32,6 @@
 
 #include "x11prop.h"
 
-
 void pa_x11_set_prop(Display *d, const char *name, const char *data) {
     Atom a = XInternAtom(d, name, False);
     XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (const unsigned char*) data, strlen(data)+1);
index 6a6a26924f656b8dc73a096fddd3dcf3c0dbcaa4..800a94582adc0b245f36a7dfaed31f1317df5e4e 100644 (file)
   USA.
 ***/
 
-#include <assert.h>
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <stdio.h>
 
 #include <pulse/xmalloc.h>
@@ -29,6 +32,8 @@
 #include <pulsecore/llist.h>
 #include <pulsecore/log.h>
 #include <pulsecore/props.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
 
 #include "x11wrap.h"
 
@@ -42,8 +47,8 @@ struct pa_x11_internal {
 };
 
 struct pa_x11_wrapper {
+    PA_REFCNT_DECLARE;
     pa_core *core;
-    int ref;
 
     char *property_name;
     Display *display;
@@ -64,7 +69,8 @@ struct pa_x11_client {
 
 /* Dispatch all pending X11 events */
 static void work(pa_x11_wrapper *w) {
-    assert(w && w->ref >= 1);
+    pa_assert(w);
+    pa_assert(PA_REFCNT_VALUE(w) >= 1);
 
     while (XPending(w->display)) {
         pa_x11_client *c;
@@ -72,7 +78,7 @@ static void work(pa_x11_wrapper *w) {
         XNextEvent(w->display, &e);
 
         for (c = w->clients; c; c = c->next) {
-            assert(c->callback);
+            pa_assert(c->callback);
             if (c->callback(w, &e, c->userdata) != 0)
                 break;
         }
@@ -82,14 +88,24 @@ static void work(pa_x11_wrapper *w) {
 /* IO notification event for the X11 display connection */
 static void display_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
     pa_x11_wrapper *w = userdata;
-    assert(m && e && fd >= 0 && w && w->ref >= 1);
+
+    pa_assert(m);
+    pa_assert(e);
+    pa_assert(fd >= 0);
+    pa_assert(w);
+    pa_assert(PA_REFCNT_VALUE(w) >= 1);
+
     work(w);
 }
 
 /* Deferred notification event. Called once each main loop iteration */
 static void defer_event(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
     pa_x11_wrapper *w = userdata;
-    assert(m && e && w && w->ref >= 1);
+
+    pa_assert(m);
+    pa_assert(e);
+    pa_assert(w);
+    pa_assert(PA_REFCNT_VALUE(w) >= 1);
 
     m->defer_enable(e, 0);
 
@@ -99,7 +115,12 @@ static void defer_event(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
 /* IO notification event for X11 internal connections */
 static void internal_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
     pa_x11_wrapper *w = userdata;
-    assert(m && e && fd >= 0 && w && w->ref >= 1);
+
+    pa_assert(m);
+    pa_assert(e);
+    pa_assert(fd >= 0);
+    pa_assert(w);
+    pa_assert(PA_REFCNT_VALUE(w) >= 1);
 
     XProcessInternalConnection(w->display, fd);
 
@@ -109,10 +130,9 @@ static void internal_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC
 /* Add a new IO source for the specified X11 internal connection */
 static pa_x11_internal* x11_internal_add(pa_x11_wrapper *w, int fd) {
     pa_x11_internal *i;
-    assert(fd >= 0);
+    pa_assert(fd >= 0);
 
-    i = pa_xmalloc(sizeof(pa_x11_internal));
-    assert(i);
+    i = pa_xnew(pa_x11_internal, 1);
     i->wrapper = w;
     i->io_event = w->core->mainloop->io_new(w->core->mainloop, fd, PA_IO_EVENT_INPUT, internal_io_event, w);
     i->fd = fd;
@@ -123,7 +143,7 @@ static pa_x11_internal* x11_internal_add(pa_x11_wrapper *w, int fd) {
 
 /* Remove an IO source for an X11 internal connection */
 static void x11_internal_remove(pa_x11_wrapper *w, pa_x11_internal *i) {
-    assert(i);
+    pa_assert(i);
 
     PA_LLIST_REMOVE(pa_x11_internal, w->internals, i);
     w->core->mainloop->io_free(i->io_event);
@@ -133,7 +153,10 @@ static void x11_internal_remove(pa_x11_wrapper *w, pa_x11_internal *i) {
 /* Implementation of XConnectionWatchProc */
 static void x11_watch(Display *display, XPointer userdata, int fd, Bool opening, XPointer *watch_data) {
     pa_x11_wrapper *w = (pa_x11_wrapper*) userdata;
-    assert(display && w && fd >= 0);
+
+    pa_assert(display);
+    pa_assert(w);
+    pa_assert(fd >= 0);
 
     if (opening)
         *watch_data = (XPointer) x11_internal_add(w, fd);
@@ -144,16 +167,15 @@ static void x11_watch(Display *display, XPointer userdata, int fd, Bool opening,
 static pa_x11_wrapper* x11_wrapper_new(pa_core *c, const char *name, const char *t) {
     pa_x11_wrapper*w;
     Display *d;
-    int r;
 
     if (!(d = XOpenDisplay(name))) {
         pa_log("XOpenDisplay() failed");
         return NULL;
     }
 
-    w = pa_xmalloc(sizeof(pa_x11_wrapper));
+    w = pa_xnew(pa_x11_wrapper, 1);
+    PA_REFCNT_INIT(w);
     w->core = c;
-    w->ref = 1;
     w->property_name = pa_xstrdup(t);
     w->display = d;
 
@@ -165,20 +187,17 @@ static pa_x11_wrapper* x11_wrapper_new(pa_core *c, const char *name, const char
 
     XAddConnectionWatch(d, x11_watch, (XPointer) w);
 
-    r = pa_property_set(c, w->property_name, w);
-    assert(r >= 0);
+    pa_assert_se(pa_property_set(c, w->property_name, w) >= 0);
 
     return w;
 }
 
 static void x11_wrapper_free(pa_x11_wrapper*w) {
-    int r;
-    assert(w);
+    pa_assert(w);
 
-    r = pa_property_remove(w->core, w->property_name);
-    assert(r >= 0);
+    pa_assert_se(pa_property_remove(w->core, w->property_name) >= 0);
 
-    assert(!w->clients);
+    pa_assert(!w->clients);
 
     XRemoveConnectionWatch(w->display, x11_watch, (XPointer) w);
     XCloseDisplay(w->display);
@@ -196,9 +215,10 @@ static void x11_wrapper_free(pa_x11_wrapper*w) {
 pa_x11_wrapper* pa_x11_wrapper_get(pa_core *c, const char *name) {
     char t[256];
     pa_x11_wrapper *w;
-    assert(c);
 
-    snprintf(t, sizeof(t), "x11-wrapper%s%s", name ? "-" : "", name ? name : "");
+    pa_core_assert_ref(c);
+
+    pa_snprintf(t, sizeof(t), "x11-wrapper%s%s", name ? "-" : "", name ? name : "");
     if ((w = pa_property_get(c, t)))
         return pa_x11_wrapper_ref(w);
 
@@ -206,20 +226,24 @@ pa_x11_wrapper* pa_x11_wrapper_get(pa_core *c, const char *name) {
 }
 
 pa_x11_wrapper* pa_x11_wrapper_ref(pa_x11_wrapper *w) {
-    assert(w && w->ref >= 1);
-    w->ref++;
+    pa_assert(w);
+    pa_assert(PA_REFCNT_VALUE(w) >= 1);
+
+    PA_REFCNT_INC(w);
     return w;
 }
 
 void pa_x11_wrapper_unref(pa_x11_wrapper* w) {
-    assert(w && w->ref >= 1);
+    pa_assert(w);
+    pa_assert(PA_REFCNT_VALUE(w) >= 1);
 
-    if (!(--w->ref))
+    if (PA_REFCNT_DEC(w) <= 0)
         x11_wrapper_free(w);
 }
 
 Display *pa_x11_wrapper_get_display(pa_x11_wrapper *w) {
-    assert(w && w->ref >= 1);
+    pa_assert(w);
+    pa_assert(PA_REFCNT_VALUE(w) >= 1);
 
     /* Somebody is using us, schedule a output buffer flush */
     w->core->mainloop->defer_enable(w->defer_event, 1);
@@ -229,9 +253,11 @@ Display *pa_x11_wrapper_get_display(pa_x11_wrapper *w) {
 
 pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, int (*cb)(pa_x11_wrapper *w, XEvent *e, void *userdata), void *userdata) {
     pa_x11_client *c;
-    assert(w && w->ref >= 1);
 
-    c = pa_xmalloc(sizeof(pa_x11_client));
+    pa_assert(w);
+    pa_assert(PA_REFCNT_VALUE(w) >= 1);
+
+    c = pa_xnew(pa_x11_client, 1);
     c->wrapper = w;
     c->callback = cb;
     c->userdata = userdata;
@@ -242,7 +268,9 @@ pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, int (*cb)(pa_x11_wrapper *w,
 }
 
 void pa_x11_client_free(pa_x11_client *c) {
-    assert(c && c->wrapper && c->wrapper->ref >= 1);
+    pa_assert(c);
+    pa_assert(c->wrapper);
+    pa_assert(PA_REFCNT_VALUE(c->wrapper) >= 1);
 
     PA_LLIST_REMOVE(pa_x11_client, c->wrapper->clients, c);
     pa_xfree(c);
diff --git a/src/tests/asyncmsgq-test.c b/src/tests/asyncmsgq-test.c
new file mode 100644 (file)
index 0000000..380c5e7
--- /dev/null
@@ -0,0 +1,110 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published
+  by the Free Software Foundation; either version 2 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 <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <pulse/util.h>
+#include <pulse/xmalloc.h>
+#include <pulsecore/asyncmsgq.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/log.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
+
+enum {
+    OPERATION_A,
+    OPERATION_B,
+    OPERATION_C,
+    QUIT
+};
+
+static void the_thread(void *_q) {
+    pa_asyncmsgq *q = _q;
+    int quit = 0;
+
+    do {
+        int code = 0;
+
+        pa_assert_se(pa_asyncmsgq_get(q, NULL, &code, NULL, NULL, NULL, 1) == 0);
+
+        switch (code) {
+
+            case OPERATION_A:
+                printf("Operation A\n");
+                break;
+
+            case OPERATION_B:
+                printf("Operation B\n");
+                break;
+
+            case OPERATION_C:
+                printf("Operation C\n");
+                break;
+
+            case QUIT:
+                printf("quit\n");
+                quit = 1;
+                break;
+        }
+
+        pa_asyncmsgq_done(q, 0);
+
+    } while (!quit);
+}
+
+int main(int argc, char *argv[]) {
+    pa_asyncmsgq *q;
+    pa_thread *t;
+
+    pa_assert_se(q = pa_asyncmsgq_new(0));
+
+    pa_assert_se(t = pa_thread_new(the_thread, q));
+
+    printf("Operation A post\n");
+    pa_asyncmsgq_post(q, NULL, OPERATION_A, NULL, 0, NULL, NULL);
+
+    pa_thread_yield();
+
+    printf("Operation B post\n");
+    pa_asyncmsgq_post(q, NULL, OPERATION_B, NULL, 0, NULL, NULL);
+
+    pa_thread_yield();
+
+    printf("Operation C send\n");
+    pa_asyncmsgq_send(q, NULL, OPERATION_C, NULL, 0, NULL);
+
+    pa_thread_yield();
+
+    printf("Quit post\n");
+    pa_asyncmsgq_post(q, NULL, QUIT, NULL, 0, NULL, NULL);
+
+    pa_thread_free(t);
+
+    pa_asyncmsgq_unref(q);
+
+    return 0;
+}
diff --git a/src/tests/asyncq-test.c b/src/tests/asyncq-test.c
new file mode 100644 (file)
index 0000000..09b2004
--- /dev/null
@@ -0,0 +1,87 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published
+  by the Free Software Foundation; either version 2 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 <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <pulse/util.h>
+#include <pulse/xmalloc.h>
+#include <pulsecore/asyncq.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/log.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
+
+static void producer(void *_q) {
+    pa_asyncq *q = _q;
+    int i;
+
+    for (i = 0; i < 1000; i++) {
+        printf("pushing %i\n", i);
+        pa_asyncq_push(q, PA_UINT_TO_PTR(i+1), 1);
+    }
+
+    pa_asyncq_push(q, PA_UINT_TO_PTR(-1), 1);
+    printf("pushed end\n");
+}
+
+static void consumer(void *_q) {
+    pa_asyncq *q = _q;
+    void *p;
+    int i;
+
+    sleep(1);
+
+    for (i = 0;; i++) {
+        p = pa_asyncq_pop(q, 1);
+
+        if (p == PA_UINT_TO_PTR(-1))
+            break;
+
+        pa_assert(p == PA_UINT_TO_PTR(i+1));
+
+        printf("popped %i\n", i);
+    }
+
+    printf("popped end\n");
+}
+
+int main(int argc, char *argv[]) {
+    pa_asyncq *q;
+    pa_thread *t1, *t2;
+
+    pa_assert_se(q = pa_asyncq_new(0));
+
+    pa_assert_se(t1 = pa_thread_new(producer, q));
+    pa_assert_se(t2 = pa_thread_new(consumer, q));
+
+    pa_thread_free(t1);
+    pa_thread_free(t2);
+
+    pa_asyncq_free(q, NULL);
+
+    return 0;
+}
index 6879eae5359b34df1e473d9690bdbd10272097bf..8628f521116007265aaed12a8c1630155e8438d9 100644 (file)
@@ -1,5 +1,9 @@
 /* $Id$ */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <pulsecore/hook-list.h>
 #include <pulsecore/log.h>
 
index 3953043fb96bd83194b80d80e03015e177a2b7d7..85a509d4e18ba6af21fd202b3791a46fa92b154a 100644 (file)
@@ -137,7 +137,7 @@ int main(int argc, char *argv[]) {
             pa_gettimeofday(&now);
 
             rtc = pa_timeval_diff(&now, &start);
-            printf("%i\t%llu\t%llu\t%llu\t%llu\t%u\n", k, rtc, t, rtc-old_rtc, t-old_t, changed);
+            printf("%i\t%llu\t%llu\t%llu\t%llu\t%u\n", k, (unsigned long long) rtc, (unsigned long long) t, (unsigned long long) (rtc-old_rtc), (unsigned long long) (t-old_t), changed);
             old_t = t;
             old_rtc = rtc;
         }
index db76712b4f315776939bbe65637147d89e4eca13..d1013118494cb887bae413780d64dd3d97fbb3a9 100644 (file)
@@ -59,24 +59,29 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
             c.index = c.length = 0;
         }
 
-        assert(c.index < c.memblock->length);
+        assert(c.index < pa_memblock_get_length(c.memblock));
 
-        l = c.memblock->length - c.index;
+        l = pa_memblock_get_length(c.memblock) - c.index;
 
         l = l <= 1 ? l : rand() % (l-1) +1 ;
 
-        if ((r = read(STDIN_FILENO, (uint8_t*) c.memblock->data + c.index, l)) <= 0) {
+        p = pa_memblock_acquire(c.memblock);
+
+        if ((r = read(STDIN_FILENO, (uint8_t*) p + c.index, l)) <= 0) {
+            pa_memblock_release(c.memblock);
             fprintf(stderr, "read() failed: %s\n", r < 0 ? strerror(errno) : "EOF");
             break;
         }
 
+        pa_memblock_release(c.memblock);
+
         c.length = r;
         pa_mcalign_push(a, &c);
         fprintf(stderr, "Read %ld bytes\n", (long)r);
 
         c.index += r;
 
-        if (c.index >= c.memblock->length) {
+        if (c.index >= pa_memblock_get_length(c.memblock)) {
             pa_memblock_unref(c.memblock);
             pa_memchunk_reset(&c);
         }
@@ -87,7 +92,9 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
             if (pa_mcalign_pop(a, &t) < 0)
                 break;
 
-            pa_loop_write(STDOUT_FILENO, (uint8_t*) t.memblock->data + t.index, t.length, NULL);
+            p = pa_memblock_acquire(t.memblock);
+            pa_loop_write(STDOUT_FILENO, (uint8_t*) p + t.index, t.length, NULL);
+            pa_memblock_release(t.memblock);
             fprintf(stderr, "Wrote %lu bytes.\n", (unsigned long) t.length);
 
             pa_memblock_unref(t.memblock);
index 8d25ba38fc91124bb476bda2e5f892bda6b26070..2b9d3401d7c3b0384ae4dd55551c350d54cf4fb5 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdio.h>
 #include <unistd.h>
 
 #include <pulsecore/memblock.h>
+#include <pulsecore/macro.h>
 #include <pulse/xmalloc.h>
 
 static void release_cb(pa_memimport *i, uint32_t block_id, void *userdata) {
@@ -76,6 +76,7 @@ int main(int argc, char *argv[]) {
     pa_memblock* blocks[5];
     uint32_t id, shm_id;
     size_t offset, size;
+    char *x;
 
     const char txt[] = "This is a test!";
 
@@ -87,13 +88,20 @@ int main(int argc, char *argv[]) {
     pa_mempool_get_shm_id(pool_b, &id_b);
     pa_mempool_get_shm_id(pool_c, &id_c);
 
-    assert(pool_a && pool_b && pool_c);
+    pa_assert(pool_a && pool_b && pool_c);
 
     blocks[0] = pa_memblock_new_fixed(pool_a, (void*) txt, sizeof(txt), 1);
+
     blocks[1] = pa_memblock_new(pool_a, sizeof(txt));
-    snprintf(blocks[1]->data, blocks[1]->length, "%s", txt);
+    x = pa_memblock_acquire(blocks[1]);
+    snprintf(x, pa_memblock_get_length(blocks[1]), "%s", txt);
+    pa_memblock_release(blocks[1]);
+
     blocks[2] = pa_memblock_new_pool(pool_a, sizeof(txt));
-    snprintf(blocks[2]->data, blocks[2]->length, "%s", txt);
+    x = pa_memblock_acquire(blocks[2]);
+    snprintf(x, pa_memblock_get_length(blocks[2]), "%s", txt);
+    pa_memblock_release(blocks[2]);
+
     blocks[3] = pa_memblock_new_malloced(pool_a, pa_xstrdup(txt), sizeof(txt));
     blocks[4] = NULL;
 
@@ -101,43 +109,47 @@ int main(int argc, char *argv[]) {
         printf("Memory block %u\n", i);
 
         mb_a = blocks[i];
-        assert(mb_a);
+        pa_assert(mb_a);
 
         export_a = pa_memexport_new(pool_a, revoke_cb, (void*) "A");
         export_b = pa_memexport_new(pool_b, revoke_cb, (void*) "B");
 
-        assert(export_a && export_b);
+        pa_assert(export_a && export_b);
 
         import_b = pa_memimport_new(pool_b, release_cb, (void*) "B");
         import_c = pa_memimport_new(pool_c, release_cb, (void*) "C");
 
-        assert(import_b && import_c);
+        pa_assert(import_b && import_c);
 
         r = pa_memexport_put(export_a, mb_a, &id, &shm_id, &offset, &size);
-        assert(r >= 0);
-        assert(shm_id == id_a);
+        pa_assert(r >= 0);
+        pa_assert(shm_id == id_a);
 
         printf("A: Memory block exported as %u\n", id);
 
         mb_b = pa_memimport_get(import_b, id, shm_id, offset, size);
-        assert(mb_b);
+        pa_assert(mb_b);
         r = pa_memexport_put(export_b, mb_b, &id, &shm_id, &offset, &size);
-        assert(r >= 0);
-        assert(shm_id == id_a || shm_id == id_b);
+        pa_assert(r >= 0);
+        pa_assert(shm_id == id_a || shm_id == id_b);
         pa_memblock_unref(mb_b);
 
         printf("B: Memory block exported as %u\n", id);
 
         mb_c = pa_memimport_get(import_c, id, shm_id, offset, size);
-        assert(mb_c);
-        printf("1 data=%s\n", (char*) mb_c->data);
+        pa_assert(mb_c);
+        x = pa_memblock_acquire(mb_c);
+        printf("1 data=%s\n", x);
+        pa_memblock_release(mb_c);
 
         print_stats(pool_a, "A");
         print_stats(pool_b, "B");
         print_stats(pool_c, "C");
 
         pa_memexport_free(export_b);
-        printf("2 data=%s\n", (char*) mb_c->data);
+        x = pa_memblock_acquire(mb_c);
+        printf("2 data=%s\n", x);
+        pa_memblock_release(mb_c);
         pa_memblock_unref(mb_c);
 
         pa_memimport_free(import_b);
index 1c0b7fed3222dc21e885ec40fba8a50ae66df525..25ea399bc52d9c813f5050ef6e24a9153a0f4568 100644 (file)
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <stdio.h>
+#include <signal.h>
 
 #include <pulsecore/memblockq.h>
 #include <pulsecore/log.h>
@@ -48,22 +49,22 @@ int main(int argc, char *argv[]) {
     bq = pa_memblockq_new(0, 40, 10, 2, 4, 4, silence);
     assert(bq);
 
-    chunk1.memblock = pa_memblock_new_fixed(p, (char*) "AA", 2, 1);
+    chunk1.memblock = pa_memblock_new_fixed(p, (char*) "11", 2, 1);
     chunk1.index = 0;
     chunk1.length = 2;
     assert(chunk1.memblock);
 
-    chunk2.memblock = pa_memblock_new_fixed(p, (char*) "TTBB", 4, 1);
+    chunk2.memblock = pa_memblock_new_fixed(p, (char*) "XX22", 4, 1);
     chunk2.index = 2;
     chunk2.length = 2;
     assert(chunk2.memblock);
 
-    chunk3.memblock = pa_memblock_new_fixed(p, (char*) "ZZZZ", 4, 1);
+    chunk3.memblock = pa_memblock_new_fixed(p, (char*) "3333", 4, 1);
     chunk3.index = 0;
     chunk3.length = 4;
     assert(chunk3.memblock);
 
-    chunk4.memblock = pa_memblock_new_fixed(p, (char*) "KKKKKKKK", 8, 1);
+    chunk4.memblock = pa_memblock_new_fixed(p, (char*) "44444444", 8, 1);
     chunk4.index = 0;
     chunk4.length = 8;
     assert(chunk4.memblock);
@@ -115,13 +116,12 @@ int main(int argc, char *argv[]) {
 
     chunk3.index += 2;
     chunk3.length -= 2;
-
     ret = pa_memblockq_push(bq, &chunk3);
     assert(ret == 0);
 
-    printf(">");
+    pa_memblockq_shorten(bq, pa_memblockq_get_length(bq)-2);
 
-    pa_memblockq_shorten(bq, 6);
+    printf(">");
 
     for (;;) {
         pa_memchunk out;
@@ -131,11 +131,13 @@ int main(int argc, char *argv[]) {
         if (pa_memblockq_peek(bq, &out) < 0)
             break;
 
-        for (e = (char*) out.memblock->data + out.index, n = 0; n < out.length; n++)
+        p = pa_memblock_acquire(out.memblock);
+        for (e = (char*) p + out.index, n = 0; n < out.length; n++)
             printf("%c", *e);
+        pa_memblock_release(out.memblock);
 
         pa_memblock_unref(out.memblock);
-        pa_memblockq_drop(bq, &out, out.length);
+        pa_memblockq_drop(bq, out.length);
     }
 
     printf("<\n");
diff --git a/src/tests/queue-test.c b/src/tests/queue-test.c
new file mode 100644 (file)
index 0000000..b357ab1
--- /dev/null
@@ -0,0 +1,69 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published
+  by the Free Software Foundation; either version 2 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 <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <pulse/util.h>
+#include <pulse/xmalloc.h>
+#include <pulsecore/queue.h>
+#include <pulsecore/log.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
+
+int main(int argc, char *argv[]) {
+    pa_queue *q;
+
+    pa_assert_se(q = pa_queue_new());
+
+    pa_assert(pa_queue_is_empty(q));
+
+    pa_queue_push(q, (void*) "eins");
+    pa_log("%s\n", (char*) pa_queue_pop(q));
+
+    pa_assert(pa_queue_is_empty(q));
+
+    pa_queue_push(q, (void*) "zwei");
+    pa_queue_push(q, (void*) "drei");
+    pa_queue_push(q, (void*) "vier");
+
+    pa_log("%s\n", (char*) pa_queue_pop(q));
+    pa_log("%s\n", (char*) pa_queue_pop(q));
+
+    pa_queue_push(q, (void*) "fuenf");
+
+    pa_log("%s\n", (char*) pa_queue_pop(q));
+    pa_log("%s\n", (char*) pa_queue_pop(q));
+
+    pa_assert(pa_queue_is_empty(q));
+
+    pa_queue_push(q, (void*) "sechs");
+    pa_queue_push(q, (void*) "sieben");
+
+    pa_queue_free(q, NULL, NULL);
+
+    return 0;
+}
diff --git a/src/tests/resampler-test.c b/src/tests/resampler-test.c
new file mode 100644 (file)
index 0000000..3b4a738
--- /dev/null
@@ -0,0 +1,227 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published
+  by the Free Software Foundation; either version 2 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 <pulse/sample.h>
+#include <pulse/volume.h>
+
+#include <pulsecore/resampler.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/endianmacros.h>
+#include <pulsecore/memblock.h>
+#include <pulsecore/sample-util.h>
+
+#include <liboil/liboil.h>
+
+static float swap_float(float a) {
+    uint32_t *b = (uint32_t*) &a;
+    *b = PA_UINT32_SWAP(*b);
+    return a;
+}
+
+static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) {
+    void *d;
+    unsigned i;
+
+    d = pa_memblock_acquire(chunk->memblock);
+
+    switch (ss->format) {
+
+        case PA_SAMPLE_U8:
+        case PA_SAMPLE_ULAW:
+        case PA_SAMPLE_ALAW: {
+            uint8_t *u = d;
+
+            for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
+                printf("0x%02x ", *(u++));
+
+            break;
+        }
+
+        case PA_SAMPLE_S16NE:
+        case PA_SAMPLE_S16RE: {
+            uint16_t *u = d;
+
+            for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
+                printf("0x%04x ", *(u++));
+
+            break;
+        }
+
+        case PA_SAMPLE_FLOAT32NE:
+        case PA_SAMPLE_FLOAT32RE: {
+            float *u = d;
+
+            for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
+                printf("%1.3g ",  ss->format == PA_SAMPLE_FLOAT32NE ? *u : swap_float(*u));
+                u++;
+            }
+
+            break;
+        }
+
+        default:
+            pa_assert_not_reached();
+    }
+
+    printf("\n");
+
+    pa_memblock_release(chunk->memblock);
+}
+
+static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) {
+    pa_memblock *r;
+    void *d;
+    unsigned i;
+
+    pa_assert_se(r = pa_memblock_new(pool, pa_frame_size(ss) * 10));
+    d = pa_memblock_acquire(r);
+
+    switch (ss->format) {
+
+        case PA_SAMPLE_U8:
+        case PA_SAMPLE_ULAW:
+        case PA_SAMPLE_ALAW: {
+            uint8_t *u = d;
+
+            u[0] = 0x00;
+            u[1] = 0xFF;
+            u[2] = 0x7F;
+            u[3] = 0x80;
+            u[4] = 0x9f;
+            u[5] = 0x3f;
+            u[6] = 0x1;
+            u[7] = 0xF0;
+            u[8] = 0x20;
+            u[9] = 0x21;
+            break;
+        }
+
+        case PA_SAMPLE_S16NE:
+        case PA_SAMPLE_S16RE: {
+            uint16_t *u = d;
+
+            u[0] = 0x0000;
+            u[1] = 0xFFFF;
+            u[2] = 0x7FFF;
+            u[3] = 0x8000;
+            u[4] = 0x9fff;
+            u[5] = 0x3fff;
+            u[6] = 0x1;
+            u[7] = 0xF000;
+            u[8] = 0x20;
+            u[9] = 0x21;
+            break;
+        }
+
+        case PA_SAMPLE_FLOAT32NE:
+        case PA_SAMPLE_FLOAT32RE: {
+            float *u = d;
+
+            u[0] = 0.0;
+            u[1] = -1.0;
+            u[2] = 1.0;
+            u[3] = 4711;
+            u[4] = 0.222;
+            u[5] = 0.33;
+            u[6] = -.3;
+            u[7] = 99;
+            u[8] = -0.555;
+            u[9] = -.123;
+
+            if (ss->format == PA_SAMPLE_FLOAT32RE)
+                for (i = 0; i < 10; i++)
+                    u[i] = swap_float(u[i]);
+
+            break;
+        }
+
+        default:
+            pa_assert_not_reached();
+    }
+
+    pa_memblock_release(r);
+
+    return r;
+}
+
+int main(int argc, char *argv[]) {
+    pa_mempool *pool;
+    pa_sample_spec a, b;
+    pa_cvolume v;
+
+    oil_init();
+    pa_log_set_maximal_level(PA_LOG_DEBUG);
+
+    pa_assert_se(pool = pa_mempool_new(FALSE));
+
+    a.channels = b.channels = 1;
+    a.rate = b.rate = 44100;
+
+    v.channels = a.channels;
+    v.values[0] = pa_sw_volume_from_linear(0.5);
+
+    for (a.format = 0; a.format < PA_SAMPLE_MAX; a.format ++) {
+        for (b.format = 0; b.format < PA_SAMPLE_MAX; b.format ++) {
+
+            pa_resampler *forth, *back;
+            pa_memchunk i, j, k;
+
+            printf("=== %s -> %s -> %s -> /2\n",
+                   pa_sample_format_to_string(a.format),
+                   pa_sample_format_to_string(b.format),
+                   pa_sample_format_to_string(a.format));
+
+            pa_assert_se(forth = pa_resampler_new(pool, &a, NULL, &b, NULL, PA_RESAMPLER_AUTO, FALSE));
+            pa_assert_se(back = pa_resampler_new(pool, &b, NULL, &a, NULL, PA_RESAMPLER_AUTO, FALSE));
+
+            i.memblock = generate_block(pool, &a);
+            i.length = pa_memblock_get_length(i.memblock);
+            i.index = 0;
+            pa_resampler_run(forth, &i, &j);
+            pa_resampler_run(back, &j, &k);
+
+            dump_block(&a, &i);
+            dump_block(&b, &j);
+            dump_block(&a, &k);
+
+            pa_memblock_unref(j.memblock);
+            pa_memblock_unref(k.memblock);
+
+            pa_volume_memchunk(&i, &a, &v);
+            dump_block(&a, &i);
+
+            pa_memblock_unref(i.memblock);
+
+            pa_resampler_free(forth);
+            pa_resampler_free(back);
+        }
+    }
+
+    pa_mempool_free(pool);
+
+    return 0;
+}
diff --git a/src/tests/rtpoll-test.c b/src/tests/rtpoll-test.c
new file mode 100644 (file)
index 0000000..3ab992a
--- /dev/null
@@ -0,0 +1,91 @@
+/* $Id: thread-test.c 1621 2007-08-10 22:00:22Z lennart $ */
+
+/***
+  This file is part of PulseAudio.
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published
+  by the Free Software Foundation; either version 2 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 <signal.h>
+#include <poll.h>
+
+#include <pulsecore/log.h>
+#include <pulsecore/rtpoll.h>
+#include <pulsecore/rtsig.h>
+
+static int before(pa_rtpoll_item *i) {
+    pa_log("before");
+    return 0;
+}
+
+static void after(pa_rtpoll_item *i) {
+    pa_log("after");
+}
+
+static int worker(pa_rtpoll_item *w) {
+    pa_log("worker");
+    return 0;
+}
+
+int main(int argc, char *argv[]) {
+    pa_rtpoll *p;
+    pa_rtpoll_item *i, *w;
+    struct pollfd *pollfd;
+
+    pa_rtsig_configure(SIGRTMIN+10, SIGRTMAX);
+
+    p = pa_rtpoll_new();
+
+    i = pa_rtpoll_item_new(p, PA_RTPOLL_EARLY, 1);
+    pa_rtpoll_item_set_before_callback(i, before);
+    pa_rtpoll_item_set_after_callback(i, after);
+
+    pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
+    pollfd->fd = 0;
+    pollfd->events = POLLIN;
+
+    w = pa_rtpoll_item_new(p, PA_RTPOLL_NORMAL, 0);
+    pa_rtpoll_item_set_before_callback(w, worker);
+
+    pa_rtpoll_install(p);
+    pa_rtpoll_set_timer_periodic(p, 10000000); /* 10 s */
+
+    pa_rtpoll_run(p, 1);
+
+    pa_rtpoll_item_free(i);
+
+    i = pa_rtpoll_item_new(p, PA_RTPOLL_EARLY, 1);
+    pa_rtpoll_item_set_before_callback(i, before);
+    pa_rtpoll_item_set_after_callback(i, after);
+
+    pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
+    pollfd->fd = 0;
+    pollfd->events = POLLIN;
+
+    pa_rtpoll_run(p, 1);
+
+    pa_rtpoll_item_free(i);
+
+    pa_rtpoll_item_free(w);
+
+    pa_rtpoll_free(p);
+
+    return 0;
+}
diff --git a/src/tests/sig2str-test.c b/src/tests/sig2str-test.c
new file mode 100644 (file)
index 0000000..52cb9db
--- /dev/null
@@ -0,0 +1,39 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published
+  by the Free Software Foundation; either version 2 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 <signal.h>
+#include <stdio.h>
+
+#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
+
+int main(int argc, char *argv[]) {
+    int sig;
+
+    for (sig = -1; sig <= NSIG; sig++)
+        printf("%i = %s\n", sig, pa_sig2str(sig));
+
+    return 0;
+}
diff --git a/src/tests/smoother-test.c b/src/tests/smoother-test.c
new file mode 100644 (file)
index 0000000..caa7df7
--- /dev/null
@@ -0,0 +1,80 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published
+  by the Free Software Foundation; either version 2 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 <pulsecore/time-smoother.h>
+#include <pulse/timeval.h>
+
+int main(int argc, char*argv[]) {
+    pa_usec_t x;
+    unsigned u = 0;
+    pa_smoother *s;
+    int m;
+
+/*     unsigned msec[] = { */
+/*         200, 200, */
+/*         300, 320, */
+/*         400, 400, */
+/*         500, 480, */
+/*         0, 0 */
+/*     }; */
+
+    int msec[200];
+
+    srand(0);
+
+    for (m = 0, u = 0; u < PA_ELEMENTSOF(msec)-2; u+= 2) {
+
+        msec[u] = m+1;
+        msec[u+1] = m + rand() % 2000 - 1000;
+
+        m += rand() % 100;
+
+        if (msec[u+1] < 0)
+            msec[u+1] = 0;
+    }
+
+    msec[PA_ELEMENTSOF(msec)-2] = 0;
+    msec[PA_ELEMENTSOF(msec)-1] = 0;
+
+    s = pa_smoother_new(1000*PA_USEC_PER_MSEC, 2000*PA_USEC_PER_MSEC, TRUE);
+
+    for (x = 0, u = 0; x < PA_USEC_PER_SEC * 10; x += PA_USEC_PER_MSEC) {
+
+        while (msec[u] > 0 && (pa_usec_t) msec[u]*PA_USEC_PER_MSEC < x) {
+            pa_smoother_put(s, msec[u]*PA_USEC_PER_MSEC, msec[u+1]*PA_USEC_PER_MSEC);
+            printf("%i\t\t%i\n", msec[u],  msec[u+1]);
+            u += 2;
+        }
+
+        printf("%llu\t%llu\n", x/PA_USEC_PER_MSEC, pa_smoother_get(s, x)/PA_USEC_PER_MSEC);
+    }
+
+    pa_smoother_free(s);
+
+    return 0;
+}
index 9d0e5de16e68b379b7264c4f3cad3aa570ca7174..558e53a5bd401821b97713e2e281db5480605b73 100644 (file)
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
 
 #include <pulse/timeval.h>
 #include <pulse/util.h>
+#include <pulse/thread-mainloop.h>
 
 #include <pulsecore/gccmacro.h>
-#include <pulse/thread-mainloop.h>
+#include <pulsecore/macro.h>
 
 static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) {
+    pa_assert_se(pa_threaded_mainloop_in_thread(userdata));
     fprintf(stderr, "TIME EVENT START\n");
     pa_threaded_mainloop_signal(userdata, 1);
     fprintf(stderr, "TIME EVENT END\n");
@@ -45,15 +46,15 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
     pa_threaded_mainloop *m;
     struct timeval tv;
 
-    m = pa_threaded_mainloop_new();
-    assert(m);
-    a = pa_threaded_mainloop_get_api(m);
-    assert(a);
+    pa_assert_se(m = pa_threaded_mainloop_new());
+    pa_assert_se(a = pa_threaded_mainloop_get_api(m));
 
     pa_threaded_mainloop_start(m);
 
     pa_threaded_mainloop_lock(m);
 
+    pa_assert_se(!pa_threaded_mainloop_in_thread(m));
+
     pa_gettimeofday(&tv);
     tv.tv_sec += 5;
     a->time_new(a, &tv, tcb, m);
index 2153c98546f73b373dfe1ccb0d8f1b77238149eb..72dde6cbb942201727ba8d4fbbbd3a81fe807fca 100644 (file)
@@ -42,7 +42,7 @@ static void once_func(void) {
     pa_log("once!");
 }
 
-static pa_once_t once = PA_ONCE_INIT;
+static pa_once once = PA_ONCE_INIT;
 
 static void thread_func(void *data) {
     pa_tls_set(tls, data);
@@ -72,7 +72,7 @@ static void thread_func(void *data) {
 
         pa_mutex_unlock(mutex);
 
-        pa_once(&once, once_func);
+        pa_run_once(&once, once_func);
 
         pa_cond_signal(cond2, 0);
 
@@ -98,7 +98,7 @@ int main(int argc, char *argv[]) {
 
     assert(pa_thread_is_running(pa_thread_self()));
 
-    mutex = pa_mutex_new(0);
+    mutex = pa_mutex_new(FALSE, FALSE);
     cond1 = pa_cond_new();
     cond2 = pa_cond_new();
     tls = pa_tls_new(pa_xfree);
index b95cbfeee0ca612dc05e03f70cdbd0a8e2f43f17..c963987ff8b61329eee12aab0fd5168279a641b9 100644 (file)
 static pa_context *context = NULL;
 static pa_mainloop_api *mainloop_api = NULL;
 
-static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL;
+static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL, *module_name = NULL, *module_args = NULL;
 static uint32_t sink_input_idx = PA_INVALID_INDEX, source_output_idx = PA_INVALID_INDEX;
+static uint32_t module_index;
+static int suspend;
 
 static SNDFILE *sndfile = NULL;
 static pa_stream *sample_stream = NULL;
@@ -69,7 +71,11 @@ static enum {
     REMOVE_SAMPLE,
     LIST,
     MOVE_SINK_INPUT,
-    MOVE_SOURCE_OUTPUT
+    MOVE_SOURCE_OUTPUT,
+    LOAD_MODULE,
+    UNLOAD_MODULE,
+    SUSPEND_SINK,
+    SUSPEND_SOURCE,
 } action = NONE;
 
 static void quit(int ret) {
@@ -354,7 +360,7 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info
            i->sink,
            pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
            pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
-           pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
+           i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
            (double) i->buffer_usec,
            (double) i->sink_usec,
            i->resample_method ? i->resample_method : "n/a");
@@ -492,6 +498,18 @@ static void simple_callback(pa_context *c, int success, void *userdata) {
     complete_action();
 }
 
+static void index_callback(pa_context *c, uint32_t idx, void *userdata) {
+    if (idx == PA_INVALID_INDEX) {
+        fprintf(stderr, "Failure: %s\n", pa_strerror(pa_context_errno(c)));
+        quit(1);
+        return;
+    }
+
+    printf("%u\n", idx);
+
+    complete_action();
+}
+
 static void stream_state_callback(pa_stream *s, void *userdata) {
     assert(s);
 
@@ -594,6 +612,28 @@ static void context_state_callback(pa_context *c, void *userdata) {
                     pa_operation_unref(pa_context_move_source_output_by_name(c, source_output_idx, source_name, simple_callback, NULL));
                     break;
 
+                case LOAD_MODULE:
+                    pa_operation_unref(pa_context_load_module(c, module_name, module_args, index_callback, NULL));
+                    break;
+
+                case UNLOAD_MODULE:
+                    pa_operation_unref(pa_context_unload_module(c, module_index, simple_callback, NULL));
+                    break;
+
+                case SUSPEND_SINK:
+                    if (sink_name)
+                        pa_operation_unref(pa_context_suspend_sink_by_name(c, sink_name, suspend, simple_callback, NULL));
+                    else
+                        pa_operation_unref(pa_context_suspend_sink_by_index(c, PA_INVALID_INDEX, suspend, simple_callback, NULL));
+                    break;
+
+                case SUSPEND_SOURCE:
+                    if (source_name)
+                        pa_operation_unref(pa_context_suspend_source_by_name(c, source_name, suspend, simple_callback, NULL));
+                    else
+                        pa_operation_unref(pa_context_suspend_source_by_index(c, PA_INVALID_INDEX, suspend, simple_callback, NULL));
+                    break;
+
                 default:
                     assert(0);
             }
@@ -624,12 +664,16 @@ static void help(const char *argv0) {
            "%s [options] play-sample NAME [SINK]\n"
            "%s [options] move-sink-input ID SINK\n"
            "%s [options] move-source-output ID SOURCE\n"
-           "%s [options] remove-sample NAME\n\n"
+           "%s [options] remove-sample NAME\n"
+           "%s [options] load-module NAME [ARGS ...]\n"
+           "%s [options] unload-module ID\n"
+           "%s [options] suspend-sink [SINK] 1|0\n"
+           "%s [options] suspend-source [SOURCE] 1|0\n\n"
            "  -h, --help                            Show this help\n"
            "      --version                         Show version\n\n"
            "  -s, --server=SERVER                   The name of the server to connect to\n"
            "  -n, --client-name=NAME                How to call this client on the server\n",
-           argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0);
+           argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0);
 }
 
 enum { ARG_VERSION = 256 };
@@ -728,7 +772,7 @@ int main(int argc, char *argv[]) {
             sample_length = sfinfo.frames*pa_frame_size(&sample_spec);
         } else if (!strcmp(argv[optind], "play-sample")) {
             action = PLAY_SAMPLE;
-            if (optind+1 >= argc) {
+            if (argc != optind+2 && argc != optind+3) {
                 fprintf(stderr, "You have to specify a sample name to play\n");
                 goto quit;
             }
@@ -740,7 +784,7 @@ int main(int argc, char *argv[]) {
 
         } else if (!strcmp(argv[optind], "remove-sample")) {
             action = REMOVE_SAMPLE;
-            if (optind+1 >= argc) {
+            if (argc != optind+2) {
                 fprintf(stderr, "You have to specify a sample name to remove\n");
                 goto quit;
             }
@@ -748,7 +792,7 @@ int main(int argc, char *argv[]) {
             sample_name = pa_xstrdup(argv[optind+1]);
         } else if (!strcmp(argv[optind], "move-sink-input")) {
             action = MOVE_SINK_INPUT;
-            if (optind+2 >= argc) {
+            if (argc != optind+3) {
                 fprintf(stderr, "You have to specify a sink input index and a sink\n");
                 goto quit;
             }
@@ -757,13 +801,72 @@ int main(int argc, char *argv[]) {
             sink_name = pa_xstrdup(argv[optind+2]);
         } else if (!strcmp(argv[optind], "move-source-output")) {
             action = MOVE_SOURCE_OUTPUT;
-            if (optind+2 >= argc) {
+            if (argc != optind+3) {
                 fprintf(stderr, "You have to specify a source output index and a source\n");
                 goto quit;
             }
 
             source_output_idx = atoi(argv[optind+1]);
             source_name = pa_xstrdup(argv[optind+2]);
+        } else if (!strcmp(argv[optind], "load-module")) {
+            int i;
+            size_t n = 0;
+            char *p;
+
+            action = LOAD_MODULE;
+
+            if (argc <= optind+1) {
+                fprintf(stderr, "You have to specify a module name and arguments.\n");
+                goto quit;
+            }
+
+            module_name = argv[optind+1];
+
+            for (i = optind+2; i < argc; i++)
+                n += strlen(argv[i])+1;
+
+            if (n > 0) {
+                p = module_args = pa_xnew0(char, n);
+
+                for (i = optind+2; i < argc; i++)
+                    p += sprintf(p, "%s%s", p == module_args ? "" : " ", argv[i]);
+            }
+
+        } else if (!strcmp(argv[optind], "unload-module")) {
+            action = UNLOAD_MODULE;
+
+            if (argc != optind+2) {
+                fprintf(stderr, "You have to specify a module index\n");
+                goto quit;
+            }
+
+            module_index = atoi(argv[optind+1]);
+
+        } else if (!strcmp(argv[optind], "suspend-sink")) {
+            action = SUSPEND_SINK;
+
+            if (argc > optind+3 || optind+1 >= argc) {
+                fprintf(stderr, "You may not specify more than one sink. You have to specify at least one boolean value.\n");
+                goto quit;
+            }
+
+            suspend = !!atoi(argv[argc-1]);
+
+            if (argc > optind+2)
+                sink_name = pa_xstrdup(argv[optind+1]);
+
+        } else if (!strcmp(argv[optind], "suspend-source")) {
+            action = SUSPEND_SOURCE;
+
+            if (argc > optind+3 || optind+1 >= argc) {
+                fprintf(stderr, "You may not specify more than one source. You have to specify at least one boolean value.\n");
+                goto quit;
+            }
+
+            suspend = !!atoi(argv[argc-1]);
+
+            if (argc > optind+2)
+                source_name = pa_xstrdup(argv[optind+1]);
         }
     }
 
@@ -819,6 +922,8 @@ quit:
     pa_xfree(sample_name);
     pa_xfree(sink_name);
     pa_xfree(source_name);
+    pa_xfree(module_args);
+    pa_xfree(client_name);
 
     return ret;
 }
index 95fc9ed3e9610b4d58c45e5aaa0e923e3beeca9b..b48af93cd67a5b05060ba56a67a25b3cb8d9b587 100644 (file)
 # define SIOCINQ FIONREAD
 #endif
 
+/* make sure gcc doesn't redefine open and friends as macros */
+#undef open
+#undef open64
+
 typedef enum {
     FD_INFO_MIXER,
     FD_INFO_STREAM,
@@ -259,9 +263,9 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \
 
 static void debug(int level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3);
 
-#define DEBUG_LEVEL_ALWAYS             0
-#define DEBUG_LEVEL_NORMAL             1
-#define DEBUG_LEVEL_VERBOSE            2
+#define DEBUG_LEVEL_ALWAYS                0
+#define DEBUG_LEVEL_NORMAL                1
+#define DEBUG_LEVEL_VERBOSE                2
 
 static void debug(int level, const char *format, ...) {
     va_list ap;
@@ -421,7 +425,7 @@ static void fd_info_unref(fd_info *i) {
     pthread_mutex_lock(&i->mutex);
     assert(i->ref >= 1);
     r = --i->ref;
-       debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref);
+        debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref);
     pthread_mutex_unlock(&i->mutex);
 
     if (r <= 0)
@@ -1395,7 +1399,7 @@ static int sndstat_open(int flags, int *_errno) {
 
     if (flags != O_RDONLY
 #ifdef O_LARGEFILE
-       && flags != (O_RDONLY|O_LARGEFILE)
+        && flags != (O_RDONLY|O_LARGEFILE)
 #endif
        ) {
         *_errno = EACCES;
@@ -1436,34 +1440,23 @@ fail:
     return -1;
 }
 
-int open(const char *filename, int flags, ...) {
-    va_list args;
-    mode_t mode = 0;
+static int real_open(const char *filename, int flags, mode_t mode) {
     int r, _errno = 0;
 
     debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename);
 
-    va_start(args, flags);
-    if (flags & O_CREAT) {
-      if (sizeof(mode_t) < sizeof(int))
-       mode = va_arg(args, int);
-      else
-        mode = va_arg(args, mode_t);
-    }
-    va_end(args);
-
     if (!function_enter()) {
         LOAD_OPEN_FUNC();
         return _open(filename, flags, mode);
     }
 
-    if (dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0)) {
+    if (dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0))
         r = dsp_open(flags, &_errno);
-    } else if (mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0) {
+    else if (mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0)
         r = mixer_open(flags, &_errno);
-    } else if (sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0) {
+    else if (sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0)
         r = sndstat_open(flags, &_errno);
-    else {
+    else {
         function_exit();
         LOAD_OPEN_FUNC();
         return _open(filename, flags, mode);
@@ -1477,6 +1470,22 @@ int open(const char *filename, int flags, ...) {
     return r;
 }
 
+int open(const char *filename, int flags, ...) {
+    va_list args;
+    mode_t mode = 0;
+
+    if (flags & O_CREAT) {
+        va_start(args, flags);
+        if (sizeof(mode_t) < sizeof(int))
+            mode = va_arg(args, int);
+        else
+            mode = va_arg(args, mode_t);
+        va_end(args);
+    }
+
+    return real_open(filename, flags, mode);
+}
+
 static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) {
     int ret = -1;
 
@@ -2023,9 +2032,9 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno)
 
             *(int*)  argp = DSP_CAP_DUPLEX | DSP_CAP_TRIGGER
 #ifdef DSP_CAP_MULTI
-             | DSP_CAP_MULTI
+              | DSP_CAP_MULTI
 #endif
-             ;
+              ;
             break;
 
         case SNDCTL_DSP_GETODELAY: {
@@ -2497,10 +2506,14 @@ int open64(const char *filename, int flags, ...) {
 
     debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename);
 
-    va_start(args, flags);
-    if (flags & O_CREAT)
-        mode = va_arg(args, mode_t);
-    va_end(args);
+    if (flags & O_CREAT) {
+        va_start(args, flags);
+        if (sizeof(mode_t) < sizeof(int))
+            mode = va_arg(args, int);
+        else
+            mode = va_arg(args, mode_t);
+        va_end(args);
+    }
 
     if (strcmp(filename, "/dev/dsp") != 0 &&
         strcmp(filename, "/dev/adsp") != 0 &&
@@ -2510,7 +2523,7 @@ int open64(const char *filename, int flags, ...) {
         return _open64(filename, flags, mode);
     }
 
-    return open(filename, flags, mode);
+    return real_open(filename, flags, mode);
 }
 
 #endif
@@ -2602,7 +2615,7 @@ FILE* fopen(const char *filename, const char *mode) {
     if ((((mode[1] == 'b') || (mode[1] == 't')) && (mode[2] == '+')) || (mode[1] == '+'))
         m = O_RDWR;
 
-    if ((fd = open(filename, m)) < 0)
+    if ((fd = real_open(filename, m, 0)) < 0)
         return NULL;
 
     if (!(f = fdopen(fd, mode))) {
index 2c779a7a3ea9d67644228a879480dbc416517930..e7076d2d3362c800c3b0315a8c43b473f251be3d 100644 (file)
@@ -123,7 +123,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) {
     else
         pa_xfree(data);
 
-    if (bytes < length) {
+    if (bytes < (sf_count_t) length) {
         sf_close(sndfile);
         sndfile = NULL;
         pa_operation_unref(pa_stream_drain(s, stream_drain_complete, NULL));
diff --git a/src/utils/pasuspender.c b/src/utils/pasuspender.c
new file mode 100644 (file)
index 0000000..ae59086
--- /dev/null
@@ -0,0 +1,316 @@
+/* $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 <sys/types.h>
+#include <sys/wait.h>
+
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <getopt.h>
+
+#include <sndfile.h>
+
+#ifdef __linux__
+#include <sys/prctl.h>
+#endif
+
+#include <pulse/pulseaudio.h>
+#include <pulsecore/macro.h>
+
+#if PA_API_VERSION < 10
+#error Invalid PulseAudio API version
+#endif
+
+#define BUFSIZE 1024
+
+static pa_context *context = NULL;
+static pa_mainloop_api *mainloop_api = NULL;
+static char **child_argv = NULL;
+static int child_argc = 0;
+static pid_t child_pid = (pid_t) -1;
+static int child_ret = 0;
+static int dead = 1;
+
+static void quit(int ret) {
+    pa_assert(mainloop_api);
+    mainloop_api->quit(mainloop_api, ret);
+}
+
+
+static void context_drain_complete(pa_context *c, void *userdata) {
+    pa_context_disconnect(c);
+}
+
+static void drain(void) {
+    pa_operation *o;
+
+    if (!(o = pa_context_drain(context, context_drain_complete, NULL)))
+        pa_context_disconnect(context);
+    else
+        pa_operation_unref(o);
+}
+
+static void start_child(void) {
+
+    if ((child_pid = fork()) < 0) {
+
+        fprintf(stderr, "fork(): %s\n", strerror(errno));
+        quit(1);
+
+    } else if (child_pid == 0) {
+        /* Child */
+
+#ifdef __linux__
+        prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
+#endif
+
+        if (execvp(child_argv[0], child_argv) < 0)
+            fprintf(stderr, "execvp(): %s\n", strerror(errno));
+
+        _exit(1);
+
+    } else {
+
+        /* parent */
+        dead = 0;
+    }
+}
+
+static void suspend_complete(pa_context *c, int success, void *userdata) {
+    static int n = 0;
+
+    n++;
+
+    if (!success) {
+        fprintf(stderr, "Failure to suspend: %s\n", pa_strerror(pa_context_errno(c)));
+        quit(1);
+        return;
+    }
+
+    if (n >= 2)
+        start_child();
+}
+
+static void resume_complete(pa_context *c, int success, void *userdata) {
+    static int n = 0;
+
+    n++;
+
+    if (!success) {
+        fprintf(stderr, "Failure to resume: %s\n", pa_strerror(pa_context_errno(c)));
+        quit(1);
+        return;
+    }
+
+    if (n >= 2)
+        drain(); /* drain and quit */
+}
+
+static void context_state_callback(pa_context *c, void *userdata) {
+    pa_assert(c);
+
+    switch (pa_context_get_state(c)) {
+        case PA_CONTEXT_CONNECTING:
+        case PA_CONTEXT_AUTHORIZING:
+        case PA_CONTEXT_SETTING_NAME:
+            break;
+
+        case PA_CONTEXT_READY:
+            if (pa_context_is_local(c)) {
+                pa_operation_unref(pa_context_suspend_sink_by_index(c, PA_INVALID_INDEX, 1, suspend_complete, NULL));
+                pa_operation_unref(pa_context_suspend_source_by_index(c, PA_INVALID_INDEX, 1, suspend_complete, NULL));
+            } else
+                start_child();
+
+            break;
+
+        case PA_CONTEXT_TERMINATED:
+            quit(0);
+            break;
+
+        case PA_CONTEXT_FAILED:
+        default:
+            fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c)));
+
+            pa_context_unref(context);
+            context = NULL;
+
+            if (child_pid == (pid_t) -1)
+                /* not started yet, then we do it now */
+                start_child();
+            else if (dead)
+                /* already started, and dead, so let's quit */
+                quit(1);
+
+            break;
+    }
+}
+
+static void sigint_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) {
+    fprintf(stderr, "Got SIGINT, exiting.\n");
+    quit(0);
+}
+
+static void sigchld_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) {
+    int status = 0;
+    pid_t p;
+
+    p = waitpid(-1, &status, WNOHANG);
+
+    if (p != child_pid)
+        return;
+
+    dead = 1;
+
+    if (WIFEXITED(status))
+        child_ret = WEXITSTATUS(status);
+    else if (WIFSIGNALED(status)) {
+        fprintf(stderr, "WARNING: Child process terminated by signal %u\n", WTERMSIG(status));
+        child_ret = 1;
+    }
+
+    if (context) {
+        if (pa_context_is_local(context)) {
+            /* A context is around, so let's resume */
+            pa_operation_unref(pa_context_suspend_sink_by_index(context, PA_INVALID_INDEX, 0, resume_complete, NULL));
+            pa_operation_unref(pa_context_suspend_source_by_index(context, PA_INVALID_INDEX, 0, resume_complete, NULL));
+        } else
+            drain();
+    } else
+        /* Hmm, no context here, so let's terminate right away */
+        quit(0);
+}
+
+static void help(const char *argv0) {
+
+    printf("%s [options] ... \n\n"
+           "  -h, --help                            Show this help\n"
+           "      --version                         Show version\n"
+           "  -s, --server=SERVER                   The name of the server to connect to\n\n",
+           argv0);
+}
+
+enum {
+    ARG_VERSION = 256
+};
+
+int main(int argc, char *argv[]) {
+    pa_mainloop* m = NULL;
+    int c, ret = 1;
+    char *server = NULL, *bn;
+
+    static const struct option long_options[] = {
+        {"server",      1, NULL, 's'},
+        {"version",     0, NULL, ARG_VERSION},
+        {"help",        0, NULL, 'h'},
+        {NULL,          0, NULL, 0}
+    };
+
+    if (!(bn = strrchr(argv[0], '/')))
+        bn = argv[0];
+    else
+        bn++;
+
+    while ((c = getopt_long(argc, argv, "s:h", long_options, NULL)) != -1) {
+        switch (c) {
+            case 'h' :
+                help(bn);
+                ret = 0;
+                goto quit;
+
+            case ARG_VERSION:
+                printf("pasuspender "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version());
+                ret = 0;
+                goto quit;
+
+            case 's':
+                pa_xfree(server);
+                server = pa_xstrdup(optarg);
+                break;
+
+            default:
+                goto quit;
+        }
+    }
+
+    child_argv = argv + optind;
+    child_argc = argc - optind;
+
+    if (child_argc <= 0) {
+        help(bn);
+        ret = 0;
+        goto quit;
+    }
+
+    if (!(m = pa_mainloop_new())) {
+        fprintf(stderr, "pa_mainloop_new() failed.\n");
+        goto quit;
+    }
+
+    pa_assert_se(mainloop_api = pa_mainloop_get_api(m));
+    pa_assert_se(pa_signal_init(mainloop_api) == 0);
+    pa_signal_new(SIGINT, sigint_callback, NULL);
+    pa_signal_new(SIGCHLD, sigchld_callback, NULL);
+#ifdef SIGPIPE
+    signal(SIGPIPE, SIG_IGN);
+#endif
+
+    if (!(context = pa_context_new(mainloop_api, bn))) {
+        fprintf(stderr, "pa_context_new() failed.\n");
+        goto quit;
+    }
+
+    pa_context_set_state_callback(context, context_state_callback, NULL);
+    pa_context_connect(context, server, PA_CONTEXT_NOAUTOSPAWN, NULL);
+
+    if (pa_mainloop_run(m, &ret) < 0) {
+        fprintf(stderr, "pa_mainloop_run() failed.\n");
+        goto quit;
+    }
+
+quit:
+    if (context)
+        pa_context_unref(context);
+
+    if (m) {
+        pa_signal_done();
+        pa_mainloop_free(m);
+    }
+
+    pa_xfree(server);
+
+    if (!dead)
+        kill(child_pid, SIGTERM);
+
+    return ret == 0 ? child_ret : ret;
+}
diff --git a/todo b/todo
index 7b4ce7864135b49ea5b20ef8ff692bf95df8125a..f579bebe3b8a1220d331dc233675a9ab2beb8c72 100644 (file)
--- a/todo
+++ b/todo
@@ -4,7 +4,6 @@ Build System:
 - Remove symdef files and use macros (like most other projects)
 - Use own name mangling scheme instead of ltdl's, which will eliminate the
   need for .la files or extra trickery.
-- build pulsecore only statically by default, it's not a public API yet
 
 Porting:
 - rtp module ported to Win32 (sendmsg/recvmsg emulation)
@@ -13,16 +12,12 @@ I18N:
 - iconv stuff sent from utils to server (UTF-8)
 - iconv sample loading in server
 - Document utf8.h, timeval.h and util.h
-- gettextify polypaudio
+- gettextify pulseaudio
 
 Cleanups:
 - drop dependency of libpolyp on libX11, instead use an external mini binary
-- merge module-oss-mmap into module-oss
 - module-tunnel: improve latency calculation
 - use software volume when hardware doesn't support all channels (alsa done)
-- silence generation should be moved into the core to avoid races and code
-  duplication in the backends
-- don't read/write audio data from/to ALSA devices if noone is listening
 - using POSIX monotonous clocks wherever possible instead of gettimeofday()
 
 Test:
@@ -35,7 +30,6 @@ Auth/Crypto:
 - sasl auth 
 
 Features:
-- alsa mmap driver
 - alsa driver with hw mixing
 - "window manager for sound"
 - chroot()
@@ -52,7 +46,8 @@ Features:
 - Support for device selection in waveout driver
 - add an API to libpulse for allocating memory from the pa_context memory pool
 - allow buffer metric changes during runtime
-- "include" command in configuration files. should have glob support.
+- better ".include" command in configuration files. should have glob support.
+- recursive .if
 
 Long term:
 - pass meta info for hearing impaired